mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Purge using namespace std
This commit is contained in:
parent
5d7533b540
commit
a9c8b4b4d1
@ -51,11 +51,11 @@ To set indentation and tab width settings uniformly, the repository contains an
|
|||||||
## 1. Namespaces
|
## 1. Namespaces
|
||||||
|
|
||||||
1. No `using namespace` declarations in header files.
|
1. No `using namespace` declarations in header files.
|
||||||
2. Use `using namespace std;` in cpp files, but avoid importing namespaces from boost and others.
|
2. `using namespace solidity;` and other project local namespaces is fine in cpp files, and generally encouraged.
|
||||||
3. All symbols should be declared in a namespace except for final applications.
|
3. Avoid `using namespace` at file level for third party libraries, such as boost, ranges, etc.
|
||||||
4. Use anonymous namespaces for helpers whose scope is a cpp file only.
|
4. All symbols should be declared in a namespace except for final applications.
|
||||||
5. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
|
5. Use anonymous namespaces for helpers whose scope is a cpp file only.
|
||||||
6. Do not use `std::` qualifier in cpp files (see 2.), except for `std::move` and `std::forward`, which will otherwise cause the `check_style` step to fail.
|
6. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
|
||||||
|
|
||||||
Only in the header:
|
Only in the header:
|
||||||
```cpp
|
```cpp
|
||||||
@ -66,16 +66,6 @@ std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Only in the cpp file:
|
|
||||||
```cpp
|
|
||||||
#include <cassert>
|
|
||||||
using namespace std;
|
|
||||||
tuple<float, float> myNamespace::meanAndSigma(vector<float> const& _v)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. Preprocessor
|
## 2. Preprocessor
|
||||||
|
|
||||||
1. File comment is always at top, and includes:
|
1. File comment is always at top, and includes:
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
@ -77,7 +76,7 @@ unsigned Assembly::codeSize(unsigned subTagSize) const
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location)
|
std::string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location)
|
||||||
{
|
{
|
||||||
if (!_location.hasText() || _sourceCodes.empty())
|
if (!_location.hasText() || _sourceCodes.empty())
|
||||||
return {};
|
return {};
|
||||||
@ -92,7 +91,7 @@ string locationFromSources(StringMap const& _sourceCodes, SourceLocation const&
|
|||||||
class Functionalizer
|
class Functionalizer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Functionalizer (ostream& _out, string const& _prefix, StringMap const& _sourceCodes, Assembly const& _assembly):
|
Functionalizer (std::ostream& _out, std::string const& _prefix, StringMap const& _sourceCodes, Assembly const& _assembly):
|
||||||
m_out(_out), m_prefix(_prefix), m_sourceCodes(_sourceCodes), m_assembly(_assembly)
|
m_out(_out), m_prefix(_prefix), m_sourceCodes(_sourceCodes), m_assembly(_assembly)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -105,7 +104,7 @@ public:
|
|||||||
printLocation(_debugInfoSelection);
|
printLocation(_debugInfoSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
string expression = _item.toAssemblyText(m_assembly);
|
std::string expression = _item.toAssemblyText(m_assembly);
|
||||||
|
|
||||||
if (!(
|
if (!(
|
||||||
_item.canBeFunctional() &&
|
_item.canBeFunctional() &&
|
||||||
@ -114,7 +113,7 @@ public:
|
|||||||
))
|
))
|
||||||
{
|
{
|
||||||
flush();
|
flush();
|
||||||
m_out << m_prefix << (_item.type() == Tag ? "" : " ") << expression << endl;
|
m_out << m_prefix << (_item.type() == Tag ? "" : " ") << expression << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_item.arguments() > 0)
|
if (_item.arguments() > 0)
|
||||||
@ -137,8 +136,8 @@ public:
|
|||||||
|
|
||||||
void flush()
|
void flush()
|
||||||
{
|
{
|
||||||
for (string const& expression: m_pending)
|
for (std::string const& expression: m_pending)
|
||||||
m_out << m_prefix << " " << expression << endl;
|
m_out << m_prefix << " " << expression << std::endl;
|
||||||
m_pending.clear();
|
m_pending.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +153,7 @@ public:
|
|||||||
if (m_location.sourceName)
|
if (m_location.sourceName)
|
||||||
m_out << " " + escapeAndQuoteString(*m_location.sourceName);
|
m_out << " " + escapeAndQuoteString(*m_location.sourceName);
|
||||||
if (m_location.hasText())
|
if (m_location.hasText())
|
||||||
m_out << ":" << to_string(m_location.start) + ":" + to_string(m_location.end);
|
m_out << ":" << std::to_string(m_location.start) + ":" + std::to_string(m_location.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_debugInfoSelection.snippet)
|
if (_debugInfoSelection.snippet)
|
||||||
@ -165,15 +164,15 @@ public:
|
|||||||
m_out << locationFromSources(m_sourceCodes, m_location);
|
m_out << locationFromSources(m_sourceCodes, m_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_out << " */" << endl;
|
m_out << " */" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
strings m_pending;
|
strings m_pending;
|
||||||
SourceLocation m_location;
|
SourceLocation m_location;
|
||||||
|
|
||||||
ostream& m_out;
|
std::ostream& m_out;
|
||||||
string const& m_prefix;
|
std::string const& m_prefix;
|
||||||
StringMap const& m_sourceCodes;
|
StringMap const& m_sourceCodes;
|
||||||
Assembly const& m_assembly;
|
Assembly const& m_assembly;
|
||||||
};
|
};
|
||||||
@ -181,9 +180,9 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Assembly::assemblyStream(
|
void Assembly::assemblyStream(
|
||||||
ostream& _out,
|
std::ostream& _out,
|
||||||
DebugInfoSelection const& _debugInfoSelection,
|
DebugInfoSelection const& _debugInfoSelection,
|
||||||
string const& _prefix,
|
std::string const& _prefix,
|
||||||
StringMap const& _sourceCodes
|
StringMap const& _sourceCodes
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
@ -195,34 +194,34 @@ void Assembly::assemblyStream(
|
|||||||
|
|
||||||
if (!m_data.empty() || !m_subs.empty())
|
if (!m_data.empty() || !m_subs.empty())
|
||||||
{
|
{
|
||||||
_out << _prefix << "stop" << endl;
|
_out << _prefix << "stop" << std::endl;
|
||||||
for (auto const& i: m_data)
|
for (auto const& i: m_data)
|
||||||
if (u256(i.first) >= m_subs.size())
|
if (u256(i.first) >= m_subs.size())
|
||||||
_out << _prefix << "data_" << toHex(u256(i.first)) << " " << util::toHex(i.second) << endl;
|
_out << _prefix << "data_" << toHex(u256(i.first)) << " " << util::toHex(i.second) << std::endl;
|
||||||
|
|
||||||
for (size_t i = 0; i < m_subs.size(); ++i)
|
for (size_t i = 0; i < m_subs.size(); ++i)
|
||||||
{
|
{
|
||||||
_out << endl << _prefix << "sub_" << i << ": assembly {\n";
|
_out << std::endl << _prefix << "sub_" << i << ": assembly {\n";
|
||||||
m_subs[i]->assemblyStream(_out, _debugInfoSelection, _prefix + " ", _sourceCodes);
|
m_subs[i]->assemblyStream(_out, _debugInfoSelection, _prefix + " ", _sourceCodes);
|
||||||
_out << _prefix << "}" << endl;
|
_out << _prefix << "}" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_auxiliaryData.size() > 0)
|
if (m_auxiliaryData.size() > 0)
|
||||||
_out << endl << _prefix << "auxdata: 0x" << util::toHex(m_auxiliaryData) << endl;
|
_out << std::endl << _prefix << "auxdata: 0x" << util::toHex(m_auxiliaryData) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
string Assembly::assemblyString(
|
std::string Assembly::assemblyString(
|
||||||
DebugInfoSelection const& _debugInfoSelection,
|
DebugInfoSelection const& _debugInfoSelection,
|
||||||
StringMap const& _sourceCodes
|
StringMap const& _sourceCodes
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
ostringstream tmp;
|
std::ostringstream tmp;
|
||||||
assemblyStream(tmp, _debugInfoSelection, "", _sourceCodes);
|
assemblyStream(tmp, _debugInfoSelection, "", _sourceCodes);
|
||||||
return tmp.str();
|
return tmp.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices, bool _includeSourceList) const
|
Json::Value Assembly::assemblyJSON(std::map<std::string, unsigned> const& _sourceIndices, bool _includeSourceList) const
|
||||||
{
|
{
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
root[".code"] = Json::arrayValue;
|
root[".code"] = Json::arrayValue;
|
||||||
@ -244,7 +243,7 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
|
|||||||
jsonItem["end"] = item.location().end;
|
jsonItem["end"] = item.location().end;
|
||||||
if (item.m_modifierDepth != 0)
|
if (item.m_modifierDepth != 0)
|
||||||
jsonItem["modifierDepth"] = static_cast<int>(item.m_modifierDepth);
|
jsonItem["modifierDepth"] = static_cast<int>(item.m_modifierDepth);
|
||||||
string jumpType = item.getJumpTypeAsString();
|
std::string jumpType = item.getJumpTypeAsString();
|
||||||
if (!jumpType.empty())
|
if (!jumpType.empty())
|
||||||
jsonItem["jumpType"] = jumpType;
|
jsonItem["jumpType"] = jumpType;
|
||||||
if (name == "PUSHLIB")
|
if (name == "PUSHLIB")
|
||||||
@ -286,8 +285,8 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
|
|||||||
|
|
||||||
for (size_t i = 0; i < m_subs.size(); ++i)
|
for (size_t i = 0; i < m_subs.size(); ++i)
|
||||||
{
|
{
|
||||||
stringstream hexStr;
|
std::stringstream hexStr;
|
||||||
hexStr << hex << i;
|
hexStr << std::hex << i;
|
||||||
data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceIndices, /*_includeSourceList = */false);
|
data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceIndices, /*_includeSourceList = */false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,7 +297,7 @@ Json::Value Assembly::assemblyJSON(map<string, unsigned> const& _sourceIndices,
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyItem Assembly::namedTag(string const& _name, size_t _params, size_t _returns, optional<uint64_t> _sourceID)
|
AssemblyItem Assembly::namedTag(std::string const& _name, size_t _params, size_t _returns, std::optional<uint64_t> _sourceID)
|
||||||
{
|
{
|
||||||
assertThrow(!_name.empty(), AssemblyException, "Empty named tag.");
|
assertThrow(!_name.empty(), AssemblyException, "Empty named tag.");
|
||||||
if (m_namedTags.count(_name))
|
if (m_namedTags.count(_name))
|
||||||
@ -312,21 +311,21 @@ AssemblyItem Assembly::namedTag(string const& _name, size_t _params, size_t _ret
|
|||||||
return AssemblyItem{Tag, m_namedTags.at(_name).id};
|
return AssemblyItem{Tag, m_namedTags.at(_name).id};
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyItem Assembly::newPushLibraryAddress(string const& _identifier)
|
AssemblyItem Assembly::newPushLibraryAddress(std::string const& _identifier)
|
||||||
{
|
{
|
||||||
h256 h(util::keccak256(_identifier));
|
h256 h(util::keccak256(_identifier));
|
||||||
m_libraries[h] = _identifier;
|
m_libraries[h] = _identifier;
|
||||||
return AssemblyItem{PushLibraryAddress, h};
|
return AssemblyItem{PushLibraryAddress, h};
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyItem Assembly::newPushImmutable(string const& _identifier)
|
AssemblyItem Assembly::newPushImmutable(std::string const& _identifier)
|
||||||
{
|
{
|
||||||
h256 h(util::keccak256(_identifier));
|
h256 h(util::keccak256(_identifier));
|
||||||
m_immutables[h] = _identifier;
|
m_immutables[h] = _identifier;
|
||||||
return AssemblyItem{PushImmutable, h};
|
return AssemblyItem{PushImmutable, h};
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyItem Assembly::newImmutableAssignment(string const& _identifier)
|
AssemblyItem Assembly::newImmutableAssignment(std::string const& _identifier)
|
||||||
{
|
{
|
||||||
h256 h(util::keccak256(_identifier));
|
h256 h(util::keccak256(_identifier));
|
||||||
m_immutables[h] = _identifier;
|
m_immutables[h] = _identifier;
|
||||||
@ -339,9 +338,9 @@ Assembly& Assembly::optimise(OptimiserSettings const& _settings)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
map<u256, u256> const& Assembly::optimiseInternal(
|
std::map<u256, u256> const& Assembly::optimiseInternal(
|
||||||
OptimiserSettings const& _settings,
|
OptimiserSettings const& _settings,
|
||||||
set<size_t> _tagsReferencedFromOutside
|
std::set<size_t> _tagsReferencedFromOutside
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (m_tagReplacements)
|
if (m_tagReplacements)
|
||||||
@ -352,7 +351,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
|
|||||||
{
|
{
|
||||||
OptimiserSettings settings = _settings;
|
OptimiserSettings settings = _settings;
|
||||||
Assembly& sub = *m_subs[subId];
|
Assembly& sub = *m_subs[subId];
|
||||||
map<u256, u256> const& subTagReplacements = sub.optimiseInternal(
|
std::map<u256, u256> const& subTagReplacements = sub.optimiseInternal(
|
||||||
settings,
|
settings,
|
||||||
JumpdestRemover::referencedTags(m_items, subId)
|
JumpdestRemover::referencedTags(m_items, subId)
|
||||||
);
|
);
|
||||||
@ -360,7 +359,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
|
|||||||
BlockDeduplicator::applyTagReplacement(m_items, subTagReplacements, subId);
|
BlockDeduplicator::applyTagReplacement(m_items, subTagReplacements, subId);
|
||||||
}
|
}
|
||||||
|
|
||||||
map<u256, u256> tagReplacements;
|
std::map<u256, u256> tagReplacements;
|
||||||
// Iterate until no new optimisation possibilities are found.
|
// Iterate until no new optimisation possibilities are found.
|
||||||
for (unsigned count = 1; count > 0;)
|
for (unsigned count = 1; count > 0;)
|
||||||
{
|
{
|
||||||
@ -401,7 +400,7 @@ map<u256, u256> const& Assembly::optimiseInternal(
|
|||||||
for (auto const& replacement: deduplicator.replacedTags())
|
for (auto const& replacement: deduplicator.replacedTags())
|
||||||
{
|
{
|
||||||
assertThrow(
|
assertThrow(
|
||||||
replacement.first <= numeric_limits<size_t>::max() && replacement.second <= numeric_limits<size_t>::max(),
|
replacement.first <= std::numeric_limits<size_t>::max() && replacement.second <= std::numeric_limits<size_t>::max(),
|
||||||
OptimizerException,
|
OptimizerException,
|
||||||
"Invalid tag replacement."
|
"Invalid tag replacement."
|
||||||
);
|
);
|
||||||
@ -494,7 +493,7 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
LinkerObject& ret = m_assembledObject;
|
LinkerObject& ret = m_assembledObject;
|
||||||
|
|
||||||
size_t subTagSize = 1;
|
size_t subTagSize = 1;
|
||||||
map<u256, pair<string, vector<size_t>>> immutableReferencesBySub;
|
std::map<u256, std::pair<std::string, std::vector<size_t>>> immutableReferencesBySub;
|
||||||
for (auto const& sub: m_subs)
|
for (auto const& sub: m_subs)
|
||||||
{
|
{
|
||||||
auto const& linkerObject = sub->assemble();
|
auto const& linkerObject = sub->assemble();
|
||||||
@ -508,7 +507,7 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
immutableReferencesBySub = linkerObject.immutableReferences;
|
immutableReferencesBySub = linkerObject.immutableReferences;
|
||||||
}
|
}
|
||||||
for (size_t tagPos: sub->m_tagPositionsInBytecode)
|
for (size_t tagPos: sub->m_tagPositionsInBytecode)
|
||||||
if (tagPos != numeric_limits<size_t>::max() && tagPos > subTagSize)
|
if (tagPos != std::numeric_limits<size_t>::max() && tagPos > subTagSize)
|
||||||
subTagSize = tagPos;
|
subTagSize = tagPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,11 +530,11 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
);
|
);
|
||||||
|
|
||||||
unsigned bytesRequiredForCode = codeSize(static_cast<unsigned>(subTagSize));
|
unsigned bytesRequiredForCode = codeSize(static_cast<unsigned>(subTagSize));
|
||||||
m_tagPositionsInBytecode = vector<size_t>(m_usedTags, numeric_limits<size_t>::max());
|
m_tagPositionsInBytecode = std::vector<size_t>(m_usedTags, std::numeric_limits<size_t>::max());
|
||||||
map<size_t, pair<size_t, size_t>> tagRef;
|
std::map<size_t, std::pair<size_t, size_t>> tagRef;
|
||||||
multimap<h256, unsigned> dataRef;
|
std::multimap<h256, unsigned> dataRef;
|
||||||
multimap<size_t, size_t> subRef;
|
std::multimap<size_t, size_t> subRef;
|
||||||
vector<unsigned> sizeRef; ///< Pointers to code locations where the size of the program is inserted
|
std::vector<unsigned> sizeRef; ///< Pointers to code locations where the size of the program is inserted
|
||||||
unsigned bytesPerTag = numberEncodingSize(bytesRequiredForCode);
|
unsigned bytesPerTag = numberEncodingSize(bytesRequiredForCode);
|
||||||
uint8_t tagPush = static_cast<uint8_t>(pushInstruction(bytesPerTag));
|
uint8_t tagPush = static_cast<uint8_t>(pushInstruction(bytesPerTag));
|
||||||
|
|
||||||
@ -550,7 +549,7 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
for (AssemblyItem const& i: m_items)
|
for (AssemblyItem const& i: m_items)
|
||||||
{
|
{
|
||||||
// store position of the invalid jump destination
|
// store position of the invalid jump destination
|
||||||
if (i.type() != Tag && m_tagPositionsInBytecode[0] == numeric_limits<size_t>::max())
|
if (i.type() != Tag && m_tagPositionsInBytecode[0] == std::numeric_limits<size_t>::max())
|
||||||
m_tagPositionsInBytecode[0] = ret.bytecode.size();
|
m_tagPositionsInBytecode[0] = ret.bytecode.size();
|
||||||
|
|
||||||
switch (i.type())
|
switch (i.type())
|
||||||
@ -583,21 +582,21 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
}
|
}
|
||||||
case PushData:
|
case PushData:
|
||||||
ret.bytecode.push_back(dataRefPush);
|
ret.bytecode.push_back(dataRefPush);
|
||||||
dataRef.insert(make_pair(h256(i.data()), ret.bytecode.size()));
|
dataRef.insert(std::make_pair(h256(i.data()), ret.bytecode.size()));
|
||||||
ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef);
|
ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef);
|
||||||
break;
|
break;
|
||||||
case PushSub:
|
case PushSub:
|
||||||
assertThrow(i.data() <= numeric_limits<size_t>::max(), AssemblyException, "");
|
assertThrow(i.data() <= std::numeric_limits<size_t>::max(), AssemblyException, "");
|
||||||
ret.bytecode.push_back(dataRefPush);
|
ret.bytecode.push_back(dataRefPush);
|
||||||
subRef.insert(make_pair(static_cast<size_t>(i.data()), ret.bytecode.size()));
|
subRef.insert(std::make_pair(static_cast<size_t>(i.data()), ret.bytecode.size()));
|
||||||
ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef);
|
ret.bytecode.resize(ret.bytecode.size() + bytesPerDataRef);
|
||||||
break;
|
break;
|
||||||
case PushSubSize:
|
case PushSubSize:
|
||||||
{
|
{
|
||||||
assertThrow(i.data() <= numeric_limits<size_t>::max(), AssemblyException, "");
|
assertThrow(i.data() <= std::numeric_limits<size_t>::max(), AssemblyException, "");
|
||||||
auto s = subAssemblyById(static_cast<size_t>(i.data()))->assemble().bytecode.size();
|
auto s = subAssemblyById(static_cast<size_t>(i.data()))->assemble().bytecode.size();
|
||||||
i.setPushedValue(u256(s));
|
i.setPushedValue(u256(s));
|
||||||
unsigned b = max<unsigned>(1, numberEncodingSize(s));
|
unsigned b = std::max<unsigned>(1, numberEncodingSize(s));
|
||||||
ret.bytecode.push_back(static_cast<uint8_t>(pushInstruction(b)));
|
ret.bytecode.push_back(static_cast<uint8_t>(pushInstruction(b)));
|
||||||
ret.bytecode.resize(ret.bytecode.size() + b);
|
ret.bytecode.resize(ret.bytecode.size() + b);
|
||||||
bytesRef byr(&ret.bytecode.back() + 1 - b, b);
|
bytesRef byr(&ret.bytecode.back() + 1 - b, b);
|
||||||
@ -618,7 +617,7 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
break;
|
break;
|
||||||
case PushImmutable:
|
case PushImmutable:
|
||||||
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::PUSH32));
|
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::PUSH32));
|
||||||
// Maps keccak back to the "identifier" string of that immutable.
|
// Maps keccak back to the "identifier" std::string of that immutable.
|
||||||
ret.immutableReferences[i.data()].first = m_immutables.at(i.data());
|
ret.immutableReferences[i.data()].first = m_immutables.at(i.data());
|
||||||
// Record the bytecode offset of the PUSH32 argument.
|
// Record the bytecode offset of the PUSH32 argument.
|
||||||
ret.immutableReferences[i.data()].second.emplace_back(ret.bytecode.size());
|
ret.immutableReferences[i.data()].second.emplace_back(ret.bytecode.size());
|
||||||
@ -661,10 +660,10 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
case Tag:
|
case Tag:
|
||||||
{
|
{
|
||||||
assertThrow(i.data() != 0, AssemblyException, "Invalid tag position.");
|
assertThrow(i.data() != 0, AssemblyException, "Invalid tag position.");
|
||||||
assertThrow(i.splitForeignPushTag().first == numeric_limits<size_t>::max(), AssemblyException, "Foreign tag.");
|
assertThrow(i.splitForeignPushTag().first == std::numeric_limits<size_t>::max(), AssemblyException, "Foreign tag.");
|
||||||
size_t tagId = static_cast<size_t>(i.data());
|
size_t tagId = static_cast<size_t>(i.data());
|
||||||
assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large.");
|
assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large.");
|
||||||
assertThrow(m_tagPositionsInBytecode[tagId] == numeric_limits<size_t>::max(), AssemblyException, "Duplicate tag position.");
|
assertThrow(m_tagPositionsInBytecode[tagId] == std::numeric_limits<size_t>::max(), AssemblyException, "Duplicate tag position.");
|
||||||
m_tagPositionsInBytecode[tagId] = ret.bytecode.size();
|
m_tagPositionsInBytecode[tagId] = ret.bytecode.size();
|
||||||
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::JUMPDEST));
|
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::JUMPDEST));
|
||||||
break;
|
break;
|
||||||
@ -686,7 +685,7 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
// Append an INVALID here to help tests find miscompilation.
|
// Append an INVALID here to help tests find miscompilation.
|
||||||
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::INVALID));
|
ret.bytecode.push_back(static_cast<uint8_t>(Instruction::INVALID));
|
||||||
|
|
||||||
map<LinkerObject, size_t> subAssemblyOffsets;
|
std::map<LinkerObject, size_t> subAssemblyOffsets;
|
||||||
for (auto const& [subIdPath, bytecodeOffset]: subRef)
|
for (auto const& [subIdPath, bytecodeOffset]: subRef)
|
||||||
{
|
{
|
||||||
LinkerObject subObject = subAssemblyById(subIdPath)->assemble();
|
LinkerObject subObject = subAssemblyById(subIdPath)->assemble();
|
||||||
@ -709,15 +708,15 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
{
|
{
|
||||||
size_t subId;
|
size_t subId;
|
||||||
size_t tagId;
|
size_t tagId;
|
||||||
tie(subId, tagId) = i.second;
|
std::tie(subId, tagId) = i.second;
|
||||||
assertThrow(subId == numeric_limits<size_t>::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id");
|
assertThrow(subId == std::numeric_limits<size_t>::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id");
|
||||||
vector<size_t> const& tagPositions =
|
std::vector<size_t> const& tagPositions =
|
||||||
subId == numeric_limits<size_t>::max() ?
|
subId == std::numeric_limits<size_t>::max() ?
|
||||||
m_tagPositionsInBytecode :
|
m_tagPositionsInBytecode :
|
||||||
m_subs[subId]->m_tagPositionsInBytecode;
|
m_subs[subId]->m_tagPositionsInBytecode;
|
||||||
assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag.");
|
assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag.");
|
||||||
size_t pos = tagPositions[tagId];
|
size_t pos = tagPositions[tagId];
|
||||||
assertThrow(pos != numeric_limits<size_t>::max(), AssemblyException, "Reference to tag without position.");
|
assertThrow(pos != std::numeric_limits<size_t>::max(), AssemblyException, "Reference to tag without position.");
|
||||||
assertThrow(numberEncodingSize(pos) <= bytesPerTag, AssemblyException, "Tag too large for reserved space.");
|
assertThrow(numberEncodingSize(pos) <= bytesPerTag, AssemblyException, "Tag too large for reserved space.");
|
||||||
bytesRef r(ret.bytecode.data() + i.first, bytesPerTag);
|
bytesRef r(ret.bytecode.data() + i.first, bytesPerTag);
|
||||||
toBigEndian(pos, r);
|
toBigEndian(pos, r);
|
||||||
@ -725,7 +724,7 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
for (auto const& [name, tagInfo]: m_namedTags)
|
for (auto const& [name, tagInfo]: m_namedTags)
|
||||||
{
|
{
|
||||||
size_t position = m_tagPositionsInBytecode.at(tagInfo.id);
|
size_t position = m_tagPositionsInBytecode.at(tagInfo.id);
|
||||||
optional<size_t> tagIndex;
|
std::optional<size_t> tagIndex;
|
||||||
for (auto&& [index, item]: m_items | ranges::views::enumerate)
|
for (auto&& [index, item]: m_items | ranges::views::enumerate)
|
||||||
if (item.type() == Tag && static_cast<size_t>(item.data()) == tagInfo.id)
|
if (item.type() == Tag && static_cast<size_t>(item.data()) == tagInfo.id)
|
||||||
{
|
{
|
||||||
@ -733,7 +732,7 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret.functionDebugData[name] = {
|
ret.functionDebugData[name] = {
|
||||||
position == numeric_limits<size_t>::max() ? nullopt : optional<size_t>{position},
|
position == std::numeric_limits<size_t>::max() ? std::nullopt : std::optional<size_t>{position},
|
||||||
tagIndex,
|
tagIndex,
|
||||||
tagInfo.sourceID,
|
tagInfo.sourceID,
|
||||||
tagInfo.params,
|
tagInfo.params,
|
||||||
@ -764,7 +763,7 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<size_t> Assembly::decodeSubPath(size_t _subObjectId) const
|
std::vector<size_t> Assembly::decodeSubPath(size_t _subObjectId) const
|
||||||
{
|
{
|
||||||
if (_subObjectId < m_subs.size())
|
if (_subObjectId < m_subs.size())
|
||||||
return {_subObjectId};
|
return {_subObjectId};
|
||||||
@ -779,7 +778,7 @@ vector<size_t> Assembly::decodeSubPath(size_t _subObjectId) const
|
|||||||
return subIdPathIt->first;
|
return subIdPathIt->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Assembly::encodeSubPath(vector<size_t> const& _subPath)
|
size_t Assembly::encodeSubPath(std::vector<size_t> const& _subPath)
|
||||||
{
|
{
|
||||||
assertThrow(!_subPath.empty(), AssemblyException, "");
|
assertThrow(!_subPath.empty(), AssemblyException, "");
|
||||||
if (_subPath.size() == 1)
|
if (_subPath.size() == 1)
|
||||||
@ -790,7 +789,7 @@ size_t Assembly::encodeSubPath(vector<size_t> const& _subPath)
|
|||||||
|
|
||||||
if (m_subPaths.find(_subPath) == m_subPaths.end())
|
if (m_subPaths.find(_subPath) == m_subPaths.end())
|
||||||
{
|
{
|
||||||
size_t objectId = numeric_limits<size_t>::max() - m_subPaths.size();
|
size_t objectId = std::numeric_limits<size_t>::max() - m_subPaths.size();
|
||||||
assertThrow(objectId >= m_subs.size(), AssemblyException, "");
|
assertThrow(objectId >= m_subs.size(), AssemblyException, "");
|
||||||
m_subPaths[_subPath] = objectId;
|
m_subPaths[_subPath] = objectId;
|
||||||
}
|
}
|
||||||
@ -800,7 +799,7 @@ size_t Assembly::encodeSubPath(vector<size_t> const& _subPath)
|
|||||||
|
|
||||||
Assembly const* Assembly::subAssemblyById(size_t _subId) const
|
Assembly const* Assembly::subAssemblyById(size_t _subId) const
|
||||||
{
|
{
|
||||||
vector<size_t> subIds = decodeSubPath(_subId);
|
std::vector<size_t> subIds = decodeSubPath(_subId);
|
||||||
Assembly const* currentAssembly = this;
|
Assembly const* currentAssembly = this;
|
||||||
for (size_t currentSubId: subIds)
|
for (size_t currentSubId: subIds)
|
||||||
{
|
{
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std::literals;
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
@ -40,10 +40,10 @@ static_assert(sizeof(size_t) <= 8, "size_t must be at most 64-bits wide");
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
string toStringInHex(u256 _value)
|
std::string toStringInHex(u256 _value)
|
||||||
{
|
{
|
||||||
stringstream hexStr;
|
std::stringstream hexStr;
|
||||||
hexStr << uppercase << hex << _value;
|
hexStr << std::uppercase << std::hex << _value;
|
||||||
return hexStr.str();
|
return hexStr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,16 +60,16 @@ AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<size_t, size_t> AssemblyItem::splitForeignPushTag() const
|
std::pair<size_t, size_t> AssemblyItem::splitForeignPushTag() const
|
||||||
{
|
{
|
||||||
assertThrow(m_type == PushTag || m_type == Tag, util::Exception, "");
|
assertThrow(m_type == PushTag || m_type == Tag, util::Exception, "");
|
||||||
u256 combined = u256(data());
|
u256 combined = u256(data());
|
||||||
size_t subId = static_cast<size_t>((combined >> 64) - 1);
|
size_t subId = static_cast<size_t>((combined >> 64) - 1);
|
||||||
size_t tag = static_cast<size_t>(combined & 0xffffffffffffffffULL);
|
size_t tag = static_cast<size_t>(combined & 0xffffffffffffffffULL);
|
||||||
return make_pair(subId, tag);
|
return std::make_pair(subId, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<string, string> AssemblyItem::nameAndData(langutil::EVMVersion _evmVersion) const
|
std::pair<std::string, std::string> AssemblyItem::nameAndData(langutil::EVMVersion _evmVersion) const
|
||||||
{
|
{
|
||||||
switch (type())
|
switch (type())
|
||||||
{
|
{
|
||||||
@ -111,7 +111,7 @@ void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag)
|
|||||||
{
|
{
|
||||||
assertThrow(m_type == PushTag || m_type == Tag, util::Exception, "");
|
assertThrow(m_type == PushTag || m_type == Tag, util::Exception, "");
|
||||||
u256 data = _tag;
|
u256 data = _tag;
|
||||||
if (_subId != numeric_limits<size_t>::max())
|
if (_subId != std::numeric_limits<size_t>::max())
|
||||||
data |= (u256(_subId) + 1) << 64;
|
data |= (u256(_subId) + 1) << 64;
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision)
|
|||||||
case Tag: // 1 byte for the JUMPDEST
|
case Tag: // 1 byte for the JUMPDEST
|
||||||
return 1;
|
return 1;
|
||||||
case Push:
|
case Push:
|
||||||
return 1 + max<size_t>(1, numberEncodingSize(data()));
|
return 1 + std::max<size_t>(1, numberEncodingSize(data()));
|
||||||
case PushSubSize:
|
case PushSubSize:
|
||||||
case PushProgramSize:
|
case PushProgramSize:
|
||||||
return 1 + 4; // worst case: a 16MB program
|
return 1 + 4; // worst case: a 16MB program
|
||||||
@ -158,7 +158,7 @@ size_t AssemblyItem::bytesRequired(size_t _addressLength, Precision _precision)
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
case VerbatimBytecode:
|
case VerbatimBytecode:
|
||||||
return get<2>(*m_verbatimBytecode).size();
|
return std::get<2>(*m_verbatimBytecode).size();
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ size_t AssemblyItem::arguments() const
|
|||||||
// the same across all EVM versions except for the instruction name.
|
// the same across all EVM versions except for the instruction name.
|
||||||
return static_cast<size_t>(instructionInfo(instruction(), EVMVersion()).args);
|
return static_cast<size_t>(instructionInfo(instruction(), EVMVersion()).args);
|
||||||
else if (type() == VerbatimBytecode)
|
else if (type() == VerbatimBytecode)
|
||||||
return get<0>(*m_verbatimBytecode);
|
return std::get<0>(*m_verbatimBytecode);
|
||||||
else if (type() == AssignImmutable)
|
else if (type() == AssignImmutable)
|
||||||
return 2;
|
return 2;
|
||||||
else
|
else
|
||||||
@ -200,7 +200,7 @@ size_t AssemblyItem::returnValues() const
|
|||||||
case Tag:
|
case Tag:
|
||||||
return 0;
|
return 0;
|
||||||
case VerbatimBytecode:
|
case VerbatimBytecode:
|
||||||
return get<1>(*m_verbatimBytecode);
|
return std::get<1>(*m_verbatimBytecode);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ bool AssemblyItem::canBeFunctional() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string AssemblyItem::getJumpTypeAsString() const
|
std::string AssemblyItem::getJumpTypeAsString() const
|
||||||
{
|
{
|
||||||
switch (m_jumpType)
|
switch (m_jumpType)
|
||||||
{
|
{
|
||||||
@ -247,9 +247,9 @@ string AssemblyItem::getJumpTypeAsString() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
|
std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
|
||||||
{
|
{
|
||||||
string text;
|
std::string text;
|
||||||
switch (type())
|
switch (type())
|
||||||
{
|
{
|
||||||
case Operation:
|
case Operation:
|
||||||
@ -265,26 +265,26 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
|
|||||||
{
|
{
|
||||||
size_t sub{0};
|
size_t sub{0};
|
||||||
size_t tag{0};
|
size_t tag{0};
|
||||||
tie(sub, tag) = splitForeignPushTag();
|
std::tie(sub, tag) = splitForeignPushTag();
|
||||||
if (sub == numeric_limits<size_t>::max())
|
if (sub == std::numeric_limits<size_t>::max())
|
||||||
text = string("tag_") + to_string(tag);
|
text = std::string("tag_") + std::to_string(tag);
|
||||||
else
|
else
|
||||||
text = string("tag_") + to_string(sub) + "_" + to_string(tag);
|
text = std::string("tag_") + std::to_string(sub) + "_" + std::to_string(tag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Tag:
|
case Tag:
|
||||||
assertThrow(data() < 0x10000, AssemblyException, "Declaration of sub-assembly tag.");
|
assertThrow(data() < 0x10000, AssemblyException, "Declaration of sub-assembly tag.");
|
||||||
text = string("tag_") + to_string(static_cast<size_t>(data())) + ":";
|
text = std::string("tag_") + std::to_string(static_cast<size_t>(data())) + ":";
|
||||||
break;
|
break;
|
||||||
case PushData:
|
case PushData:
|
||||||
text = string("data_") + toHex(data());
|
text = std::string("data_") + toHex(data());
|
||||||
break;
|
break;
|
||||||
case PushSub:
|
case PushSub:
|
||||||
case PushSubSize:
|
case PushSubSize:
|
||||||
{
|
{
|
||||||
vector<string> subPathComponents;
|
std::vector<std::string> subPathComponents;
|
||||||
for (size_t subPathComponentId: _assembly.decodeSubPath(static_cast<size_t>(data())))
|
for (size_t subPathComponentId: _assembly.decodeSubPath(static_cast<size_t>(data())))
|
||||||
subPathComponents.emplace_back("sub_" + to_string(subPathComponentId));
|
subPathComponents.emplace_back("sub_" + std::to_string(subPathComponentId));
|
||||||
text =
|
text =
|
||||||
(type() == PushSub ? "dataOffset"s : "dataSize"s) +
|
(type() == PushSub ? "dataOffset"s : "dataSize"s) +
|
||||||
"(" +
|
"(" +
|
||||||
@ -293,25 +293,25 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PushProgramSize:
|
case PushProgramSize:
|
||||||
text = string("bytecodeSize");
|
text = std::string("bytecodeSize");
|
||||||
break;
|
break;
|
||||||
case PushLibraryAddress:
|
case PushLibraryAddress:
|
||||||
text = string("linkerSymbol(\"") + toHex(data()) + string("\")");
|
text = std::string("linkerSymbol(\"") + toHex(data()) + std::string("\")");
|
||||||
break;
|
break;
|
||||||
case PushDeployTimeAddress:
|
case PushDeployTimeAddress:
|
||||||
text = string("deployTimeAddress()");
|
text = std::string("deployTimeAddress()");
|
||||||
break;
|
break;
|
||||||
case PushImmutable:
|
case PushImmutable:
|
||||||
text = string("immutable(\"") + "0x" + util::toHex(toCompactBigEndian(data(), 1)) + "\")";
|
text = std::string("immutable(\"") + "0x" + util::toHex(toCompactBigEndian(data(), 1)) + "\")";
|
||||||
break;
|
break;
|
||||||
case AssignImmutable:
|
case AssignImmutable:
|
||||||
text = string("assignImmutable(\"") + "0x" + util::toHex(toCompactBigEndian(data(), 1)) + "\")";
|
text = std::string("assignImmutable(\"") + "0x" + util::toHex(toCompactBigEndian(data(), 1)) + "\")";
|
||||||
break;
|
break;
|
||||||
case UndefinedItem:
|
case UndefinedItem:
|
||||||
assertThrow(false, AssemblyException, "Invalid assembly item.");
|
assertThrow(false, AssemblyException, "Invalid assembly item.");
|
||||||
break;
|
break;
|
||||||
case VerbatimBytecode:
|
case VerbatimBytecode:
|
||||||
text = string("verbatimbytecode_") + util::toHex(get<2>(*m_verbatimBytecode));
|
text = std::string("verbatimbytecode_") + util::toHex(std::get<2>(*m_verbatimBytecode));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assertThrow(false, InvalidOpcode, "");
|
assertThrow(false, InvalidOpcode, "");
|
||||||
@ -328,7 +328,7 @@ string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note: This method is exclusively used for debugging.
|
// Note: This method is exclusively used for debugging.
|
||||||
ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item)
|
std::ostream& solidity::evmasm::operator<<(std::ostream& _out, AssemblyItem const& _item)
|
||||||
{
|
{
|
||||||
switch (_item.type())
|
switch (_item.type())
|
||||||
{
|
{
|
||||||
@ -338,12 +338,12 @@ ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item)
|
|||||||
_out << "\t" << _item.getJumpTypeAsString();
|
_out << "\t" << _item.getJumpTypeAsString();
|
||||||
break;
|
break;
|
||||||
case Push:
|
case Push:
|
||||||
_out << " PUSH " << hex << _item.data() << dec;
|
_out << " PUSH " << std::hex << _item.data() << std::dec;
|
||||||
break;
|
break;
|
||||||
case PushTag:
|
case PushTag:
|
||||||
{
|
{
|
||||||
size_t subId = _item.splitForeignPushTag().first;
|
size_t subId = _item.splitForeignPushTag().first;
|
||||||
if (subId == numeric_limits<size_t>::max())
|
if (subId == std::numeric_limits<size_t>::max())
|
||||||
_out << " PushTag " << _item.splitForeignPushTag().second;
|
_out << " PushTag " << _item.splitForeignPushTag().second;
|
||||||
else
|
else
|
||||||
_out << " PushTag " << subId << ":" << _item.splitForeignPushTag().second;
|
_out << " PushTag " << subId << ":" << _item.splitForeignPushTag().second;
|
||||||
@ -353,20 +353,20 @@ ostream& solidity::evmasm::operator<<(ostream& _out, AssemblyItem const& _item)
|
|||||||
_out << " Tag " << _item.data();
|
_out << " Tag " << _item.data();
|
||||||
break;
|
break;
|
||||||
case PushData:
|
case PushData:
|
||||||
_out << " PushData " << hex << static_cast<unsigned>(_item.data()) << dec;
|
_out << " PushData " << std::hex << static_cast<unsigned>(_item.data()) << std::dec;
|
||||||
break;
|
break;
|
||||||
case PushSub:
|
case PushSub:
|
||||||
_out << " PushSub " << hex << static_cast<size_t>(_item.data()) << dec;
|
_out << " PushSub " << std::hex << static_cast<size_t>(_item.data()) << std::dec;
|
||||||
break;
|
break;
|
||||||
case PushSubSize:
|
case PushSubSize:
|
||||||
_out << " PushSubSize " << hex << static_cast<size_t>(_item.data()) << dec;
|
_out << " PushSubSize " << std::hex << static_cast<size_t>(_item.data()) << std::dec;
|
||||||
break;
|
break;
|
||||||
case PushProgramSize:
|
case PushProgramSize:
|
||||||
_out << " PushProgramSize";
|
_out << " PushProgramSize";
|
||||||
break;
|
break;
|
||||||
case PushLibraryAddress:
|
case PushLibraryAddress:
|
||||||
{
|
{
|
||||||
string hash(util::h256((_item.data())).hex());
|
std::string hash(util::h256((_item.data())).hex());
|
||||||
_out << " PushLibraryAddress " << hash.substr(0, 8) + "..." + hash.substr(hash.length() - 8);
|
_out << " PushLibraryAddress " << hash.substr(0, 8) + "..." + hash.substr(hash.length() - 8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -411,12 +411,12 @@ size_t AssemblyItem::opcodeCount() const noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string AssemblyItem::computeSourceMapping(
|
std::string AssemblyItem::computeSourceMapping(
|
||||||
AssemblyItems const& _items,
|
AssemblyItems const& _items,
|
||||||
map<string, unsigned> const& _sourceIndicesMap
|
std::map<std::string, unsigned> const& _sourceIndicesMap
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
string ret;
|
std::string ret;
|
||||||
|
|
||||||
int prevStart = -1;
|
int prevStart = -1;
|
||||||
int prevLength = -1;
|
int prevLength = -1;
|
||||||
@ -465,17 +465,17 @@ string AssemblyItem::computeSourceMapping(
|
|||||||
if (components-- > 0)
|
if (components-- > 0)
|
||||||
{
|
{
|
||||||
if (location.start != prevStart)
|
if (location.start != prevStart)
|
||||||
ret += to_string(location.start);
|
ret += std::to_string(location.start);
|
||||||
if (components-- > 0)
|
if (components-- > 0)
|
||||||
{
|
{
|
||||||
ret += ':';
|
ret += ':';
|
||||||
if (length != prevLength)
|
if (length != prevLength)
|
||||||
ret += to_string(length);
|
ret += std::to_string(length);
|
||||||
if (components-- > 0)
|
if (components-- > 0)
|
||||||
{
|
{
|
||||||
ret += ':';
|
ret += ':';
|
||||||
if (sourceIndex != prevSourceIndex)
|
if (sourceIndex != prevSourceIndex)
|
||||||
ret += to_string(sourceIndex);
|
ret += std::to_string(sourceIndex);
|
||||||
if (components-- > 0)
|
if (components-- > 0)
|
||||||
{
|
{
|
||||||
ret += ':';
|
ret += ':';
|
||||||
@ -485,7 +485,7 @@ string AssemblyItem::computeSourceMapping(
|
|||||||
{
|
{
|
||||||
ret += ':';
|
ret += ':';
|
||||||
if (modifierDepth != prevModifierDepth)
|
if (modifierDepth != prevModifierDepth)
|
||||||
ret += to_string(modifierDepth);
|
ret += std::to_string(modifierDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,7 +493,7 @@ string AssemblyItem::computeSourceMapping(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (item.opcodeCount() > 1)
|
if (item.opcodeCount() > 1)
|
||||||
ret += string(item.opcodeCount() - 1, ';');
|
ret += std::string(item.opcodeCount() - 1, ';');
|
||||||
|
|
||||||
prevStart = location.start;
|
prevStart = location.start;
|
||||||
prevLength = length;
|
prevLength = length;
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
|
|
||||||
@ -49,7 +48,7 @@ bool BlockDeduplicator::deduplicate()
|
|||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
function<bool(size_t, size_t)> comparator = [&](size_t _i, size_t _j)
|
std::function<bool(size_t, size_t)> comparator = [&](size_t _i, size_t _j)
|
||||||
{
|
{
|
||||||
if (_i == _j)
|
if (_i == _j)
|
||||||
return false;
|
return false;
|
||||||
@ -81,7 +80,7 @@ bool BlockDeduplicator::deduplicate()
|
|||||||
for (; ; ++iterations)
|
for (; ; ++iterations)
|
||||||
{
|
{
|
||||||
//@todo this should probably be optimized.
|
//@todo this should probably be optimized.
|
||||||
set<size_t, function<bool(size_t, size_t)>> blocksSeen(comparator);
|
std::set<size_t, std::function<bool(size_t, size_t)>> blocksSeen(comparator);
|
||||||
for (size_t i = 0; i < m_items.size(); ++i)
|
for (size_t i = 0; i < m_items.size(); ++i)
|
||||||
{
|
{
|
||||||
if (m_items.at(i).type() != Tag)
|
if (m_items.at(i).type() != Tag)
|
||||||
@ -101,7 +100,7 @@ bool BlockDeduplicator::deduplicate()
|
|||||||
|
|
||||||
bool BlockDeduplicator::applyTagReplacement(
|
bool BlockDeduplicator::applyTagReplacement(
|
||||||
AssemblyItems& _items,
|
AssemblyItems& _items,
|
||||||
map<u256, u256> const& _replacements,
|
std::map<u256, u256> const& _replacements,
|
||||||
size_t _subId
|
size_t _subId
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -111,7 +110,7 @@ bool BlockDeduplicator::applyTagReplacement(
|
|||||||
{
|
{
|
||||||
size_t subId;
|
size_t subId;
|
||||||
size_t tagId;
|
size_t tagId;
|
||||||
tie(subId, tagId) = item.splitForeignPushTag();
|
std::tie(subId, tagId) = item.splitForeignPushTag();
|
||||||
if (subId != _subId)
|
if (subId != _subId)
|
||||||
continue;
|
continue;
|
||||||
auto it = _replacements.find(tagId);
|
auto it = _replacements.find(tagId);
|
||||||
|
@ -30,12 +30,11 @@
|
|||||||
|
|
||||||
#include <range/v3/view/reverse.hpp>
|
#include <range/v3/view/reverse.hpp>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
|
|
||||||
vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
|
std::vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
|
||||||
{
|
{
|
||||||
optimizeBreakingItem();
|
optimizeBreakingItem();
|
||||||
|
|
||||||
@ -52,11 +51,11 @@ vector<AssemblyItem> CommonSubexpressionEliminator::getOptimizedItems()
|
|||||||
m_state = std::move(nextState);
|
m_state = std::move(nextState);
|
||||||
});
|
});
|
||||||
|
|
||||||
map<int, Id> initialStackContents;
|
std::map<int, Id> initialStackContents;
|
||||||
map<int, Id> targetStackContents;
|
std::map<int, Id> targetStackContents;
|
||||||
int minHeight = m_state.stackHeight() + 1;
|
int minHeight = m_state.stackHeight() + 1;
|
||||||
if (!m_state.stackElements().empty())
|
if (!m_state.stackElements().empty())
|
||||||
minHeight = min(minHeight, m_state.stackElements().begin()->first);
|
minHeight = std::min(minHeight, m_state.stackElements().begin()->first);
|
||||||
for (int height = minHeight; height <= m_initialState.stackHeight(); ++height)
|
for (int height = minHeight; height <= m_initialState.stackHeight(); ++height)
|
||||||
initialStackContents[height] = m_initialState.stackElement(height, SourceLocation());
|
initialStackContents[height] = m_initialState.stackElement(height, SourceLocation());
|
||||||
for (int height = minHeight; height <= m_state.stackHeight(); ++height)
|
for (int height = minHeight; height <= m_state.stackHeight(); ++height)
|
||||||
@ -125,19 +124,19 @@ void CommonSubexpressionEliminator::optimizeBreakingItem()
|
|||||||
|
|
||||||
CSECodeGenerator::CSECodeGenerator(
|
CSECodeGenerator::CSECodeGenerator(
|
||||||
ExpressionClasses& _expressionClasses,
|
ExpressionClasses& _expressionClasses,
|
||||||
vector<CSECodeGenerator::StoreOperation> const& _storeOperations
|
std::vector<CSECodeGenerator::StoreOperation> const& _storeOperations
|
||||||
):
|
):
|
||||||
m_expressionClasses(_expressionClasses)
|
m_expressionClasses(_expressionClasses)
|
||||||
{
|
{
|
||||||
for (auto const& store: _storeOperations)
|
for (auto const& store: _storeOperations)
|
||||||
m_storeOperations[make_pair(store.target, store.slot)].push_back(store);
|
m_storeOperations[std::make_pair(store.target, store.slot)].push_back(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
AssemblyItems CSECodeGenerator::generateCode(
|
AssemblyItems CSECodeGenerator::generateCode(
|
||||||
unsigned _initialSequenceNumber,
|
unsigned _initialSequenceNumber,
|
||||||
int _initialStackHeight,
|
int _initialStackHeight,
|
||||||
map<int, Id> const& _initialStack,
|
std::map<int, Id> const& _initialStack,
|
||||||
map<int, Id> const& _targetStackContents
|
std::map<int, Id> const& _targetStackContents
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_stackHeight = _initialStackHeight;
|
m_stackHeight = _initialStackHeight;
|
||||||
@ -156,7 +155,7 @@ AssemblyItems CSECodeGenerator::generateCode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// store all needed sequenced expressions
|
// store all needed sequenced expressions
|
||||||
set<pair<unsigned, Id>> sequencedExpressions;
|
std::set<std::pair<unsigned, Id>> sequencedExpressions;
|
||||||
for (auto const& p: m_neededBy)
|
for (auto const& p: m_neededBy)
|
||||||
for (auto id: {p.first, p.second})
|
for (auto id: {p.first, p.second})
|
||||||
if (unsigned seqNr = m_expressionClasses.representative(id).sequenceNumber)
|
if (unsigned seqNr = m_expressionClasses.representative(id).sequenceNumber)
|
||||||
@ -165,7 +164,7 @@ AssemblyItems CSECodeGenerator::generateCode(
|
|||||||
// @todo quick fix for now. Proper fix needs to choose representative with higher
|
// @todo quick fix for now. Proper fix needs to choose representative with higher
|
||||||
// sequence number during dependency analysis.
|
// sequence number during dependency analysis.
|
||||||
assertThrow(seqNr >= _initialSequenceNumber, StackTooDeepException, util::stackTooDeepString);
|
assertThrow(seqNr >= _initialSequenceNumber, StackTooDeepException, util::stackTooDeepString);
|
||||||
sequencedExpressions.insert(make_pair(seqNr, id));
|
sequencedExpressions.insert(std::make_pair(seqNr, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform all operations on storage and memory in order, if they are needed.
|
// Perform all operations on storage and memory in order, if they are needed.
|
||||||
@ -230,7 +229,7 @@ void CSECodeGenerator::addDependencies(Id _c)
|
|||||||
for (Id argument: expr.arguments)
|
for (Id argument: expr.arguments)
|
||||||
{
|
{
|
||||||
addDependencies(argument);
|
addDependencies(argument);
|
||||||
m_neededBy.insert(make_pair(argument, _c));
|
m_neededBy.insert(std::make_pair(argument, _c));
|
||||||
}
|
}
|
||||||
if (expr.item && expr.item->type() == Operation && (
|
if (expr.item && expr.item->type() == Operation && (
|
||||||
expr.item->instruction() == Instruction::SLOAD ||
|
expr.item->instruction() == Instruction::SLOAD ||
|
||||||
@ -294,7 +293,7 @@ void CSECodeGenerator::addDependencies(Id _c)
|
|||||||
if (it->sequenceNumber < expr.sequenceNumber)
|
if (it->sequenceNumber < expr.sequenceNumber)
|
||||||
latestStore = it->expression;
|
latestStore = it->expression;
|
||||||
addDependencies(latestStore);
|
addDependencies(latestStore);
|
||||||
m_neededBy.insert(make_pair(latestStore, _c));
|
m_neededBy.insert(std::make_pair(latestStore, _c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,7 +330,7 @@ void CSECodeGenerator::generateClassElement(Id _c, bool _allowSequenced)
|
|||||||
OptimizerException,
|
OptimizerException,
|
||||||
"Undefined item requested but not available."
|
"Undefined item requested but not available."
|
||||||
);
|
);
|
||||||
vector<Id> const& arguments = expr.arguments;
|
std::vector<Id> const& arguments = expr.arguments;
|
||||||
for (Id arg: arguments | ranges::views::reverse)
|
for (Id arg: arguments | ranges::views::reverse)
|
||||||
generateClassElement(arg);
|
generateClassElement(arg);
|
||||||
|
|
||||||
@ -495,7 +494,7 @@ void CSECodeGenerator::appendOrRemoveSwap(int _fromPosition, SourceLocation cons
|
|||||||
m_classPositions[m_stack[m_stackHeight]].insert(_fromPosition);
|
m_classPositions[m_stack[m_stackHeight]].insert(_fromPosition);
|
||||||
m_classPositions[m_stack[_fromPosition]].erase(_fromPosition);
|
m_classPositions[m_stack[_fromPosition]].erase(_fromPosition);
|
||||||
m_classPositions[m_stack[_fromPosition]].insert(m_stackHeight);
|
m_classPositions[m_stack[_fromPosition]].insert(m_stackHeight);
|
||||||
swap(m_stack[m_stackHeight], m_stack[_fromPosition]);
|
std::swap(m_stack[m_stackHeight], m_stack[_fromPosition]);
|
||||||
}
|
}
|
||||||
if (m_generatedItems.size() >= 2 &&
|
if (m_generatedItems.size() >= 2 &&
|
||||||
SemanticInformation::isSwapInstruction(m_generatedItems.back()) &&
|
SemanticInformation::isSwapInstruction(m_generatedItems.back()) &&
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <libevmasm/Assembly.h>
|
#include <libevmasm/Assembly.h>
|
||||||
#include <libevmasm/GasMeter.h>
|
#include <libevmasm/GasMeter.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
|
|
||||||
@ -39,11 +38,11 @@ unsigned ConstantOptimisationMethod::optimiseConstants(
|
|||||||
AssemblyItems& _items = _assembly.items();
|
AssemblyItems& _items = _assembly.items();
|
||||||
|
|
||||||
unsigned optimisations = 0;
|
unsigned optimisations = 0;
|
||||||
map<AssemblyItem, size_t> pushes;
|
std::map<AssemblyItem, size_t> pushes;
|
||||||
for (AssemblyItem const& item: _items)
|
for (AssemblyItem const& item: _items)
|
||||||
if (item.type() == Push)
|
if (item.type() == Push)
|
||||||
pushes[item]++;
|
pushes[item]++;
|
||||||
map<u256, AssemblyItems> pendingReplacements;
|
std::map<u256, AssemblyItems> pendingReplacements;
|
||||||
for (auto it: pushes)
|
for (auto it: pushes)
|
||||||
{
|
{
|
||||||
AssemblyItem const& item = it.first;
|
AssemblyItem const& item = it.first;
|
||||||
@ -108,7 +107,7 @@ size_t ConstantOptimisationMethod::bytesRequired(AssemblyItems const& _items)
|
|||||||
|
|
||||||
void ConstantOptimisationMethod::replaceConstants(
|
void ConstantOptimisationMethod::replaceConstants(
|
||||||
AssemblyItems& _items,
|
AssemblyItems& _items,
|
||||||
map<u256, AssemblyItems> const& _replacements
|
std::map<u256, AssemblyItems> const& _replacements
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
AssemblyItems replaced;
|
AssemblyItems replaced;
|
||||||
@ -255,7 +254,7 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value)
|
|||||||
bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const
|
bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const& _routine) const
|
||||||
{
|
{
|
||||||
// This is a tiny EVM that can only evaluate some instructions.
|
// This is a tiny EVM that can only evaluate some instructions.
|
||||||
vector<u256> stack;
|
std::vector<u256> stack;
|
||||||
for (AssemblyItem const& item: _routine)
|
for (AssemblyItem const& item: _routine)
|
||||||
{
|
{
|
||||||
switch (item.type())
|
switch (item.type())
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include <libevmasm/SemanticInformation.h>
|
#include <libevmasm/SemanticInformation.h>
|
||||||
#include <libevmasm/KnownState.h>
|
#include <libevmasm/KnownState.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
|
|
||||||
@ -64,7 +63,7 @@ void ControlFlowGraph::findLargestTag()
|
|||||||
{
|
{
|
||||||
// Assert that it can be converted.
|
// Assert that it can be converted.
|
||||||
BlockId(item.data());
|
BlockId(item.data());
|
||||||
m_lastUsedId = max(unsigned(item.data()), m_lastUsedId);
|
m_lastUsedId = std::max(unsigned(item.data()), m_lastUsedId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +110,7 @@ void ControlFlowGraph::splitBlocks()
|
|||||||
|
|
||||||
void ControlFlowGraph::resolveNextLinks()
|
void ControlFlowGraph::resolveNextLinks()
|
||||||
{
|
{
|
||||||
map<unsigned, BlockId> blockByBeginPos;
|
std::map<unsigned, BlockId> blockByBeginPos;
|
||||||
for (auto const& idAndBlock: m_blocks)
|
for (auto const& idAndBlock: m_blocks)
|
||||||
if (idAndBlock.second.begin != idAndBlock.second.end)
|
if (idAndBlock.second.begin != idAndBlock.second.end)
|
||||||
blockByBeginPos[idAndBlock.second.begin] = idAndBlock.first;
|
blockByBeginPos[idAndBlock.second.begin] = idAndBlock.first;
|
||||||
@ -138,8 +137,8 @@ void ControlFlowGraph::resolveNextLinks()
|
|||||||
|
|
||||||
void ControlFlowGraph::removeUnusedBlocks()
|
void ControlFlowGraph::removeUnusedBlocks()
|
||||||
{
|
{
|
||||||
vector<BlockId> blocksToProcess{BlockId::initial()};
|
std::vector<BlockId> blocksToProcess{BlockId::initial()};
|
||||||
set<BlockId> neededBlocks{BlockId::initial()};
|
std::set<BlockId> neededBlocks{BlockId::initial()};
|
||||||
while (!blocksToProcess.empty())
|
while (!blocksToProcess.empty())
|
||||||
{
|
{
|
||||||
BasicBlock const& block = m_blocks.at(blocksToProcess.back());
|
BasicBlock const& block = m_blocks.at(blocksToProcess.back());
|
||||||
@ -219,16 +218,16 @@ void ControlFlowGraph::gatherKnowledge()
|
|||||||
{
|
{
|
||||||
// @todo actually we know that memory is filled with zeros at the beginning,
|
// @todo actually we know that memory is filled with zeros at the beginning,
|
||||||
// we could make use of that.
|
// we could make use of that.
|
||||||
KnownStatePointer emptyState = make_shared<KnownState>();
|
KnownStatePointer emptyState = std::make_shared<KnownState>();
|
||||||
bool unknownJumpEncountered = false;
|
bool unknownJumpEncountered = false;
|
||||||
|
|
||||||
struct WorkQueueItem {
|
struct WorkQueueItem {
|
||||||
BlockId blockId;
|
BlockId blockId;
|
||||||
KnownStatePointer state;
|
KnownStatePointer state;
|
||||||
set<BlockId> blocksSeen;
|
std::set<BlockId> blocksSeen;
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<WorkQueueItem> workQueue{WorkQueueItem{BlockId::initial(), emptyState->copy(), set<BlockId>()}};
|
std::vector<WorkQueueItem> workQueue{WorkQueueItem{BlockId::initial(), emptyState->copy(), std::set<BlockId>()}};
|
||||||
auto addWorkQueueItem = [&](WorkQueueItem const& _currentItem, BlockId _to, KnownStatePointer const& _state)
|
auto addWorkQueueItem = [&](WorkQueueItem const& _currentItem, BlockId _to, KnownStatePointer const& _state)
|
||||||
{
|
{
|
||||||
WorkQueueItem item;
|
WorkQueueItem item;
|
||||||
@ -275,7 +274,7 @@ void ControlFlowGraph::gatherKnowledge()
|
|||||||
assertThrow(block.begin <= pc && pc == block.end - 1, OptimizerException, "");
|
assertThrow(block.begin <= pc && pc == block.end - 1, OptimizerException, "");
|
||||||
//@todo in the case of JUMPI, add knowledge about the condition to the state
|
//@todo in the case of JUMPI, add knowledge about the condition to the state
|
||||||
// (for both values of the condition)
|
// (for both values of the condition)
|
||||||
set<u256> tags = state->tagsInExpression(
|
std::set<u256> tags = state->tagsInExpression(
|
||||||
state->stackElement(state->stackHeight(), langutil::SourceLocation{})
|
state->stackElement(state->stackHeight(), langutil::SourceLocation{})
|
||||||
);
|
);
|
||||||
state->feedItem(m_items.at(pc++));
|
state->feedItem(m_items.at(pc++));
|
||||||
@ -289,7 +288,7 @@ void ControlFlowGraph::gatherKnowledge()
|
|||||||
unknownJumpEncountered = true;
|
unknownJumpEncountered = true;
|
||||||
for (auto const& it: m_blocks)
|
for (auto const& it: m_blocks)
|
||||||
if (it.second.begin < it.second.end && m_items[it.second.begin].type() == Tag)
|
if (it.second.begin < it.second.end && m_items[it.second.begin].type() == Tag)
|
||||||
workQueue.push_back(WorkQueueItem{it.first, emptyState->copy(), set<BlockId>()});
|
workQueue.push_back(WorkQueueItem{it.first, emptyState->copy(), std::set<BlockId>()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -321,16 +320,16 @@ void ControlFlowGraph::gatherKnowledge()
|
|||||||
|
|
||||||
BasicBlocks ControlFlowGraph::rebuildCode()
|
BasicBlocks ControlFlowGraph::rebuildCode()
|
||||||
{
|
{
|
||||||
map<BlockId, unsigned> pushes;
|
std::map<BlockId, unsigned> pushes;
|
||||||
for (auto& idAndBlock: m_blocks)
|
for (auto& idAndBlock: m_blocks)
|
||||||
for (BlockId ref: idAndBlock.second.pushedTags)
|
for (BlockId ref: idAndBlock.second.pushedTags)
|
||||||
if (m_blocks.count(ref))
|
if (m_blocks.count(ref))
|
||||||
pushes[ref]++;
|
pushes[ref]++;
|
||||||
|
|
||||||
set<BlockId> blocksToAdd;
|
std::set<BlockId> blocksToAdd;
|
||||||
for (auto it: m_blocks)
|
for (auto it: m_blocks)
|
||||||
blocksToAdd.insert(it.first);
|
blocksToAdd.insert(it.first);
|
||||||
set<BlockId> blocksAdded;
|
std::set<BlockId> blocksAdded;
|
||||||
BasicBlocks blocks;
|
BasicBlocks blocks;
|
||||||
|
|
||||||
for (
|
for (
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include <libsolutil/CommonIO.h>
|
#include <libsolutil/CommonIO.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
@ -31,7 +30,7 @@ using namespace solidity::evmasm;
|
|||||||
void solidity::evmasm::eachInstruction(
|
void solidity::evmasm::eachInstruction(
|
||||||
bytes const& _mem,
|
bytes const& _mem,
|
||||||
langutil::EVMVersion _evmVersion,
|
langutil::EVMVersion _evmVersion,
|
||||||
function<void(Instruction,u256 const&)> const& _onInstruction
|
std::function<void(Instruction,u256 const&)> const& _onInstruction
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
for (auto it = _mem.begin(); it < _mem.end(); ++it)
|
for (auto it = _mem.begin(); it < _mem.end(); ++it)
|
||||||
@ -58,9 +57,9 @@ void solidity::evmasm::eachInstruction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string solidity::evmasm::disassemble(bytes const& _mem, langutil::EVMVersion _evmVersion, string const& _delimiter)
|
std::string solidity::evmasm::disassemble(bytes const& _mem, langutil::EVMVersion _evmVersion, std::string const& _delimiter)
|
||||||
{
|
{
|
||||||
stringstream ret;
|
std::stringstream ret;
|
||||||
eachInstruction(_mem, _evmVersion, [&](Instruction _instr, u256 const& _data) {
|
eachInstruction(_mem, _evmVersion, [&](Instruction _instr, u256 const& _data) {
|
||||||
if (!isValidInstruction(_instr))
|
if (!isValidInstruction(_instr))
|
||||||
ret << "0x" << std::uppercase << std::hex << static_cast<int>(_instr) << _delimiter;
|
ret << "0x" << std::uppercase << std::hex << static_cast<int>(_instr) << _delimiter;
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
@ -58,10 +57,10 @@ bool ExpressionClasses::Expression::operator==(ExpressionClasses::Expression con
|
|||||||
std::tie(_other.item->data(), _other.arguments, _other.sequenceNumber);
|
std::tie(_other.item->data(), _other.arguments, _other.sequenceNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t ExpressionClasses::Expression::ExpressionHash::operator()(Expression const& _expression) const
|
size_t ExpressionClasses::Expression::ExpressionHash::operator()(Expression const& _expression) const
|
||||||
{
|
{
|
||||||
assertThrow(!!_expression.item, OptimizerException, "");
|
assertThrow(!!_expression.item, OptimizerException, "");
|
||||||
std::size_t seed = 0;
|
size_t seed = 0;
|
||||||
auto type = _expression.item->type();
|
auto type = _expression.item->type();
|
||||||
boost::hash_combine(seed, type);
|
boost::hash_combine(seed, type);
|
||||||
|
|
||||||
@ -171,7 +170,7 @@ bool ExpressionClasses::knownNonZero(Id _c)
|
|||||||
|
|
||||||
u256 const* ExpressionClasses::knownConstant(Id _c)
|
u256 const* ExpressionClasses::knownConstant(Id _c)
|
||||||
{
|
{
|
||||||
map<unsigned, Expression const*> matchGroups;
|
std::map<unsigned, Expression const*> matchGroups;
|
||||||
Pattern constant(Push);
|
Pattern constant(Push);
|
||||||
constant.setMatchGroup(1, matchGroups);
|
constant.setMatchGroup(1, matchGroups);
|
||||||
if (!constant.matches(representative(_c), *this))
|
if (!constant.matches(representative(_c), *this))
|
||||||
@ -181,15 +180,15 @@ u256 const* ExpressionClasses::knownConstant(Id _c)
|
|||||||
|
|
||||||
AssemblyItem const* ExpressionClasses::storeItem(AssemblyItem const& _item)
|
AssemblyItem const* ExpressionClasses::storeItem(AssemblyItem const& _item)
|
||||||
{
|
{
|
||||||
m_spareAssemblyItems.push_back(make_shared<AssemblyItem>(_item));
|
m_spareAssemblyItems.push_back(std::make_shared<AssemblyItem>(_item));
|
||||||
return m_spareAssemblyItems.back().get();
|
return m_spareAssemblyItems.back().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const
|
std::string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const
|
||||||
{
|
{
|
||||||
Expression const& expr = representative(_id);
|
Expression const& expr = representative(_id);
|
||||||
stringstream str;
|
std::stringstream str;
|
||||||
str << dec << expr.id << ":";
|
str << std::dec << expr.id << ":";
|
||||||
if (expr.item)
|
if (expr.item)
|
||||||
{
|
{
|
||||||
str << *expr.item << "(";
|
str << *expr.item << "(";
|
||||||
@ -212,25 +211,25 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr)
|
|||||||
_expr.item->type() != Operation ||
|
_expr.item->type() != Operation ||
|
||||||
!SemanticInformation::isDeterministic(*_expr.item)
|
!SemanticInformation::isDeterministic(*_expr.item)
|
||||||
)
|
)
|
||||||
return numeric_limits<unsigned>::max();
|
return std::numeric_limits<unsigned>::max();
|
||||||
|
|
||||||
if (auto match = rules.findFirstMatch(_expr, *this))
|
if (auto match = rules.findFirstMatch(_expr, *this))
|
||||||
{
|
{
|
||||||
// Debug info
|
// Debug info
|
||||||
if (false)
|
if (false)
|
||||||
{
|
{
|
||||||
cout << "Simplifying " << *_expr.item << "(";
|
std::cout << "Simplifying " << *_expr.item << "(";
|
||||||
for (Id arg: _expr.arguments)
|
for (Id arg: _expr.arguments)
|
||||||
cout << fullDAGToString(arg) << ", ";
|
std::cout << fullDAGToString(arg) << ", ";
|
||||||
cout << ")" << endl;
|
std::cout << ")" << std::endl;
|
||||||
cout << "with rule " << match->pattern.toString() << endl;
|
std::cout << "with rule " << match->pattern.toString() << std::endl;
|
||||||
cout << "to " << match->action().toString() << endl;
|
std::cout << "to " << match->action().toString() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->location()));
|
return rebuildExpression(ExpressionTemplate(match->action(), _expr.item->location()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return numeric_limits<unsigned>::max();
|
return std::numeric_limits<unsigned>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionClasses::Id ExpressionClasses::rebuildExpression(ExpressionTemplate const& _template)
|
ExpressionClasses::Id ExpressionClasses::rebuildExpression(ExpressionTemplate const& _template)
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include <libevmasm/KnownState.h>
|
#include <libevmasm/KnownState.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
@ -32,7 +31,7 @@ GasMeter::GasConsumption& GasMeter::GasConsumption::operator+=(GasConsumption co
|
|||||||
if (isInfinite)
|
if (isInfinite)
|
||||||
return *this;
|
return *this;
|
||||||
bigint v = bigint(value) + _other.value;
|
bigint v = bigint(value) + _other.value;
|
||||||
if (v > numeric_limits<u256>::max())
|
if (v > std::numeric_limits<u256>::max())
|
||||||
*this = infinite();
|
*this = infinite();
|
||||||
else
|
else
|
||||||
value = u256(v);
|
value = u256(v);
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ u256 executionCost(RangeType const& _itemRange, langutil::EVMVersion _evmVersion
|
|||||||
[&gasMeter](auto const& _item) { return gasMeter.estimateMax(_item, false); }
|
[&gasMeter](auto const& _item) { return gasMeter.estimateMax(_item, false); }
|
||||||
), GasMeter::GasConsumption());
|
), GasMeter::GasConsumption());
|
||||||
if (gasConsumption.isInfinite)
|
if (gasConsumption.isInfinite)
|
||||||
return numeric_limits<u256>::max();
|
return std::numeric_limits<u256>::max();
|
||||||
else
|
else
|
||||||
return gasConsumption.value;
|
return gasConsumption.value;
|
||||||
}
|
}
|
||||||
@ -66,14 +65,14 @@ uint64_t codeSize(RangeType const& _itemRange)
|
|||||||
[](auto const& _item) { return _item.bytesRequired(2, Precision::Approximate); }
|
[](auto const& _item) { return _item.bytesRequired(2, Precision::Approximate); }
|
||||||
), 0u);
|
), 0u);
|
||||||
}
|
}
|
||||||
/// @returns the tag id, if @a _item is a PushTag or Tag into the current subassembly, nullopt otherwise.
|
/// @returns the tag id, if @a _item is a PushTag or Tag into the current subassembly, std::nullopt otherwise.
|
||||||
optional<size_t> getLocalTag(AssemblyItem const& _item)
|
std::optional<size_t> getLocalTag(AssemblyItem const& _item)
|
||||||
{
|
{
|
||||||
if (_item.type() != PushTag && _item.type() != Tag)
|
if (_item.type() != PushTag && _item.type() != Tag)
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
auto [subId, tag] = _item.splitForeignPushTag();
|
auto [subId, tag] = _item.splitForeignPushTag();
|
||||||
if (subId != numeric_limits<size_t>::max())
|
if (subId != std::numeric_limits<size_t>::max())
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,7 +98,7 @@ bool Inliner::isInlineCandidate(size_t _tag, ranges::span<AssemblyItem const> _i
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyItems const& _items) const
|
std::map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyItems const& _items) const
|
||||||
{
|
{
|
||||||
std::map<size_t, ranges::span<AssemblyItem const>> inlinableBlockItems;
|
std::map<size_t, ranges::span<AssemblyItem const>> inlinableBlockItems;
|
||||||
std::map<size_t, uint64_t> numPushTags;
|
std::map<size_t, uint64_t> numPushTags;
|
||||||
@ -108,7 +107,7 @@ map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyI
|
|||||||
{
|
{
|
||||||
// The number of PushTags approximates the number of calls to a block.
|
// The number of PushTags approximates the number of calls to a block.
|
||||||
if (item.type() == PushTag)
|
if (item.type() == PushTag)
|
||||||
if (optional<size_t> tag = getLocalTag(item))
|
if (std::optional<size_t> tag = getLocalTag(item))
|
||||||
++numPushTags[*tag];
|
++numPushTags[*tag];
|
||||||
|
|
||||||
// We can only inline blocks with straight control flow that end in a jump.
|
// We can only inline blocks with straight control flow that end in a jump.
|
||||||
@ -116,7 +115,7 @@ map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyI
|
|||||||
if (lastTag && SemanticInformation::breaksCSEAnalysisBlock(item, false))
|
if (lastTag && SemanticInformation::breaksCSEAnalysisBlock(item, false))
|
||||||
{
|
{
|
||||||
ranges::span<AssemblyItem const> block = _items | ranges::views::slice(*lastTag + 1, index + 1);
|
ranges::span<AssemblyItem const> block = _items | ranges::views::slice(*lastTag + 1, index + 1);
|
||||||
if (optional<size_t> tag = getLocalTag(_items[*lastTag]))
|
if (std::optional<size_t> tag = getLocalTag(_items[*lastTag]))
|
||||||
if (isInlineCandidate(*tag, block))
|
if (isInlineCandidate(*tag, block))
|
||||||
inlinableBlockItems[*tag] = block;
|
inlinableBlockItems[*tag] = block;
|
||||||
lastTag.reset();
|
lastTag.reset();
|
||||||
@ -130,7 +129,7 @@ map<size_t, Inliner::InlinableBlock> Inliner::determineInlinableBlocks(AssemblyI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store the number of PushTags alongside the assembly items and discard tags that are never pushed.
|
// Store the number of PushTags alongside the assembly items and discard tags that are never pushed.
|
||||||
map<size_t, InlinableBlock> result;
|
std::map<size_t, InlinableBlock> result;
|
||||||
for (auto&& [tag, items]: inlinableBlockItems)
|
for (auto&& [tag, items]: inlinableBlockItems)
|
||||||
if (uint64_t const* numPushes = util::valueOrNullptr(numPushTags, tag))
|
if (uint64_t const* numPushes = util::valueOrNullptr(numPushTags, tag))
|
||||||
result.emplace(tag, InlinableBlock{items, *numPushes});
|
result.emplace(tag, InlinableBlock{items, *numPushes});
|
||||||
@ -199,7 +198,7 @@ bool Inliner::shouldInlineFullFunctionBody(size_t _tag, ranges::span<AssemblyIte
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _jump, InlinableBlock const& _block) const
|
std::optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _jump, InlinableBlock const& _block) const
|
||||||
{
|
{
|
||||||
assertThrow(_jump == Instruction::JUMP, OptimizerException, "");
|
assertThrow(_jump == Instruction::JUMP, OptimizerException, "");
|
||||||
AssemblyItem blockExit = _block.items.back();
|
AssemblyItem blockExit = _block.items.back();
|
||||||
@ -232,7 +231,7 @@ optional<AssemblyItem> Inliner::shouldInline(size_t _tag, AssemblyItem const& _j
|
|||||||
return blockExit;
|
return blockExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -252,7 +251,7 @@ void Inliner::optimise()
|
|||||||
AssemblyItem const& nextItem = *next(it);
|
AssemblyItem const& nextItem = *next(it);
|
||||||
if (item.type() == PushTag && nextItem == Instruction::JUMP)
|
if (item.type() == PushTag && nextItem == Instruction::JUMP)
|
||||||
{
|
{
|
||||||
if (optional<size_t> tag = getLocalTag(item))
|
if (std::optional<size_t> tag = getLocalTag(item))
|
||||||
if (auto* inlinableBlock = util::valueOrNullptr(inlinableBlocks, *tag))
|
if (auto* inlinableBlock = util::valueOrNullptr(inlinableBlocks, *tag))
|
||||||
if (auto exitItem = shouldInline(*tag, nextItem, *inlinableBlock))
|
if (auto exitItem = shouldInline(*tag, nextItem, *inlinableBlock))
|
||||||
{
|
{
|
||||||
@ -264,7 +263,7 @@ void Inliner::optimise()
|
|||||||
// We might increase the number of push tags to other blocks.
|
// We might increase the number of push tags to other blocks.
|
||||||
for (AssemblyItem const& inlinedItem: inlinableBlock->items)
|
for (AssemblyItem const& inlinedItem: inlinableBlock->items)
|
||||||
if (inlinedItem.type() == PushTag)
|
if (inlinedItem.type() == PushTag)
|
||||||
if (optional<size_t> duplicatedTag = getLocalTag(inlinedItem))
|
if (std::optional<size_t> duplicatedTag = getLocalTag(inlinedItem))
|
||||||
if (auto* block = util::valueOrNullptr(inlinableBlocks, *duplicatedTag))
|
if (auto* block = util::valueOrNullptr(inlinableBlocks, *duplicatedTag))
|
||||||
++block->pushTagCount;
|
++block->pushTagCount;
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <libevmasm/Instruction.h>
|
#include <libevmasm/Instruction.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
@ -335,7 +334,7 @@ InstructionInfo solidity::evmasm::instructionInfo(Instruction _inst, langutil::E
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
return InstructionInfo({"<INVALID_INSTRUCTION: " + to_string(static_cast<unsigned>(_inst)) + ">", 0, 0, 0, false, Tier::Invalid});
|
return InstructionInfo({"<INVALID_INSTRUCTION: " + std::to_string(static_cast<unsigned>(_inst)) + ">", 0, 0, 0, false, Tier::Invalid});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,14 +26,13 @@
|
|||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
|
|
||||||
bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside)
|
bool JumpdestRemover::optimise(std::set<size_t> const& _tagsReferencedFromOutside)
|
||||||
{
|
{
|
||||||
set<size_t> references{referencedTags(m_items, numeric_limits<size_t>::max())};
|
std::set<size_t> references{referencedTags(m_items, std::numeric_limits<size_t>::max())};
|
||||||
references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end());
|
references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end());
|
||||||
|
|
||||||
size_t initialSize = m_items.size();
|
size_t initialSize = m_items.size();
|
||||||
@ -46,7 +45,7 @@ bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside)
|
|||||||
if (_item.type() != Tag)
|
if (_item.type() != Tag)
|
||||||
return false;
|
return false;
|
||||||
auto asmIdAndTag = _item.splitForeignPushTag();
|
auto asmIdAndTag = _item.splitForeignPushTag();
|
||||||
assertThrow(asmIdAndTag.first == numeric_limits<size_t>::max(), OptimizerException, "Sub-assembly tag used as label.");
|
assertThrow(asmIdAndTag.first == std::numeric_limits<size_t>::max(), OptimizerException, "Sub-assembly tag used as label.");
|
||||||
size_t tag = asmIdAndTag.second;
|
size_t tag = asmIdAndTag.second;
|
||||||
return !references.count(tag);
|
return !references.count(tag);
|
||||||
}
|
}
|
||||||
@ -55,9 +54,9 @@ bool JumpdestRemover::optimise(set<size_t> const& _tagsReferencedFromOutside)
|
|||||||
return m_items.size() != initialSize;
|
return m_items.size() != initialSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
set<size_t> JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t _subId)
|
std::set<size_t> JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t _subId)
|
||||||
{
|
{
|
||||||
set<size_t> ret;
|
std::set<size_t> ret;
|
||||||
for (auto const& item: _items)
|
for (auto const& item: _items)
|
||||||
if (item.type() == PushTag)
|
if (item.type() == PushTag)
|
||||||
{
|
{
|
||||||
|
@ -28,17 +28,16 @@
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
|
|
||||||
ostream& KnownState::stream(ostream& _out) const
|
std::ostream& KnownState::stream(std::ostream& _out) const
|
||||||
{
|
{
|
||||||
auto streamExpressionClass = [this](ostream& _out, Id _id)
|
auto streamExpressionClass = [this](std::ostream& _out, Id _id)
|
||||||
{
|
{
|
||||||
auto const& expr = m_expressionClasses->representative(_id);
|
auto const& expr = m_expressionClasses->representative(_id);
|
||||||
_out << " " << dec << _id << ": ";
|
_out << " " << std::dec << _id << ": ";
|
||||||
if (!expr.item)
|
if (!expr.item)
|
||||||
_out << " no item";
|
_out << " no item";
|
||||||
else if (expr.item->type() == UndefinedItem)
|
else if (expr.item->type() == UndefinedItem)
|
||||||
@ -46,26 +45,26 @@ ostream& KnownState::stream(ostream& _out) const
|
|||||||
else
|
else
|
||||||
_out << *expr.item;
|
_out << *expr.item;
|
||||||
if (expr.sequenceNumber)
|
if (expr.sequenceNumber)
|
||||||
_out << "@" << dec << expr.sequenceNumber;
|
_out << "@" << std::dec << expr.sequenceNumber;
|
||||||
_out << "(";
|
_out << "(";
|
||||||
for (Id arg: expr.arguments)
|
for (Id arg: expr.arguments)
|
||||||
_out << dec << arg << ",";
|
_out << std::dec << arg << ",";
|
||||||
_out << ")" << endl;
|
_out << ")" << std::endl;
|
||||||
};
|
};
|
||||||
|
|
||||||
_out << "=== State ===" << endl;
|
_out << "=== State ===" << std::endl;
|
||||||
_out << "Stack height: " << dec << m_stackHeight << endl;
|
_out << "Stack height: " << std::dec << m_stackHeight << std::endl;
|
||||||
_out << "Equivalence classes:" << endl;
|
_out << "Equivalence classes:" << std::endl;
|
||||||
for (Id eqClass = 0; eqClass < m_expressionClasses->size(); ++eqClass)
|
for (Id eqClass = 0; eqClass < m_expressionClasses->size(); ++eqClass)
|
||||||
streamExpressionClass(_out, eqClass);
|
streamExpressionClass(_out, eqClass);
|
||||||
|
|
||||||
_out << "Stack:" << endl;
|
_out << "Stack:" << std::endl;
|
||||||
for (auto const& it: m_stackElements)
|
for (auto const& it: m_stackElements)
|
||||||
{
|
{
|
||||||
_out << " " << dec << it.first << ": ";
|
_out << " " << std::dec << it.first << ": ";
|
||||||
streamExpressionClass(_out, it.second);
|
streamExpressionClass(_out, it.second);
|
||||||
}
|
}
|
||||||
_out << "Storage:" << endl;
|
_out << "Storage:" << std::endl;
|
||||||
for (auto const& it: m_storageContent)
|
for (auto const& it: m_storageContent)
|
||||||
{
|
{
|
||||||
_out << " ";
|
_out << " ";
|
||||||
@ -73,7 +72,7 @@ ostream& KnownState::stream(ostream& _out) const
|
|||||||
_out << ": ";
|
_out << ": ";
|
||||||
streamExpressionClass(_out, it.second);
|
streamExpressionClass(_out, it.second);
|
||||||
}
|
}
|
||||||
_out << "Memory:" << endl;
|
_out << "Memory:" << std::endl;
|
||||||
for (auto const& it: m_memoryContent)
|
for (auto const& it: m_memoryContent)
|
||||||
{
|
{
|
||||||
_out << " ";
|
_out << " ";
|
||||||
@ -149,7 +148,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
|
|||||||
);
|
);
|
||||||
else if (instruction != Instruction::POP)
|
else if (instruction != Instruction::POP)
|
||||||
{
|
{
|
||||||
vector<Id> arguments(static_cast<size_t>(info.args));
|
std::vector<Id> arguments(static_cast<size_t>(info.args));
|
||||||
for (size_t i = 0; i < static_cast<size_t>(info.args); ++i)
|
for (size_t i = 0; i < static_cast<size_t>(info.args); ++i)
|
||||||
arguments[i] = stackElement(m_stackHeight - static_cast<int>(i), _item.location());
|
arguments[i] = stackElement(m_stackHeight - static_cast<int>(i), _item.location());
|
||||||
switch (_item.instruction())
|
switch (_item.instruction())
|
||||||
@ -233,8 +232,8 @@ void KnownState::reduceToCommonKnowledge(KnownState const& _other, bool _combine
|
|||||||
++it;
|
++it;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set<u256> theseTags = tagsInExpression(it->second);
|
std::set<u256> theseTags = tagsInExpression(it->second);
|
||||||
set<u256> otherTags = tagsInExpression(other);
|
std::set<u256> otherTags = tagsInExpression(other);
|
||||||
if (!theseTags.empty() && !otherTags.empty())
|
if (!theseTags.empty() && !otherTags.empty())
|
||||||
{
|
{
|
||||||
theseTags.insert(otherTags.begin(), otherTags.end());
|
theseTags.insert(otherTags.begin(), otherTags.end());
|
||||||
@ -251,7 +250,7 @@ void KnownState::reduceToCommonKnowledge(KnownState const& _other, bool _combine
|
|||||||
// Use the smaller stack height. Essential to terminate in case of loops.
|
// Use the smaller stack height. Essential to terminate in case of loops.
|
||||||
if (m_stackHeight > _other.m_stackHeight)
|
if (m_stackHeight > _other.m_stackHeight)
|
||||||
{
|
{
|
||||||
map<int, Id> shiftedStack;
|
std::map<int, Id> shiftedStack;
|
||||||
for (auto const& stackElement: m_stackElements)
|
for (auto const& stackElement: m_stackElements)
|
||||||
shiftedStack[stackElement.first - stackDiff] = stackElement.second;
|
shiftedStack[stackElement.first - stackDiff] = stackElement.second;
|
||||||
m_stackElements = std::move(shiftedStack);
|
m_stackElements = std::move(shiftedStack);
|
||||||
@ -261,7 +260,7 @@ void KnownState::reduceToCommonKnowledge(KnownState const& _other, bool _combine
|
|||||||
intersect(m_storageContent, _other.m_storageContent);
|
intersect(m_storageContent, _other.m_storageContent);
|
||||||
intersect(m_memoryContent, _other.m_memoryContent);
|
intersect(m_memoryContent, _other.m_memoryContent);
|
||||||
if (_combineSequenceNumbers)
|
if (_combineSequenceNumbers)
|
||||||
m_sequenceNumber = max(m_sequenceNumber, _other.m_sequenceNumber);
|
m_sequenceNumber = std::max(m_sequenceNumber, _other.m_sequenceNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KnownState::operator==(KnownState const& _other) const
|
bool KnownState::operator==(KnownState const& _other) const
|
||||||
@ -316,7 +315,7 @@ void KnownState::swapStackElements(
|
|||||||
stackElement(_stackHeightA, _location);
|
stackElement(_stackHeightA, _location);
|
||||||
stackElement(_stackHeightB, _location);
|
stackElement(_stackHeightB, _location);
|
||||||
|
|
||||||
swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]);
|
std::swap(m_stackElements[_stackHeightA], m_stackElements[_stackHeightB]);
|
||||||
}
|
}
|
||||||
|
|
||||||
KnownState::StoreOperation KnownState::storeInStorage(
|
KnownState::StoreOperation KnownState::storeInStorage(
|
||||||
@ -400,7 +399,7 @@ KnownState::Id KnownState::applyKeccak256(
|
|||||||
if (!l || *l > 128)
|
if (!l || *l > 128)
|
||||||
return m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber);
|
return m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber);
|
||||||
unsigned length = unsigned(*l);
|
unsigned length = unsigned(*l);
|
||||||
vector<Id> arguments;
|
std::vector<Id> arguments;
|
||||||
for (unsigned i = 0; i < length; i += 32)
|
for (unsigned i = 0; i < length; i += 32)
|
||||||
{
|
{
|
||||||
Id slot = m_expressionClasses->find(
|
Id slot = m_expressionClasses->find(
|
||||||
@ -426,19 +425,19 @@ KnownState::Id KnownState::applyKeccak256(
|
|||||||
return m_knownKeccak256Hashes[{arguments, length}] = v;
|
return m_knownKeccak256Hashes[{arguments, length}] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
set<u256> KnownState::tagsInExpression(KnownState::Id _expressionId)
|
std::set<u256> KnownState::tagsInExpression(KnownState::Id _expressionId)
|
||||||
{
|
{
|
||||||
if (m_tagUnions.left.count(_expressionId))
|
if (m_tagUnions.left.count(_expressionId))
|
||||||
return m_tagUnions.left.at(_expressionId);
|
return m_tagUnions.left.at(_expressionId);
|
||||||
// Might be a tag, then return the set of itself.
|
// Might be a tag, then return the set of itself.
|
||||||
ExpressionClasses::Expression expr = m_expressionClasses->representative(_expressionId);
|
ExpressionClasses::Expression expr = m_expressionClasses->representative(_expressionId);
|
||||||
if (expr.item && expr.item->type() == PushTag)
|
if (expr.item && expr.item->type() == PushTag)
|
||||||
return set<u256>({expr.item->data()});
|
return std::set<u256>({expr.item->data()});
|
||||||
else
|
else
|
||||||
return set<u256>();
|
return std::set<u256>();
|
||||||
}
|
}
|
||||||
|
|
||||||
KnownState::Id KnownState::tagUnion(set<u256> _tags)
|
KnownState::Id KnownState::tagUnion(std::set<u256> _tags)
|
||||||
{
|
{
|
||||||
if (m_tagUnions.right.count(_tags))
|
if (m_tagUnions.right.count(_tags))
|
||||||
return m_tagUnions.right.at(_tags);
|
return m_tagUnions.right.at(_tags);
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <libsolutil/CommonData.h>
|
#include <libsolutil/CommonData.h>
|
||||||
#include <libsolutil/Keccak256.h>
|
#include <libsolutil/Keccak256.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
@ -36,24 +35,24 @@ void LinkerObject::append(LinkerObject const& _other)
|
|||||||
bytecode += _other.bytecode;
|
bytecode += _other.bytecode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkerObject::link(map<string, h160> const& _libraryAddresses)
|
void LinkerObject::link(std::map<std::string, h160> const& _libraryAddresses)
|
||||||
{
|
{
|
||||||
std::map<size_t, std::string> remainingRefs;
|
std::map<size_t, std::string> remainingRefs;
|
||||||
for (auto const& linkRef: linkReferences)
|
for (auto const& linkRef: linkReferences)
|
||||||
if (h160 const* address = matchLibrary(linkRef.second, _libraryAddresses))
|
if (h160 const* address = matchLibrary(linkRef.second, _libraryAddresses))
|
||||||
copy(address->data(), address->data() + 20, bytecode.begin() + vector<uint8_t>::difference_type(linkRef.first));
|
copy(address->data(), address->data() + 20, bytecode.begin() + std::vector<uint8_t>::difference_type(linkRef.first));
|
||||||
else
|
else
|
||||||
remainingRefs.insert(linkRef);
|
remainingRefs.insert(linkRef);
|
||||||
linkReferences.swap(remainingRefs);
|
linkReferences.swap(remainingRefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
string LinkerObject::toHex() const
|
std::string LinkerObject::toHex() const
|
||||||
{
|
{
|
||||||
string hex = solidity::util::toHex(bytecode);
|
std::string hex = solidity::util::toHex(bytecode);
|
||||||
for (auto const& ref: linkReferences)
|
for (auto const& ref: linkReferences)
|
||||||
{
|
{
|
||||||
size_t pos = ref.first * 2;
|
size_t pos = ref.first * 2;
|
||||||
string hash = libraryPlaceholder(ref.second);
|
std::string hash = libraryPlaceholder(ref.second);
|
||||||
hex[pos] = hex[pos + 1] = hex[pos + 38] = hex[pos + 39] = '_';
|
hex[pos] = hex[pos + 1] = hex[pos + 38] = hex[pos + 39] = '_';
|
||||||
for (size_t i = 0; i < 36; ++i)
|
for (size_t i = 0; i < 36; ++i)
|
||||||
hex[pos + 2 + i] = hash.at(i);
|
hex[pos + 2 + i] = hash.at(i);
|
||||||
@ -61,15 +60,15 @@ string LinkerObject::toHex() const
|
|||||||
return hex;
|
return hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
string LinkerObject::libraryPlaceholder(string const& _libraryName)
|
std::string LinkerObject::libraryPlaceholder(std::string const& _libraryName)
|
||||||
{
|
{
|
||||||
return "$" + keccak256(_libraryName).hex().substr(0, 34) + "$";
|
return "$" + keccak256(_libraryName).hex().substr(0, 34) + "$";
|
||||||
}
|
}
|
||||||
|
|
||||||
h160 const*
|
h160 const*
|
||||||
LinkerObject::matchLibrary(
|
LinkerObject::matchLibrary(
|
||||||
string const& _linkRefName,
|
std::string const& _linkRefName,
|
||||||
map<string, h160> const& _libraryAddresses
|
std::map<std::string, h160> const& _libraryAddresses
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto it = _libraryAddresses.find(_linkRefName);
|
auto it = _libraryAddresses.find(_linkRefName);
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <libevmasm/KnownState.h>
|
#include <libevmasm/KnownState.h>
|
||||||
#include <libevmasm/SemanticInformation.h>
|
#include <libevmasm/SemanticInformation.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
|
|
||||||
@ -38,17 +37,17 @@ PathGasMeter::PathGasMeter(AssemblyItems const& _items, langutil::EVMVersion _ev
|
|||||||
|
|
||||||
GasMeter::GasConsumption PathGasMeter::estimateMax(
|
GasMeter::GasConsumption PathGasMeter::estimateMax(
|
||||||
size_t _startIndex,
|
size_t _startIndex,
|
||||||
shared_ptr<KnownState> const& _state
|
std::shared_ptr<KnownState> const& _state
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto path = make_unique<GasPath>();
|
auto path = std::make_unique<GasPath>();
|
||||||
path->index = _startIndex;
|
path->index = _startIndex;
|
||||||
path->state = _state->copy();
|
path->state = _state->copy();
|
||||||
queue(std::move(path));
|
queue(std::move(path));
|
||||||
|
|
||||||
GasMeter::GasConsumption gas;
|
GasMeter::GasConsumption gas;
|
||||||
while (!m_queue.empty() && !gas.isInfinite)
|
while (!m_queue.empty() && !gas.isInfinite)
|
||||||
gas = max(gas, handleQueueItem());
|
gas = std::max(gas, handleQueueItem());
|
||||||
return gas;
|
return gas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,10 +66,10 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
|
|||||||
{
|
{
|
||||||
assertThrow(!m_queue.empty(), OptimizerException, "");
|
assertThrow(!m_queue.empty(), OptimizerException, "");
|
||||||
|
|
||||||
unique_ptr<GasPath> path = std::move(m_queue.rbegin()->second);
|
std::unique_ptr<GasPath> path = std::move(m_queue.rbegin()->second);
|
||||||
m_queue.erase(--m_queue.end());
|
m_queue.erase(--m_queue.end());
|
||||||
|
|
||||||
shared_ptr<KnownState> state = path->state;
|
std::shared_ptr<KnownState> state = path->state;
|
||||||
GasMeter meter(state, m_evmVersion, path->largestMemoryAccess);
|
GasMeter meter(state, m_evmVersion, path->largestMemoryAccess);
|
||||||
ExpressionClasses& classes = state->expressionClasses();
|
ExpressionClasses& classes = state->expressionClasses();
|
||||||
GasMeter::GasConsumption gas = path->gas;
|
GasMeter::GasConsumption gas = path->gas;
|
||||||
@ -82,7 +81,7 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
|
|||||||
// return the current gas value.
|
// return the current gas value.
|
||||||
return gas;
|
return gas;
|
||||||
|
|
||||||
set<u256> jumpTags;
|
std::set<u256> jumpTags;
|
||||||
for (; index < m_items.size() && !gas.isInfinite; ++index)
|
for (; index < m_items.size() && !gas.isInfinite; ++index)
|
||||||
{
|
{
|
||||||
bool branchStops = false;
|
bool branchStops = false;
|
||||||
@ -121,7 +120,7 @@ GasMeter::GasConsumption PathGasMeter::handleQueueItem()
|
|||||||
|
|
||||||
for (u256 const& tag: jumpTags)
|
for (u256 const& tag: jumpTags)
|
||||||
{
|
{
|
||||||
auto newPath = make_unique<GasPath>();
|
auto newPath = std::make_unique<GasPath>();
|
||||||
newPath->index = m_items.size();
|
newPath->index = m_items.size();
|
||||||
if (m_tagPositions.count(tag))
|
if (m_tagPositions.count(tag))
|
||||||
newPath->index = m_tagPositions.at(tag);
|
newPath->index = m_tagPositions.at(tag);
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include <libevmasm/AssemblyItem.h>
|
#include <libevmasm/AssemblyItem.h>
|
||||||
#include <libevmasm/SemanticInformation.h>
|
#include <libevmasm/SemanticInformation.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ struct OptimiserState
|
|||||||
{
|
{
|
||||||
AssemblyItems const& items;
|
AssemblyItems const& items;
|
||||||
size_t i;
|
size_t i;
|
||||||
back_insert_iterator<AssemblyItems> out;
|
std::back_insert_iterator<AssemblyItems> out;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename FunctionType>
|
template<typename FunctionType>
|
||||||
@ -55,8 +54,8 @@ struct SimplePeepholeOptimizerMethod
|
|||||||
template <size_t... Indices>
|
template <size_t... Indices>
|
||||||
static bool applyRule(
|
static bool applyRule(
|
||||||
AssemblyItems::const_iterator _in,
|
AssemblyItems::const_iterator _in,
|
||||||
back_insert_iterator<AssemblyItems> _out,
|
std::back_insert_iterator<AssemblyItems> _out,
|
||||||
index_sequence<Indices...>
|
std::index_sequence<Indices...>
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return Method::applySimple(_in[Indices]..., _out);
|
return Method::applySimple(_in[Indices]..., _out);
|
||||||
@ -66,7 +65,7 @@ struct SimplePeepholeOptimizerMethod
|
|||||||
static constexpr size_t WindowSize = FunctionParameterCount<decltype(Method::applySimple)>::value - 1;
|
static constexpr size_t WindowSize = FunctionParameterCount<decltype(Method::applySimple)>::value - 1;
|
||||||
if (
|
if (
|
||||||
_state.i + WindowSize <= _state.items.size() &&
|
_state.i + WindowSize <= _state.items.size() &&
|
||||||
applyRule(_state.items.begin() + static_cast<ptrdiff_t>(_state.i), _state.out, make_index_sequence<WindowSize>{})
|
applyRule(_state.items.begin() + static_cast<ptrdiff_t>(_state.i), _state.out, std::make_index_sequence<WindowSize>{})
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_state.i += WindowSize;
|
_state.i += WindowSize;
|
||||||
@ -81,7 +80,7 @@ struct Identity: SimplePeepholeOptimizerMethod<Identity>
|
|||||||
{
|
{
|
||||||
static bool applySimple(
|
static bool applySimple(
|
||||||
AssemblyItem const& _item,
|
AssemblyItem const& _item,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
*_out = _item;
|
*_out = _item;
|
||||||
@ -94,7 +93,7 @@ struct PushPop: SimplePeepholeOptimizerMethod<PushPop>
|
|||||||
static bool applySimple(
|
static bool applySimple(
|
||||||
AssemblyItem const& _push,
|
AssemblyItem const& _push,
|
||||||
AssemblyItem const& _pop,
|
AssemblyItem const& _pop,
|
||||||
back_insert_iterator<AssemblyItems>
|
std::back_insert_iterator<AssemblyItems>
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto t = _push.type();
|
auto t = _push.type();
|
||||||
@ -111,7 +110,7 @@ struct OpPop: SimplePeepholeOptimizerMethod<OpPop>
|
|||||||
static bool applySimple(
|
static bool applySimple(
|
||||||
AssemblyItem const& _op,
|
AssemblyItem const& _op,
|
||||||
AssemblyItem const& _pop,
|
AssemblyItem const& _pop,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (_pop == Instruction::POP && _op.type() == Operation)
|
if (_pop == Instruction::POP && _op.type() == Operation)
|
||||||
@ -133,7 +132,7 @@ struct OpStop: SimplePeepholeOptimizerMethod<OpStop>
|
|||||||
static bool applySimple(
|
static bool applySimple(
|
||||||
AssemblyItem const& _op,
|
AssemblyItem const& _op,
|
||||||
AssemblyItem const& _stop,
|
AssemblyItem const& _stop,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (_stop == Instruction::STOP)
|
if (_stop == Instruction::STOP)
|
||||||
@ -164,7 +163,7 @@ struct OpReturnRevert: SimplePeepholeOptimizerMethod<OpReturnRevert>
|
|||||||
AssemblyItem const& _push,
|
AssemblyItem const& _push,
|
||||||
AssemblyItem const& _pushOrDup,
|
AssemblyItem const& _pushOrDup,
|
||||||
AssemblyItem const& _returnRevert,
|
AssemblyItem const& _returnRevert,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
@ -191,7 +190,7 @@ struct DoubleSwap: SimplePeepholeOptimizerMethod<DoubleSwap>
|
|||||||
static size_t applySimple(
|
static size_t applySimple(
|
||||||
AssemblyItem const& _s1,
|
AssemblyItem const& _s1,
|
||||||
AssemblyItem const& _s2,
|
AssemblyItem const& _s2,
|
||||||
back_insert_iterator<AssemblyItems>
|
std::back_insert_iterator<AssemblyItems>
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return _s1 == _s2 && SemanticInformation::isSwapInstruction(_s1);
|
return _s1 == _s2 && SemanticInformation::isSwapInstruction(_s1);
|
||||||
@ -203,7 +202,7 @@ struct DoublePush: SimplePeepholeOptimizerMethod<DoublePush>
|
|||||||
static bool applySimple(
|
static bool applySimple(
|
||||||
AssemblyItem const& _push1,
|
AssemblyItem const& _push1,
|
||||||
AssemblyItem const& _push2,
|
AssemblyItem const& _push2,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data())
|
if (_push1.type() == Push && _push2.type() == Push && _push1.data() == _push2.data())
|
||||||
@ -222,7 +221,7 @@ struct CommutativeSwap: SimplePeepholeOptimizerMethod<CommutativeSwap>
|
|||||||
static bool applySimple(
|
static bool applySimple(
|
||||||
AssemblyItem const& _swap,
|
AssemblyItem const& _swap,
|
||||||
AssemblyItem const& _op,
|
AssemblyItem const& _op,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Remove SWAP1 if following instruction is commutative
|
// Remove SWAP1 if following instruction is commutative
|
||||||
@ -244,10 +243,10 @@ struct SwapComparison: SimplePeepholeOptimizerMethod<SwapComparison>
|
|||||||
static bool applySimple(
|
static bool applySimple(
|
||||||
AssemblyItem const& _swap,
|
AssemblyItem const& _swap,
|
||||||
AssemblyItem const& _op,
|
AssemblyItem const& _op,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
static map<Instruction, Instruction> const swappableOps{
|
static std::map<Instruction, Instruction> const swappableOps{
|
||||||
{ Instruction::LT, Instruction::GT },
|
{ Instruction::LT, Instruction::GT },
|
||||||
{ Instruction::GT, Instruction::LT },
|
{ Instruction::GT, Instruction::LT },
|
||||||
{ Instruction::SLT, Instruction::SGT },
|
{ Instruction::SLT, Instruction::SGT },
|
||||||
@ -274,7 +273,7 @@ struct DupSwap: SimplePeepholeOptimizerMethod<DupSwap>
|
|||||||
static size_t applySimple(
|
static size_t applySimple(
|
||||||
AssemblyItem const& _dupN,
|
AssemblyItem const& _dupN,
|
||||||
AssemblyItem const& _swapN,
|
AssemblyItem const& _swapN,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
@ -299,7 +298,7 @@ struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod<IsZeroIsZeroJumpI>
|
|||||||
AssemblyItem const& _iszero2,
|
AssemblyItem const& _iszero2,
|
||||||
AssemblyItem const& _pushTag,
|
AssemblyItem const& _pushTag,
|
||||||
AssemblyItem const& _jumpi,
|
AssemblyItem const& _jumpi,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
@ -325,7 +324,7 @@ struct EqIsZeroJumpI: SimplePeepholeOptimizerMethod<EqIsZeroJumpI>
|
|||||||
AssemblyItem const& _iszero,
|
AssemblyItem const& _iszero,
|
||||||
AssemblyItem const& _pushTag,
|
AssemblyItem const& _pushTag,
|
||||||
AssemblyItem const& _jumpi,
|
AssemblyItem const& _jumpi,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
@ -354,7 +353,7 @@ struct DoubleJump: SimplePeepholeOptimizerMethod<DoubleJump>
|
|||||||
AssemblyItem const& _pushTag2,
|
AssemblyItem const& _pushTag2,
|
||||||
AssemblyItem const& _jump,
|
AssemblyItem const& _jump,
|
||||||
AssemblyItem const& _tag1,
|
AssemblyItem const& _tag1,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
@ -383,7 +382,7 @@ struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext>
|
|||||||
AssemblyItem const& _pushTag,
|
AssemblyItem const& _pushTag,
|
||||||
AssemblyItem const& _jump,
|
AssemblyItem const& _jump,
|
||||||
AssemblyItem const& _tag,
|
AssemblyItem const& _tag,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
@ -409,7 +408,7 @@ struct TagConjunctions: SimplePeepholeOptimizerMethod<TagConjunctions>
|
|||||||
AssemblyItem const& _pushTag,
|
AssemblyItem const& _pushTag,
|
||||||
AssemblyItem const& _pushConstant,
|
AssemblyItem const& _pushConstant,
|
||||||
AssemblyItem const& _and,
|
AssemblyItem const& _and,
|
||||||
back_insert_iterator<AssemblyItems> _out
|
std::back_insert_iterator<AssemblyItems> _out
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (_and != Instruction::AND)
|
if (_and != Instruction::AND)
|
||||||
@ -444,7 +443,7 @@ struct TruthyAnd: SimplePeepholeOptimizerMethod<TruthyAnd>
|
|||||||
AssemblyItem const& _push,
|
AssemblyItem const& _push,
|
||||||
AssemblyItem const& _not,
|
AssemblyItem const& _not,
|
||||||
AssemblyItem const& _and,
|
AssemblyItem const& _and,
|
||||||
back_insert_iterator<AssemblyItems>
|
std::back_insert_iterator<AssemblyItems>
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
|
@ -25,11 +25,10 @@
|
|||||||
#include <libevmasm/SemanticInformation.h>
|
#include <libevmasm/SemanticInformation.h>
|
||||||
#include <libevmasm/AssemblyItem.h>
|
#include <libevmasm/AssemblyItem.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
|
|
||||||
vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(Instruction _instruction)
|
std::vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(Instruction _instruction)
|
||||||
{
|
{
|
||||||
switch (_instruction)
|
switch (_instruction)
|
||||||
{
|
{
|
||||||
@ -111,7 +110,7 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
|
|||||||
case Instruction::DELEGATECALL:
|
case Instruction::DELEGATECALL:
|
||||||
{
|
{
|
||||||
size_t paramCount = static_cast<size_t>(instructionInfo(_instruction, langutil::EVMVersion()).args);
|
size_t paramCount = static_cast<size_t>(instructionInfo(_instruction, langutil::EVMVersion()).args);
|
||||||
vector<Operation> operations{
|
std::vector<Operation> operations{
|
||||||
Operation{Location::Memory, Effect::Read, paramCount - 4, paramCount - 3, {}},
|
Operation{Location::Memory, Effect::Read, paramCount - 4, paramCount - 3, {}},
|
||||||
Operation{Location::Storage, Effect::Read, {}, {}, {}}
|
Operation{Location::Storage, Effect::Read, {}, {}, {}}
|
||||||
};
|
};
|
||||||
@ -130,7 +129,7 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
|
|||||||
}
|
}
|
||||||
case Instruction::CREATE:
|
case Instruction::CREATE:
|
||||||
case Instruction::CREATE2:
|
case Instruction::CREATE2:
|
||||||
return vector<Operation>{
|
return std::vector<Operation>{
|
||||||
Operation{
|
Operation{
|
||||||
Location::Memory,
|
Location::Memory,
|
||||||
Effect::Read,
|
Effect::Read,
|
||||||
@ -143,7 +142,7 @@ vector<SemanticInformation::Operation> SemanticInformation::readWriteOperations(
|
|||||||
};
|
};
|
||||||
case Instruction::MSIZE:
|
case Instruction::MSIZE:
|
||||||
// This is just to satisfy the assert below.
|
// This is just to satisfy the assert below.
|
||||||
return vector<Operation>{};
|
return std::vector<Operation>{};
|
||||||
default:
|
default:
|
||||||
assertThrow(storage(_instruction) == None && memory(_instruction) == None, AssemblyException, "");
|
assertThrow(storage(_instruction) == None && memory(_instruction) == None, AssemblyException, "");
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::evmasm;
|
using namespace solidity::evmasm;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
@ -92,7 +91,7 @@ Rules::Rules()
|
|||||||
Y.setMatchGroup(6, m_matchGroups);
|
Y.setMatchGroup(6, m_matchGroups);
|
||||||
Z.setMatchGroup(7, m_matchGroups);
|
Z.setMatchGroup(7, m_matchGroups);
|
||||||
|
|
||||||
addRules(simplificationRuleList(nullopt, A, B, C, W, X, Y, Z));
|
addRules(simplificationRuleList(std::nullopt, A, B, C, W, X, Y, Z));
|
||||||
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +102,7 @@ Pattern::Pattern(Instruction _instruction, std::initializer_list<Pattern> _argum
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pattern::setMatchGroup(unsigned _group, map<unsigned, Expression const*>& _matchGroups)
|
void Pattern::setMatchGroup(unsigned _group, std::map<unsigned, Expression const*>& _matchGroups)
|
||||||
{
|
{
|
||||||
m_matchGroup = _group;
|
m_matchGroup = _group;
|
||||||
m_matchGroups = &_matchGroups;
|
m_matchGroups = &_matchGroups;
|
||||||
@ -135,9 +134,9 @@ AssemblyItem Pattern::toAssemblyItem(SourceLocation const& _location) const
|
|||||||
return AssemblyItem(m_type, data(), _location);
|
return AssemblyItem(m_type, data(), _location);
|
||||||
}
|
}
|
||||||
|
|
||||||
string Pattern::toString() const
|
std::string Pattern::toString() const
|
||||||
{
|
{
|
||||||
stringstream s;
|
std::stringstream s;
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case Operation:
|
case Operation:
|
||||||
@ -146,7 +145,7 @@ string Pattern::toString() const
|
|||||||
break;
|
break;
|
||||||
case Push:
|
case Push:
|
||||||
if (m_data)
|
if (m_data)
|
||||||
s << "PUSH " << hex << data();
|
s << "PUSH " << std::hex << data();
|
||||||
else
|
else
|
||||||
s << "PUSH ";
|
s << "PUSH ";
|
||||||
break;
|
break;
|
||||||
@ -155,15 +154,15 @@ string Pattern::toString() const
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (m_data)
|
if (m_data)
|
||||||
s << "t=" << dec << m_type << " d=" << hex << data();
|
s << "t=" << std::dec << m_type << " d=" << std::hex << data();
|
||||||
else
|
else
|
||||||
s << "t=" << dec << m_type << " d: nullptr";
|
s << "t=" << std::dec << m_type << " d: nullptr";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!m_requireDataMatch)
|
if (!m_requireDataMatch)
|
||||||
s << " ~";
|
s << " ~";
|
||||||
if (m_matchGroup)
|
if (m_matchGroup)
|
||||||
s << "[" << dec << m_matchGroup << "]";
|
s << "[" << std::dec << m_matchGroup << "]";
|
||||||
s << "(";
|
s << "(";
|
||||||
for (Pattern const& p: m_arguments)
|
for (Pattern const& p: m_arguments)
|
||||||
s << p.toString() << ", ";
|
s << p.toString() << ", ";
|
||||||
@ -216,9 +215,9 @@ ExpressionTemplate::ExpressionTemplate(Pattern const& _pattern, SourceLocation c
|
|||||||
arguments.emplace_back(arg, _location);
|
arguments.emplace_back(arg, _location);
|
||||||
}
|
}
|
||||||
|
|
||||||
string ExpressionTemplate::toString() const
|
std::string ExpressionTemplate::toString() const
|
||||||
{
|
{
|
||||||
stringstream s;
|
std::stringstream s;
|
||||||
if (hasId)
|
if (hasId)
|
||||||
s << id;
|
s << id;
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user