From ce0a3e93f2e2a29a179d6c8d7f98b01310d7f909 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 7 Mar 2022 12:49:23 +0100 Subject: [PATCH 1/5] Store whether an evmasm Assembly is creation code. --- Changelog.md | 1 + libevmasm/Assembly.cpp | 8 ++++--- libevmasm/Assembly.h | 6 ++++- libsolidity/codegen/CompilerContext.h | 2 +- libyul/AssemblyStack.cpp | 8 +++++-- libyul/backends/evm/AbstractAssembly.h | 2 +- libyul/backends/evm/EVMObjectCompiler.cpp | 5 +++- libyul/backends/evm/EthAssemblyAdapter.cpp | 4 ++-- libyul/backends/evm/EthAssemblyAdapter.h | 2 +- libyul/backends/evm/NoOutputAssembly.cpp | 2 +- libyul/backends/evm/NoOutputAssembly.h | 2 +- test/cmdlineTests/yul_optimize_runs/output | 5 ++-- test/libevmasm/Assembler.cpp | 18 +++++++------- test/libevmasm/Optimiser.cpp | 4 ++-- .../semanticTests/array/reusing_memory.sol | 2 +- .../constructor/arrays_in_constructors.sol | 2 +- .../bytes_in_constructors_packer.sol | 2 +- .../creation_function_call_with_args.sol | 2 +- .../creation_function_call_with_salt.sol | 2 +- .../inheritance/value_for_constructor.sol | 2 +- .../salted_create_with_value.sol | 2 +- test/libyul/EVMCodeTransformTest.cpp | 2 +- test/tools/fuzzer_common.cpp | 24 ++++++++++--------- 23 files changed, 62 insertions(+), 47 deletions(-) diff --git a/Changelog.md b/Changelog.md index 181c386aa..63588731f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: * JSON-AST: Added selector field for errors and events. Bugfixes: + * Yul IR Code Generation: Optimize embedded creation code with correct settings. This fixes potential mismatches between the constructor code of a contract compiled in isolation and the bytecode in ``type(C).creationCode``, resp. the bytecode used for ``new C(...)``. ### 0.8.12 (2022-02-16) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 55d23e283..492d434c8 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -411,13 +411,15 @@ map const& Assembly::optimiseInternal( if (m_tagReplacements) return *m_tagReplacements; + assertThrow(_settings.isCreation == m_creation, OptimizerException, "Mismatching creation settings."); + // Run optimisation for sub-assemblies. for (size_t subId = 0; subId < m_subs.size(); ++subId) { OptimiserSettings settings = _settings; - // Disable creation mode for sub-assemblies. - settings.isCreation = false; - map const& subTagReplacements = m_subs[subId]->optimiseInternal( + Assembly& sub = *m_subs[subId]; + settings.isCreation = sub.isCreation(); + map const& subTagReplacements = sub.optimiseInternal( settings, JumpdestRemover::referencedTags(m_items, subId) ); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 97807e223..270d85480 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -48,7 +48,7 @@ using AssemblyPointer = std::shared_ptr; class Assembly { public: - explicit Assembly(std::string _name = std::string()):m_name(std::move(_name)) { } + Assembly(bool _creation, std::string _name): m_creation(_creation), m_name(std::move(_name)) { } AssemblyItem newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); } AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); } @@ -157,6 +157,8 @@ public: std::vector decodeSubPath(size_t _subObjectId) const; size_t encodeSubPath(std::vector const& _subPath); + bool isCreation() const { return m_creation; } + protected: /// Does the same operations as @a optimise, but should only be applied to a sub and /// returns the replaced tags. Also takes an argument containing the tags of this assembly @@ -214,6 +216,8 @@ protected: mutable std::vector m_tagPositionsInBytecode; int m_deposit = 0; + /// True, if the assembly contains contract creation code. + bool const m_creation = false; /// Internal name of the assembly object, only used with the Yul backend /// currently std::string m_name; diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index cd71d5a4d..a796ac60b 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -65,7 +65,7 @@ public: RevertStrings _revertStrings, CompilerContext* _runtimeContext = nullptr ): - m_asm(std::make_shared()), + m_asm(std::make_shared(_runtimeContext != nullptr, std::string{})), m_evmVersion(_evmVersion), m_revertStrings(_revertStrings), m_reservedMemory{0}, diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp index 30ad58d77..5d0ddd81a 100644 --- a/libyul/AssemblyStack.cpp +++ b/libyul/AssemblyStack.cpp @@ -38,6 +38,7 @@ #include #include +#include #include using namespace std; @@ -194,7 +195,10 @@ void AssemblyStack::optimize(Object& _object, bool _isCreation) yulAssert(_object.analysisInfo, ""); for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) - optimize(*subObject, false); + { + bool isCreation = !boost::ends_with(subObject->name.str(), "_deployed"); + optimize(*subObject, isCreation); + } Dialect const& dialect = languageToDialect(m_language, m_evmVersion); unique_ptr meter; @@ -281,7 +285,7 @@ AssemblyStack::assembleEVMWithDeployed(optional _deployName) const yulAssert(m_parserResult->code, ""); yulAssert(m_parserResult->analysisInfo, ""); - evmasm::Assembly assembly; + evmasm::Assembly assembly(true, {}); EthAssemblyAdapter adapter(assembly); compileEVM(adapter, m_optimiserSettings.optimizeStackAllocation); diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index 66d5333e2..2d7be9001 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -98,7 +98,7 @@ public: /// Append the assembled size as a constant. virtual void appendAssemblySize() = 0; /// Creates a new sub-assembly, which can be referenced using dataSize and dataOffset. - virtual std::pair, SubID> createSubAssembly(std::string _name = "") = 0; + virtual std::pair, SubID> createSubAssembly(bool _creation, std::string _name = "") = 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/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index c3c95d8bc..b60e383e6 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -30,6 +30,8 @@ #include #include +#include + using namespace solidity::yul; using namespace std; @@ -48,7 +50,8 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) for (auto const& subNode: _object.subObjects) if (auto* subObject = dynamic_cast(subNode.get())) { - auto subAssemblyAndID = m_assembly.createSubAssembly(subObject->name.str()); + bool isCreation = !boost::ends_with(subObject->name.str(), "_deployed"); + auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name.str()); context.subIDs[subObject->name] = subAssemblyAndID.second; subObject->subId = subAssemblyAndID.second; compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize); diff --git a/libyul/backends/evm/EthAssemblyAdapter.cpp b/libyul/backends/evm/EthAssemblyAdapter.cpp index 1c41534b2..5d7b4cbf4 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.cpp +++ b/libyul/backends/evm/EthAssemblyAdapter.cpp @@ -122,9 +122,9 @@ void EthAssemblyAdapter::appendAssemblySize() m_assembly.appendProgramSize(); } -pair, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(string _name) +pair, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, string _name) { - shared_ptr assembly{make_shared(std::move(_name))}; + shared_ptr assembly{make_shared(_creation, std::move(_name))}; auto sub = m_assembly.newSub(assembly); return {make_shared(*assembly), static_cast(sub.data())}; } diff --git a/libyul/backends/evm/EthAssemblyAdapter.h b/libyul/backends/evm/EthAssemblyAdapter.h index c11b375f6..87047ccbf 100644 --- a/libyul/backends/evm/EthAssemblyAdapter.h +++ b/libyul/backends/evm/EthAssemblyAdapter.h @@ -55,7 +55,7 @@ public: void appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) override; void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override; void appendAssemblySize() override; - std::pair, SubID> createSubAssembly(std::string _name = {}) override; + std::pair, SubID> createSubAssembly(bool _creation, std::string _name = {}) 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 62c0ad119..e26204201 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -98,7 +98,7 @@ void NoOutputAssembly::appendAssemblySize() appendInstruction(evmasm::Instruction::PUSH1); } -pair, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(std::string) +pair, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(bool, std::string) { yulAssert(false, "Sub assemblies not implemented."); return {}; diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index b41d7f4a6..1103392ef 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -65,7 +65,7 @@ public: void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override; void appendAssemblySize() override; - std::pair, SubID> createSubAssembly(std::string _name = "") override; + std::pair, SubID> createSubAssembly(bool _creation, std::string _name = "") override; void appendDataOffset(std::vector const& _subPath) override; void appendDataSize(std::vector const& _subPath) override; SubID appendData(bytes const& _data) override; diff --git a/test/cmdlineTests/yul_optimize_runs/output b/test/cmdlineTests/yul_optimize_runs/output index b95184440..357c796ee 100644 --- a/test/cmdlineTests/yul_optimize_runs/output +++ b/test/cmdlineTests/yul_optimize_runs/output @@ -21,7 +21,7 @@ object "RunsTest1" { Binary representation: -602580600c6000396000f3fe7fabc123450000000000000000000000000000000000000000000000000000000060005500 +600c80600c6000396000f3fe63abc1234560e01b60005500 Text representation: /* "yul_optimize_runs/input.yul":106:125 */ @@ -40,8 +40,7 @@ Text representation: stop sub_0: assembly { - /* "yul_optimize_runs/input.yul":237:257 */ - 0xabc1234500000000000000000000000000000000000000000000000000000000 + shl(0xe0, 0xabc12345) /* "yul_optimize_runs/input.yul":277:278 */ 0x00 /* "yul_optimize_runs/input.yul":270:288 */ diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 78e598bca..3a3167816 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -58,11 +58,11 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) { "root.asm", 0 }, { "sub.asm", 1 } }; - Assembly _assembly; + Assembly _assembly{false, {}}; auto root_asm = make_shared("root.asm"); _assembly.setSourceLocation({1, 3, root_asm}); - Assembly _subAsm; + Assembly _subAsm{false, {}}; auto sub_asm = make_shared("sub.asm"); _subAsm.setSourceLocation({6, 8, sub_asm}); // PushImmutable @@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) { *subName, 1 } }; - auto subAsm = make_shared(); + auto subAsm = make_shared(false, string{}); for (char i = 0; i < numImmutables; ++i) { for (int r = 0; r < numActualRefs; ++r) @@ -207,7 +207,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps) } } - Assembly assembly; + Assembly assembly{true, {}}; for (char i = 1; i <= numImmutables; ++i) { assembly.setSourceLocation({10*i, 10*i + 3+i, assemblyName}); @@ -256,11 +256,11 @@ BOOST_AUTO_TEST_CASE(immutable) { "root.asm", 0 }, { "sub.asm", 1 } }; - Assembly _assembly; + Assembly _assembly{true, {}}; auto root_asm = make_shared("root.asm"); _assembly.setSourceLocation({1, 3, root_asm}); - Assembly _subAsm; + Assembly _subAsm{false, {}}; auto sub_asm = make_shared("sub.asm"); _subAsm.setSourceLocation({6, 8, sub_asm}); _subAsm.appendImmutable("someImmutable"); @@ -349,10 +349,10 @@ BOOST_AUTO_TEST_CASE(immutable) BOOST_AUTO_TEST_CASE(subobject_encode_decode) { - Assembly assembly; + Assembly assembly{true, {}}; - shared_ptr subAsmPtr = make_shared(); - shared_ptr subSubAsmPtr = make_shared(); + shared_ptr subAsmPtr = make_shared(false, string{}); + shared_ptr subSubAsmPtr = make_shared(false, string{}); assembly.appendSubroutine(subAsmPtr); subAsmPtr->appendSubroutine(subSubAsmPtr); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index c8bb93c41..278a7c77f 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1250,8 +1250,8 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) // tag unifications (due to block deduplication) is also // visible at the super-assembly. - Assembly main; - AssemblyPointer sub = make_shared(); + Assembly main{false, {}}; + AssemblyPointer sub = make_shared(true, string{}); sub->append(u256(1)); auto t1 = sub->newTag(); diff --git a/test/libsolidity/semanticTests/array/reusing_memory.sol b/test/libsolidity/semanticTests/array/reusing_memory.sol index ee91ce7f7..ba0ca8abd 100644 --- a/test/libsolidity/semanticTests/array/reusing_memory.sol +++ b/test/libsolidity/semanticTests/array/reusing_memory.sol @@ -26,6 +26,6 @@ contract Main { // compileViaYul: also // ---- // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 -// gas irOptimized: 113598 +// gas irOptimized: 113610 // gas legacy: 126596 // gas legacyOptimized: 113823 diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index cc303899a..21de2ac97 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 -// gas irOptimized: 443960 +// gas irOptimized: 444029 // gas legacy: 590683 // gas legacyOptimized: 448326 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index ffe0fb8c2..d5e633924 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 300804 +// gas irOptimized: 300885 // gas legacy: 428917 // gas legacyOptimized: 298128 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol index 685d8a7de..c4a65bb55 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol @@ -17,7 +17,7 @@ contract D { // compileViaYul: also // ---- // constructor(): 2 -> -// gas irOptimized: 203967 +// gas irOptimized: 203963 // gas legacy: 245842 // gas legacyOptimized: 195676 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol index a768a2836..7ed638418 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol @@ -18,7 +18,7 @@ contract D { // compileViaYul: also // ---- // constructor(): 2 -> -// gas irOptimized: 204130 +// gas irOptimized: 204126 // gas legacy: 246202 // gas legacyOptimized: 195914 // f() -> 2 diff --git a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol index e6f94bdcf..462de46a7 100644 --- a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol +++ b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol @@ -42,7 +42,7 @@ contract Main { // compileViaYul: also // ---- // constructor(), 22 wei -> -// gas irOptimized: 284287 +// gas irOptimized: 284283 // gas legacy: 402045 // gas legacyOptimized: 266772 // getFlag() -> true diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index 4ce8b5149..eb9d93ee2 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -22,6 +22,6 @@ contract A { // compileViaYul: also // ---- // f(), 10 ether -> 3007, 3008, 3009 -// gas irOptimized: 272413 +// gas irOptimized: 272449 // gas legacy: 422501 // gas legacyOptimized: 287472 diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 8986acc1b..679493f35 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -65,7 +65,7 @@ TestCase::TestResult EVMCodeTransformTest::run(ostream& _stream, string const& _ return TestResult::FatalError; } - evmasm::Assembly assembly; + evmasm::Assembly assembly{false, {}}; EthAssemblyAdapter adapter(assembly); EVMObjectCompiler::compile( *stack.parserResult(), diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index 82066bf52..094a84554 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -185,25 +185,27 @@ void FuzzerUtil::testConstantOptimizer(string const& _input, bool _quiet) if (!_quiet) cout << "Got " << numbers.size() << " inputs:" << endl; - Assembly assembly; - for (u256 const& n: numbers) - { - if (!_quiet) - cout << n << endl; - assembly.append(n); - } for (bool isCreation: {false, true}) + { + Assembly assembly{isCreation, {}}; + for (u256 const& n: numbers) + { + if (!_quiet) + cout << n << endl; + assembly.append(n); + } for (unsigned runs: {1u, 2u, 3u, 20u, 40u, 100u, 200u, 400u, 1000u}) { // Make a copy here so that each time we start with the original state. Assembly tmp = assembly; ConstantOptimisationMethod::optimiseConstants( - isCreation, - runs, - langutil::EVMVersion{}, - tmp + isCreation, + runs, + langutil::EVMVersion{}, + tmp ); } + } } void FuzzerUtil::testStandardCompiler(string const& _input, bool _quiet) From 0a9d752b8b9bd033a0a302ffe68b0c7e516cafe7 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 7 Mar 2022 13:06:58 +0100 Subject: [PATCH 2/5] Add test case and adjust tests. --- .../viair_subobject_optimization/args | 1 + .../viair_subobject_optimization/input.sol | 20 + .../viair_subobject_optimization/output | 379 ++++++++++++++++++ test/cmdlineTests/yul_optimize_runs/input.yul | 6 +- test/cmdlineTests/yul_optimize_runs/output | 25 +- .../semanticTests/array/reusing_memory.sol | 2 +- .../constructor/arrays_in_constructors.sol | 2 +- .../bytes_in_constructors_packer.sol | 2 +- .../creation_function_call_with_args.sol | 2 +- .../creation_function_call_with_salt.sol | 2 +- .../inheritance/value_for_constructor.sol | 2 +- .../salted_create_with_value.sol | 2 +- 12 files changed, 423 insertions(+), 22 deletions(-) create mode 100644 test/cmdlineTests/viair_subobject_optimization/args create mode 100644 test/cmdlineTests/viair_subobject_optimization/input.sol create mode 100644 test/cmdlineTests/viair_subobject_optimization/output diff --git a/test/cmdlineTests/viair_subobject_optimization/args b/test/cmdlineTests/viair_subobject_optimization/args new file mode 100644 index 000000000..51e6fa519 --- /dev/null +++ b/test/cmdlineTests/viair_subobject_optimization/args @@ -0,0 +1 @@ +--experimental-via-ir --optimize --asm \ No newline at end of file diff --git a/test/cmdlineTests/viair_subobject_optimization/input.sol b/test/cmdlineTests/viair_subobject_optimization/input.sol new file mode 100644 index 000000000..74549134a --- /dev/null +++ b/test/cmdlineTests/viair_subobject_optimization/input.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >0.0.0; + +contract C { + constructor(uint x) { + // In earlier versions of the compiler, the resulting assembly pushed the constant + // 0xFFFFFFFFFFFFFFFF42 directly in the subassembly of D, while it was optimized to + // ``sub(shl(0x48, 0x01), 0xbe)`` when C was compiled in isolation. + // Now the assembly is expected to contain two instances of ``sub(shl(0x48, 0x01), 0xbe)``, + // one in the creation code of ``C`` directly, one in a subassembly of ``D``. + // The constant 0xFFFFFFFFFFFFFFFF42 should not occur in the assembly output at all. + if (x == 0xFFFFFFFFFFFFFFFF42) + revert(); + } +} +contract D { + function f() public pure returns (bytes memory) { + return type(C).creationCode; + } +} diff --git a/test/cmdlineTests/viair_subobject_optimization/output b/test/cmdlineTests/viair_subobject_optimization/output new file mode 100644 index 000000000..8b5666b37 --- /dev/null +++ b/test/cmdlineTests/viair_subobject_optimization/output @@ -0,0 +1,379 @@ + +======= viair_subobject_optimization/input.sol:C ======= +EVM assembly: + /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_6, callvalue) + 0x1f + bytecodeSize + codesize + dup2 + swap1 + sub + swap2 + dup3 + add + not(0x1f) + and + dup4 + add + swap2 + sub(shl(0x40, 0x01), 0x01) + dup4 + gt + dup5 + dup5 + lt + or + tag_4 + jumpi + dup1 + dup5 + swap3 + 0x20 + swap5 + 0x40 + mstore + dup4 + codecopy + dup2 + add + sub + slt + tag_6 + jumpi + tag_8 + swap1 + mload + tag_1 + jump // in +tag_8: + mload(0x40) + dataSize(sub_0) + swap1 + dup2 + dataOffset(sub_0) + dup3 + codecopy + return +tag_6: + pop + 0x00 + dup1 + revert +tag_4: + pop + pop + pop + pop + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x41) + revert(0x00, 0x24) + /* "viair_subobject_optimization/input.sol":76:666 constructor(uint x) {... */ +tag_1: + sub(shl(0x48, 0x01), 0xbe) + /* "viair_subobject_optimization/input.sol":620:645 x == 0xFFFFFFFFFFFFFFFF42 */ + eq + /* "viair_subobject_optimization/input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ + tag_6 + jumpi + /* "viair_subobject_optimization/input.sol":76:666 constructor(uint x) {... */ + jump // out +stop + +sub_0: assembly { + /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + mstore(0x40, 0x80) + 0x00 + dup1 + revert + + auxdata: +} + + +======= viair_subobject_optimization/input.sol:D ======= +EVM assembly: + /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_1, callvalue) + dataSize(sub_0) + swap1 + dup2 + dataOffset(sub_0) + dup3 + codecopy + return +tag_1: + pop + 0x00 + dup1 + revert +stop + +sub_0: assembly { + /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_2, iszero(lt(calldatasize, 0x04))) + tag_3: + pop + 0x00 + dup1 + revert + tag_2: + 0x00 + swap1 + dup2 + calldataload + 0xe0 + shr + 0x26121ff0 + eq + tag_4 + jumpi + pop + jump(tag_3) + tag_4: + jumpi(tag_8, callvalue) + dup2 + add(calldatasize, not(0x03)) + slt + tag_8 + jumpi + /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ + dataSize(sub_0) + /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + 0x3f + dup2 + add + not(0x1f) + and + dup3 + add + 0xffffffffffffffff + dup2 + gt + dup4 + dup3 + lt + or + tag_10 + jumpi + tag_12 + swap4 + pop + 0x40 + mstore + /* "viair_subobject_optimization/input.sol":745:765 type(C).creationCode */ + dup1 + dup3 + mstore + dataOffset(sub_0) + 0x20 + dup4 + add + codecopy + /* "viair_subobject_optimization/input.sol":669:772 contract D {... */ + mload(0x40) + swap2 + dup3 + swap2 + dup3 + tag_1 + jump // in + tag_12: + sub + swap1 + return + tag_10: + pop + pop + shl(0xe0, 0x4e487b71) + dup3 + mstore + pop + mstore(0x04, 0x41) + 0x24 + swap1 + revert + tag_8: + pop + dup1 + revert + tag_1: + swap2 + swap1 + swap2 + 0x20 + dup1 + dup3 + mstore + dup4 + mload + swap1 + dup2 + dup2 + dup5 + add + mstore + 0x00 + swap5 + tag_13: + dup3 + dup7 + lt + tag_14 + jumpi + pop + pop + dup1 + 0x40 + swap4 + swap5 + gt + tag_16 + jumpi + tag_17: + 0x1f + add + not(0x1f) + and + add + add + swap1 + jump // out + tag_16: + 0x00 + dup4 + dup3 + dup5 + add + add + mstore + jump(tag_17) + tag_14: + dup6 + dup2 + add + dup3 + add + mload + dup5 + dup8 + add + 0x40 + add + mstore + swap5 + dup2 + add + swap5 + jump(tag_13) + stop + + sub_0: assembly { + /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + 0x80 + dup1 + 0x40 + mstore + jumpi(tag_6, callvalue) + 0x1f + bytecodeSize + codesize + dup2 + swap1 + sub + swap2 + dup3 + add + not(0x1f) + and + dup4 + add + swap2 + sub(shl(0x40, 0x01), 0x01) + dup4 + gt + dup5 + dup5 + lt + or + tag_4 + jumpi + dup1 + dup5 + swap3 + 0x20 + swap5 + 0x40 + mstore + dup4 + codecopy + dup2 + add + sub + slt + tag_6 + jumpi + tag_8 + swap1 + mload + tag_1 + jump // in + tag_8: + mload(0x40) + dataSize(sub_0) + swap1 + dup2 + dataOffset(sub_0) + dup3 + codecopy + return + tag_6: + pop + 0x00 + dup1 + revert + tag_4: + pop + pop + pop + pop + mstore(0x00, shl(0xe0, 0x4e487b71)) + mstore(0x04, 0x41) + revert(0x00, 0x24) + /* "viair_subobject_optimization/input.sol":76:666 constructor(uint x) {... */ + tag_1: + sub(shl(0x48, 0x01), 0xbe) + /* "viair_subobject_optimization/input.sol":620:645 x == 0xFFFFFFFFFFFFFFFF42 */ + eq + /* "viair_subobject_optimization/input.sol":616:661 if (x == 0xFFFFFFFFFFFFFFFF42)... */ + tag_6 + jumpi + /* "viair_subobject_optimization/input.sol":76:666 constructor(uint x) {... */ + jump // out + stop + + sub_0: assembly { + /* "viair_subobject_optimization/input.sol":61:668 contract C {... */ + mstore(0x40, 0x80) + 0x00 + dup1 + revert + + auxdata: + } + } + + auxdata: +} diff --git a/test/cmdlineTests/yul_optimize_runs/input.yul b/test/cmdlineTests/yul_optimize_runs/input.yul index 07c602a4a..6088853e6 100644 --- a/test/cmdlineTests/yul_optimize_runs/input.yul +++ b/test/cmdlineTests/yul_optimize_runs/input.yul @@ -1,10 +1,10 @@ object "RunsTest1" { code { // Deploy the contract - datacopy(0, dataoffset("Runtime"), datasize("Runtime")) - return(0, datasize("Runtime")) + datacopy(0, dataoffset("Runtime_deployed"), datasize("Runtime_deployed")) + return(0, datasize("Runtime_deployed")) } - object "Runtime" { + object "Runtime_deployed" { code { let funcSel := shl(224, 0xabc12345) sstore(0, funcSel) diff --git a/test/cmdlineTests/yul_optimize_runs/output b/test/cmdlineTests/yul_optimize_runs/output index 357c796ee..6f4ba8390 100644 --- a/test/cmdlineTests/yul_optimize_runs/output +++ b/test/cmdlineTests/yul_optimize_runs/output @@ -5,12 +5,12 @@ Pretty printed source: object "RunsTest1" { code { { - let _1 := datasize("Runtime") - datacopy(0, dataoffset("Runtime"), _1) + let _1 := datasize("Runtime_deployed") + datacopy(0, dataoffset("Runtime_deployed"), _1) return(0, _1) } } - object "Runtime" { + object "Runtime_deployed" { code { { sstore(0, 0xabc1234500000000000000000000000000000000000000000000000000000000) @@ -21,30 +21,31 @@ object "RunsTest1" { Binary representation: -600c80600c6000396000f3fe63abc1234560e01b60005500 +602580600c6000396000f3fe7fabc123450000000000000000000000000000000000000000000000000000000060005500 Text representation: - /* "yul_optimize_runs/input.yul":106:125 */ + /* "yul_optimize_runs/input.yul":115:143 */ dataSize(sub_0) - /* "yul_optimize_runs/input.yul":83:104 */ + /* "yul_optimize_runs/input.yul":83:113 */ dup1 dataOffset(sub_0) /* "yul_optimize_runs/input.yul":80:81 */ 0x00 - /* "yul_optimize_runs/input.yul":71:126 */ + /* "yul_optimize_runs/input.yul":71:144 */ codecopy /* "yul_optimize_runs/input.yul":80:81 */ 0x00 - /* "yul_optimize_runs/input.yul":135:165 */ + /* "yul_optimize_runs/input.yul":153:192 */ return stop sub_0: assembly { - shl(0xe0, 0xabc12345) - /* "yul_optimize_runs/input.yul":277:278 */ + /* "yul_optimize_runs/input.yul":273:293 */ + 0xabc1234500000000000000000000000000000000000000000000000000000000 + /* "yul_optimize_runs/input.yul":313:314 */ 0x00 - /* "yul_optimize_runs/input.yul":270:288 */ + /* "yul_optimize_runs/input.yul":306:324 */ sstore - /* "yul_optimize_runs/input.yul":208:298 */ + /* "yul_optimize_runs/input.yul":244:334 */ stop } diff --git a/test/libsolidity/semanticTests/array/reusing_memory.sol b/test/libsolidity/semanticTests/array/reusing_memory.sol index ba0ca8abd..7a05b5328 100644 --- a/test/libsolidity/semanticTests/array/reusing_memory.sol +++ b/test/libsolidity/semanticTests/array/reusing_memory.sol @@ -26,6 +26,6 @@ contract Main { // compileViaYul: also // ---- // f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1 -// gas irOptimized: 113610 +// gas irOptimized: 113613 // gas legacy: 126596 // gas legacyOptimized: 113823 diff --git a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol index 21de2ac97..031deb64c 100644 --- a/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol +++ b/test/libsolidity/semanticTests/constructor/arrays_in_constructors.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8 -// gas irOptimized: 444029 +// gas irOptimized: 443989 // gas legacy: 590683 // gas legacyOptimized: 448326 diff --git a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol index d5e633924..8264a93ed 100644 --- a/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol +++ b/test/libsolidity/semanticTests/constructor/bytes_in_constructors_packer.sol @@ -26,6 +26,6 @@ contract Creator { // compileViaYul: also // ---- // f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h" -// gas irOptimized: 300885 +// gas irOptimized: 300837 // gas legacy: 428917 // gas legacyOptimized: 298128 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol index c4a65bb55..0b9407814 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_args.sol @@ -17,7 +17,7 @@ contract D { // compileViaYul: also // ---- // constructor(): 2 -> -// gas irOptimized: 203963 +// gas irOptimized: 203982 // gas legacy: 245842 // gas legacyOptimized: 195676 // f() -> 2 diff --git a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol index 7ed638418..a4796ac82 100644 --- a/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol +++ b/test/libsolidity/semanticTests/functionCall/creation_function_call_with_salt.sol @@ -18,7 +18,7 @@ contract D { // compileViaYul: also // ---- // constructor(): 2 -> -// gas irOptimized: 204126 +// gas irOptimized: 204145 // gas legacy: 246202 // gas legacyOptimized: 195914 // f() -> 2 diff --git a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol index 462de46a7..aea318e65 100644 --- a/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol +++ b/test/libsolidity/semanticTests/inheritance/value_for_constructor.sol @@ -42,7 +42,7 @@ contract Main { // compileViaYul: also // ---- // constructor(), 22 wei -> -// gas irOptimized: 284283 +// gas irOptimized: 284321 // gas legacy: 402045 // gas legacyOptimized: 266772 // getFlag() -> true diff --git a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol index eb9d93ee2..780cc32b8 100644 --- a/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol +++ b/test/libsolidity/semanticTests/salted_create/salted_create_with_value.sol @@ -22,6 +22,6 @@ contract A { // compileViaYul: also // ---- // f(), 10 ether -> 3007, 3008, 3009 -// gas irOptimized: 272449 +// gas irOptimized: 272467 // gas legacy: 422501 // gas legacyOptimized: 287472 From b57e8564267d0aefdb8e9a71f89ccbf4dbbabd0c Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 7 Mar 2022 16:24:20 +0100 Subject: [PATCH 3/5] Adjust documentation. --- docs/yul.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/yul.rst b/docs/yul.rst index e4775ee4d..8a584db1d 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -1124,6 +1124,11 @@ regular strings in native encoding. For code, Above, ``Block`` refers to ``Block`` in the Yul code grammar explained in the previous chapter. +.. note:: + + An object with a name that ends in ``_deployed`` is treated as deployed code by the Yul optimizer. + The only consequence of this is a different gas cost heuristic in the optimizer. + .. note:: Data objects or sub-objects whose names contain a ``.`` can be defined @@ -1172,17 +1177,17 @@ An example Yul Object is shown below: // now return the runtime object (the currently // executing code is the constructor code) - size := datasize("runtime") + size := datasize("Contract1_deployed") offset := allocate(size) // This will turn into a memory->memory copy for Ewasm and // a codecopy for EVM - datacopy(offset, dataoffset("runtime"), size) + datacopy(offset, dataoffset("Contract1_deployed"), size) return(offset, size) } data "Table2" hex"4123" - object "runtime" { + object "Contract1_deployed" { code { function allocate(size) -> ptr { ptr := mload(0x40) @@ -1204,7 +1209,7 @@ An example Yul Object is shown below: // code here ... } - object "runtime" { + object "Contract2_deployed" { code { // code here ... } From e0c837b33b7c72d64572d42655f7d56769bcdefd Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 7 Mar 2022 17:39:52 +0100 Subject: [PATCH 4/5] Remove isCreation flag from OptimiserSettings. --- libevmasm/Assembly.cpp | 9 +++------ libevmasm/Assembly.h | 1 - libsolidity/codegen/CompilerContext.cpp | 3 +-- libyul/AssemblyStack.cpp | 3 +-- test/libevmasm/Optimiser.cpp | 3 +-- 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 492d434c8..6d7b97cc4 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -411,14 +411,11 @@ map const& Assembly::optimiseInternal( if (m_tagReplacements) return *m_tagReplacements; - assertThrow(_settings.isCreation == m_creation, OptimizerException, "Mismatching creation settings."); - // Run optimisation for sub-assemblies. for (size_t subId = 0; subId < m_subs.size(); ++subId) { OptimiserSettings settings = _settings; Assembly& sub = *m_subs[subId]; - settings.isCreation = sub.isCreation(); map const& subTagReplacements = sub.optimiseInternal( settings, JumpdestRemover::referencedTags(m_items, subId) @@ -438,7 +435,7 @@ map const& Assembly::optimiseInternal( m_items, _tagsReferencedFromOutside, _settings.expectedExecutionsPerDeployment, - _settings.isCreation, + isCreation(), _settings.evmVersion }.optimise(); @@ -539,8 +536,8 @@ map const& Assembly::optimiseInternal( if (_settings.runConstantOptimiser) ConstantOptimisationMethod::optimiseConstants( - _settings.isCreation, - _settings.isCreation ? 1 : _settings.expectedExecutionsPerDeployment, + isCreation(), + isCreation() ? 1 : _settings.expectedExecutionsPerDeployment, _settings.evmVersion, *this ); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 270d85480..11bc16662 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -117,7 +117,6 @@ public: struct OptimiserSettings { - bool isCreation = false; bool runInliner = false; bool runJumpdestRemover = false; bool runPeephole = false; diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 700f53d1f..a01dafc91 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -572,8 +572,7 @@ void CompilerContext::updateSourceLocation() evmasm::Assembly::OptimiserSettings CompilerContext::translateOptimiserSettings(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, false, m_evmVersion, 0}; - asmSettings.isCreation = true; + evmasm::Assembly::OptimiserSettings asmSettings{false, false, false, false, false, false, m_evmVersion, 0}; asmSettings.runInliner = _settings.runInliner; asmSettings.runJumpdestRemover = _settings.runJumpdestRemover; asmSettings.runPeephole = _settings.runPeephole; diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp index 5d0ddd81a..3fefb9caf 100644 --- a/libyul/AssemblyStack.cpp +++ b/libyul/AssemblyStack.cpp @@ -72,8 +72,7 @@ evmasm::Assembly::OptimiserSettings translateOptimiserSettings( ) { // Constructing it this way so that we notice changes in the fields. - evmasm::Assembly::OptimiserSettings asmSettings{false, false, false, false, false, false, false, _evmVersion, 0}; - asmSettings.isCreation = true; + evmasm::Assembly::OptimiserSettings asmSettings{false, false, false, false, false, false, _evmVersion, 0}; asmSettings.runInliner = _settings.runInliner; asmSettings.runJumpdestRemover = _settings.runJumpdestRemover; asmSettings.runPeephole = _settings.runPeephole; diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 278a7c77f..44fbde927 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -1278,7 +1278,6 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) main.append(u256(8)); Assembly::OptimiserSettings settings; - settings.isCreation = false; settings.runInliner = false; settings.runJumpdestRemover = true; settings.runPeephole = true; @@ -1287,7 +1286,7 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies) settings.runConstantOptimiser = true; settings.evmVersion = solidity::test::CommonOptions::get().evmVersion(); settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment; -; + main.optimise(settings); AssemblyItems expectationMain{ From e7a3814977c0ba0715e910068e5a0430e3b90770 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 9 Mar 2022 16:52:30 +0100 Subject: [PATCH 5/5] Unit test. --- test/libsolidity/SolidityEndToEndTest.cpp | 28 +++++++++++++++++++ .../SolidityExecutionFramework.cpp | 1 + test/libsolidity/SolidityExecutionFramework.h | 5 ++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 314d4283e..5a76a16c6 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -84,6 +84,34 @@ struct SolidityEndToEndTestExecutionFramework: public SolidityExecutionFramework BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, SolidityEndToEndTestExecutionFramework) +BOOST_AUTO_TEST_CASE(creation_code_optimizer) +{ + string codeC = R"( + contract C { + constructor(uint x) { + if (x == 0xFFFFFFFFFFFFFFFF42) + revert(); + } + } + )"; + string codeD = R"( + contract D { + function f() public pure returns (bytes memory) { + return type(C).creationCode; + } + } + )"; + + m_metadataHash = CompilerStack::MetadataHash::None; + ALSO_VIA_YUL({ + bytes bytecodeC = compileContract(codeC); + reset(); + compileAndRun(codeC + codeD); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x20, bytecodeC.size()) + encode(bytecodeC, false)); + m_doEwasmTestrun = false; + }) +} + unsigned constexpr roundTo32(unsigned _num) { return (_num + 31) / 32 * 32; diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index f3921613f..7ff226a69 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -62,6 +62,7 @@ bytes SolidityExecutionFramework::multiSourceCompileContract( m_compiler.enableEvmBytecodeGeneration(!m_compileViaYul); m_compiler.enableIRGeneration(m_compileViaYul); m_compiler.setRevertStringBehaviour(m_revertStrings); + m_compiler.setMetadataHash(m_metadataHash); if (!m_compiler.compile()) { // The testing framework expects an exception for diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index e0e02cf95..202addffa 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -75,11 +75,12 @@ public: /// the latter only if it is forced. static std::string addPreamble(std::string const& _sourceCode); protected: - - solidity::frontend::CompilerStack m_compiler; + using CompilerStack = solidity::frontend::CompilerStack; + CompilerStack m_compiler; bool m_compileViaYul = false; bool m_compileToEwasm = false; bool m_showMetadata = false; + CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS; RevertStrings m_revertStrings = RevertStrings::Default; };