mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #12748 from ethereum/markCreationAssembly
Store whether an evmasm Assembly is creation code.
This commit is contained in:
commit
efc00bef55
@ -8,6 +8,7 @@ Compiler Features:
|
|||||||
* JSON-AST: Added selector field for errors and events.
|
* JSON-AST: Added selector field for errors and events.
|
||||||
|
|
||||||
Bugfixes:
|
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)
|
### 0.8.12 (2022-02-16)
|
||||||
|
13
docs/yul.rst
13
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.
|
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::
|
.. note::
|
||||||
|
|
||||||
Data objects or sub-objects whose names contain a ``.`` can be defined
|
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
|
// now return the runtime object (the currently
|
||||||
// executing code is the constructor code)
|
// executing code is the constructor code)
|
||||||
size := datasize("runtime")
|
size := datasize("Contract1_deployed")
|
||||||
offset := allocate(size)
|
offset := allocate(size)
|
||||||
// This will turn into a memory->memory copy for Ewasm and
|
// This will turn into a memory->memory copy for Ewasm and
|
||||||
// a codecopy for EVM
|
// a codecopy for EVM
|
||||||
datacopy(offset, dataoffset("runtime"), size)
|
datacopy(offset, dataoffset("Contract1_deployed"), size)
|
||||||
return(offset, size)
|
return(offset, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
data "Table2" hex"4123"
|
data "Table2" hex"4123"
|
||||||
|
|
||||||
object "runtime" {
|
object "Contract1_deployed" {
|
||||||
code {
|
code {
|
||||||
function allocate(size) -> ptr {
|
function allocate(size) -> ptr {
|
||||||
ptr := mload(0x40)
|
ptr := mload(0x40)
|
||||||
@ -1204,7 +1209,7 @@ An example Yul Object is shown below:
|
|||||||
// code here ...
|
// code here ...
|
||||||
}
|
}
|
||||||
|
|
||||||
object "runtime" {
|
object "Contract2_deployed" {
|
||||||
code {
|
code {
|
||||||
// code here ...
|
// code here ...
|
||||||
}
|
}
|
||||||
|
@ -415,9 +415,8 @@ map<u256, u256> const& Assembly::optimiseInternal(
|
|||||||
for (size_t subId = 0; subId < m_subs.size(); ++subId)
|
for (size_t subId = 0; subId < m_subs.size(); ++subId)
|
||||||
{
|
{
|
||||||
OptimiserSettings settings = _settings;
|
OptimiserSettings settings = _settings;
|
||||||
// Disable creation mode for sub-assemblies.
|
Assembly& sub = *m_subs[subId];
|
||||||
settings.isCreation = false;
|
map<u256, u256> const& subTagReplacements = sub.optimiseInternal(
|
||||||
map<u256, u256> const& subTagReplacements = m_subs[subId]->optimiseInternal(
|
|
||||||
settings,
|
settings,
|
||||||
JumpdestRemover::referencedTags(m_items, subId)
|
JumpdestRemover::referencedTags(m_items, subId)
|
||||||
);
|
);
|
||||||
@ -436,7 +435,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
|
|||||||
m_items,
|
m_items,
|
||||||
_tagsReferencedFromOutside,
|
_tagsReferencedFromOutside,
|
||||||
_settings.expectedExecutionsPerDeployment,
|
_settings.expectedExecutionsPerDeployment,
|
||||||
_settings.isCreation,
|
isCreation(),
|
||||||
_settings.evmVersion
|
_settings.evmVersion
|
||||||
}.optimise();
|
}.optimise();
|
||||||
|
|
||||||
@ -537,8 +536,8 @@ map<u256, u256> const& Assembly::optimiseInternal(
|
|||||||
|
|
||||||
if (_settings.runConstantOptimiser)
|
if (_settings.runConstantOptimiser)
|
||||||
ConstantOptimisationMethod::optimiseConstants(
|
ConstantOptimisationMethod::optimiseConstants(
|
||||||
_settings.isCreation,
|
isCreation(),
|
||||||
_settings.isCreation ? 1 : _settings.expectedExecutionsPerDeployment,
|
isCreation() ? 1 : _settings.expectedExecutionsPerDeployment,
|
||||||
_settings.evmVersion,
|
_settings.evmVersion,
|
||||||
*this
|
*this
|
||||||
);
|
);
|
||||||
|
@ -48,7 +48,7 @@ using AssemblyPointer = std::shared_ptr<Assembly>;
|
|||||||
class Assembly
|
class Assembly
|
||||||
{
|
{
|
||||||
public:
|
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 newTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++); }
|
||||||
AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); }
|
AssemblyItem newPushTag() { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++); }
|
||||||
@ -117,7 +117,6 @@ public:
|
|||||||
|
|
||||||
struct OptimiserSettings
|
struct OptimiserSettings
|
||||||
{
|
{
|
||||||
bool isCreation = false;
|
|
||||||
bool runInliner = false;
|
bool runInliner = false;
|
||||||
bool runJumpdestRemover = false;
|
bool runJumpdestRemover = false;
|
||||||
bool runPeephole = false;
|
bool runPeephole = false;
|
||||||
@ -157,6 +156,8 @@ public:
|
|||||||
std::vector<size_t> decodeSubPath(size_t _subObjectId) const;
|
std::vector<size_t> decodeSubPath(size_t _subObjectId) const;
|
||||||
size_t encodeSubPath(std::vector<size_t> const& _subPath);
|
size_t encodeSubPath(std::vector<size_t> const& _subPath);
|
||||||
|
|
||||||
|
bool isCreation() const { return m_creation; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Does the same operations as @a optimise, but should only be applied to a sub and
|
/// 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
|
/// returns the replaced tags. Also takes an argument containing the tags of this assembly
|
||||||
@ -214,6 +215,8 @@ protected:
|
|||||||
mutable std::vector<size_t> m_tagPositionsInBytecode;
|
mutable std::vector<size_t> m_tagPositionsInBytecode;
|
||||||
|
|
||||||
int m_deposit = 0;
|
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
|
/// Internal name of the assembly object, only used with the Yul backend
|
||||||
/// currently
|
/// currently
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
@ -572,8 +572,7 @@ void CompilerContext::updateSourceLocation()
|
|||||||
evmasm::Assembly::OptimiserSettings CompilerContext::translateOptimiserSettings(OptimiserSettings const& _settings)
|
evmasm::Assembly::OptimiserSettings CompilerContext::translateOptimiserSettings(OptimiserSettings const& _settings)
|
||||||
{
|
{
|
||||||
// Constructing it this way so that we notice changes in the fields.
|
// 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};
|
evmasm::Assembly::OptimiserSettings asmSettings{false, false, false, false, false, false, m_evmVersion, 0};
|
||||||
asmSettings.isCreation = true;
|
|
||||||
asmSettings.runInliner = _settings.runInliner;
|
asmSettings.runInliner = _settings.runInliner;
|
||||||
asmSettings.runJumpdestRemover = _settings.runJumpdestRemover;
|
asmSettings.runJumpdestRemover = _settings.runJumpdestRemover;
|
||||||
asmSettings.runPeephole = _settings.runPeephole;
|
asmSettings.runPeephole = _settings.runPeephole;
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
RevertStrings _revertStrings,
|
RevertStrings _revertStrings,
|
||||||
CompilerContext* _runtimeContext = nullptr
|
CompilerContext* _runtimeContext = nullptr
|
||||||
):
|
):
|
||||||
m_asm(std::make_shared<evmasm::Assembly>()),
|
m_asm(std::make_shared<evmasm::Assembly>(_runtimeContext != nullptr, std::string{})),
|
||||||
m_evmVersion(_evmVersion),
|
m_evmVersion(_evmVersion),
|
||||||
m_revertStrings(_revertStrings),
|
m_revertStrings(_revertStrings),
|
||||||
m_reservedMemory{0},
|
m_reservedMemory{0},
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
#include <libevmasm/Assembly.h>
|
#include <libevmasm/Assembly.h>
|
||||||
#include <liblangutil/Scanner.h>
|
#include <liblangutil/Scanner.h>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -71,8 +72,7 @@ evmasm::Assembly::OptimiserSettings translateOptimiserSettings(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Constructing it this way so that we notice changes in the fields.
|
// 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};
|
evmasm::Assembly::OptimiserSettings asmSettings{false, false, false, false, false, false, _evmVersion, 0};
|
||||||
asmSettings.isCreation = true;
|
|
||||||
asmSettings.runInliner = _settings.runInliner;
|
asmSettings.runInliner = _settings.runInliner;
|
||||||
asmSettings.runJumpdestRemover = _settings.runJumpdestRemover;
|
asmSettings.runJumpdestRemover = _settings.runJumpdestRemover;
|
||||||
asmSettings.runPeephole = _settings.runPeephole;
|
asmSettings.runPeephole = _settings.runPeephole;
|
||||||
@ -194,7 +194,10 @@ void AssemblyStack::optimize(Object& _object, bool _isCreation)
|
|||||||
yulAssert(_object.analysisInfo, "");
|
yulAssert(_object.analysisInfo, "");
|
||||||
for (auto& subNode: _object.subObjects)
|
for (auto& subNode: _object.subObjects)
|
||||||
if (auto subObject = dynamic_cast<Object*>(subNode.get()))
|
if (auto subObject = dynamic_cast<Object*>(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);
|
Dialect const& dialect = languageToDialect(m_language, m_evmVersion);
|
||||||
unique_ptr<GasMeter> meter;
|
unique_ptr<GasMeter> meter;
|
||||||
@ -281,7 +284,7 @@ AssemblyStack::assembleEVMWithDeployed(optional<string_view> _deployName) const
|
|||||||
yulAssert(m_parserResult->code, "");
|
yulAssert(m_parserResult->code, "");
|
||||||
yulAssert(m_parserResult->analysisInfo, "");
|
yulAssert(m_parserResult->analysisInfo, "");
|
||||||
|
|
||||||
evmasm::Assembly assembly;
|
evmasm::Assembly assembly(true, {});
|
||||||
EthAssemblyAdapter adapter(assembly);
|
EthAssemblyAdapter adapter(assembly);
|
||||||
compileEVM(adapter, m_optimiserSettings.optimizeStackAllocation);
|
compileEVM(adapter, m_optimiserSettings.optimizeStackAllocation);
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ public:
|
|||||||
/// Append the assembled size as a constant.
|
/// Append the assembled size as a constant.
|
||||||
virtual void appendAssemblySize() = 0;
|
virtual void appendAssemblySize() = 0;
|
||||||
/// Creates a new sub-assembly, which can be referenced using dataSize and dataOffset.
|
/// Creates a new sub-assembly, which can be referenced using dataSize and dataOffset.
|
||||||
virtual std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(std::string _name = "") = 0;
|
virtual std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(bool _creation, std::string _name = "") = 0;
|
||||||
/// Appends the offset of the given sub-assembly or data.
|
/// Appends the offset of the given sub-assembly or data.
|
||||||
virtual void appendDataOffset(std::vector<SubID> const& _subPath) = 0;
|
virtual void appendDataOffset(std::vector<SubID> const& _subPath) = 0;
|
||||||
/// Appends the size of the given sub-assembly or data.
|
/// Appends the size of the given sub-assembly or data.
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include <libyul/Object.h>
|
#include <libyul/Object.h>
|
||||||
#include <libyul/Exceptions.h>
|
#include <libyul/Exceptions.h>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
using namespace solidity::yul;
|
using namespace solidity::yul;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -48,7 +50,8 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize)
|
|||||||
for (auto const& subNode: _object.subObjects)
|
for (auto const& subNode: _object.subObjects)
|
||||||
if (auto* subObject = dynamic_cast<Object*>(subNode.get()))
|
if (auto* subObject = dynamic_cast<Object*>(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;
|
context.subIDs[subObject->name] = subAssemblyAndID.second;
|
||||||
subObject->subId = subAssemblyAndID.second;
|
subObject->subId = subAssemblyAndID.second;
|
||||||
compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize);
|
compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize);
|
||||||
|
@ -122,9 +122,9 @@ void EthAssemblyAdapter::appendAssemblySize()
|
|||||||
m_assembly.appendProgramSize();
|
m_assembly.appendProgramSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(string _name)
|
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, string _name)
|
||||||
{
|
{
|
||||||
shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>(std::move(_name))};
|
shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>(_creation, std::move(_name))};
|
||||||
auto sub = m_assembly.newSub(assembly);
|
auto sub = m_assembly.newSub(assembly);
|
||||||
return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())};
|
return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())};
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ public:
|
|||||||
void appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) override;
|
void appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _jumpType) override;
|
||||||
void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override;
|
void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override;
|
||||||
void appendAssemblySize() override;
|
void appendAssemblySize() override;
|
||||||
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(std::string _name = {}) override;
|
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(bool _creation, std::string _name = {}) override;
|
||||||
void appendDataOffset(std::vector<SubID> const& _subPath) override;
|
void appendDataOffset(std::vector<SubID> const& _subPath) override;
|
||||||
void appendDataSize(std::vector<SubID> const& _subPath) override;
|
void appendDataSize(std::vector<SubID> const& _subPath) override;
|
||||||
SubID appendData(bytes const& _data) override;
|
SubID appendData(bytes const& _data) override;
|
||||||
|
@ -98,7 +98,7 @@ void NoOutputAssembly::appendAssemblySize()
|
|||||||
appendInstruction(evmasm::Instruction::PUSH1);
|
appendInstruction(evmasm::Instruction::PUSH1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(std::string)
|
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly(bool, std::string)
|
||||||
{
|
{
|
||||||
yulAssert(false, "Sub assemblies not implemented.");
|
yulAssert(false, "Sub assemblies not implemented.");
|
||||||
return {};
|
return {};
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override;
|
void appendJumpToIf(LabelID _labelId, JumpType _jumpType) override;
|
||||||
|
|
||||||
void appendAssemblySize() override;
|
void appendAssemblySize() override;
|
||||||
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(std::string _name = "") override;
|
std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly(bool _creation, std::string _name = "") override;
|
||||||
void appendDataOffset(std::vector<SubID> const& _subPath) override;
|
void appendDataOffset(std::vector<SubID> const& _subPath) override;
|
||||||
void appendDataSize(std::vector<SubID> const& _subPath) override;
|
void appendDataSize(std::vector<SubID> const& _subPath) override;
|
||||||
SubID appendData(bytes const& _data) override;
|
SubID appendData(bytes const& _data) override;
|
||||||
|
1
test/cmdlineTests/viair_subobject_optimization/args
Normal file
1
test/cmdlineTests/viair_subobject_optimization/args
Normal file
@ -0,0 +1 @@
|
|||||||
|
--experimental-via-ir --optimize --asm
|
20
test/cmdlineTests/viair_subobject_optimization/input.sol
Normal file
20
test/cmdlineTests/viair_subobject_optimization/input.sol
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
379
test/cmdlineTests/viair_subobject_optimization/output
Normal file
379
test/cmdlineTests/viair_subobject_optimization/output
Normal file
@ -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: <AUXDATA REMOVED>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
======= 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 REMOVED>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auxdata: <AUXDATA REMOVED>
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
object "RunsTest1" {
|
object "RunsTest1" {
|
||||||
code {
|
code {
|
||||||
// Deploy the contract
|
// Deploy the contract
|
||||||
datacopy(0, dataoffset("Runtime"), datasize("Runtime"))
|
datacopy(0, dataoffset("Runtime_deployed"), datasize("Runtime_deployed"))
|
||||||
return(0, datasize("Runtime"))
|
return(0, datasize("Runtime_deployed"))
|
||||||
}
|
}
|
||||||
object "Runtime" {
|
object "Runtime_deployed" {
|
||||||
code {
|
code {
|
||||||
let funcSel := shl(224, 0xabc12345)
|
let funcSel := shl(224, 0xabc12345)
|
||||||
sstore(0, funcSel)
|
sstore(0, funcSel)
|
||||||
|
@ -5,12 +5,12 @@ Pretty printed source:
|
|||||||
object "RunsTest1" {
|
object "RunsTest1" {
|
||||||
code {
|
code {
|
||||||
{
|
{
|
||||||
let _1 := datasize("Runtime")
|
let _1 := datasize("Runtime_deployed")
|
||||||
datacopy(0, dataoffset("Runtime"), _1)
|
datacopy(0, dataoffset("Runtime_deployed"), _1)
|
||||||
return(0, _1)
|
return(0, _1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
object "Runtime" {
|
object "Runtime_deployed" {
|
||||||
code {
|
code {
|
||||||
{
|
{
|
||||||
sstore(0, 0xabc1234500000000000000000000000000000000000000000000000000000000)
|
sstore(0, 0xabc1234500000000000000000000000000000000000000000000000000000000)
|
||||||
@ -24,28 +24,28 @@ Binary representation:
|
|||||||
602580600c6000396000f3fe7fabc123450000000000000000000000000000000000000000000000000000000060005500
|
602580600c6000396000f3fe7fabc123450000000000000000000000000000000000000000000000000000000060005500
|
||||||
|
|
||||||
Text representation:
|
Text representation:
|
||||||
/* "yul_optimize_runs/input.yul":106:125 */
|
/* "yul_optimize_runs/input.yul":115:143 */
|
||||||
dataSize(sub_0)
|
dataSize(sub_0)
|
||||||
/* "yul_optimize_runs/input.yul":83:104 */
|
/* "yul_optimize_runs/input.yul":83:113 */
|
||||||
dup1
|
dup1
|
||||||
dataOffset(sub_0)
|
dataOffset(sub_0)
|
||||||
/* "yul_optimize_runs/input.yul":80:81 */
|
/* "yul_optimize_runs/input.yul":80:81 */
|
||||||
0x00
|
0x00
|
||||||
/* "yul_optimize_runs/input.yul":71:126 */
|
/* "yul_optimize_runs/input.yul":71:144 */
|
||||||
codecopy
|
codecopy
|
||||||
/* "yul_optimize_runs/input.yul":80:81 */
|
/* "yul_optimize_runs/input.yul":80:81 */
|
||||||
0x00
|
0x00
|
||||||
/* "yul_optimize_runs/input.yul":135:165 */
|
/* "yul_optimize_runs/input.yul":153:192 */
|
||||||
return
|
return
|
||||||
stop
|
stop
|
||||||
|
|
||||||
sub_0: assembly {
|
sub_0: assembly {
|
||||||
/* "yul_optimize_runs/input.yul":237:257 */
|
/* "yul_optimize_runs/input.yul":273:293 */
|
||||||
0xabc1234500000000000000000000000000000000000000000000000000000000
|
0xabc1234500000000000000000000000000000000000000000000000000000000
|
||||||
/* "yul_optimize_runs/input.yul":277:278 */
|
/* "yul_optimize_runs/input.yul":313:314 */
|
||||||
0x00
|
0x00
|
||||||
/* "yul_optimize_runs/input.yul":270:288 */
|
/* "yul_optimize_runs/input.yul":306:324 */
|
||||||
sstore
|
sstore
|
||||||
/* "yul_optimize_runs/input.yul":208:298 */
|
/* "yul_optimize_runs/input.yul":244:334 */
|
||||||
stop
|
stop
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,11 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
|
|||||||
{ "root.asm", 0 },
|
{ "root.asm", 0 },
|
||||||
{ "sub.asm", 1 }
|
{ "sub.asm", 1 }
|
||||||
};
|
};
|
||||||
Assembly _assembly;
|
Assembly _assembly{false, {}};
|
||||||
auto root_asm = make_shared<string>("root.asm");
|
auto root_asm = make_shared<string>("root.asm");
|
||||||
_assembly.setSourceLocation({1, 3, root_asm});
|
_assembly.setSourceLocation({1, 3, root_asm});
|
||||||
|
|
||||||
Assembly _subAsm;
|
Assembly _subAsm{false, {}};
|
||||||
auto sub_asm = make_shared<string>("sub.asm");
|
auto sub_asm = make_shared<string>("sub.asm");
|
||||||
_subAsm.setSourceLocation({6, 8, sub_asm});
|
_subAsm.setSourceLocation({6, 8, sub_asm});
|
||||||
// PushImmutable
|
// PushImmutable
|
||||||
@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps)
|
|||||||
{ *subName, 1 }
|
{ *subName, 1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
auto subAsm = make_shared<Assembly>();
|
auto subAsm = make_shared<Assembly>(false, string{});
|
||||||
for (char i = 0; i < numImmutables; ++i)
|
for (char i = 0; i < numImmutables; ++i)
|
||||||
{
|
{
|
||||||
for (int r = 0; r < numActualRefs; ++r)
|
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)
|
for (char i = 1; i <= numImmutables; ++i)
|
||||||
{
|
{
|
||||||
assembly.setSourceLocation({10*i, 10*i + 3+i, assemblyName});
|
assembly.setSourceLocation({10*i, 10*i + 3+i, assemblyName});
|
||||||
@ -256,11 +256,11 @@ BOOST_AUTO_TEST_CASE(immutable)
|
|||||||
{ "root.asm", 0 },
|
{ "root.asm", 0 },
|
||||||
{ "sub.asm", 1 }
|
{ "sub.asm", 1 }
|
||||||
};
|
};
|
||||||
Assembly _assembly;
|
Assembly _assembly{true, {}};
|
||||||
auto root_asm = make_shared<string>("root.asm");
|
auto root_asm = make_shared<string>("root.asm");
|
||||||
_assembly.setSourceLocation({1, 3, root_asm});
|
_assembly.setSourceLocation({1, 3, root_asm});
|
||||||
|
|
||||||
Assembly _subAsm;
|
Assembly _subAsm{false, {}};
|
||||||
auto sub_asm = make_shared<string>("sub.asm");
|
auto sub_asm = make_shared<string>("sub.asm");
|
||||||
_subAsm.setSourceLocation({6, 8, sub_asm});
|
_subAsm.setSourceLocation({6, 8, sub_asm});
|
||||||
_subAsm.appendImmutable("someImmutable");
|
_subAsm.appendImmutable("someImmutable");
|
||||||
@ -349,10 +349,10 @@ BOOST_AUTO_TEST_CASE(immutable)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(subobject_encode_decode)
|
BOOST_AUTO_TEST_CASE(subobject_encode_decode)
|
||||||
{
|
{
|
||||||
Assembly assembly;
|
Assembly assembly{true, {}};
|
||||||
|
|
||||||
shared_ptr<Assembly> subAsmPtr = make_shared<Assembly>();
|
shared_ptr<Assembly> subAsmPtr = make_shared<Assembly>(false, string{});
|
||||||
shared_ptr<Assembly> subSubAsmPtr = make_shared<Assembly>();
|
shared_ptr<Assembly> subSubAsmPtr = make_shared<Assembly>(false, string{});
|
||||||
|
|
||||||
assembly.appendSubroutine(subAsmPtr);
|
assembly.appendSubroutine(subAsmPtr);
|
||||||
subAsmPtr->appendSubroutine(subSubAsmPtr);
|
subAsmPtr->appendSubroutine(subSubAsmPtr);
|
||||||
|
@ -1250,8 +1250,8 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies)
|
|||||||
// tag unifications (due to block deduplication) is also
|
// tag unifications (due to block deduplication) is also
|
||||||
// visible at the super-assembly.
|
// visible at the super-assembly.
|
||||||
|
|
||||||
Assembly main;
|
Assembly main{false, {}};
|
||||||
AssemblyPointer sub = make_shared<Assembly>();
|
AssemblyPointer sub = make_shared<Assembly>(true, string{});
|
||||||
|
|
||||||
sub->append(u256(1));
|
sub->append(u256(1));
|
||||||
auto t1 = sub->newTag();
|
auto t1 = sub->newTag();
|
||||||
@ -1278,7 +1278,6 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies)
|
|||||||
main.append(u256(8));
|
main.append(u256(8));
|
||||||
|
|
||||||
Assembly::OptimiserSettings settings;
|
Assembly::OptimiserSettings settings;
|
||||||
settings.isCreation = false;
|
|
||||||
settings.runInliner = false;
|
settings.runInliner = false;
|
||||||
settings.runJumpdestRemover = true;
|
settings.runJumpdestRemover = true;
|
||||||
settings.runPeephole = true;
|
settings.runPeephole = true;
|
||||||
@ -1287,7 +1286,7 @@ BOOST_AUTO_TEST_CASE(jumpdest_removal_subassemblies)
|
|||||||
settings.runConstantOptimiser = true;
|
settings.runConstantOptimiser = true;
|
||||||
settings.evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
settings.evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
||||||
settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment;
|
settings.expectedExecutionsPerDeployment = OptimiserSettings{}.expectedExecutionsPerDeployment;
|
||||||
;
|
|
||||||
main.optimise(settings);
|
main.optimise(settings);
|
||||||
|
|
||||||
AssemblyItems expectationMain{
|
AssemblyItems expectationMain{
|
||||||
|
@ -84,6 +84,34 @@ struct SolidityEndToEndTestExecutionFramework: public SolidityExecutionFramework
|
|||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, SolidityEndToEndTestExecutionFramework)
|
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)
|
unsigned constexpr roundTo32(unsigned _num)
|
||||||
{
|
{
|
||||||
return (_num + 31) / 32 * 32;
|
return (_num + 31) / 32 * 32;
|
||||||
|
@ -62,6 +62,7 @@ bytes SolidityExecutionFramework::multiSourceCompileContract(
|
|||||||
m_compiler.enableEvmBytecodeGeneration(!m_compileViaYul);
|
m_compiler.enableEvmBytecodeGeneration(!m_compileViaYul);
|
||||||
m_compiler.enableIRGeneration(m_compileViaYul);
|
m_compiler.enableIRGeneration(m_compileViaYul);
|
||||||
m_compiler.setRevertStringBehaviour(m_revertStrings);
|
m_compiler.setRevertStringBehaviour(m_revertStrings);
|
||||||
|
m_compiler.setMetadataHash(m_metadataHash);
|
||||||
if (!m_compiler.compile())
|
if (!m_compiler.compile())
|
||||||
{
|
{
|
||||||
// The testing framework expects an exception for
|
// The testing framework expects an exception for
|
||||||
|
@ -75,11 +75,12 @@ public:
|
|||||||
/// the latter only if it is forced.
|
/// the latter only if it is forced.
|
||||||
static std::string addPreamble(std::string const& _sourceCode);
|
static std::string addPreamble(std::string const& _sourceCode);
|
||||||
protected:
|
protected:
|
||||||
|
using CompilerStack = solidity::frontend::CompilerStack;
|
||||||
solidity::frontend::CompilerStack m_compiler;
|
CompilerStack m_compiler;
|
||||||
bool m_compileViaYul = false;
|
bool m_compileViaYul = false;
|
||||||
bool m_compileToEwasm = false;
|
bool m_compileToEwasm = false;
|
||||||
bool m_showMetadata = false;
|
bool m_showMetadata = false;
|
||||||
|
CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS;
|
||||||
RevertStrings m_revertStrings = RevertStrings::Default;
|
RevertStrings m_revertStrings = RevertStrings::Default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,6 +26,6 @@ contract Main {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1
|
// f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1
|
||||||
// gas irOptimized: 113598
|
// gas irOptimized: 113613
|
||||||
// gas legacy: 126596
|
// gas legacy: 126596
|
||||||
// gas legacyOptimized: 113823
|
// gas legacyOptimized: 113823
|
||||||
|
@ -26,6 +26,6 @@ contract Creator {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8
|
// f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8
|
||||||
// gas irOptimized: 443960
|
// gas irOptimized: 443989
|
||||||
// gas legacy: 590683
|
// gas legacy: 590683
|
||||||
// gas legacyOptimized: 448326
|
// gas legacyOptimized: 448326
|
||||||
|
@ -26,6 +26,6 @@ contract Creator {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h"
|
// f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h"
|
||||||
// gas irOptimized: 300804
|
// gas irOptimized: 300837
|
||||||
// gas legacy: 428917
|
// gas legacy: 428917
|
||||||
// gas legacyOptimized: 298128
|
// gas legacyOptimized: 298128
|
||||||
|
@ -17,7 +17,7 @@ contract D {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// constructor(): 2 ->
|
// constructor(): 2 ->
|
||||||
// gas irOptimized: 203967
|
// gas irOptimized: 203982
|
||||||
// gas legacy: 245842
|
// gas legacy: 245842
|
||||||
// gas legacyOptimized: 195676
|
// gas legacyOptimized: 195676
|
||||||
// f() -> 2
|
// f() -> 2
|
||||||
|
@ -18,7 +18,7 @@ contract D {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// constructor(): 2 ->
|
// constructor(): 2 ->
|
||||||
// gas irOptimized: 204130
|
// gas irOptimized: 204145
|
||||||
// gas legacy: 246202
|
// gas legacy: 246202
|
||||||
// gas legacyOptimized: 195914
|
// gas legacyOptimized: 195914
|
||||||
// f() -> 2
|
// f() -> 2
|
||||||
|
@ -42,7 +42,7 @@ contract Main {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// constructor(), 22 wei ->
|
// constructor(), 22 wei ->
|
||||||
// gas irOptimized: 284287
|
// gas irOptimized: 284321
|
||||||
// gas legacy: 402045
|
// gas legacy: 402045
|
||||||
// gas legacyOptimized: 266772
|
// gas legacyOptimized: 266772
|
||||||
// getFlag() -> true
|
// getFlag() -> true
|
||||||
|
@ -22,6 +22,6 @@ contract A {
|
|||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
// f(), 10 ether -> 3007, 3008, 3009
|
// f(), 10 ether -> 3007, 3008, 3009
|
||||||
// gas irOptimized: 272413
|
// gas irOptimized: 272467
|
||||||
// gas legacy: 422501
|
// gas legacy: 422501
|
||||||
// gas legacyOptimized: 287472
|
// gas legacyOptimized: 287472
|
||||||
|
@ -65,7 +65,7 @@ TestCase::TestResult EVMCodeTransformTest::run(ostream& _stream, string const& _
|
|||||||
return TestResult::FatalError;
|
return TestResult::FatalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
evmasm::Assembly assembly;
|
evmasm::Assembly assembly{false, {}};
|
||||||
EthAssemblyAdapter adapter(assembly);
|
EthAssemblyAdapter adapter(assembly);
|
||||||
EVMObjectCompiler::compile(
|
EVMObjectCompiler::compile(
|
||||||
*stack.parserResult(),
|
*stack.parserResult(),
|
||||||
|
@ -185,25 +185,27 @@ void FuzzerUtil::testConstantOptimizer(string const& _input, bool _quiet)
|
|||||||
if (!_quiet)
|
if (!_quiet)
|
||||||
cout << "Got " << numbers.size() << " inputs:" << endl;
|
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})
|
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})
|
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.
|
// Make a copy here so that each time we start with the original state.
|
||||||
Assembly tmp = assembly;
|
Assembly tmp = assembly;
|
||||||
ConstantOptimisationMethod::optimiseConstants(
|
ConstantOptimisationMethod::optimiseConstants(
|
||||||
isCreation,
|
isCreation,
|
||||||
runs,
|
runs,
|
||||||
langutil::EVMVersion{},
|
langutil::EVMVersion{},
|
||||||
tmp
|
tmp
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuzzerUtil::testStandardCompiler(string const& _input, bool _quiet)
|
void FuzzerUtil::testStandardCompiler(string const& _input, bool _quiet)
|
||||||
|
Loading…
Reference in New Issue
Block a user