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 001/394] 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 f621b2089e9b..4265b91d3f3e 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 000000000000..6ed926304db2 --- /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 000000000000..bc254a03a24b --- /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 002/394] 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 4265b91d3f3e..58c1b17b5c33 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 000000000000..3ec123a8ed7c --- /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 59bc1b677b57..6438f330c386 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 e98936aaabbd..dcbdcdca3b0c 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 fd24f06cbb2b..00f12fc71de6 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 c0d1e87270ef..5f0c79da534d 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 f976be03c339..09c10448695c 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 eef0b29fa3c0..799e53d06d42 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 743b0513cc56..b35f341417a2 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 20a536b5e556..1b759f8b395a 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 9045d8034003..9c4d73a13a25 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 f6c084b001a7..d744bd7bd247 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 003/394] 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 6ed926304db2..b9513f70dfce 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 bc254a03a24b..6f486b737f13 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 973f286f286a..025054b9504c 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 dcbdcdca3b0c..ebd6d84a9680 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 799e53d06d42..6fb0453c186b 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 b35f341417a2..c3ea8b94f8aa 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 1b759f8b395a..acf1a37aa43f 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 9c4d73a13a25..e2a66ab74fba 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 0ed17c870a1f..b088e3b55ed8 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 859b24151592..acda15ce81a5 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 d744bd7bd247..10573b012298 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 004/394] 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 b9513f70dfce..85bd41d10ed6 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 6f486b737f13..72752cfefd45 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 ebd6d84a9680..35c9db0dfe8c 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 fecd1329cd7a2bb0b77428ac8d02bb6b86c72d24 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Wed, 9 Oct 2024 13:06:41 +0200 Subject: [PATCH 005/394] 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 cf8c720f6b36..682931dc414d 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 64cab51f54c5..d8a2b2b1ac5f 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 ae725774c48a..bab95c457b6a 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 ae89bb56f31a..942153d3cd6c 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 301dbfb658e4..bdf51d2a5566 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 000000000000..d26af22a70dc --- /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 006/394] 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 7c36ff73b436..b78269a3d6c1 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 eabd5b9eee9d..13af14b75b97 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 007/394] 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 85bd41d10ed6..4537c8c5d8fc 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 72752cfefd45..b0b9ccb7a3dc 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 008/394] [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 27baf5485104..5efb080554a8 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 009/394] 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 5efb080554a8..9b5ee447e6d6 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 8df5b4dfe043..91e2ef9aff4d 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 010/394] 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 b187ea84c74f..f1910648378f 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 011/394] 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 c68df205f941..007b6187c747 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 012/394] 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 50c69b179dd1..b9d883dcde06 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 23c24ce305fd..75d86136e9e0 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 7a153de7d362..a878d375d02b 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 badeb21fe7f9..253e7e0d5ae0 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 5d6dd1b23dea..126c3ad6f691 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 fe899870022e..3310d80b8e26 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 7ed321cd48e6..9a891be915d7 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 930a34cf1a04..d0850972b442 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 343a17b4a4a1..484a7a241d81 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 9f7fca9adc8d..46a0ec0f7a6d 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 8ca10add2f26..1171303af291 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 915567489816..381cb999f0ed 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 681c24c0eecb..b6a0552cb7b1 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 cab7987ea9cc..7bf365031b5b 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 d1261d2464a4..f0ae32b1b661 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 2a19d0a88f69..fb5b7fb89489 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 7be2db96b923..8750f164991a 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 74574be13c3f..88ec2c3542c7 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 aa20ac6799b1..309d995469a9 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 9b63bdc1b12c..82c2fd766e2c 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 d288503babbf..230535525007 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 e14b010083cb..74f613cdfffa 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 c6fd0ac80527..18d31087f9c5 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 13c95235571e..9d32cadc0cd7 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 91a456461f00..ba0319108b27 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 f75260224005..805beb42495d 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 c046b182ff21..1a087f9c9430 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 4f8cda7a4c49..dbd802e3384d 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 f18535d71189..efb41524b5cc 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 ae06509429a5..0275e1665ae5 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 fb2339cebb09..f7f945abf58a 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 cc630758957a..7348b2e20cd4 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 d9f1d84fcb4f..a1e55ade4ae1 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 b18c902db60f..047eae408730 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 14a1c02b1f33..3858b5984dba 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 013/394] enable euler ext test --- .circleci/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ca1043685c1f..79a149a7ec63 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 014/394] 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 000000000000..d254bff83d54 --- /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 000000000000..06496f4a26e7 --- /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 000000000000..b64e82bd0d14 --- /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 000000000000..80cc66cd19b7 --- /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 000000000000..0b40ad0723d6 --- /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 000000000000..dab55ebd1045 --- /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 015/394] 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 5eb079db18d0..01270ef44316 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 016/394] 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 f4e88de3c17d..897952452412 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 017/394] 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 897952452412..3ecc813c3da0 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 d2cbdb11b360..18a87f7bf59b 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 018/394] 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 ab26526e14c2..8f645f6fddcb 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 de1ac20f2015..9b15936d642f 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 1bc805780145..202bb2256463 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 f06c72bac2ff..226a126c368c 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 943f34ee4c1f..b9bb21227c29 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 a3629eec2db8..2ed773cc9e7b 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 6435e0f15455..bdd663c411ac 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 682931dc414d..9eb5465475cb 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 fe45008962c8..ed06bebac90b 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 6bfdc9cb9de3..9e9d5e542ca6 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 e3a2e01e1b1f..36a437c8cecf 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 011081dedaac..7dc89e38e0e9 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 c444a71435c0..9d8bd73a3465 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 8d7dda0bb50c..6d3aacb248a0 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 000000000000..0078e6e68e36 --- /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 000000000000..bd29cf65979c --- /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 000000000000..5f768feebd32 --- /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 000000000000..8b1c7ab8015c --- /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 000000000000..552620a72a0e --- /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 000000000000..08de0df183af --- /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 000000000000..08e8037842ed --- /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 000000000000..0fe3221f1a52 --- /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 d2cbdb11b360..768734458bec 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 019/394] 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 a3b6c0708b6a..75cdd2dd1796 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 b0ba53bce95c..040e7ce43b39 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 020/394] 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 ad8899fb11bd..4447a0b8e97f 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 06539dd89373..66727585dbcb 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 82aea42f5299..2ca3d62f004a 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 a47c4feda27f..f394054d74f0 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 a4511324e901..a7274ce639db 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 021/394] 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 6ece23805aac..aac943517e02 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 000000000000..8cc186b92401 --- /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 000000000000..e5d519bdef00 --- /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 0233a1cf078a..76f0368ab9ca 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 15a41cb9f3dc..efa82f48c9b7 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 022/394] 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 8cc186b92401..88c2f7a99811 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 e5d519bdef00..c87dce2adad6 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 023/394] 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 88c2f7a99811..a08636e27272 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 024/394] 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 a08636e27272..1792963672fe 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 c87dce2adad6..79c516d0197b 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 025/394] 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 13af14b75b97..0ebefa6590f1 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 007b6187c747..e3927d4dfb1b 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 8ce2c5d62dfe..009103a498f8 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 d8ce4f2d0c7a..c5248e42e2f4 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 b791de3ef361..33aa08b463e4 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 d254bff83d54..74c8e867fc91 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 b64e82bd0d14..d6089273bf44 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 0b40ad0723d6..cc87ecd4988e 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 dab55ebd1045..3869f7c652bd 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 08a2814c95e3..a98c7a323015 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 026/394] 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 cc87ecd4988e..4d2aea1f147a 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 d6089273bf44..123edc75ddd6 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 027/394] 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 819a4b1c8eaf..51d30ae5d191 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 33aa08b463e4..4816ee531c07 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 028/394] 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 3f347fcf4f91..52593fab7ced 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 029/394] 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 3589e953f60f..3b0d73597dc4 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 76f0368ab9ca..21356bffa6c0 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 030/394] 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 000000000000..85691014f827 --- /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 000000000000..aee56abf8600 --- /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 000000000000..d09a6c1a5396 --- /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 000000000000..1147466b54ef --- /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 000000000000..4165f70ba640 --- /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 000000000000..18fa4288c5a2 --- /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 000000000000..4af41df671fb --- /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 000000000000..85691014f827 --- /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 000000000000..3a287ee760ad --- /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 031/394] 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 76f0368ab9ca..9509a4b86d4e 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 032/394] 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 9509a4b86d4e..1e4c3e21e430 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 033/394] 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 7bc0ebc7bf58..a42cec172d49 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 3b16205e7d86..6a3a902edffe 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 911230d224ce..69d24cf42669 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 772e8575dbfd..a9e4fa9313da 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 9eb5465475cb..84eb39daa834 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 d41b41a36a42..f7741dfae924 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 000000000000..8ee17de4b668 --- /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 58c1b17b5c33..cc4c5051c4bd 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 471a164e523b..2694eef1c385 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 3b0d73597dc4..a707771a2512 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 3f347fcf4f91..d86ffbc7a05e 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 1bb23cbc9282..0ea8f4e5a9fc 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 46ef933ba28e..1b523c4dd7e8 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 694639565421..e354649e75d6 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 9e9d5e542ca6..e50e849d700f 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 cc064c3a0f1e..45be636d811d 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 539279bf20d9..64ff94cf6102 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 9d8bd73a3465..19d21bccd54a 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 35c9db0dfe8c..8e52e78e7983 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 92b91e8ae1e9..dacd061806aa 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 073d621cc2cf..f74568421a4f 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 c078885e8ba4..478d7b9d911b 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 bf8952355d1f..022ac199ebb2 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 11325936c7c6..55219f6eae37 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 9f9bf958f129..71a0963d5542 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 d0839e765ee8..b1f069e1b434 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 afd005b719d5..0f6583285c14 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 c6387f808e0e..df18a687f477 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 cb7cd4164b03..bab02a2e1813 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 98d938a3621e..9402bbfb370f 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 d57a61332e3e..6f3f1760a852 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 19f262060fc0..001ff147d4b5 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 d945dbcac7f5..5b5ad0eee197 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 72c0f70ca281..0fcd35bda1ed 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 7e3f93475f80..4b242c82f4fd 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 13a6ba9ee526..eb639f8a6c3f 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 75cdd2dd1796..a88000f09014 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 c50ddac14412..f4f056697638 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 d0850972b442..d9ea91cbd351 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 6ac3cd1bd817..b43021ea7a52 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 21e97f0769c8..433ff3f072e3 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 034/394] 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 a707771a2512..20c2ae3f022c 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 1b523c4dd7e8..4596b225253e 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 e50e849d700f..e9beabef6df9 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 45be636d811d..b784866285a7 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 19d21bccd54a..97bf962d0a0c 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 6d3aacb248a0..cc70d75afdae 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 035/394] 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 e9beabef6df9..e95e2246fcf2 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 b784866285a7..f6ebb93409b0 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 036/394] 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 20c2ae3f022c..62d18bdf0ec8 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 4596b225253e..fe6e0ec8ee1d 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 f6ebb93409b0..1443b44811fa 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 b67cb77cdd50..1475246f1686 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 d37ade2cd211..07ba34a75458 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 97bf962d0a0c..5e82cc6fd3a5 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 478d7b9d911b..a9a8282a680e 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 022ac199ebb2..8b3282888865 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 b1f069e1b434..7ee9a9b8c5d5 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 0f6583285c14..d082bb78d676 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 9402bbfb370f..d6961b6f8ca3 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 01ab1adbd7e3..53ff25325996 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 4b242c82f4fd..e75472f068f5 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 a88000f09014..9f6b88412f9c 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 037/394] 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 038/394] 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 039/394] 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 e95e2246fcf2..1ed422551402 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 040/394] 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 6571cf6dd7a2..865a568f62da 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 041/394] 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 f9ec9b0110ed..f8e1ebbdc805 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 042/394] 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 d23249d2200d..4c6f2a60f6b0 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 7ec97678e990..cd133dab0b8d 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 f6b01e9b2cbf..3ecad6b35d48 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 11ee3a702f8c..7764e89abc59 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 8b90cb3c1324..e75a75b5fbb6 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 68ef6404cdb8..78cca4390a61 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 f3cd0758c0ea..09d392567c3b 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 38f658653641..e4c7c7bd004f 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 d46fdda8a917..b51effdcb322 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 1f98000b0ec3..2a3673fade2c 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 760f1d7a75ad..f1f37340e7d1 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 043/394] 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 b78269a3d6c1..a0a8313b095c 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 4c6f2a60f6b0..02257031a4d9 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 c89c56f4f583..2bd870549c2d 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 02b1c85ffe0e..fe5421acd202 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 0b796035d313..1c4c48090645 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 fda573d3d4cf..a7f792453f09 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 c52a83a26183..7f413f91a999 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 91b88cb9c842..6368dc1eafcb 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 d8448fc0beca..a3aef325b0b1 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 b76cdd252281..2ecb8cbcc45c 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 07e138710624..7ab087bbdb99 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 8de36b1ee4e8..bf4337810dc9 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 56cca82c0832..0d6d7341e52c 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 cd133dab0b8d..dcef00b5fd0e 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 8b90cb3c1324..e75a75b5fbb6 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 3a857d4848c9..e75a75b5fbb6 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 78cca4390a61..8891b0e18c59 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 f21d4d4c8f46..e75a75b5fbb6 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 eefa60785bb2..f4137ae42961 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 16fb77513081..8690a6e96cf1 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 ed6f627b5adb..25f08dff48ee 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 c13e9ce07fc7..d2446c5f92e6 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 4b4f7a3ace98..e4b42c926378 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 b2d1b4acc6d0..3bc9da4d63fe 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 4c21a02a6bbb..dbf28814d0ea 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 813185adf497..b785895947f5 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 968095bb2b19..ef4b19c1d41c 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 5ddb61a2226d..3e6dbe6411c5 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 dd8a529a2f1f..65cd7b72cc3d 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 c1d567cfec7d..16779bb89a1f 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 d7721037fb88..3e8e4f409650 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 2b94abc0e02b..256a8870e10b 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 2a535329aca4..7d87fb07c405 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 80e27e7e2a77..182bf15cc026 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 34df5c0e0fb9..3b6630e6db47 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 bfc95b35a2fd..a28e4852b0f2 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 b18d5426f5b8..ef02b7839d60 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 644ecdb122f8..3057ae0ec4f6 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 76ad6db55384..30f6a0ba9781 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 2a9f39d1a2fa..e4d9bfdff56c 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 fce586987795..bbc3a79cf1a1 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 d5daba699912..5f4fad62abca 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 044/394] 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 a0a8313b095c..836d2cccb79e 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 2bd870549c2d..8b22da7dbd3b 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 1c4c48090645..5925a50ac480 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 045/394] 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 bb88d1201678..decd51392815 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 92aaa847c921..7db996fafc88 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 046/394] Add changelog entry about Z3 switch --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 0ebefa6590f1..4c2885c9a8b8 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 047/394] 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 02257031a4d9..0bd74a410300 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 2a32c4fcda63..5c642b0e2a64 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 0914f8305dc3..0430f0d21ea0 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 a7f792453f09..6f3eb6c4cd02 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 7f413f91a999..9f23aff6fb67 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 a3aef325b0b1..2ceecfcf9088 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 048/394] 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 79a149a7ec63..a8f6d755247b 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 4cf3927d1d06..8b40bb2c58ad 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 a79630b6e59b..000000000000 --- 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 98f21246c297..000000000000 --- 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 efd656259819..000000000000 --- 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 ee5270f440c9..000000000000 --- 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 0211f600d9f1..000000000000 --- 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 5e755cb24b0a..000000000000 --- 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 9b24b32dbfe1..000000000000 --- 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 6f3eb6c4cd02..679309766c36 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 049/394] 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 3d58fed43709..4fdb85aea335 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 050/394] 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 4fdb85aea335..8b41105f1fc8 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 4607250a62fb..aa38e6c7a0af 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 1caa5357e534..6a70c1cc8f77 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 051/394] 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 004bb4a6141d..b2fe490cc597 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 8b41105f1fc8..2201f3c9dd1e 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 aa38e6c7a0af..5929144049a2 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 052/394] 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 730bb6319586..e95caa7c1cf6 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 a8f6d755247b..eb516140608e 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 8b40bb2c58ad..ccbd8a6c4e93 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 092b8636b8e9..0a00fb1528c4 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 f9ea64860ae9..272d0bc4d6e5 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 5473dbb5240c..0d63d48212f9 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 053/394] 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 dacd061806aa..e7b3c9e6d73e 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 054/394] 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 d4debab9381a..554019135b80 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 1ed422551402..27a1f1426d75 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 055/394] 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 4f7b88fe974f..3c781ea78f07 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 056/394] 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 45cc83aec318..42dabbf05ed3 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 057/394] 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 202bb2256463..3ce6238bc8be 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 5f768feebd32..1c06caa5e36d 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 058/394] 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 cbe0219676fa..e3ea50d099ef 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 059/394] Update ReleaseChecklist.md --- ReleaseChecklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 8ca2e7f96ed3..a70afe0cb503 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 060/394] 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 8b1c7ab8015c..b38222917af0 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 061/394] 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 d663bef858c5..0dcfba47135f 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 062/394] 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 eb516140608e..0bd7932ce0eb 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 488201bae3ff..9631a72568c9 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 86c14901b22c..1c7882448ca1 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 063/394] 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 84eb39daa834..a234fdb813d1 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 d8a2b2b1ac5f..7673e375ad20 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 8ece236bf425..9cc6bd864320 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 c6ba5311ad5c..4b8119ffa5b4 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 230f97866e09..3a89db4bcc23 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 8b559e23f46d..877e447c78db 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 2c2ef4272904..6ad3899e96c5 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 d3cb6418fd30..6ef4b267b67e 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 6562e1743588..41b856edd2f0 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 000000000000..bcbbca624cef --- /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 064/394] 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 8f645f6fddcb..153ab547e9a8 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 9b15936d642f..daeea6e8cf0e 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 3ce6238bc8be..d26e01f8a7ab 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 226a126c368c..e51d07b16150 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 b9bb21227c29..5122fb01f604 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 2ed773cc9e7b..d9e96c49ad48 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 87d41f6c13a0..e909a7074dbb 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 bdd663c411ac..9041ae793492 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 e087dc69a575..fd47fec10184 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 2bf837697b47..01220e87b86d 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 44fc5a935a86..48b646d3536c 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 9f01b74fc246..ed29a8bb3971 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 69d24cf42669..1304eca9a3e8 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 60a93bbf01d9..457b28e37396 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 a234fdb813d1..8ed0b414211c 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 ed06bebac90b..7c44dfa78dc1 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 27a1f1426d75..9de3e40fc598 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 36a437c8cecf..604177c4f78a 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 7dc89e38e0e9..d0bd3e14aff5 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 5e82cc6fd3a5..0497b11b63fb 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 cc70d75afdae..5af1bd418026 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 d5c02fc82151..975582f669ba 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 0105ea97298a..133815b97dd7 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 09306772c9a9..d4d9190ff68d 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 17f6df675585..26d37caf4625 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 000000000000..63558294f120 --- /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 000000000000..4169d52ab3b8 --- /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 000000000000..f3acc8277511 --- /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 000000000000..1e9fad7d0244 --- /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 000000000000..7efaada8bcd4 --- /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 000000000000..2d193a800d17 --- /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 000000000000..be345ff0a925 --- /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 b43021ea7a52..0f1f37451569 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 065/394] 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 df18a687f477..328ef83b8e7b 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 066/394] 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 9c3b1e4bcabf..ea2116f0352a 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 977db11c4c12..4159b875f39d 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 b6dde8c5511f..e5c11c491462 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 98023b64cfc6..6f50636a77cb 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 067/394] 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 f4f056697638..7c68d577bb74 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 6f50636a77cb..f749a229ca11 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 068/394] 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 7183c64a3f18..4e7a5cd508b4 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 4a0f636dc974..84de00656e90 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 96b1ea54823d..97ffb17e917f 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 69d24cf42669..5054e1aa1d03 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 a9e4fa9313da..80c442b88146 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 e3927d4dfb1b..f24fae3cd476 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 523825830f46..75e3400b7d3e 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 cc17c6a04ce3..6eda13fcd83a 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 c6ba5311ad5c..0d5e120a8b85 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 230f97866e09..15b94044b838 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 511fc979ddb0..6a6354f94b36 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 123dedcb483d..67f5b70dd003 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 1443b44811fa..65cc70f162b7 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 07ba34a75458..5154bd37fe1c 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 15d057455ac8..70c020b9cee3 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 a5871f7f111d..d63c3287dd41 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 ff8c2b7cff28..c6b5f8cfc63c 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 efa82f48c9b7..e4eac31df505 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 6562e1743588..9b72fdc29389 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 2255272b6b5e..54c61f875a79 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 6c86ac21f32f..9691efa216b4 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 b9d883dcde06..799f64ce7948 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 a878d375d02b..bd9a9da07918 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 308afef5f904..c17beb84d5c8 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 832b5dfb8f7c..2412812888b0 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 41806fcd6a5a..b214b80c01c4 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 cbe0219676fa..a1a5e8c583b0 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 fa7fbe274c95..25cc8c5505f5 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 069/394] 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 13770989b91d..6219d51b81e5 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 d09a6c1a5396..a43c553c4839 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 3a287ee760ad..d68997bff969 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 070/394] 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 6219d51b81e5..17737533fd16 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 a43c553c4839..8d3fc5b7e057 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 d68997bff969..d8f2025b3ed3 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 071/394] 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 2316d83d586e..451e766ddf52 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 072/394] 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 451e766ddf52..30235c4785b2 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 9acaccb67f79..3f5fe0bbfd5b 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 073/394] 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 30235c4785b2..bbba60bad6fc 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 3f5fe0bbfd5b..16e47ee4fb38 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 074/394] 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 bbba60bad6fc..9b82c5767cf7 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 16e47ee4fb38..b003f0ba18d2 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 075/394] 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 4a053d51beea..23119484d103 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 076/394] 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 9de3e40fc598..d7167fc77eea 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 077/394] 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 22b20bc8c267..cd1a88ab7c1f 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 197259998fcd..2d8e023220ac 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 3f0af6f981d2..35563d890712 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 078/394] 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 0f4aa6e337e1..73b4d5083c54 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 079/394] 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 f7741dfae924..26a4d386dddc 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 080/394] 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 0bd7932ce0eb..a39fad80b0a6 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 081/394] 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 a3aab07fba29..b62ea3e2df8a 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 727652f56000..0e2df8a900fc 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 082/394] 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 1ca46ccbc260..1f702851c066 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 083/394] 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 b2fe490cc597..48151a637713 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 084/394] 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 153ab547e9a8..fdc27241550b 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 daeea6e8cf0e..4b52ca3d7970 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 d26e01f8a7ab..96c007ea5ce7 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 e51d07b16150..a9c46bb14edb 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 c978bae2bb39..3ba8cfcd3523 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 a501b487f45a..3ee3a39cbdc4 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 50a783e1a6e5..f202b358e5f0 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 5122fb01f604..60ec75f9284e 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 d9e96c49ad48..76998c538d5f 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 7afa715a88df..7ded5ae90889 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 40937e73f107..64650eaeea9f 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 e909a7074dbb..99a5a0f4348e 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 9041ae793492..f469f337d632 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 604177c4f78a..d8810b261db3 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 000000000000..b13f3c3625e5 --- /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 0f1f37451569..044fff8ce6f4 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 085/394] 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 dd29d9a498a2..2642c0f5c821 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 554019135b80..8de6b53d4832 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 d7167fc77eea..f998b7abbc6d 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 000000000000..cbc76b1dea17 --- /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 086/394] 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 25ab26544318..d2c9c86e7b2e 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 087/394] 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 decd51392815..3cdadef95300 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 088/394] 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 a39fad80b0a6..994a200329bf 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 089/394] 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 4c75649ae8a0..273eac6020ed 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 c853f95eddea..800524669048 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 604560554ad5..4d02d3e181fe 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 2642c0f5c821..c81c9562a58c 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 b7987cc001aa..7ad83795cae7 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 7de8a42fe521..7bcbf6ad14fb 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 61a8d0b431b1..97d7273e9424 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 4020530864a0..b44d39c3498e 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 52920340055a..1d157663a56d 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 35891b459939..d26901c230cc 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 090/394] 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 994a200329bf..15d3b4fc5c46 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 000000000000..df31cd316abd --- /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 091/394] 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 cd1a88ab7c1f..b3e879574689 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 092/394] 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 91e2ef9aff4d..327920e216d2 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 093/394] 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 15cb71f5be8c..9cfcafd4bf27 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 094/394] 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 1773859d4eaf..e8e8fed5880b 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 095/394] 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 4b52ca3d7970..f2da01e22f9a 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 ae6d1bf9c617..032ed4411aca 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 3878ae0fdd75..66553bc06633 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 096/394] 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 fdc27241550b..5bf8e25082e9 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 032ed4411aca..c9d0633e4c2c 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 76998c538d5f..84c6e34e6272 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 c5248e42e2f4..351a17b897d6 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 cccd241d9416..14e502301f20 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 097/394] 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 dff85b489ca3..4c359c4117f9 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 098/394] 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 5ef5a6eff333..191e803861e2 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 099/394] 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 15d3b4fc5c46..542118f6deef 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 4c359c4117f9..c606913e4e93 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 836d2cccb79e..729da0d72e23 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 dc862b1f7efc..a53393f1d34c 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 bb4ef03428e7..54f3233531fa 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 79be48b3ae81..3b9a4798688a 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 100/394] Document memory alignment (#15586) --- docs/assembly.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/assembly.rst b/docs/assembly.rst index a0a9d06dc76c..09e158e489c6 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 101/394] 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 5bf8e25082e9..584c46455aa4 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 f2da01e22f9a..7ef03460cbcb 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 000000000000..06aebd6742da --- /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 102/394] 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 584c46455aa4..f8734b5fc3da 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 103/394] 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 f8734b5fc3da..4719d357fc40 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 000000000000..2225fe6ebbd2 --- /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 104/394] 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 8ed0b414211c..aedf4fd0708f 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 000000000000..f39d6f2d8639 --- /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 105/394] 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 23119484d103..79ba8da6e5be 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 106/394] 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 3ee3a39cbdc4..1eff35fb2d66 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 60ec75f9284e..82ed73cc994e 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 84c6e34e6272..351a6981c070 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 99a5a0f4348e..4d61240fb198 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 f469f337d632..26364f2af2a2 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 f998b7abbc6d..de1201481a3c 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 000000000000..2dcd04ca62a2 --- /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 044fff8ce6f4..92ac56d6919f 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 107/394] 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 96c007ea5ce7..ea670eb0a2b3 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 a9c46bb14edb..62e21008b769 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 4d61240fb198..c27945b82e51 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 b62832f238af..457f60052a6a 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 108/394] 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 4719d357fc40..29b8c8a4057c 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 7ef03460cbcb..db567a917b10 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 62e21008b769..28b2fb537545 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 7c44dfa78dc1..6fe234782e10 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 d8810b261db3..d9cf47f4dabe 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 d0bd3e14aff5..29a6fba7bef1 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 0497b11b63fb..c9d6c6292fb5 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 5af1bd418026..2669a277c4a4 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 109/394] 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 fe6e0ec8ee1d..e92515e988ad 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 77feaea7b469..1d0227a56b71 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 65cc70f162b7..58944bdc701f 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 8ef01f0b6a86..89a75019ec31 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 7e648ca964bb..2c072bcca2f6 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 1a30842aecc8..3d1d5f7b0d76 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 fc846a9deced..44cbbd43a4b3 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 6ad3899e96c5..71a0463c9b17 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 6ef4b267b67e..02c6de1594e3 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 110/394] 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 aedf4fd0708f..491effe8e619 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 111/394] 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 b7264bc0e96d..0aaaea58105c 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 44cea06d3f7c..e9de50a610c3 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 f50d2d23b028..49af089ef82f 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 9f570045f78e..6116b1df7347 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 06aebd6742da..46df86355091 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 000000000000..72167f72ab04 --- /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 000000000000..623bf6ded6fb --- /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 f39d6f2d8639..314d4fa3df72 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 112/394] 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 de1201481a3c..4d160b03049e 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 000000000000..00042ae65076 --- /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 113/394] 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 ee52bf53c27d..5d59308ae3d9 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 84de00656e90..c09b33a0081e 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 97ffb17e917f..3548d0ae7850 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 f51846280a8f..be734fa6b906 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 459d9d9becd5..692169fd29c6 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 f3df8c178e9d..2d7ff472c5e9 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 26a4d386dddc..baef6a3c52ad 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 3bd0531f4fdd..0dfa610d07ae 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 2109b69ae7ee..295c4a87c786 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 6a6354f94b36..d7c1526cb587 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 67f5b70dd003..123dedcb483d 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 71a0463c9b17..686fb6695e89 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 c6b5f8cfc63c..0bef31472e49 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 9691efa216b4..daa8f61aa81b 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 799f64ce7948..3dc576c8ed20 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 bd9a9da07918..46a7c99fea51 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 253e7e0d5ae0..0e7d411a3d3d 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 c17beb84d5c8..ad7485aeae15 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 0f94f309dce4..9b8d2073cdcd 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 3221dce8c699..5b634de36232 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 25cc8c5505f5..9e16826d9c7e 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 114/394] 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 c09b33a0081e..5c859f54f872 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 5841fdfd3249..5ba19014995b 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 6eda13fcd83a..6b63c863883e 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 0dfa610d07ae..54ec6a3cfd7a 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 10a55217ca59..32f60c8ebe6f 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 ad7485aeae15..dc05810bc672 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 9e16826d9c7e..6d182782701e 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 115/394] 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 5c859f54f872..25829d96a9f4 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 3469ee7d278a..2805b8daf8d0 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 3548d0ae7850..d7db52e7616a 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 116/394] 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 25829d96a9f4..3cf713a942fe 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 d7db52e7616a..57a23fb803ce 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 491effe8e619..b00982faf882 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 7673e375ad20..6235b530d16d 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 d7c1526cb587..992c41b4d921 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 0bef31472e49..a9c5b0f2a05b 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 5f0c79da534d..ad825cdf5073 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 117/394] 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 877e447c78db..a7bf415a5aa4 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 5b5ad0eee197..1698ac5eef7a 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 1d0018897c00..e97fbd0c31a5 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 118/394] 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 686fb6695e89..a421a2d024e2 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 70c020b9cee3..b0b086a7e2b0 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 a9c5b0f2a05b..805dd9291017 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 9b8d2073cdcd..d75fbbe1598e 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 5b634de36232..b164bfb4f3d1 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 119/394] 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 3cf713a942fe..4d53b9c234b9 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 992c41b4d921..181cbaa8fe4e 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 805dd9291017..766f96821b18 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 e4eac31df505..bd3e1aa054e3 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 d75fbbe1598e..a7452d0537fe 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 120/394] 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 9cc6bd864320..cc46ecb77000 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 160aeca8c783..1b7bf65a5b1b 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 a421a2d024e2..04b931a248e8 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 02c6de1594e3..2dc32d78759a 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 daa8f61aa81b..1956db84c6b7 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 a7452d0537fe..351d705cc517 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 6f603e335d46..de2fdd28632a 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 121/394] 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 04e16293fd96..e4d25f195fb7 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 1240b6877f1a..c44f9bababf3 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 a6b59e157e90..c2077239a5b6 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 122/394] 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 478d8d947cf5..8bfb9c51a0dc 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 723192e2d0c4..7592f55ec55b 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 c7ad4594aab8..eb5439f595be 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 21092e312a7c..3b1e3e614d4e 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 123/394] 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 f24fae3cd476..b90a30242727 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 8d3fc5b7e057..c224164c52ec 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 d8f2025b3ed3..8339d02c735f 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 124/394] 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 17737533fd16..65c0805f984a 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 37520e194b21..91f9d040e404 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 a7bf415a5aa4..22c1fcb7dcc4 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 c224164c52ec..fc47f4f7b937 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 18fa4288c5a2..ac154fc16246 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 8339d02c735f..6848d7db9ddb 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 125/394] 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 4bbfb42437b0..dd32d6a604d1 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 434c5e9c5a3a..2341ee62a6c5 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 126/394] 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 4d160b03049e..161f92336b4c 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 58944bdc701f..5d5ea90a99be 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 127/394] 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 30c09039ef79..ef411e08a49a 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 7ec729b1c7a3..328ff76e22c0 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 128/394] 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 29b8c8a4057c..e5c62958f6e6 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 26d37caf4625..5d134f277865 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 1c06caa5e36d..5d2115f95af6 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 46df86355091..fac0f7b5df29 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 63558294f120..aaffee722f8a 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 b38222917af0..06ebdaa3ce38 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 72167f72ab04..65361efa3b5e 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 2225fe6ebbd2..0c9f9a382497 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 b13f3c3625e5..d5f2f6c2117b 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 129/394] 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 b00982faf882..f1664ad685c8 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 000000000000..4ed95e6c3f5a --- /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 130/394] 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 a42cec172d49..11d8e84c6601 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 6a3a902edffe..cbd538551106 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 5d59308ae3d9..344bfb39d2a6 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 be734fa6b906..b19499b9a7d1 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 8aba4f248c07..868fc84b2827 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 b00982faf882..7d395a208a99 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 6235b530d16d..e8c02fbec132 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 226ac52a5ac8..fd36dd26022c 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 75e3400b7d3e..458142e29346 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 692169fd29c6..a937be62fb7a 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 baef6a3c52ad..66ac22a08e72 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 d4616a2a9508..b546e179fd96 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 5ba19014995b..a3f7b4ca2b23 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 6b63c863883e..d889d83f80ec 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 2694eef1c385..28089b029fca 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 99e83c2130e7..bf3f536a49a8 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 dd32d6a604d1..e7caf1b2dff4 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 2341ee62a6c5..a4a558a855b9 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 0ea8f4e5a9fc..d7aed27c339f 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 35d7dfa43254..5e4b2002b0d0 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 e92515e988ad..990456732bb9 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 e354649e75d6..f77e4e047d7a 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 161f92336b4c..c73a9a79483f 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 64ff94cf6102..57593fdc26da 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 a7ac67c3a6c3..de1174acee00 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 89a75019ec31..3a1b78e1eb31 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 2c072bcca2f6..88ecc2967763 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 e7b3c9e6d73e..b47248dd58bc 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 dae4352a02c4..0fd238c4052d 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 269c7adeedff..9e85651ad346 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 04b1c96cd2e1..e1c3a16aa3ea 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 5470558ce93a..2cc7a6648392 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 427161b3c784..12c1c5e72b19 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 f457f55838d3..9b69835dc4f1 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 23e9a2511588..722cbba4a796 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 a34f3f4e2aa3..d238f8da2148 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 f74568421a4f..87a14d259070 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 d7dc42596ca4..35f8168eba73 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 a9a8282a680e..53afb5e77785 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 8b3282888865..ac08fb0be196 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 5a4b199caefd..7d0f78b534c2 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 a0b54c590ff5..87f8cae161a6 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 10d15126e645..bbbf039d56ed 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 ab4bbcfa43a8..1dbd5ca98004 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 598d2e90037d..4aa7be1bb556 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 71a0963d5542..1bdaa552ba16 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 7ee9a9b8c5d5..6324085e65c2 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 d082bb78d676..111f26fec5f3 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 328ef83b8e7b..4b390f4f271a 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 e939070238e5..4620194a4e51 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 aaf8b9f68232..4c85d77f5246 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 41a19fe99fc7..067aee2a399c 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 bab02a2e1813..cbbf14e8f84a 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 784ec4311e0f..4df59b354c45 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 d719302dcbc2..6061fa3e9725 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 e7210da69a0a..c6897c173529 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 731f4b3b8195..ceaa8f06b359 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 46ea7b96af66..78daadbc4ee4 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 d6961b6f8ca3..36163c6c5f21 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 b4a496303373..d878076929a6 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 2a196a68f956..f2e7d040802e 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 c85b87a01c32..d03a91eeeba9 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 546c465b5c43..04bfe9a7a06d 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 d6db837f8485..cde9b64f67d1 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 0fc2e311ca50..2adc73ced8e3 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 c68d52f9a7bb..7430c26c3046 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 6f3f1760a852..0572a9003523 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 001ff147d4b5..8fc225bee0a4 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 911a1be0a812..430834d8304b 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 1698ac5eef7a..a505126ae9f1 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 e97fbd0c31a5..9fdeb78d031e 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 0fcd35bda1ed..8a7549cc125a 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 9362ee8557ec..2d48464ca62f 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 2dc32d78759a..766cd4928447 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 e75472f068f5..15df64b3f252 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 73b4d5083c54..e233b57e9e2d 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 1fd888f7af8c..0db52c9690df 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 eb639f8a6c3f..6de2ebf4cacd 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 9f6b88412f9c..91568f4d65be 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 040e7ce43b39..37d26bbb0c85 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 7c68d577bb74..6f2f1ee938f8 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 f749a229ca11..6da33a9866c6 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 a98c7a323015..b797564b7234 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 0aaaea58105c..bd0bf0a802d2 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 46a7c99fea51..204150ad837e 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 0e7d411a3d3d..eefeb90109bc 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 49af089ef82f..b41f7f21e820 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 40fdcc5b15f4..baf8e0c8e543 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 433ff3f072e3..2709d1b468aa 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 131/394] 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 000000000000..80f84c1349c5 --- /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 000000000000..3c4517fdde0c --- /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 132/394] 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 2cc7a6648392..6e8e8ed62f57 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 133/394] 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 7d395a208a99..ddd7ad1539aa 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 bd9438e5abc9..d6c13f0d3751 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 b47248dd58bc..4597c56a5917 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 1dbd5ca98004..0d59dab2d2e7 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 134/394] 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 9d816061c209..55f5af4cf3ab 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 000000000000..77c10694749b --- /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 000000000000..79bfb4499386 --- /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 135/394] 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 d982c43f2b59..0b344728220c 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 136/394] 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 0e2df8a900fc..fa2ce20948c2 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 81b3b8374697..f017481be5aa 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 b19499b9a7d1..6a49db68e7aa 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 458142e29346..6705197f943f 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 2d7ff472c5e9..830e44b3acb1 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 d889d83f80ec..60a7f9a0f289 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 5a1c76297012..2ef7a4bfa003 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 62d18bdf0ec8..2afd4a579288 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 295c4a87c786..c865b906ed37 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 a4a558a855b9..64b5f456ac1f 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 5e4b2002b0d0..9c25450bf96f 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 35f8168eba73..713c35f0229c 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 86ebf296c290..829138471752 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 7d0f78b534c2..5b1cf25ffe1f 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 f252536c599e..701af3ad1561 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 08d8d158f699..36d178b086c1 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 08ff08648428..f8cf70d56e13 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 662c8c389936..b004c9b5211a 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 0b223e9859b2..2581b23de1e2 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 067aee2a399c..1c21a0115985 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 78daadbc4ee4..0852f8902592 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 53ff25325996..cdcc28822d94 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 3da50359a764..ec936d39af1b 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 3312e203d7ae..cfe297d4d7a4 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 0ff5077cc694..f3426d60f8f8 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 89bfcef814d0..7425a1906532 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 9fdeb78d031e..9d3c724af2d7 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 2d48464ca62f..f4b584b99ca4 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 b0b086a7e2b0..d5590006c855 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 bd3e1aa054e3..b0c3314089b7 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 ea2116f0352a..73628c929671 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 37d26bbb0c85..cd9a7e341d7f 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 e5c11c491462..2c51224c0f39 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 6da33a9866c6..45d363dfc9fc 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 7f8bb842e9e1..47f3aca48db9 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 54c61f875a79..e36e81052cc9 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 e9de50a610c3..953a27b22004 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 09c10448695c..13ca2027ab98 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 6116b1df7347..e1c6dc7f912f 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 2412812888b0..207a4b8ce09e 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 b214b80c01c4..bc513e7481b4 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 356a190709a7..427a30d9ea08 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 be4bf582d665..7ac7f3aad157 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 137/394] 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 48b646d3536c..688ab258a94d 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 138/394] 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 bab95c457b6a..43f73d4d71d4 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 409d6f6960e1..c3d21d258295 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 b797564b7234..9826f4b19468 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 3dc576c8ed20..50c546e36c5d 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 75d86136e9e0..da2eaad0eca0 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 204150ad837e..d19d87844fcf 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 baf8e0c8e543..258bc9204aa5 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 484a7a241d81..25b348dfb2d9 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 139/394] 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 82ed73cc994e..649a6c863486 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 351a6981c070..a1b9af364a0d 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 c27945b82e51..a9672efa53b0 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 26364f2af2a2..6f7ac91397d9 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 55f5af4cf3ab..fd826eaecd18 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 c73a9a79483f..bb7a96953034 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 92ac56d6919f..94a6c3b1ee3f 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 140/394] 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 9b2e0ea7723e..babe43357fbb 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 141/394] 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 000000000000..d0322b1a9e2e --- /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 000000000000..d9d7fde15997 --- /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 000000000000..1e503ca94a65 --- /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 000000000000..a8352c254d8e --- /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 000000000000..6aec96aa2e3c --- /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 000000000000..0515c8d265b4 --- /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 000000000000..fbfb5074b6fd --- /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 142/394] 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 1beb451de8b0..41b0bf86590a 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 143/394] =?UTF-8?q?style=EF=BC=9A=20SETTINGS=5FPRESETS=20i?= =?UTF-8?q?s=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 821b5cb750eb..96bd3c1eebfa 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 144/394] 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 e5c62958f6e6..12bb3cccc13c 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 145/394] 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 993541472637..4264bf71d46f 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 b3bd8b91fb09..a517a750c323 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 b90a30242727..fa84364681cd 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 bf1e5caf7c04..0999e30ed30b 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 20983b650990..3df712a43a76 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 000000000000..9443bac0605f --- /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 146/394] 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 4c2885c9a8b8..29b5870bc8fa 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 351a17b897d6..56f955f4013d 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 147/394] 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 56f955f4013d..b5279c624a9e 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 30fe1dd7ecb7..a72904ee6c31 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 7bfbb076a389..3f82bcbaab54 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 3181da426000..c1bb2eb3eb6d 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 1512900e1c85..2b6dc1f73e85 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 2a654d20a9cb..621a029076e2 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 513f8148a0f9..ad0e9f40aa1f 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 3234be1817fd..514280afcc80 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 148/394] 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 5626f8d436e7..7d0125eecff0 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 0081ba4a9d27..582cf1edab6e 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 5d66ea10d042..44812e230ab0 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 8d0b1ccb640d..c686963df317 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 db9119deebeb..6e8670e14e0a 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 1afebac5c5c8..9012ad083c02 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 e321a5298603..76699c2e3b6c 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 f91ba758f08b..4caa4aa1e1a4 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 149/394] 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 7d0125eecff0..fdaf3f35be1d 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 150/394] 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 d7aed27c339f..aa744415bf9d 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 151/394] 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 da2eaad0eca0..3b3432f8ed26 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 152/394] 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 22c1fcb7dcc4..4517853a31e3 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 de1174acee00..fb61e70f6489 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 5154bd37fe1c..cca346ae7845 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 3b3432f8ed26..1ba74a6e24da 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 153/394] 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 1ba74a6e24da..288c35570fe8 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 154/394] 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 fa84364681cd..dbfa4febe578 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 4517853a31e3..97c67d3b58ad 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 155/394] 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 dbfa4febe578..6a50b04c5d28 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 009103a498f8..81a039403b9b 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 b5279c624a9e..9357310c07e4 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 97c67d3b58ad..caa1bef87953 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 4816ee531c07..f2bb4af107bb 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 126c3ad6f691..d507aa333b06 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 156/394] 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 fd47fec10184..89ce999492fc 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 01220e87b86d..1a995734d28d 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 688ab258a94d..e8bb7a87436f 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 092edfab4fa8..c528b1aa7c0e 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 157/394] 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 2dcd04ca62a2..1d8ae6ddc588 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 158/394] 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 12bb3cccc13c..1fe4fa7d97b8 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 6ca064445012..af3a45a97304 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 159/394] 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 990456732bb9..cce5c98557e2 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 160/394] 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 000000000000..18532c5a6d3f --- /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 000000000000..2bf18f0c6d4d --- /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 000000000000..905eef6c758a --- /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 000000000000..9bd38bbacf31 --- /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 000000000000..47be2b30ed16 --- /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 000000000000..31af508c7b40 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..2bf18f0c6d4d --- /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 161/394] 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 29b5870bc8fa..9aaa1ca8b022 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 ddb6b70d1253..8c8bb7ab05b8 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 989cc4d5e3a0..55e4d56216b7 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 6a50b04c5d28..9649b79c842a 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 caa1bef87953..dfab4b6878c0 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 de391f591044..f9837e553ed4 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 162/394] 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 942153d3cd6c..9505a2caafe5 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 163/394] 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 288c35570fe8..3d80281c7d91 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 ee32b4431579..7baa751c3c0f 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 5e119cc73f8f..3d9d55e7822b 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 d743836cbcdb..060d0f428f64 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 eb1a787c061f..df22777245e6 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 78bf0a168268..5c1f027a47eb 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 b02710598fd5..92ecf2314055 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 37d372fb9949..20403c5121c1 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 96637da89fc1..c5fea43e809c 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 507b354413b6..669d62bb89bb 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 17ccdd3caf39..f92aa29548cf 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 e8d9bb30cc1b..4f667cf17124 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 1d157663a56d..78e78880818f 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 d0fc0506f88c..401b6927fdbf 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 bee0d3f635d9..6dc0cacff95a 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 5a9e7704e68a..2fad31cc7b02 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 97bffac381a1..8683163931b8 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 c18fb7c37e50..698f508307ec 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 08dda5a3bc28..e7c752a15589 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 9ac0c00bf8f2..b043977f77c9 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 fcc8278e6719..4266f1499c52 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 1cc19a464105..e83d68dd0fbe 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 e44e3b43729b..bef2538670bf 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 3d6286efdb07..e9f44f11d7ab 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 f8480bc91ea8..077a2e428d37 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 1ce02483dcbf..e834b7aa8ef6 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 cee19ab93fdc..23ab75b59bc8 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 49ffb3971be3..ed0a297bb649 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 3404dc53628c..eee735565a68 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 a80e66c10efa..dde7e1269471 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 db8783502340..fdf2f695bd90 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 9be91989d00a..4d0531a4dcfb 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 11e77c62694e..a7ef081e2601 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 214020ccdc37..adaa154614fb 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 e3002f34d942..3d10ecd42018 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 13decd3231ae..b9bbeeb385fe 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 13e3065ccc97..1af5c6454acc 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 f1cde362aef4..329d354ce6e6 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 2adfe7892bce..a2f2a1b476df 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 09a0d6feeb9e..d42e5928a155 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 ed497467d57e..3d6b68000188 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 bec4c834ff58..707c8a30655b 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 b9a814700abd..8f3e28390fdb 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 aa46f7a4a538..32b3704fd99a 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 f72d80fad0b5..a7fb935a49f0 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 ef7cd668c1c1..f8541dd3f1f7 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 666fefe1aa64..2c28d52a3062 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 164/394] 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 dc05810bc672..03f05ffa2ae9 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 351d705cc517..19b2176c10f5 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 bc513e7481b4..df5c84039b0f 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 4e9387f6f51e..2f372c3254c1 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 eff96f831eaf..d15043972693 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 165/394] 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 dfab4b6878c0..791b7103ded8 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 f9837e553ed4..94688fddcaaf 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 9826f4b19468..0f4230d5adec 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 32f60c8ebe6f..e64558bd48a9 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 e36e81052cc9..de402c29a9da 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 1956db84c6b7..a030af487eb1 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 bd0bf0a802d2..c0ab37956e4c 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 953a27b22004..f6c8ddfce5db 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 50c546e36c5d..2249ba110cb1 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 3d80281c7d91..624a44c3e538 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 d19d87844fcf..4dab4ace2d49 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 ac0653733f03..3490c854a0b5 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 eefeb90109bc..6e75442f0621 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 5c7b5fc34de0..9e74cd150e49 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 d507aa333b06..f7d331d94acb 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 3310d80b8e26..604ad0346c27 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 9a891be915d7..23d8aaa57f8e 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 ad825cdf5073..c23a2ca5faf9 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 13ca2027ab98..51dd3c86d1a0 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 b41f7f21e820..0db063740006 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 e1c6dc7f912f..c7259a02a963 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 aa37e85afdd8..70f54b86ac71 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 27e59ee61439..9aab3298e1c5 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 25b348dfb2d9..d97211b9761d 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 d591591332ce..b4a21b69a277 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 03f05ffa2ae9..1048fb468854 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 207a4b8ce09e..02fd6a0b2700 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 166/394] 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 9aaa1ca8b022..731640653d5a 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 9649b79c842a..9d76ced02330 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 81a039403b9b..f36eedde0611 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 791b7103ded8..03e22c8d1a80 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 e0f4e37e6ae0..0fa7fcff3cda 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 50438175895e..2134068db614 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 18bf550c066b..9aa5fce1211a 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 9f5bb8eab5b1..f1125b4d232b 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 5c127eb4a253..68d3bfc7ae03 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 ed7db1ec6c8b..858b9132dd32 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 7357d174a8d5..7d7948671419 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 604f9b029800..8e51bd1886c1 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 63df5c044916..0382672fe38e 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 58c74b9ad0b8..88a407fef98d 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 404cbc4bce0d..0e3cb3b6cb47 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 b113c6bcce52..ada627037e49 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 e80024a98ad8..adb9fbe699ce 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 20be0208c11f..e763fa18be20 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 7415ed6e85f0..b9205f01b1d9 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 fa32ec7dd86a..1282c24daf89 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 cb730221dfcd..3ee670cd585c 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 9bc6243029d1..ba467a67b131 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 8391734aec0f..b5162bcd9720 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 15ca25931efd..3ebd54d4541a 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 ea41bbf3ec7a..2518a4b57e47 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 9932c4c3d48b..9346264edbcd 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 a93555fd7120..e62728770d90 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 167/394] 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 cce5c98557e2..3986d54a0a36 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 000000000000..c1ed84ca4249 --- /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 000000000000..f3869c9ad48c --- /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 000000000000..610c9a4580cd --- /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 000000000000..9c0a0acdc779 --- /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 000000000000..1000cfd31f44 --- /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 000000000000..88010bd72555 --- /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 168/394] 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 96637da89fc1..515765ad268b 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 b5cc611879ec..09ce0b84a2b2 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 17ccdd3caf39..e78cda9cba17 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 e8d9bb30cc1b..dda389524edd 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 1d157663a56d..bf6ed9f14b6e 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 d0fc0506f88c..cf38dc0b4a04 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 bee0d3f635d9..eb912cbe2c00 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 5a9e7704e68a..42186ca69dde 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 97bffac381a1..402555e2d6ed 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 c18fb7c37e50..583173222628 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 08dda5a3bc28..6a53eab99108 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 9ac0c00bf8f2..ecaf79f76f0e 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 fcc8278e6719..4fe4dcd4e5be 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 1cc19a464105..977f8c9d638d 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 e44e3b43729b..7d3d9605703d 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 3d6286efdb07..ad5098af7f6d 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 f8480bc91ea8..20651dd49e48 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 666fefe1aa64..e0ff7eddf5f9 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 c1ed84ca4249..f4792619f185 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 f3869c9ad48c..0276b4cad5e9 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 610c9a4580cd..8cbb294cda49 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 9d32cadc0cd7..ddacd8b45dde 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 90c4b380e48c..f65c7505cb9d 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 ccf97422f44f..e01a8dcb3610 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 169/394] 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 4dab4ace2d49..cb24ed764c32 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 3490c854a0b5..9a7b77c14968 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 170/394] 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 bb02dba1d8ac..01dfd877cdee 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 e605ff1e514a..c8b467094132 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 038c368a29d9..3d1e2d836d37 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 171/394] 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 9631a72568c9..940ff1122aa9 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 172/394] 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 b7f7f8ae5735..d357447ac3e8 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 1267c1a2d92c..bc801ff5782b 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 2805b8daf8d0..17559fbf4182 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 c908c7ae0936..ffeaa790e1e8 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 6c06cdcc94e6..5ea99d603083 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 89ce999492fc..f33461b632a7 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 e8bb7a87436f..ae2a12c71c32 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 ed29a8bb3971..60d5d25cd026 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 babe43357fbb..3ae151593d33 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 9d76ced02330..2a859ea24517 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 5ff4e7a190fc..16220fd619b0 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 0999e30ed30b..bf9c6b16afb9 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 3df712a43a76..b6d40eed029a 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 55daf6d3d547..ee1ed30195e5 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 173/394] 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 8fe8d36f9bb8..aeeb1a0c1aa4 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 69896ebf1584..55abe4804c56 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 036d6ca629a3..13db633b9b06 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 7d068338b091..e59cb4214a23 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 bf3f0c0c9b74..a811d12c89f6 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 159f2943d432..76e5193d9720 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 13abe72c5cce..10a4ee06dbb5 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 5947b257363f..ed4eb6e4d15f 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 43d1fdab848f..d45c65524902 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 c04f039188c4..a736cab912fa 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 b968a07a161d..d70508b7645d 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 0a1250a8ba62..ef7b5dcf8cad 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 320349cda9ed..13c80b7b6273 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 2416f124ec37..14bb7cf07c6c 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 09fe0a1cc32d..1020f697dd06 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 dee3af35415f..7bc2982b78f1 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 07b12ad96cb7..b0a20f14310d 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 cc9d8ca6a134..905e1d3492d0 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 5845e9b56e15..b7d9bb5f454b 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 3260fa30ff23..46a9090c24d8 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 174/394] 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 14722535e446..39b0e6681abe 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 1337ae3f6f07..998411abf863 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 175/394] 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 940ff1122aa9..71c2a952adac 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 176/394] 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 6fa822fade47..95c30ac645db 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 2989c1acd8f9..e23a7bff2562 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 0d24ef505273..d9cacf5caf44 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 e1cce4acd764..2b7822f5f855 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 83e55c1a9c1e..5ab62e892285 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 6bf8f89394fa..aedbec0b081f 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 e921fcf125ba..2ea33955e9c8 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 d2c391582ed5..d198fd9927f1 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 e20e1d982427..b59bdafc2780 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 6ad4dd3bee43..40ef138136cd 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 982fcd28feb9..fae9a24fd757 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 afb442ed7f97..871c15eab388 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 177/394] 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 1fe4fa7d97b8..001865b2c4c0 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 db567a917b10..92dfb0a44008 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 ea670eb0a2b3..424b9eedaa39 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 28b2fb537545..babf2b7b7051 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 6fe234782e10..7a3e6b7422be 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 d9cf47f4dabe..b608859e2ba8 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 29a6fba7bef1..93e7c816abf4 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 c9d6c6292fb5..840372fcaf83 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 2669a277c4a4..64832b083df9 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 3a1b78e1eb31..139df8af6098 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 e050d2b52220..bed3add8a6fe 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 178/394] 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 840372fcaf83..322191984fd4 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 179/394] 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 4537c8c5d8fc..6ecd559ca806 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 fc47f4f7b937..bb13b3e91503 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 ac154fc16246..a65c164d631d 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 6848d7db9ddb..f6f2ec6d8f42 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 6fb0453c186b..3f7f329a48d5 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 c3ea8b94f8aa..6d801124cda3 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 b088e3b55ed8..f816df462b91 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 acda15ce81a5..1263d4782db8 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 10573b012298..91b3daeeeded 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 180/394] 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 4264bf71d46f..b461fa283026 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 a517a750c323..e4bc12705314 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 f017481be5aa..3f817b180fd9 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 181/394] 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 43f73d4d71d4..30738dcfc6dd 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 c3d21d258295..866f6945a645 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 182/394] 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 183/394] 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 001865b2c4c0..17c4ee10e741 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 184/394] 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 17c4ee10e741..430124e2adad 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 185/394] 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 70f54b86ac71..88046c02f8a1 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 000000000000..8695e938d7fb --- /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 186/394] 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 430124e2adad..1cd3e11faf8f 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 000000000000..1d163c232ca6 --- /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 000000000000..ce69a69a51c5 --- /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 187/394] 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 1cd3e11faf8f..19201545e524 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 188/394] 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 b1222b49d1ae..3a6383002dc3 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 8ed413cfe199..a8e9afeaf2de 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 b3993e39f3df..fb08c667ce54 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 7cb95a99d0bc..79d838349af9 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 3d0e024da83b..ac220283a8e6 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 189/394] 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 71c2a952adac..318192de4443 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 190/394] 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 c25025ccf77c..96a9538f1b4e 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 191/394] 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 da109086a916..881f70007374 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 192/394] 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 c606913e4e93..f618bd9d3e70 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 8bfb9c51a0dc..d8eb9a903f52 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 aae11521e50d..743d924d793e 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 26a9e116f054..ad4f5bdadccc 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 193/394] 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 542118f6deef..18dc57ebdbec 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 a53393f1d34c..93556a557e09 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 194/394] 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 6ecd559ca806..aecaed6ffa18 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 bb13b3e91503..81c0e49e5930 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 a65c164d631d..ac154fc16246 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 f6f2ec6d8f42..dd4dece740a0 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 3f7f329a48d5..6fb0453c186b 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 6d801124cda3..c3ea8b94f8aa 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 f816df462b91..b088e3b55ed8 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 1263d4782db8..acda15ce81a5 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 91b3daeeeded..10573b012298 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 195/394] 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 03e22c8d1a80..aa8a328204d2 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 81c0e49e5930..303d51bbbbf4 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 ac154fc16246..c79692c3c035 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 dd4dece740a0..0508769d7cb0 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 196/394] 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 cf959de79c1a..55c9fd684ecc 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 197/394] 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 273eac6020ed..898042b7f8c3 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 198/394] 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 e3a42c295f8c..000000000000 --- 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 fb599d21d2e4..000000000000 --- 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 199/394] 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 09e158e489c6..c1af2907aed8 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 200/394] 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 0b06b2b7ae12..f25690aadc57 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 201/394] 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 6f7ac91397d9..832b6ebaaf6b 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 202/394] 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 832b6ebaaf6b..ac087b8fcc47 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 203/394] 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 0d63d48212f9..57499b812166 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 204/394] 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 731640653d5a..521ee8793e88 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 7e338d9f80b9..01627007f03e 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 000000000000..c92fe2a7e356 --- /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 205/394] 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 3ec123a8ed7c..863fa30f6c7d 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 6438f330c386..394ce00c58c4 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 206/394] 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 8e52e78e7983..733f4967d806 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 207/394] 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 aecaed6ffa18..a0bfeb5bb143 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 b0b9ccb7a3dc..6ec0d16884d6 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 00f12fc71de6..9397e0e207c1 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 208/394] 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 5e3e0c0ec61b..881e48ea1b32 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 209/394] 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 6a49db68e7aa..d5988ee05386 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 210/394] 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 ef411e08a49a..a53f931ca3e6 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 211/394] 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 a53f931ca3e6..b4f42fd52381 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 212/394] 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 521ee8793e88..cc094ff11cf5 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 213/394] 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 3f0b1b04e283..ec41956ae32e 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 214/394] 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 521ee8793e88..e31cc636b4d2 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 0bd74a410300..f9bb3b8f60b7 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 000000000000..891662f65af1 --- /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 215/394] [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 6324085e65c2..b3c78129aa47 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 91568f4d65be..5d50e4599bfd 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 216/394] 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 19201545e524..22bff5415333 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 217/394] 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 881f70007374..5503de1bfe34 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 aed014592c1b..dedaa766f912 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 d75b63b4ac8b..baf7fb222f1c 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 f9d0afa4cf59..adfea7946d50 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 23be74230cca..08a12f9d2cab 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 218/394] 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 424b9eedaa39..3bc7ef7049a6 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 5d134f277865..d38adba184c0 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 aaffee722f8a..3d5ef85bc9a5 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 219/394] 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 fde0f27ecc5a..00a38727daa1 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 88fc76a9c307..cd84da2234f7 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 1a5451ef5191..b663ede77bb5 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 66ac22a08e72..8377b8178d3d 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 b546e179fd96..75c1cba873f9 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 123dedcb483d..954ade311f84 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 220/394] 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 743d924d793e..f02cce06a99a 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 221/394] 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 f02cce06a99a..7e70bcc22b17 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 222/394] 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 7e70bcc22b17..1dbf48e9b45f 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 223/394] 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 18dc57ebdbec..c24604c84e90 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 224/394] 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 7ad83795cae7..fe99c9f24651 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 791cea011610..4db9bc43b257 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 225/394] 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 b0539c403a3d..03a3f7e9b426 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 01627007f03e..6db9420b802b 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 9e5123ab5bd5..67e7899db3f2 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 226/394] 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 9b5ee447e6d6..b91635a19ab1 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 227/394] 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 238d261152c5..1d21a6e2668e 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 45857c3f891c..994cb85d479f 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 4917cfc7158d..e76b779aa474 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 92d601043dd7..2b8f7f835133 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 b91635a19ab1..6155e093b90e 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 228/394] 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 e76b779aa474..30c1c611165c 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 6155e093b90e..38d22aebdc2d 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 229/394] 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 000000000000..9b6ee266c3ed --- /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 000000000000..7a1f6d5e957e --- /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 000000000000..52f3a4320e96 --- /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 000000000000..45b9df386aa3 --- /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 000000000000..c15247fcd164 --- /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 000000000000..daaed0aa3e74 --- /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 000000000000..52f76c30cd4c --- /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 000000000000..bf7ad840cd05 --- /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 000000000000..0bc282fe3635 --- /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 000000000000..df46d16b5a69 --- /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 230/394] 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 03a3f7e9b426..c00adf0fd977 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 66ac22a08e72..8d8e91e5ce4d 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 00ecaf01a426..1235dd547c18 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 0bab7e36c74e..4e81c4865407 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 7a1f6d5e957e..9dbf877d6bc2 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 a177e8f63099..d55935aad27a 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 6c284a005956..7924f52e2340 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 77c988577620..b8c09fd59c1a 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 9f08d985aa38..9944c84f54c2 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 6337f22c1b29..272ec13d7bb0 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 1e503ca94a65..021c98dd3c6f 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 0515c8d265b4..e352f1b3a650 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 fbfb5074b6fd..0db2313a034a 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 c15247fcd164..b9b3346f48c2 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 daaed0aa3e74..6f582442322b 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 52f76c30cd4c..f146f06aeb76 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 0bc282fe3635..035efbacc46a 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 e48c27d06d81..be00e0a3584f 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 231/394] 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 fe6da11e16da..ad2e58270018 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 000000000000..c07a74de4fb4 --- /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 000000000000..9b365a374a07 --- /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 232/394] 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 c24604c84e90..be04d2a6f997 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 233/394] 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 3fb6beb2b787..a4e40e87b6b3 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 234/394] 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 fd826eaecd18..2d0eeae2bb02 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 6aec96aa2e3c..1a67818025d4 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 235/394] 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 bb7a96953034..74599eb1c449 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 236/394] 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 2d0eeae2bb02..69f2e765e0b9 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 237/394] 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 0fe3221f1a52..47986059e283 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 d9d7fde15997..000000000000 --- 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 000000000000..ab55fb21d786 --- /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 000000000000..3cb737d4bf10 --- /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 000000000000..063f8f4a835a --- /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 000000000000..17ca120e6e5f --- /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 238/394] 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 7ae1aa76e2b9..8c9c6ba5c4fa 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 32ef6d476b22..766f1bf121f5 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 239/394] 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 f8e1ebbdc805..72739bccfb91 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 240/394] 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 aab81b975c5b..e41d935a233d 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 7316cc7d57fd..84ad75514f99 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 9a37896bb568..e8e4022294fc 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 b671c94f9f9d..bb325b39110f 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 241/394] 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 f2a99340deee..f51aa2b6e5e0 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 2d917485d631..edd9a0d6d11d 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 242/394] 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 033dfc044d12..b95df8f2138c 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 6575db11face..afcb0f2d3c9e 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 243/394] 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 04b931a248e8..ae91716e5385 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 244/394] 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 d5590006c855..728acb813001 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 245/394] 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 246/394] 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 28a89ec315cb..e1987c60c17c 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 247/394] 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 f1910648378f..2f0d1d6b40d9 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 248/394] 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 c00adf0fd977..35f9b83bedda 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 679309766c36..d7bad10e7b35 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 3248f1390f64..f01f6802c337 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 000000000000..f36647ed2b04 --- /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 249/394] 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 3ae151593d33..c716c43a6070 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 250/394] 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 278edf5c273b..c4eb804eea41 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 22bff5415333..ac9f14b15498 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 df4517fc522b..f8b8b4b54d0e 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 55c9fd684ecc..e3888afadc3e 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 ad0b615c1c1e..dfd623646e3a 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 3a9432de6d02..daf4b950f2e9 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 ae2a12c71c32..dd6503ca1fbf 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 2a859ea24517..1791ad45a9d5 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 f36eedde0611..2731787a4b88 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 9357310c07e4..bcdb2901d053 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 aa8a328204d2..f58705e9cb9d 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 94688fddcaaf..b745f1b80538 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 f2bb4af107bb..d97e56638947 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 ce30a4d71db7..b8a10c372db2 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 5929144049a2..f62abb3c6043 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 3d187694e2e0..d8141cb4fcf0 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 000000000000..6edc3b560136 --- /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 000000000000..25b9640ca565 --- /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 000000000000..41f243d9c488 --- /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 000000000000..809fb09884d8 --- /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 000000000000..25b9640ca565 --- /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 000000000000..3566824b9b03 --- /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 000000000000..dfc6038785a5 --- /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 000000000000..25b9640ca565 --- /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 000000000000..8af39f64ef3c --- /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 000000000000..e7173abed3e1 --- /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 000000000000..da701aec60f5 --- /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 000000000000..e45f27f3caa8 --- /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 000000000000..4e41e41c385b --- /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 000000000000..9e104dc177cc --- /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 000000000000..3ad7350a9fe8 --- /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 000000000000..18532c5a6d3f --- /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 000000000000..920aef8e9dc2 --- /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 000000000000..86761f23659c --- /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 000000000000..0e93c5b77f30 --- /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 000000000000..18532c5a6d3f --- /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 000000000000..920aef8e9dc2 --- /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 000000000000..e132c654f042 --- /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 000000000000..1380c31d7c10 --- /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 000000000000..715f3fb4848b --- /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 000000000000..acd0b45f5335 --- /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 000000000000..702fe057d532 --- /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 000000000000..3bedf2d9e437 --- /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 000000000000..ed5894632c43 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..acd0b45f5335 --- /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 4cb0b3c93068..80cba338202d 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 e64558bd48a9..a9f4c59a74ac 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 624a44c3e538..4fff5a22e70d 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 23d8aaa57f8e..446348fa0ba3 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 6d19df01b3f8..8dfcedac8548 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 227b1b9213d8..be3e25d3302c 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 595aecdca3f4..5a9192bc3a05 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 ffeb14702183..a4515b30957a 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 7553c81c0f44..4543804926ee 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 251/394] 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 bcdb2901d053..520f4d5f1c8f 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 f62abb3c6043..56be4195dcc8 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 6edc3b560136..ac83894b301f 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 41f243d9c488..375c5cf900af 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 809fb09884d8..18053bcdac95 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 3566824b9b03..000f29c4df1a 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 000000000000..6edc3b560136 --- /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 000000000000..082f6feee994 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..25b9640ca565 --- /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 dfc6038785a5..a2193034c8db 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 8af39f64ef3c..8670e379d4e3 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 e7173abed3e1..6ac2691c2085 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 da701aec60f5..fabb25ee6720 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 e45f27f3caa8..bb93f57a8256 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 4e41e41c385b..f8fb2ce274d0 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 000000000000..e45f27f3caa8 --- /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 000000000000..3ed2f577c7aa --- /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 9e104dc177cc..f8e3ee312e6b 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 3ad7350a9fe8..4c7b4ed67197 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 000000000000..ab13b27ea6ea --- /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 000000000000..3ed2f577c7aa --- /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 000000000000..a8a5cff05d0b --- /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 000000000000..3ed2f577c7aa --- /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 86761f23659c..f3346fdd10e3 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 0e93c5b77f30..c9ab1d8f5e73 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 000000000000..18532c5a6d3f --- /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 000000000000..920aef8e9dc2 --- /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 000000000000..89994857f418 --- /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 000000000000..3ed2f577c7aa --- /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 000000000000..18532c5a6d3f --- /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 000000000000..920aef8e9dc2 --- /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 000000000000..fb232f23a1fb --- /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 000000000000..3ed2f577c7aa --- /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 80cba338202d..3161eba2a868 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 8dfcedac8548..17166268a656 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 be3e25d3302c..85eeaebe31a8 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 252/394] 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 69f2e765e0b9..b6dcbb08e2dc 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 ab55fb21d786..0b786893ec06 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 253/394] 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 74599eb1c449..611e95c39d72 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 000000000000..617aeff98929 --- /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 000000000000..a2a6540efde5 --- /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 254/394] 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 c00adf0fd977..f37cfcef0722 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 ccbd8a6c4e93..f3db974ae273 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 c2306bd75d11..1d5dc62f3ae5 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 255/394] 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 57499b812166..129d1d3a82e3 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 256/394] ci: remove cxx20 job --- .circleci/config.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index be04d2a6f997..da4be0e35ec7 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 257/394] 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 f3db974ae273..cc8435ed3c30 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 6fdb42bd76d0..7cf00fc9ed41 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 7a929939efe6..4952d7985d43 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 64650eaeea9f..3129efb4d734 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 8e3161b212aa..2a1b9ae5ba44 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 95f249516142..c77a6d0b6b50 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 c642362029d9..aa14cf6b938e 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 059054dcdbce..5198743ed67f 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 9ad18e1608bc..b01bc0529414 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 fd3fbbc02c45..4313fad7fd66 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 1bdaa552ba16..649bd85834d2 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 2581b23de1e2..739916317765 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 32df3b121a61..356056a99abd 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 04d7f64e3d73..8242c9f4792f 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 f2bb4af107bb..784967c52ef7 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 5929144049a2..c888d9a53a63 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 fdaf3f35be1d..5370542c7e0b 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 9449eddbad55..da18968928ea 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 de2fdd28632a..71a4ff54a9f4 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 258/394] 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 da4be0e35ec7..164694e4505e 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 f37cfcef0722..b942f068fa77 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 259/394] 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 a70afe0cb503..758ef79ddaa4 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 9e273188cf62..140c40c6abb3 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 773c43cc9968..cf8df3d6c47d 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 260/394] 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 ad2e58270018..00d08372d676 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 7592f55ec55b..000000000000 --- 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 261/394] 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 22f7216146a6..c975648ae2df 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 3f14f47226a9..7466af6c3863 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 fb32fb61c17a..db02e90e4881 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 379401754cac..79e500949e8b 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 000000000000..d70f5a7bf006 --- /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 000000000000..b44c2ba0d19f --- /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 000000000000..7c525bcc45e5 --- /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 000000000000..57345184256c --- /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 000000000000..a9fc2606752f --- /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 000000000000..d46c1671b6bf --- /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 000000000000..7920511eb0c4 --- /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 000000000000..83d9a33f6821 --- /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 e0d00539a4a8..ec1e3edde9a0 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 abdbc6ec15f6..93035730b1d1 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 d5b3847b1743..6a5587c972ae 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 6aea058b5d57..7c40a65034d5 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 2aadd2f208f0..ea1d7186f29f 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 8711d0b17757..8156bd4fba49 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 8695e938d7fb..42ca7eb2f8d4 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 63aeb4760296..52bf786cda73 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 a4b013e854ff..204409d3e97f 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 216b56ac649c..c52ab9e1a66c 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 47d7b59c7f0a..744a88c64578 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 e9455fafab33..681cb5028056 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 6e36025fcbd1..1afb88e2739b 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 d53e26281eae..ba80b462efd0 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 93a981d924e0..1ac18c19c5bb 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 14df40201418..3ee03d66e63d 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 837408b9a00b..a5179f3e45e2 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 19042a2df738..c8697d06b3dc 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 48a2c268e205..4fe607a0b8da 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 59426a0aa631..11fd37d9c6f0 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 00c357bb44aa..dfe4ed903274 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 989cfce9e007..9fdb7727787b 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 0efc7cbccedd..8dea8893d337 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 433d36683dfe..d1e6d50e9e80 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 faecf92c3805..181e9806ddaa 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 e1d6a74919c9..88e38b1338a4 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 9e4bc8032c78..175ab15aa59e 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 b76a5de9b729..fbcfeb15ff98 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 5b63885f2b5f..8d97e4ac0e39 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 6f0d72229947..b69b56c662cd 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 98707451e600..d81f69a082ee 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 262/394] 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 164694e4505e..8e1e85794210 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 263/394] 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 f1608890d757..a60dc1b84d46 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 264/394] 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 e6187d06e2df..e7bf053eb2c6 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 41079af03955..000000000000 --- 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 4639d34c7071..000000000000 --- 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 bc6a803de92f..000000000000 --- 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 265/394] 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 ea6d781898f0..fbecf750ab4f 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 583f1ca37b3f..f21d473413f1 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 bc70b5bef757..906fd0597d53 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 3af19ca64fbf..7a82d4f81e35 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 ea7574159500..29b19dbe711d 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 d4c47e868a1f..9587f8c37778 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 906279d17935..2b1fe023e075 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 657b4b5cfff6..bb6289768445 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 a5f56f3dc688..214752a1f45c 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 d5e105e5f536..1d8d1897c8f6 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 aa8a1ad8a860..1036b7f83a52 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 0865ed2876ad..c4d416d9a18c 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 62e1e4fba6dc..2448b3e03bc2 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 b9697c5ae1d7..517d3c148aaa 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 ae891df5dc4f..dd60679ae95b 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 e43fc475740a..d3714e7dfca5 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 1240a8251427..92d358294a1d 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 ec41099eecbb..56b1159c202c 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 7e70eb091bf6..106605c063f0 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 8b6a7b99692e..335ef26bfba6 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 000000000000..a683f531fc0e --- /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 43d0f22f6506..4ad40d531872 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 98fbcddb21b5..730243208e55 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 d43477e994ab..eb9251ec7048 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 6aac30fe4617..396633655e10 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 b270c7006694..b448d0101fac 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 843376baa553..7aaaa648f659 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 0c1c58dd821d..a781db753e30 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 266/394] 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 ed490b9a839b..e6cdef036819 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 267/394] 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 3a1c6a5a7cf9..6df9337ec862 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 268/394] 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 8e1e85794210..0c4e65954f5f 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 269/394] 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 f21d473413f1..a46b6a6a8e8d 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 bb6289768445..87bd12d58b75 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 1036b7f83a52..515dd41bb1b1 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 c4d416d9a18c..90a3f9ec8c1f 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 517d3c148aaa..cbedca48c8c4 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 56b1159c202c..364e589e55c1 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 106605c063f0..54048113c323 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 b448d0101fac..a320a2aa3eca 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 270/394] 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 41c1d0568be6..4fd3df7cfc6f 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 271/394] 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 000000000000..7cc9753bec8f --- /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 000000000000..f8db31b54cc8 --- /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 f324d2c33e30..036a2597616c 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 b21b7cfaff5e..03fb9bae673b 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 41bc072a5949..01d9658ce2cf 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 78d7b0512414..ef066593c4bc 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 1ac5d713b104..b937d1e2d1a2 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 073a125be984..9743d5318ca0 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 963ed33c70e6..e4492a4ef742 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 8aa2f8552c2b..5ae4cb0ed836 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 dd102cf51378..9a809b50a2fe 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 e5df9cc82237..6665c42efd49 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 9aa5fce1211a..e9ef53842c81 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 f1125b4d232b..5db87f0d4edb 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 b7392ff3ee74..1374c3110d35 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 68d3bfc7ae03..b7a4b4518473 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 2ca22790c128..ca52859ff928 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 858b9132dd32..74a659cd8b83 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 fc75e85947eb..72af2133f206 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 3b162a7f220a..417eea14d609 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 d719fdcd9bb7..858b9a1d2e89 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 e128f03f1f21..c525542c7e0b 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 4356efcf95d5..0961881a1257 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 000000000000..fdbb79b96970 --- /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 000000000000..f63837dcf26a --- /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 000000000000..4bc515d7c54c --- /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 da5c17a20ac0..c5ec6de71380 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 6b926e2ddecb..e92d1cfb0489 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 000000000000..da84e6ada8f1 --- /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 12cbe2939bc3..000000000000 --- 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 000000000000..c4f00843d597 --- /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 8593bdbf4fed..a6d8d7c1d31c 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 0a2282695cda..32fb4edea8bb 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 7d7948671419..92bcac8cfb7d 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 8e51bd1886c1..7c67a647a3e2 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 0382672fe38e..20e9de7649ca 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 522ca801d975..801bdd7eea18 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 96a384c54d20..0468ef093f52 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 b08172ebe469..e019026f633b 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 2aff4351ae8b..ddfa80d7fc7e 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 8b34ab906d4a..8ee7f644be0e 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 038e8c4ff99e..915048905dbc 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 816bb1c0d5f4..1178e9a2b907 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 0a63987e143e..d612d10d0abb 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 8cdf96641ada..d356fe299ae9 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 e90443e14ef5..6136665e34bd 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 2f5c356c08d0..22f81cfb0241 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 538a26e78941..8019dabb2176 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 c202046cc4d0..c4b3efedd77d 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 57e3263e3249..4a5a760f792b 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 cda5d5c349f7..96303396e032 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 f746dc35d1de..8c707006891b 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 7d057e132b17..a8fef765eea1 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 c9cade179f55..2a51276414d9 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 40eaee040cbe..8e6fcf64e34a 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 6b054b4dacfb..d110b2c8ec37 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 8fcf65480e12..f802b9a00508 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 88a407fef98d..41bb9e046ce0 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 0e3cb3b6cb47..2809575b6c44 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 ada627037e49..0a13eedcc372 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 adb9fbe699ce..d0d11105bd1c 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 e763fa18be20..c1586595b154 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 b9205f01b1d9..07c4017e0d5f 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 1282c24daf89..84e5b764027c 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 3ee670cd585c..9a714f6b9d6d 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 ba467a67b131..f0ec56875d7c 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 b5162bcd9720..7293e0f42528 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 3ebd54d4541a..27133cf1d923 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 3d5acac99be3..7a5254a1a127 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 9346264edbcd..2e1c746baf4e 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 f22b9755d652..5ac74bba7cb7 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 a0c7267d0d20..f3091ebf5351 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 071859e53fb7..8e5ebcdeb97a 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 6ecb4e4ff869..a69dcfa924b8 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 144361b9409a..9299b65d523c 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 754ff2c67488..449b628d4491 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 cf7eaabec976..00956d97e848 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 000000000000..a1b21de2cea0 --- /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 e62728770d90..f76fa84308a9 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 4387ca60a75b..e8ee980bf5ac 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 cc8ac5e8341b..9097a166c118 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 ed0b20d53793..16f57b2e8091 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 4d1710a3a160..8f275321382a 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 000000000000..ea4d20297bb9 --- /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 000000000000..fad9b7c1fa27 --- /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 000000000000..91ea709fe2a6 --- /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 000000000000..81d0f4e565b5 --- /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 000000000000..f3da4722ff7d --- /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 000000000000..d1a5be03601e --- /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 000000000000..e65ea26bd97e --- /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 000000000000..19342ec194c4 --- /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 000000000000..f8e9bc3ef136 --- /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 41120bf08111..f0bfba70ce31 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 65030cb30729..77956ffac02a 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 886d6de0ce2f..680a8f85f2f7 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 16c75d6f7291..5268f7a98e0b 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 0bb92c1fd2fa..e2fa70102dfa 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 992a51ad2a28..ff557e6865f7 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 665a17eebf63..91be09f58f22 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 f0320d8b0835..ded86c88a9a3 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 30210efc32fa..47826724e8e6 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 b2f241ff08c5..e2bf4c5d1f4b 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 f49327a92114..832f60f97b56 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 272/394] 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 ac9f14b15498..91beb9a7f3f2 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 000000000000..e7c369577ce8 --- /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 273/394] 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 7063978c5c1b..50a2ea7081d4 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 274/394] 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 0c4e65954f5f..0f75e76cd40b 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 275/394] 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 5cac3a6a9230..fe7c03fe1238 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 ac018df1acf8..20bfb3f00cf2 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 72739bccfb91..0428ffaa2cc0 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 747e27b7e372..d38dcc04514a 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 c66ce565393a..21a924b1fa78 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 276/394] 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 aac943517e02..1ec12051a619 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 a21a73e681af..000000000000 --- 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 3986d54a0a36..d9456e4c32d0 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 139df8af6098..bd5c55a3cd73 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 4597c56a5917..bf8cfd92a802 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 3d1d5f7b0d76..ecaa4198bd52 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 ac08fb0be196..b11282bb176b 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 277/394] 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 6caef22b1557..cceec2a73de0 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 7db996fafc88..5de941bf2706 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 d7bad10e7b35..86c7eb7a89f8 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 9f23aff6fb67..bd0b3f4022d9 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 d7b23156383e..2fecb734a630 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 f01f6802c337..d79ae8f82aaa 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 bf835b801d21..492e0055b008 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 20bfb3f00cf2..ca40e695d521 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 0428ffaa2cc0..738a48f706c3 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 813d08330e31..50021d986478 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 76dff6664b80..92a3b7f7b50f 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 6fb8440b7b8b..efbc2a3aef9b 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 28368f546205..9c18265be4e6 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 45c38ef3594a..486cd2c65899 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 f8d0af2f4f72..21041fee1976 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 83864075dd74..7a338f614952 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 84ada7873b07..21041fee1976 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 a800fb34d7b6..1108d790786a 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 cee9d4b9bf9c..a0be6110b5f3 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 9553a3cfb662..be0d9fa9e912 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 da3b3dcad888..de2c2aca05b7 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 da3b3dcad888..de2c2aca05b7 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 67f8df731994..0f1ce4e39454 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 b6153de5ebe5..22c2a48193c1 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 6c3b57c79553..0f1ce4e39454 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 a3f4cc03d784..79037e2236bd 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 02d538d7d64c..9562653806df 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 a28e4852b0f2..8afc574a8b9e 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 2650b08975bd..ff246b362c54 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 30f6a0ba9781..76ad6db55384 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 000000000000..b68a9aa4b464 --- /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 21a924b1fa78..e2e7e9ebd290 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 2b16f2d1aab7..be8436e82673 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 54f3233531fa..bb4ef03428e7 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 278/394] 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 5dd94aebc4f0..455cfe0842ed 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 9f23aff6fb67..222a0995b267 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 35e54ed76bc9..5387184ee0c9 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 dd0267d710b0..f58bd002c385 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 279/394] 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 f7d331d94acb..b7e475c91b1b 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 604ad0346c27..7a7941a69f95 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 280/394] 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 f45fbed925ad..10086886a622 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 64b80422c352..69a4bd65b1d9 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 931109199649..28843b25d19d 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 018d410557b0..8e075654f313 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 0f9b023b08d9..255e99e82489 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 b6ae85b838d8..4425475695a1 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 9accc54a2b05..17aabdf83832 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 866fe9dfc452..322de3c84435 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 61e1bbdd6c0e..e6d800d9b229 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 6e7a750fe980..d2d0999bfb76 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 69fa568dfd96..7331c0dbd73c 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 7a05ff5d0270..e414b8205ba7 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 b9eb6ca42892..61e979f17536 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 229618384d1e..36dfc844d934 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 000000000000..1ddc06c1dd2c --- /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 000000000000..10b39634d5de --- /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 000000000000..6235562c990f --- /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 000000000000..bc39e963344b --- /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 6f7f020fe678..c5fa0538e6e7 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 472921c1d25c..0031059c021a 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 d1b6e8e866ae..a8eafb38ea1a 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 e7bf053eb2c6..7415accabcd2 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 f811988fec9a..1ca391e81095 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 c2066ef8be1e..26bb09edca7a 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 110b1e50c724..d9a6549252f1 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 000000000000..8cec1ca1d66c --- /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 8ab4ca22722c..5f276f91c948 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 000000000000..e6c6f6eb0772 --- /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 7d0e3c8b0dbc..f1f62db03230 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 25d1935770d1..c810000e5b3c 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 359dc516ffcd..4f3c0ee1ba6a 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 6ce623ce81ea..2d4a37b48d8b 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 549512eb3e44..4d810f970987 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 f2d21c9069b3..d228d99d1767 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 22ceff337f89..b8b13b3c677f 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 f5f0b8644423..e3a6e03728e9 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 831d4bde4ab4..6c07fb4e089e 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 10d7c1852e95..0c848fc592eb 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 844a0f65706f..08065b302c99 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 ff883139a46e..79e940080f02 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 fa7dab9dab9f..465e2ee31b51 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 fe2210fa107a..81c2286d5e44 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 a5f61d2ddd67..7e3e326228a7 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 676ec32a89ae..b053deb442ed 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 000000000000..ae1fc39ec6c8 --- /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 ab7302743f64..ea891edc4e5f 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 4cb5c8c713bf..bf70caee5b54 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 a582649196c3..7629fabc1ce2 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 dd550d31a0cf..c9f50046c07d 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 281/394] 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 5370542c7e0b..f18140dac93b 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 282/394] 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 f18140dac93b..38752dde64fa 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 2b1fe023e075..c073993e1d37 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 283/394] 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 38752dde64fa..a3d1d427d7ae 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 121adbc15945..522eb7b72fed 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 000000000000..920c6b06ef32 --- /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 284/394] 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 a3d1d427d7ae..897f01c68ac3 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 55621bdcdae6..ee3f4c6bec51 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 17b6f74c8739..3b3afab3bf07 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 285/394] 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 8e7a3ddcd4a9..9bc60d1181f8 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 286/394] 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 86c7eb7a89f8..5fb2f5a9fd75 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 50021d986478..d99d60c6e284 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 287/394] 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 4447a0b8e97f..53eb24ce1915 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 46a0ec0f7a6d..ea00b4478461 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 1171303af291..2a1aa04a14dd 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 381cb999f0ed..9490986819e0 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 b6a0552cb7b1..9f82f5568023 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 7bf365031b5b..db2fee4d8392 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 f0ae32b1b661..52afde6fcad0 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 fb5b7fb89489..93512f1da5ac 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 000000000000..f62e24233db1 --- /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 000000000000..680a268885d9 --- /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 000000000000..cfb95fbecfb1 --- /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 000000000000..eecfac9a8741 --- /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 000000000000..2f1771d79008 --- /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 000000000000..39dd209bfd90 --- /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 000000000000..704702a53519 --- /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 8750f164991a..fd5a5d6c05f6 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 01270ef44316..4a29c1498d0e 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 88ec2c3542c7..9bd6413c9d3b 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 309d995469a9..0248d61f7bc4 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 82c2fd766e2c..10fcc202ea78 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 230535525007..533abbdd87c0 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 74f613cdfffa..c1bd855ad52b 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 18d31087f9c5..e77506c30fbd 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 0d1f1ff791ab..9261c7765653 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 ddacd8b45dde..08dd970211ba 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 ba0319108b27..cab45afa745f 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 805beb42495d..a1f1c7a63aea 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 1a087f9c9430..c4879f2107ad 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 dbd802e3384d..3787710e644c 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 66727585dbcb..d236f9ba0efd 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 efb41524b5cc..e5d16be3e442 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 0275e1665ae5..38b78e6dcae6 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 f7f945abf58a..3af2c0f6a05d 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 7348b2e20cd4..db386a1f1318 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 2ca3d62f004a..06736baa8710 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 a1e55ade4ae1..756260259b2c 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 f394054d74f0..c10cbaac1407 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 047eae408730..1ef30838f9a8 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 a7274ce639db..2aa89592be5a 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 3858b5984dba..892ec13fae32 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 288/394] 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 fa2ce20948c2..5cf4880075a2 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 289/394] 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 08a12f9d2cab..d4f698561a34 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 290/394] 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 920c6b06ef32..ef6abb9a9140 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 291/394] 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 b9b3346f48c2..2e4252af412d 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 035efbacc46a..66698c63377b 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 000000000000..0466cc9b62d8 --- /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 292/394] 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 4fff5a22e70d..96699b109c52 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 000000000000..77423e88c067 --- /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 09ce0b84a2b2..c7a82c412f6f 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 293/394] 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 ac4ed1b0545e..9c569811e795 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 f480bec9e1ae..e4ad176e846f 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 ed8916e63723..210b697f46a4 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 c8c4e4e1388a..98645c653739 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 c64fc93f9833..ad0168027011 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 f0db2af1b220..e2612756e7a5 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 63f0d38e43fe..2f382cab0726 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 68839721cd76..cc376652ee7b 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 fcaddd12134d..112d704e2711 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 301f50c6ea27..4d3be77e8239 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 a431c57a6c6c..e635ad5d4824 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 3710cbebdf48..1f10c90adb7c 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 19d65dca4152..c73fea65c6e0 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 abd1b1743d32..d1e00802ffab 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 9c3a5c8ba29e..6dc67840697d 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 ee7464932d3a..3bc52009e5cc 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 000000000000..4764c6d5795d --- /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 000000000000..e3f1085e065c --- /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 bcd6d0f7bba5..b362f1568c4a 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 0e366e6d4090..af609eb60b61 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 38e5ab2108d7..1820f363c52f 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 8b26a7ba3723..94d4b14fffcf 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 6ebca20f5bbb..f0c54556a423 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 078616bb3b7e..984d9a458d8c 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 dd6cdc0e44c4..772ec67cfec8 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 5fbe8d22e615..c7eb0a405b80 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 6f82ab27a6d8..9d893a7d3c5c 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 b066d998bafe..f95e6f30dcc3 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 000000000000..b7b4de23b017 --- /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 18c818d15ec6..c67a0f875545 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 840f19005b06..88d0ba64db73 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 000000000000..55c131677f5a --- /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 000000000000..7181d553ada7 --- /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 000000000000..3179ef3916ea --- /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 2a72eee3e215..ede5dc3e8273 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 418221a93824..8035d17729bd 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 000000000000..42e6d11c7b2f --- /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 3c11ca65f0db..cfa38e05ab08 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 41289503791a..fa6619d05e30 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 1d1a1491558f..a6ccbb39f83c 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 000000000000..ae69ae3f7a45 --- /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 8881fdc84887..0c7d68fc7641 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 942a3c5802cb..486921ae6304 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 2033a9be91a4..95f968d89195 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 fa6c985b4f8a..c2ea86bc82f0 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 d3dce8d781b6..c50d1b6c21d4 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 8de9147d8aed..9745dbe4760f 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 1eb0ccd6dd96..b8d4044c50d2 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 ae20f4904f88..a5f2125a0300 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 0ef2fd78ad40..410f07663dbf 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 000000000000..66a21130bbb8 --- /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 000000000000..6859f028bd34 --- /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 f8b5a3d53725..b087802ef566 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 ef6e12ab6ec2..57886d56380b 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 bb5f029803fa..d168b1886c94 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 eeff779f85e0..2a65462e86bf 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 c3183d9ec83b..dc339466f864 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 782c68663b08..788e7be21ddd 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 294/394] 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 fabeda45b80f..e7aaeadbba3d 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 4001a93092e1..718ea6770979 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 000000000000..5f5ef934bd94 --- /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 f65c7505cb9d..0e3691a426cd 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 4d0a63af4805..d6f475513b4d 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 295/394] 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 604dca1f46e2..66390f7d4741 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 000000000000..a196e46e887d --- /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 e01a8dcb3610..13f83505d48e 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 841c4106262d..fee5f7b5673a 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 296/394] 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 da962c3c0b04..5d8cd6cfde8d 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 0b83d818f087..c076c1203e11 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 b7484f5db8de..ad6eb5383796 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 ce5b6ce5c53a..61a3259a7c96 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 f5a9aeb12f34..366ceb4bd273 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 ff80edee7c94..f03d7083699f 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 3f5c887b4aeb..b2d69086a54f 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 0a5458b47e2f..93bb9ec03d7b 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 5245d7443a93..5d0da5c0633e 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 a827181fca2c..3e84df570931 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 66ea146a06ab..664692bad565 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 ede304029997..69b7acbb2bf9 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 ec9ca2fe6437..4386711a1c26 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 adedd299f579..d68d57364b2b 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 661db49ffbb6..68cae1b92129 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 0d0f92420e30..c9143d7918f5 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 297/394] 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 f9bb3b8f60b7..6b0534296f29 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 000000000000..54609b86a23c --- /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 298/394] 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 77ffe6735401..763f1ea64f41 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 299/394] 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 8a860791fa45..1c5ae6f4e707 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 d9438271ca6a..bfbc89bb4839 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 300/394] 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 9505a2caafe5..104bd1bdeefb 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 b0bdb95cb9c4..0c3f2f3bcbdd 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 301/394] 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 0c3f2f3bcbdd..1b66dd60fffb 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 4fd3df7cfc6f..8944710542a5 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 302/394] 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 cceec2a73de0..cde5636cfea1 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 2fecb734a630..08fd4a256e38 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 000000000000..a071d0f150cc --- /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 000000000000..bbff78aa73f3 --- /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 303/394] 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 dd901bc38314..d5a1fa580993 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 08fd4a256e38..c1a4d61ee145 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 304/394] 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 fe7c03fe1238..4b7ca8edb324 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 c1a4d61ee145..7c826ab36b21 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 d79ae8f82aaa..c6c549151058 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 305/394] 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 cde5636cfea1..be3209702455 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 d5a1fa580993..bd3b0d9888fe 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 000000000000..5226f886d959 --- /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 306/394] 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 1dbf48e9b45f..b5cd64a235e0 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 9b365a374a07..f66c1d8fd07f 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 eb5439f595be..fc372c709ae2 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 3b1e3e614d4e..91a31c26300a 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 307/394] 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 b5cd64a235e0..bf228d6176fb 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 308/394] 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 c44f9bababf3..64d992994ed6 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 309/394] 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 feb6a5927fc0..000000000000 --- 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 310/394] 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 0f75e76cd40b..d26ef3bd41a6 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 f618bd9d3e70..e7a0b9ddfda2 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 7295afa01ee3..53fc7b6eee9e 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 866f6945a645..27c2081346fc 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 76ad6db55384..76078a582198 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 311/394] 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 1c7882448ca1..1e765c6f9e32 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 be3209702455..0bf7cb988081 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 48151a637713..a5d5b08ccd0b 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 2201f3c9dd1e..6566f3a4acf8 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 dfbc0477342d..3d2849369eca 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 897f01c68ac3..7df39bf71ee8 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 5a57b779dc87..cc5f68e71ecf 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 15ac01396bcc..a22aacb0df03 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 312/394] 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 1e765c6f9e32..216b1ee3815a 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 ac087b8fcc47..30df93796522 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 6566f3a4acf8..a159f2e4bb2f 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 b6dcbb08e2dc..7c82d788f35f 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 611e95c39d72..4fa78f0233a4 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 fb61e70f6489..30f06bc97385 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 30738dcfc6dd..bb25d203b71e 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 104bd1bdeefb..da47c26fde90 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 000000000000..60abde356339 --- /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 d38adba184c0..81f01798a766 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 0078e6e68e36..000000000000 --- 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 000000000000..60abde356339 --- /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 5d2115f95af6..677c49b88a1b 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 0078e6e68e36..000000000000 --- 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 f63837dcf26a..d43fb5969d72 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 3d5ef85bc9a5..c11cceae85ad 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 06ebdaa3ce38..7fda77b9a666 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 0c9f9a382497..35f503c708fa 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 d5f2f6c2117b..49665784e9a2 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 08de0df183af..3622a39648e1 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 47986059e283..f6af43217faf 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 313/394] 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 c2b6b9847f3c..3493c36682df 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 8fc225bee0a4..3001d43f8e85 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 430834d8304b..d302b4aebba8 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 b3a34d283e7e..8d34ce85e408 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 314/394] 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 0bf7cb988081..5886dca26016 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 bd3b0d9888fe..3a5da1e587cc 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 000000000000..49ca28f5c8d0 --- /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 9f2fca60cefb..10a07e13648a 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 53349f0b6c30..22fccbe70d6c 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 a1c3160ea23a..1046e6a49b11 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 6ecfed7914a6..d8838195f544 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 85e2677f782a..026ad07ab674 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 f1481197f11f..cc5115052c6e 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 04b7ea7480e9..adfcb5e2301a 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 e386c4b445b3..89bc75398604 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 45cf7fe186ad..9c2981bf10b1 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 9972c7e3ff26..36b22040a2a5 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 8590b0bcfa86..e80e398fe924 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 652dd811f3d4..d0e82665ccfc 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 d6bc51ffd5c3..a41c918571a9 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 e53436a0f66c..1f0fd5829e84 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 942607bd8a6f..f6c182c1e91c 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 fc8d6e08f300..4a659978f9f4 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 315/394] 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 96a9538f1b4e..d8843e0d3a1e 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 316/394] 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 5886dca26016..c37993488a36 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 5fb2f5a9fd75..c29c21e5cc3f 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 3a5da1e587cc..c313ae54e1ae 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 520f4d5f1c8f..cf110079b026 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 b02b1ed8c702..e5b096c2a023 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 92a3b7f7b50f..e696c6ed3836 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 efbc2a3aef9b..4713ac13e3ca 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 9c18265be4e6..a55ad5cea7d1 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 12b7c324584b..000000000000 --- 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 1e2296446199..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 eb4cd572ae22..000000000000 --- 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 e3a8c32d4716..000000000000 --- 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 1e2296446199..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 eb4cd572ae22..000000000000 --- 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 64e5d88728ea..000000000000 --- 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 1e2296446199..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 eb4cd572ae22..000000000000 --- 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 1108d790786a..85c4e142c383 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 a0be6110b5f3..21fdedc40918 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 be0d9fa9e912..57c81ec50a47 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 0159c256e6ed..000000000000 --- 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 d675499f91db..000000000000 --- 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 9ebda00174b4..000000000000 --- 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 d675499f91db..000000000000 --- 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 317/394] 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 5886dca26016..0145ace66622 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 a5d5b08ccd0b..8893f6c50ba2 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 f8b8b4b54d0e..7cb05bf8bf00 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 e3888afadc3e..2fe63c11c2ec 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 520f4d5f1c8f..fb0ea4514cdc 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 590d96b9c191..665e8b487158 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 2e553c688973..92acad4bdbd9 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 b02b1ed8c702..52d158ccd5f8 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 318/394] 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 000000000000..0af885908f1e --- /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 000000000000..03aa23879874 --- /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 000000000000..c7017646aefd --- /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 000000000000..b9370e6e4f11 --- /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 000000000000..573541ac9702 --- /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 000000000000..25337fe77938 --- /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 000000000000..c7017646aefd --- /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 f649e9740882..000000000000 --- 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 8f42dca78694..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 f6cc546647c3..000000000000 --- 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 000000000000..d2ba25938f7d --- /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 000000000000..5dc5942bf7c0 --- /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 000000000000..d1d45825952d --- /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 000000000000..606862e0af8a --- /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 319/394] 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 91beb9a7f3f2..21cabcbc53b1 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 92dfb0a44008..6f30fa635176 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 17559fbf4182..5f50bbefdc92 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 fb0ea4514cdc..1671267d70e2 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 f58705e9cb9d..1ad24998ffb5 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 92acad4bdbd9..4fd730096e85 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 a8e9afeaf2de..f4b7034de544 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 320/394] 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 0145ace66622..75bd75eae178 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 8893f6c50ba2..97db1d7ceb0a 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 321/394] 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 322/394] 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 323/394] 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 5f50bbefdc92..e8c4e9bc77f7 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 5fb2f5a9fd75..1b6be157942d 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 c6c549151058..f926a0d0fc80 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 324/394] 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 f57a3b5b904c..dc52c96bdfcf 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 325/394] 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 64181bf208d3..4b46d7169f80 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 bc8f0fa00eb4..21768524f5d0 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 326/394] 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 327/394] 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 21cabcbc53b1..4dcc6a4b092b 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 6f30fa635176..30b06dd367fb 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 3bc7ef7049a6..8a917986f915 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 babf2b7b7051..b053c5b27598 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 649a6c863486..dad9804d09a8 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 a1b9af364a0d..137144715296 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 66553bc06633..6e1a00465b26 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 3129efb4d734..879f5b3272dc 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 a9672efa53b0..662436ff63c8 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 457f60052a6a..8dae6acad6f6 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 30df93796522..4fbfe8de41b0 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 7c82d788f35f..352f16f769b8 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 7a3e6b7422be..41f480f442a0 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 4fa78f0233a4..d68ef16348b1 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 b608859e2ba8..960e663dfa7a 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 93e7c816abf4..dd708b8b33de 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 322191984fd4..78025265f342 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 64832b083df9..502f90d854f5 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 0b786893ec06..71137488f293 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 3cb737d4bf10..313e17884ee5 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 17ca120e6e5f..6992e4003fb8 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 94a6c3b1ee3f..31c2ccc97744 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 328/394] 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 8e18183a81f9..0d953be93ff4 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 5b4b3460446b..297d5f6e80c9 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 329/394] 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 f6fc05636291..731f8d57944a 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 7c826ab36b21..a0b71f5941a9 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 000000000000..b174b9478810 --- /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 000000000000..54159b18074d --- /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 000000000000..39a9b7cac396 --- /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 330/394] 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 129d1d3a82e3..912c501dcc13 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 331/394] 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 912c501dcc13..261c07266fec 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 332/394] 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 261c07266fec..07d82b9c81d1 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 333/394] 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 731f8d57944a..00b7df77b912 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 1f702851c066..d282e139d22a 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 334/394] 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 e6cdef036819..da3822dcddd9 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 335/394] 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 8753d59c9a2d..1386bcfa177e 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 336/394] 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 da3822dcddd9..3b7d101d5948 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 337/394] 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 b663ede77bb5..ee3a6eb9551f 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 b11282bb176b..2407781354d0 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 5b1cf25ffe1f..7b731a4eb877 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 fe33b10a2245..bfcd9d8f630f 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 338/394] 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 00b7df77b912..3eb3abf79f38 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 f994c331d536..ad3b04098132 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 a344fad54470..5ad422913e98 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 8c8bb7ab05b8..10d7f1d116a6 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 55e4d56216b7..dc359c1b05e0 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 766f1bf121f5..2fb6a6162405 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 b461fa283026..a0d21744de88 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 b62ea3e2df8a..cf3bddf403d6 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 5cf4880075a2..cc5cc932415c 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 b8a3a4ae0057..d0fe7d97afa1 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 4e7a5cd508b4..42627b5f7f7c 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 c7933120a974..3174dc1865ea 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 344bfb39d2a6..d6cd7f43896a 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 e4a7c2da3fe9..7c5dd5be9f99 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 f985a449019a..010e99ec3d72 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 55ebe2a78c61..1cd771f9d4a8 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 1791ad45a9d5..4e9346ecfebd 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 13303170d6ad..dce729de408b 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 830df05c27c8..d208c1f8bd79 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 000000000000..76497f217954 --- /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 000000000000..e6c5250af0ff --- /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 000000000000..4fe5fe193be9 --- /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 000000000000..3cf20d57b0b8 --- /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 000000000000..aa73b10f2281 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..8babcc4f2691 --- /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 000000000000..f0b85640bd48 --- /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 000000000000..bdb03116e486 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..88bd25df1283 --- /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 000000000000..ccc12f642d1c --- /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 000000000000..d1012053f398 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..87066c4d4050 --- /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 000000000000..a84e2a2576ff --- /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 000000000000..d1012053f398 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..87066c4d4050 --- /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 000000000000..3cf20d57b0b8 --- /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 000000000000..983a9b92cd9d --- /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 000000000000..d00491fd7e5b --- /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 000000000000..fc2ea9c9bad1 --- /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 000000000000..93090d6aabb9 --- /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 000000000000..58e52d14aa9a --- /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 000000000000..d00491fd7e5b --- /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 000000000000..c90881588636 --- /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 000000000000..87066c4d4050 --- /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 000000000000..5ffa1abe3f74 --- /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 000000000000..1031f2db092c --- /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 000000000000..6a14c1198c84 --- /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 000000000000..1701f7723610 --- /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 000000000000..87af62c6753d --- /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 000000000000..f362a5d897c5 --- /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 000000000000..fc6b53c364f5 --- /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 000000000000..710703520ba7 --- /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 000000000000..9b7b1fc0e2cc --- /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 000000000000..5daf8c3c47b4 --- /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 000000000000..4781b87fabe0 --- /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 000000000000..416ca0f64670 --- /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 000000000000..7f433dabb253 --- /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 000000000000..c28596af7d3c --- /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 000000000000..2c853e837cfe --- /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 000000000000..2623fcaa7d83 --- /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 000000000000..3d256c9b1af1 --- /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 000000000000..3b034da9ef9d --- /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 000000000000..5123678b6d8a --- /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 000000000000..96a65ff9844a --- /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 000000000000..e0b1f4e5cb61 --- /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 000000000000..4bc00778cd2f --- /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 000000000000..b60654629fa4 --- /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 000000000000..198751482e44 --- /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 000000000000..2848a7c7ef1d --- /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 000000000000..0ecaf0da24e0 --- /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 000000000000..d1712a1ff10a --- /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 000000000000..7176940306fa --- /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 000000000000..03a2f8a07e0e --- /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 000000000000..0f7279fcd267 --- /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 000000000000..fa05d1276375 --- /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 339/394] 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 729da0d72e23..d95b7213ebe6 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 340/394] 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 f362a5d897c5..dc7a7ce4863e 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 710703520ba7..bbb928cb3715 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 9b7b1fc0e2cc..5c755d610ccf 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 5daf8c3c47b4..9e15ef564985 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 2623fcaa7d83..609178fd0e02 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 3d256c9b1af1..e9cd65ffe400 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 3b034da9ef9d..471a5a63c225 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 4bc00778cd2f..aca167f6b95d 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 198751482e44..7c8d483e272b 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 0ecaf0da24e0..8e048b29e992 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 03a2f8a07e0e..116a6c5e4a3b 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 341/394] 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 000000000000..3cf20d57b0b8 --- /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 000000000000..a340f7530003 --- /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 000000000000..9bb8f4a06e24 --- /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 000000000000..330f461c2d02 --- /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 000000000000..5691c0c9051e --- /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 000000000000..2d6d0745ac1a --- /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 000000000000..0f9c73b67bc4 --- /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 000000000000..2849dea65212 --- /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 000000000000..01e34b707ddd --- /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 000000000000..cb4112f41bc4 --- /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 000000000000..631b1c60ba52 --- /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 000000000000..b2bb64b199d9 --- /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 000000000000..9f8acbeb6a36 --- /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 000000000000..f6e3c3805bd2 --- /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 000000000000..1995cf698f96 --- /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 000000000000..b6926b51ff8f --- /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 000000000000..51ddd9d6c4c7 --- /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 000000000000..c9eba88e5380 --- /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 000000000000..b6d2b99d96a4 --- /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 000000000000..1b890790346b --- /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 000000000000..e3b873ca7905 --- /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 000000000000..4a6e9401f420 --- /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 000000000000..38d1085a84af --- /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 000000000000..0318625995b5 --- /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 000000000000..b5d0b0651c64 --- /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 000000000000..850798c937ed --- /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 000000000000..541dea056c2a --- /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 000000000000..e0e6625abd7d --- /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 000000000000..b7bae489fb5f --- /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 000000000000..8ddfdbfc37e1 --- /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 000000000000..cd74b20dbc78 --- /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 000000000000..0e24366b10e5 --- /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 000000000000..65923479d283 --- /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 000000000000..67954bdce1d8 --- /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 000000000000..ece4273bbbc4 --- /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 000000000000..953d791cc9ec --- /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 000000000000..b586a271e177 --- /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 000000000000..93271e125b6c --- /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 000000000000..c73dc480d912 --- /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 000000000000..7560fb83bbea --- /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 000000000000..cbb4e5ed9140 --- /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 000000000000..0549c9d607ac --- /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 000000000000..c8bc2abbcd28 --- /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 000000000000..14fb09b104c6 --- /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 000000000000..2a783a813dbe --- /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 000000000000..57d51d587f47 --- /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 000000000000..ee695075e319 --- /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 000000000000..47ae6f0b431f --- /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 000000000000..d5bd3825e8aa --- /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 000000000000..1c3c715f9da9 --- /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 000000000000..44798fdbf3db --- /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 000000000000..79d8b395b808 --- /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 000000000000..a7e9ee08977d --- /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 000000000000..4d5b2da9cd51 --- /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 000000000000..310f503579a0 --- /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 000000000000..67e63924b382 --- /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 000000000000..11c8f449cabd --- /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 000000000000..7f41e64cbdfd --- /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 000000000000..4f74c454551a --- /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 000000000000..5052d837589d --- /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 000000000000..0dbc2b371680 --- /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 000000000000..54ebb32c7f7b --- /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 000000000000..e044a6aadfdc --- /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 000000000000..9287e5a3bef8 --- /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 000000000000..a232939c74fa --- /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 000000000000..e057b6940b92 --- /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 000000000000..cce2bfbe95cb --- /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 000000000000..73fcdc485f33 --- /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 342/394] 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 eaeaf4851710..7996fd71137b 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 1f5826fdc059..f0e521c60bad 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 6d8dc416aa00..b605401e9e27 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 e12e37184687..889c163562ff 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 cf3bddf403d6..b59273b18d5d 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 cc5cc932415c..0121bef332df 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 3f817b180fd9..7adfc7a4aa2e 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 000000000000..a5ad279544f2 --- /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 000000000000..d00491fd7e5b --- /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 330f461c2d02..920e8d252c2b 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 dc7a7ce4863e..3f87f87bb394 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 5691c0c9051e..fded26fadd0d 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 2d6d0745ac1a..39e3fcec982e 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 0f9c73b67bc4..af6b9424f607 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 01e34b707ddd..6ccb2ff7a1c8 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 cb4112f41bc4..083977c7ae15 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 631b1c60ba52..7c1bfc1e60d2 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 b2bb64b199d9..f49e6c2dbda2 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 9f8acbeb6a36..b9cdd9dfaae2 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 f6e3c3805bd2..bb97172d996c 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 1995cf698f96..e06deeaaf2dc 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 c9eba88e5380..9a264247c8d0 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 b6d2b99d96a4..a3256f2df237 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 1b890790346b..68b2e2460471 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 e3b873ca7905..98c7b6057abe 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 4a6e9401f420..9e63740d89f3 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 38d1085a84af..194f0df0ea9a 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 0318625995b5..a803d005f7dd 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 8ddfdbfc37e1..d525d92066a0 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 cd74b20dbc78..a3238257466e 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 0e24366b10e5..1f2e1ecd4eda 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 e9cd65ffe400..f0c6a00985ea 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 65923479d283..6f9b39703afa 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 471a5a63c225..8e6d37ad6e1f 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 ece4273bbbc4..9901af417570 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 953d791cc9ec..e1f1b0914a9c 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 b586a271e177..6c38d15988d7 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 93271e125b6c..d341a5a764d2 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 cbb4e5ed9140..c7a72f727749 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 0549c9d607ac..77b1ed617c08 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 aca167f6b95d..f0b2a2b68b04 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 c8bc2abbcd28..12304ba8a0bd 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 14fb09b104c6..539a59c11c07 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 2a783a813dbe..0c42f3550a44 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 57d51d587f47..ee480730434c 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 ee695075e319..035e43d24ae4 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 47ae6f0b431f..4d48e410f881 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 d5bd3825e8aa..0f682d779b0b 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 44798fdbf3db..0558e28db9b6 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 79d8b395b808..9e3111f880c3 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 a7e9ee08977d..c87a98eaa919 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 67e63924b382..92c0b1147ea4 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 11c8f449cabd..70e3e441956e 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 7f41e64cbdfd..3b8292fe8cbd 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 4f74c454551a..bb1bcc0e13ba 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 5052d837589d..f426104cc2cb 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 0dbc2b371680..eb4693e488d1 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 54ebb32c7f7b..dd8ee6f9cc27 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 e044a6aadfdc..14259fd3d65d 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 9287e5a3bef8..98036416880a 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 a232939c74fa..b45ee88dd98d 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 e057b6940b92..172fb58ab12c 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 cce2bfbe95cb..bb56de728944 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 73fcdc485f33..1f08fa0ec9ee 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 343/394] 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 1eff35fb2d66..fde0819dabec 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 f202b358e5f0..286999e5c753 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 5d5ea90a99be..0440daade1ce 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 bd5c55a3cd73..07ab758d7502 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 88ecc2967763..2cb251fba8d5 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 0fd238c4052d..c5d63847153a 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 ecaa4198bd52..6abb1bb9fa1b 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 44cbbd43a4b3..9626c7ad1c77 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 ae91716e5385..1dac1a66fe21 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 766cd4928447..d62b3e93542f 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 0db063740006..841872933b9a 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 258bc9204aa5..a58510a417e9 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 344/394] 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 841872933b9a..86fd6184e26b 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 a58510a417e9..58ea124fb1df 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 2e2dd12ad325..5485ed081805 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 000000000000..a345c7b6d63d --- /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 000000000000..1f9b993cca87 --- /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 000000000000..f718937be02e --- /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 000000000000..6ec0cbb0b4ea --- /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 000000000000..6e62854a9492 --- /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 fbda89ebfd2a..fd99cea6ec15 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 345/394] 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 1dac1a66fe21..3c27cc20ff10 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 d62b3e93542f..a2a557de98d4 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 766f96821b18..17698d74e2a0 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 99e92c183edc..cc2cae6f652e 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 0e5aa9e130f5..1accb5cef647 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 5650b580da5f..02a974784140 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 023100cddee6..46c3cabb948a 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 3b43bd534309..a510c65e96b1 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 50a9d64869f5..5566f97130af 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 706a46c6280c..42084c16efc4 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 e6a9379dfde2..95ede59faa94 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 e86619e464b2..39db59956535 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 1a178abf0958..a7e9166577a9 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 37da7f9b83d6..1f87ba5b8be2 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 4480d012e69d..5b3aba01fcaa 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 4468165f1e55..c33eea9b3535 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 e6819ea903e7..0715f494522e 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 a0259b1800ef..59872e4a75f2 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 f5c068d5e382..ad9366322b18 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 27f0705157c4..8501a8d028b8 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 9f5001c87686..338c8e983ec5 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 02614c492db8..f6779917e321 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 9ce9be70ab88..1ad539b3024f 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 5a3b3454c591..c94c18ac486b 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 b9d1a5571a9a..a47d38fd037b 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 40553083ffaa..aa144950f9c8 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 8407df5d0497..e97e458da0e2 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 bde030f68ec3..8a2c52a9ad98 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 46435dd210dc..e7170a10defd 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 47db17e21198..e06dd8d8b0a9 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 346/394] 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 07ab758d7502..69cd046debd0 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 6abb1bb9fa1b..69045998c859 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 9626c7ad1c77..bf1b1917ba33 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 3c27cc20ff10..97d2c054700d 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 a2a557de98d4..13a3bbd87afa 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 86fd6184e26b..eb34eabb1776 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 347/394] 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 230408756cd0..f52ad4e1ee88 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 1ef477677447..25f3048b54f2 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 000000000000..74342f38f1cc --- /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 000000000000..0f9581e7f7f2 --- /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 000000000000..8afe2c9b3a61 --- /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 000000000000..32401186d0d7 --- /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 000f29c4df1a..38dab05afaba 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 000000000000..09535998b5be --- /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 000000000000..19a3c9e86b90 --- /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 082f6feee994..000000000000 --- 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 000000000000..38ce714e1b86 --- /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 000000000000..b2c26e5d8a50 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..25b9640ca565 --- /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 000000000000..b2c26e5d8a50 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..25b9640ca565 --- /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 000000000000..25b9640ca565 --- /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 375c5cf900af..6713431b680e 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 000000000000..e048da7bbb2f --- /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 000000000000..25b9640ca565 --- /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 000000000000..59e2579eb65a --- /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 000000000000..6a019364e6b3 --- /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 000000000000..2729b6d5d830 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..25b9640ca565 --- /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 000000000000..25b9640ca565 --- /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 8670e379d4e3..93b7b91f13e4 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 000000000000..f647c52a7eed --- /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 000000000000..25b9640ca565 --- /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 000000000000..733e47a8500b --- /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 000000000000..422a54f90d9f --- /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 000000000000..0b8a87baf622 --- /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 000000000000..8f8edcd29203 --- /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 000000000000..963bcd8d7d68 --- /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 6ac2691c2085..000000000000 --- 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 bb93f57a8256..000000000000 --- 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 000000000000..8ed44ca05de2 --- /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 000000000000..27c400f9e946 --- /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 000000000000..66b9082dcc12 --- /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 e45f27f3caa8..000000000000 --- 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 000000000000..ad74649f5d1d --- /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 3ed2f577c7aa..44867c7a75eb 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 000000000000..ad74649f5d1d --- /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 3ed2f577c7aa..44867c7a75eb 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 000000000000..35c8f940e82d --- /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 000000000000..e4681967f7db --- /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 000000000000..d7284ab6405e --- /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 f8e3ee312e6b..000000000000 --- 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 000000000000..6239a7275e4d --- /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 000000000000..fdb6c95b813e --- /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 000000000000..dce2a276e46f --- /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 000000000000..5bc9d5467345 --- /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 000000000000..fabb25ee6720 --- /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 ab13b27ea6ea..000000000000 --- 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 000000000000..8952a241f6e7 --- /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 000000000000..d7284ab6405e --- /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 000000000000..574a8b1c43cd --- /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 000000000000..1329babc3dd7 --- /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 a8a5cff05d0b..000000000000 --- 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 000000000000..a684e0dc073b --- /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 3ed2f577c7aa..44867c7a75eb 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 000000000000..1f09e3a70253 --- /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 3ed2f577c7aa..44867c7a75eb 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 000000000000..aa564d00ce86 --- /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 000000000000..3e5b81c5ef69 --- /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 000000000000..63d48b80b255 --- /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 000000000000..aa564d00ce86 --- /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 000000000000..f05e6f361aca --- /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 000000000000..963bcd8d7d68 --- /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 f3346fdd10e3..abfb7ee863af 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 000000000000..18532c5a6d3f --- /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 89994857f418..54094c67305f 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 000000000000..d7e3e6be3b40 --- /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 e132c654f042..e222dfeda8c2 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 000000000000..18532c5a6d3f --- /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 000000000000..3153a378db84 --- /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 000000000000..c9ab1d8f5e73 --- /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 000000000000..18532c5a6d3f --- /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 000000000000..920aef8e9dc2 --- /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 000000000000..180abcf31f8d --- /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 000000000000..47d0008f1eb5 --- /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 3ed2f577c7aa..000000000000 --- 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 000000000000..18532c5a6d3f --- /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 000000000000..920aef8e9dc2 --- /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 fb232f23a1fb..9f0c8b0d5cef 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 000000000000..44867c7a75eb --- /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 000000000000..18532c5a6d3f --- /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 000000000000..920aef8e9dc2 --- /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 000000000000..81b637abd5b5 --- /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 000000000000..44867c7a75eb --- /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 715f3fb4848b..a800f5c34e34 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 702fe057d532..84ba9317b85b 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 000000000000..6194b51b6942 --- /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 000000000000..645f7557ada8 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..acd0b45f5335 --- /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 000000000000..2063d860c504 --- /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 000000000000..acd0b45f5335 --- /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 000000000000..e2f0ed7f97f2 --- /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 000000000000..fd081fdaf6d3 --- /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 000000000000..7d66138755f9 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..acd0b45f5335 --- /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 000000000000..715f3fb4848b --- /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 000000000000..7d66138755f9 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..acd0b45f5335 --- /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 3161eba2a868..ec3c7db1c847 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 17166268a656..adfd24b02b26 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 348/394] 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 000000000000..8f26f2f5be8d --- /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 000000000000..cb7c405af9fa --- /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 cc4c5051c4bd..fc3302a82332 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 349/394] 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 10d7f1d116a6..9f3e293f53da 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 a0d21744de88..e56ee157d94d 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 dce729de408b..720ff2afe4ed 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 350/394] 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 2fb6a6162405..2d55b46fc9f7 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 4e9346ecfebd..2748c09cda94 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 720ff2afe4ed..08a319b5b597 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 352f16f769b8..aa3e23e2626f 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 c061a251acd6..a6949d7f8bdb 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 954ade311f84..dfa604941ab5 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 351/394] 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 a5ad279544f2..6d5d1dc46c36 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 d525d92066a0..3d60cc38d51a 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 000000000000..3b1cf05ce321 --- /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 000000000000..8b41095fb51d --- /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 77b1ed617c08..69df5d7752c3 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 0c42f3550a44..d2ac0e931d0d 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 352/394] 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 7996fd71137b..a426b8af93dd 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 353/394] 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 3eb3abf79f38..8144fdf51b56 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 a426b8af93dd..c655480bf8f1 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 354/394] 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 c655480bf8f1..08d8fc9f779b 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 f0e521c60bad..e51e39dc3963 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 7d434f896d12..7f5ea03a0ac0 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 b31bd20d5845..0f37af7195d9 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 d99d60c6e284..71206ac43f8f 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 355/394] 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 000000000000..280fb81c8e18 --- /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 000000000000..d46bdd9c3872 --- /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 356/394] 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 bb25d203b71e..8b39d4a53585 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 7df39bf71ee8..fcab682a2139 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 cdfcdfb19c48..6b2d1f3d82b8 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 0994b63a83ef..e0980c7646e6 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 357/394] 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 f52ad4e1ee88..71fbf17e288b 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 25f3048b54f2..a382c5217377 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 8b39d4a53585..d39c6db1ea9e 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 000000000000..90e7e00e2552 --- /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 000000000000..cf9a17a7dfb9 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..f123f6c8bee3 --- /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 000000000000..b5d6267fa5b0 --- /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 000000000000..02ce7958c8d7 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..0967ef424bce --- /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 000000000000..071e711e6742 --- /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 000000000000..8b50700db35a --- /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 000000000000..12cac3b2c8d9 --- /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 000000000000..8b50700db35a --- /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 000000000000..125792d0910a --- /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 000000000000..8b50700db35a --- /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 000000000000..7ec243fdeb21 --- /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 000000000000..cf9a17a7dfb9 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..0967ef424bce --- /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 358/394] 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 fcab682a2139..983615312efd 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 359/394] 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 8144fdf51b56..7b15ce945885 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 181cbaa8fe4e..07c25a0681c6 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 360/394] 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 07c25a0681c6..a09e88791577 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 361/394] 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 3cb908118ea2..ccf4added41e 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 362/394] 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 000000000000..aae75b841ce0 --- /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 000000000000..a01e842b384d --- /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 000000000000..dbf1dfdcfcda --- /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 363/394] 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 7b15ce945885..bb7a20d093d2 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 71fbf17e288b..eee29f921fc5 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 f92268180971..4f08e192f788 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 4fd730096e85..e57cd77a98a2 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 c6c3df7a2eba..49994559423a 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 000000000000..b182392aac61 --- /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 000000000000..588f4d437945 --- /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 000000000000..d00491fd7e5b --- /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 000000000000..aae75b841ce0 --- /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 dbf1dfdcfcda..b4b0139fee69 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 364/394] 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 eee29f921fc5..6bd5cd2317b3 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 365/394] 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 bb7a20d093d2..65c04b106791 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 c48cb328d5f9..12308bf0d40b 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 1fd016e54e81..b4e525c21516 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 366/394] 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 2748c09cda94..9582939f5e25 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 367/394] 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 aa3e23e2626f..b6ff862b3850 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 368/394] 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 30f06bc97385..830c32752dba 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 4b390f4f271a..894ada60962e 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 4c85d77f5246..9f5c75b43749 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 1c21a0115985..560ecfc38bfa 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 13a3bbd87afa..f70bc0c1d2a7 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 0f4230d5adec..f7d07aa4447c 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 369/394] 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 000000000000..d0fe39023051 --- /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 000000000000..685bec80771a --- /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 000000000000..842580597d12 --- /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 000000000000..5152882bb2a0 --- /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 370/394] 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 65c04b106791..13cc8db13346 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 371/394] 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 b49905130ccc..47dddb3aea08 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 93bc52bd6936..7af843fcaec9 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 22e306c4322b..65f130247147 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 372/394] 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 9582939f5e25..60ebd7642434 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 ccc12f642d1c..000000000000 --- 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 d1012053f398..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 87066c4d4050..000000000000 --- 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 a84e2a2576ff..000000000000 --- 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 d1012053f398..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 000000000000..b207f3babd3e --- /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 000000000000..d1c54c99b7d0 --- /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 000000000000..7e6575feffb2 --- /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 000000000000..9ad276caf3e4 --- /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 000000000000..de5fd53748d4 --- /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 87066c4d4050..c3dbe062ff30 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 000000000000..b8163df7a36d --- /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 000000000000..7e5e61de0edb --- /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 000000000000..ac391d192eb5 --- /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 93090d6aabb9..000000000000 --- 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 58e52d14aa9a..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 c90881588636..000000000000 --- 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 87066c4d4050..000000000000 --- 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 000000000000..e465437626b3 --- /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 000000000000..c30f9dab98a7 --- /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 000000000000..a6cc84cce511 --- /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 000000000000..b651e0e888b9 --- /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 000000000000..54eabe844702 --- /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 000000000000..004997c221bc --- /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 000000000000..62a75e7d5342 --- /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 000000000000..fdf68994be7e --- /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 000000000000..8874f28f2fd4 --- /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 000000000000..554c3fcd7e2b --- /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 000000000000..a4eeee5f28db --- /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 000000000000..73304d622965 --- /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 000000000000..9f5a5491d202 --- /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 000000000000..6ea695e6625d --- /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 000000000000..89900c0f6d0b --- /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 000000000000..9745850c0091 --- /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 000000000000..1b24b4961dbf --- /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 000000000000..dd75b1d25648 --- /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 000000000000..5dacc81ba6e1 --- /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 000000000000..6489b1e6b2fb --- /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 000000000000..1737c35bb87c --- /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 000000000000..66328261617d --- /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 000000000000..e33df29ea604 --- /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 000000000000..30cbed7f3ca2 --- /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 000000000000..1ce5207eb181 --- /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 000000000000..5b2b6d5582df --- /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 000000000000..0c1e0a78a554 --- /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 000000000000..db14ef55874c --- /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 000000000000..1a4ee2e6f9d7 --- /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 000000000000..2d17de248c34 --- /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 000000000000..c1d8f911d7c3 --- /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 000000000000..33ffc59939e9 --- /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 000000000000..bda660d056a4 --- /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 000000000000..42c917d18279 --- /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 000000000000..73dfa42f3a1b --- /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 bbb928cb3715..c5127249ab68 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 5c755d610ccf..111a4fc365f8 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 9e15ef564985..7e448bba7fd5 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 850798c937ed..32d6839abd06 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 541dea056c2a..c0ac98f57a89 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 b7bae489fb5f..f74c45ed76f1 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 609178fd0e02..fffea1458e87 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 67954bdce1d8..793b5b2689cf 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 7c8d483e272b..13e094631c23 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 1c3c715f9da9..a5876ab6e632 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 8e048b29e992..a9b5abef18b3 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 4d5b2da9cd51..e21521e39a97 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 310f503579a0..58fb725d7590 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 116a6c5e4a3b..024f5a95f941 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 373/394] 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 13cc8db13346..331a68a3f383 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 b605401e9e27..3e5a05499ea7 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 7f5ea03a0ac0..5ae3366194c6 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 0f37af7195d9..d29bda35ff8c 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 c77a6d0b6b50..1a1cf929148c 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 aa14cf6b938e..2a5cdcfc99bb 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 374/394] 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 3e5a05499ea7..657f39284544 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 889c163562ff..2fa2cb11bfd3 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 1a1cf929148c..5f543be0dfa8 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 000000000000..29733c9ca96a --- /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 000000000000..fb1008616162 --- /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 000000000000..a3efe6d3a0de --- /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 000000000000..cfbfd539de28 --- /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 375/394] 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 5f543be0dfa8..02df22dd5ce0 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 2a5cdcfc99bb..8d2453d8d503 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 57a23fb803ce..3a4dca0439ca 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 dd6503ca1fbf..27f7bedce225 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 8565fec68f26..05d799d08ffd 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 376/394] 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 cc8435ed3c30..ab90c3f2035a 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 377/394] 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 13cc8db13346..5a8438c5c5e5 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 4dcc6a4b092b..a0711cd41756 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 c1918540e625..a7441b85e264 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 000000000000..7b5de2ba9b59 --- /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 000000000000..72ac16037969 --- /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 c103a565a069..34e696d4e159 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 9582939f5e25..b927776cee59 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 6bd5cd2317b3..d5502228bda4 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 1ad24998ffb5..5adb8d6d5c9a 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 b745f1b80538..e9d75b6ae9d9 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 e57cd77a98a2..4a7f34561fbe 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 3c781ea78f07..f68ed53dc066 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 74342f38f1cc..000000000000 --- 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 25b9640ca565..000000000000 --- 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 0f9581e7f7f2..000000000000 --- 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 8afe2c9b3a61..000000000000 --- 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 32401186d0d7..000000000000 --- 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 18053bcdac95..000000000000 --- 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 25b9640ca565..000000000000 --- 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 38dab05afaba..000000000000 --- 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 09535998b5be..000000000000 --- 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 25b9640ca565..000000000000 --- 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 19a3c9e86b90..000000000000 --- 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 38ce714e1b86..000000000000 --- 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 b2c26e5d8a50..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 25b9640ca565..000000000000 --- 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 6edc3b560136..000000000000 --- 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 b2c26e5d8a50..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 25b9640ca565..000000000000 --- 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 000000000000..65974c6287da --- /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 000000000000..7714685971d2 --- /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 25b9640ca565..415509ef9aef 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 000000000000..9d002fadc317 --- /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 ac83894b301f..000000000000 --- 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 25b9640ca565..000000000000 --- 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 6713431b680e..000000000000 --- 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 e048da7bbb2f..000000000000 --- 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 25b9640ca565..000000000000 --- 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 59e2579eb65a..000000000000 --- 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 6a019364e6b3..000000000000 --- 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 2729b6d5d830..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 25b9640ca565..000000000000 --- 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 a2193034c8db..000000000000 --- 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 25b9640ca565..000000000000 --- 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 93b7b91f13e4..000000000000 --- 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 f647c52a7eed..000000000000 --- 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 25b9640ca565..000000000000 --- 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 733e47a8500b..000000000000 --- 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 0b8a87baf622..8f198f1f3adb 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 000000000000..e69de29bb2d1 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 f8fb2ce274d0..7694acea611c 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 000000000000..e69de29bb2d1 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 66b9082dcc12..b129a0c91b85 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 000000000000..e69de29bb2d1 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 fabb25ee6720..c7463f124184 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 000000000000..e69de29bb2d1 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 d7284ab6405e..eab40879c4c5 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 000000000000..e69de29bb2d1 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 4c7b4ed67197..8a8080833cf6 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 000000000000..e69de29bb2d1 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 dce2a276e46f..4f3bd68eed09 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 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_ir/output.json index fabb25ee6720..c7463f124184 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 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json b/test/cmdlineTests/standard_output_selection_ethdebug_iroptimized/output.json index d7284ab6405e..eab40879c4c5 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 000000000000..e69de29bb2d1 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 63d48b80b255..2b2f395fadd4 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 000000000000..e69de29bb2d1 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 000000000000..18532c5a6d3f --- /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 000000000000..182cdc75ddc9 --- /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 000000000000..be4fbb64fce3 --- /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 000000000000..b645222de390 --- /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 000000000000..18532c5a6d3f --- /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 000000000000..5c098cc80569 --- /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 000000000000..83acd4c42085 --- /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 000000000000..3af82e21d392 --- /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 c9ab1d8f5e73..c1f6523d5388 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 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json b/test/cmdlineTests/standard_yul_ethdebug_bytecode_iroptimized/output.json index d7e3e6be3b40..2f1d22b4df0f 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 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul b/test/cmdlineTests/standard_yul_ethdebug_deployed_bytecode/in.yul index 920aef8e9dc2..d5adfd0c28f4 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 1380c31d7c10..44183e45fdde 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 000000000000..e69de29bb2d1 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 000000000000..18532c5a6d3f --- /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 000000000000..d5adfd0c28f4 --- /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 000000000000..20779012030d --- /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 000000000000..6d8064a94f36 --- /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 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_ir/output.json b/test/cmdlineTests/standard_yul_ethdebug_ir/output.json index c9ab1d8f5e73..c1f6523d5388 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 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json b/test/cmdlineTests/standard_yul_ethdebug_iroptimize/output.json index 47d0008f1eb5..6323c1157973 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 000000000000..e69de29bb2d1 diff --git a/test/cmdlineTests/yul_ethdebug/args b/test/cmdlineTests/yul_ethdebug/args deleted file mode 100644 index a800f5c34e34..000000000000 --- 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 acd0b45f5335..000000000000 --- 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 84ba9317b85b..000000000000 --- 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 6194b51b6942..000000000000 --- 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 645f7557ada8..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 acd0b45f5335..000000000000 --- 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 2063d860c504..000000000000 --- 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 acd0b45f5335..000000000000 --- 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 e2f0ed7f97f2..000000000000 --- 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 fd081fdaf6d3..000000000000 --- 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 7d66138755f9..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 acd0b45f5335..000000000000 --- 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 715f3fb4848b..000000000000 --- 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 7d66138755f9..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 acd0b45f5335..000000000000 --- 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 3bedf2d9e437..000000000000 --- 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 ed5894632c43..000000000000 --- 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 d00491fd7e5b..000000000000 --- 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 acd0b45f5335..000000000000 --- 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 3a6383002dc3..6a41f7a7394c 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 ec3c7db1c847..b17f566613a1 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 378/394] 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 7b5de2ba9b59..6e635ef57952 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 379/394] 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 000000000000..b1647e463cb6 --- /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 380/394] 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 657f39284544..c7b7b0961622 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 2fa2cb11bfd3..ca7247c4671a 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 280fb81c8e18..43acb5b14f7e 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 29733c9ca96a..e215c26cff3e 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 fb1008616162..89012b781d80 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 f74c45ed76f1..dd298820cd93 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 793b5b2689cf..cfdefa1ed144 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 b1647e463cb6..5d1f777fd3c0 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 381/394] 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 588b1da00d0b..b47b4aa4552a 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 000000000000..484ca6a8b8f1 --- /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 557a0a0e2090..aade16fb3a2f 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 382/394] 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 484ca6a8b8f1..341975eaca09 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 383/394] 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 aade16fb3a2f..034bfe29e0c2 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 384/394] 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 034bfe29e0c2..c9c5f6ee3721 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 385/394] 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 c9c5f6ee3721..319aa4d8b1da 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 386/394] 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 341975eaca09..224e77425084 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 387/394] Bump vendored dependencies post-release --- ReleaseChecklist.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md index 758ef79ddaa4..f55384230aa4 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 388/394] 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 a60dc1b84d46..11765d3be559 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 389/394] 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 e8e8fed5880b..7c8d61afacf1 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 390/394] Fix changelog for upcoming release --- Changelog.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index b14ebb2c157f..e213ab437e35 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 391/394] 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 e213ab437e35..b1ddcacf6c94 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 2c3b6487ae50..60fcdd049a0f 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 392/394] 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 a44d9875388a..063936a9dcde 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 97db1d7ceb0a..f1b33c648220 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 393/394] 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 f1b33c648220..4984d999df27 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 83a9990ba4517360ba6e7251e3eddf5b320fabea Mon Sep 17 00:00:00 2001 From: Asuka Date: Thu, 9 Jul 2026 14:55:30 +0800 Subject: [PATCH 394/394] test: update DATALOADN EOF expectations --- test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output | 2 +- test/libyul/objectCompiler/eof/creation_with_immutables.yul | 2 +- test/libyul/objectCompiler/eof/dataloadn.yul | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output index 677c49b88a1b..355c96451e0d 100644 --- a/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output +++ b/test/cmdlineTests/strict_asm_eof_dataloadn_osaka/output @@ -14,7 +14,7 @@ object "a" { Binary representation: -ef0001010004020001000904002d0000800002d1000d5f5260205ff348656c6c6f2c20576f726c6421 +ef0001010004020001000904002d0000800002ef000d5f5260205ff348656c6c6f2c20576f726c6421 Text representation: auxdataloadn{0} diff --git a/test/libyul/objectCompiler/eof/creation_with_immutables.yul b/test/libyul/objectCompiler/eof/creation_with_immutables.yul index c11cceae85ad..abac2440ceaa 100644 --- a/test/libyul/objectCompiler/eof/creation_with_immutables.yul +++ b/test/libyul/objectCompiler/eof/creation_with_immutables.yul @@ -94,6 +94,6 @@ object "a" { // return // } // } -// Bytecode: ef0001010004020001000c030001008704000d00008000045f808080ec005f5260205ff3ef0001010004020001004c030001002304000000008000027f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205260405fee00ef000101000402000100100400400000800003d10000d10020905f5260205260405ff348656c6c6f2c20576f726c6421 +// Bytecode: ef0001010004020001000c030001008704000d00008000045f808080ec005f5260205ff3ef0001010004020001004c030001002304000000008000027f11223344556677889900112233445566778899001122334455667788990011225f527f112233445566778899001122334455667788990011223344556677889900112260205260405fee00ef000101000402000100100400400000800003ef0000ef0020905f5260205260405ff348656c6c6f2c20576f726c6421 // 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 7fda77b9a666..95b220e4591c 100644 --- a/test/libyul/objectCompiler/eof/dataloadn.yul +++ b/test/libyul/objectCompiler/eof/dataloadn.yul @@ -26,6 +26,6 @@ object "a" { // return // stop // data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 -// Bytecode: ef0001010004020001000904002d0000800002d1000d5f5260205ff348656c6c6f2c20576f726c6421 +// Bytecode: ef0001010004020001000904002d0000800002ef000d5f5260205ff348656c6c6f2c20576f726c6421 // 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