mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[libevmasm] Add support to import evm assembly json.
This commit is contained in:
parent
fe1f9c640e
commit
025422b220
54
libevmasm/AbstractAssemblyStack.h
Normal file
54
libevmasm/AbstractAssemblyStack.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libevmasm/LinkerObject.h>
|
||||
|
||||
#include <libsolutil/Common.h>
|
||||
#include <libsolutil/JSON.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace solidity::evmasm
|
||||
{
|
||||
|
||||
class AbstractAssemblyStack
|
||||
{
|
||||
public:
|
||||
virtual ~AbstractAssemblyStack() {}
|
||||
|
||||
virtual LinkerObject const& object(std::string const& _contractName) const = 0;
|
||||
virtual LinkerObject const& runtimeObject(std::string const& _contractName) const = 0;
|
||||
|
||||
virtual std::string const* sourceMapping(std::string const& _contractName) const = 0;
|
||||
virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const = 0;
|
||||
|
||||
virtual Json::Value assemblyJSON(std::string const& _contractName) const = 0;
|
||||
virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const = 0;
|
||||
|
||||
virtual std::string const filesystemFriendlyName(std::string const& _contractName) const = 0;
|
||||
|
||||
virtual std::vector<std::string> contractNames() const = 0;
|
||||
virtual std::vector<std::string> sourceNames() const = 0;
|
||||
|
||||
virtual bool compilationSuccessful() const = 0;
|
||||
};
|
||||
|
||||
} // namespace solidity::evmasm
|
@ -34,13 +34,15 @@
|
||||
#include <liblangutil/CharStream.h>
|
||||
#include <liblangutil/Exceptions.h>
|
||||
|
||||
#include <json/json.h>
|
||||
#include <libsolutil/JSON.h>
|
||||
#include <libsolutil/StringUtils.h>
|
||||
|
||||
#include <range/v3/algorithm/any_of.hpp>
|
||||
#include <range/v3/view/enumerate.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <iterator>
|
||||
|
||||
using namespace solidity;
|
||||
using namespace solidity::evmasm;
|
||||
@ -73,6 +75,210 @@ unsigned Assembly::codeSize(unsigned subTagSize) const
|
||||
}
|
||||
}
|
||||
|
||||
void Assembly::importAssemblyItemsFromJSON(Json::Value const& _code, std::vector<std::string> const& _sourceList)
|
||||
{
|
||||
solAssert(m_items.empty());
|
||||
solRequire(_code.isArray(), AssemblyImportException, "Supplied JSON is not an array.");
|
||||
for (auto current = std::begin(_code); current != std::end(_code); ++current)
|
||||
{
|
||||
auto const& item = m_items.emplace_back(createAssemblyItemFromJSON(*current, _sourceList));
|
||||
if (item == Instruction::JUMPDEST)
|
||||
solThrow(AssemblyImportException, "JUMPDEST instruction without a tag");
|
||||
else if (item.type() == AssemblyItemType::Tag)
|
||||
{
|
||||
++current;
|
||||
if (current != std::end(_code) && createAssemblyItemFromJSON(*current, _sourceList) != Instruction::JUMPDEST)
|
||||
solThrow(AssemblyImportException, "JUMPDEST expected after tag.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AssemblyItem Assembly::createAssemblyItemFromJSON(Json::Value const& _json, std::vector<std::string> const& _sourceList)
|
||||
{
|
||||
solRequire(_json.isObject(), AssemblyImportException, "Supplied JSON is not an object.");
|
||||
static std::set<std::string> const validMembers{"name", "begin", "end", "source", "value", "modifierDepth", "jumpType"};
|
||||
for (auto const& member: _json.getMemberNames())
|
||||
solRequire(
|
||||
validMembers.count(member),
|
||||
AssemblyImportException,
|
||||
"Unknown member '" + member + "'. Valid members are " +
|
||||
solidity::util::joinHumanReadable(validMembers, ", ") + "."
|
||||
);
|
||||
solRequire(isOfType<std::string>(_json["name"]), AssemblyImportException, "Member 'name' missing or not of type string.");
|
||||
solRequire(isOfTypeIfExists<int>(_json, "begin"), AssemblyImportException, "Optional member 'begin' not of type int.");
|
||||
solRequire(isOfTypeIfExists<int>(_json, "end"), AssemblyImportException, "Optional member 'end' not of type int.");
|
||||
solRequire(isOfTypeIfExists<int>(_json, "source"), AssemblyImportException, "Optional member 'source' not of type int.");
|
||||
solRequire(isOfTypeIfExists<std::string>(_json, "value"), AssemblyImportException, "Optional member 'value' not of type string.");
|
||||
solRequire(
|
||||
isOfTypeIfExists<int>(_json, "modifierDepth"),
|
||||
AssemblyImportException,
|
||||
"Optional member 'modifierDepth' not of type int."
|
||||
);
|
||||
solRequire(
|
||||
isOfTypeIfExists<std::string>(_json, "jumpType"),
|
||||
AssemblyImportException,
|
||||
"Optional member 'jumpType' not of type string."
|
||||
);
|
||||
|
||||
std::string name = get<std::string>(_json["name"]);
|
||||
solRequire(!name.empty(), AssemblyImportException, "Member 'name' was empty.");
|
||||
|
||||
SourceLocation location;
|
||||
location.start = get<int>(_json["begin"]);
|
||||
location.end = get<int>(_json["end"]);
|
||||
int srcIndex = getOrDefault<int>(_json["source"], -1);
|
||||
size_t modifierDepth = static_cast<size_t>(getOrDefault<int>(_json["modifierDepth"], 0));
|
||||
std::string value = getOrDefault<std::string>(_json["value"], "");
|
||||
std::string jumpType = getOrDefault<std::string>(_json["jumpType"], "");
|
||||
|
||||
auto updateUsedTags = [&](u256 const& data)
|
||||
{
|
||||
m_usedTags = std::max(m_usedTags, static_cast<unsigned>(data) + 1);
|
||||
return data;
|
||||
};
|
||||
|
||||
auto storeImmutableHash = [&](std::string const& _immutableName) -> h256
|
||||
{
|
||||
h256 hash(util::keccak256(_immutableName));
|
||||
solAssert(m_immutables.count(hash) == 0 || m_immutables[hash] == _immutableName);
|
||||
m_immutables[hash] = _immutableName;
|
||||
return hash;
|
||||
};
|
||||
|
||||
auto storeLibraryHash = [&](std::string const& _libraryName) -> h256
|
||||
{
|
||||
h256 hash(util::keccak256(_libraryName));
|
||||
solAssert(m_libraries.count(hash) == 0 || m_libraries[hash] == _libraryName);
|
||||
m_libraries[hash] = _libraryName;
|
||||
return hash;
|
||||
};
|
||||
|
||||
auto requireValueDefinedForInstruction = [&](std::string const& _name, std::string const& _value)
|
||||
{
|
||||
solRequire(
|
||||
!_value.empty(),
|
||||
AssemblyImportException,
|
||||
"Member 'value' was not defined for instruction '" + _name + "', but the instruction needs a value."
|
||||
);
|
||||
};
|
||||
|
||||
auto requireValueUndefinedForInstruction = [&](std::string const& _name, std::string const& _value)
|
||||
{
|
||||
solRequire(
|
||||
_value.empty(),
|
||||
AssemblyImportException,
|
||||
"Member 'value' defined for instruction '" + _name + "', but the instruction does not need a value."
|
||||
);
|
||||
};
|
||||
|
||||
solRequire(srcIndex >= -1 && srcIndex < static_cast<int>(_sourceList.size()), AssemblyImportException, "srcIndex out of bound.");
|
||||
if (srcIndex != -1)
|
||||
{
|
||||
static std::map<std::string, std::shared_ptr<std::string const>> sharedSourceNames;
|
||||
if (sharedSourceNames.find(_sourceList[static_cast<size_t>(srcIndex)]) == sharedSourceNames.end())
|
||||
sharedSourceNames[_sourceList[static_cast<size_t>(srcIndex)]] = std::make_shared<std::string>(_sourceList[static_cast<size_t>(srcIndex)]);
|
||||
location.sourceName = sharedSourceNames[_sourceList[static_cast<size_t>(srcIndex)]];
|
||||
}
|
||||
|
||||
AssemblyItem result(0);
|
||||
|
||||
if (c_instructions.count(name))
|
||||
{
|
||||
AssemblyItem item{c_instructions.at(name), location};
|
||||
if (!jumpType.empty())
|
||||
{
|
||||
if (item.instruction() == Instruction::JUMP || item.instruction() == Instruction::JUMPI)
|
||||
item.setJumpType(jumpType);
|
||||
else
|
||||
solThrow(
|
||||
AssemblyImportException,
|
||||
"Member 'jumpType' set on instruction different from JUMP or JUMPI (was set on instruction '" + name + "')"
|
||||
);
|
||||
}
|
||||
requireValueUndefinedForInstruction(name, value);
|
||||
result = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
solRequire(
|
||||
jumpType.empty(),
|
||||
AssemblyImportException,
|
||||
"Member 'jumpType' set on instruction different from JUMP or JUMPI (was set on instruction '" + name + "')"
|
||||
);
|
||||
if (name == "PUSH")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::Push, u256("0x" + value)};
|
||||
}
|
||||
else if (name == "PUSH [ErrorTag]")
|
||||
{
|
||||
requireValueUndefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::PushTag, 0};
|
||||
}
|
||||
else if (name == "PUSH [tag]")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::PushTag, updateUsedTags(u256(value))};
|
||||
}
|
||||
else if (name == "PUSH [$]")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::PushSub, u256("0x" + value)};
|
||||
}
|
||||
else if (name == "PUSH #[$]")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::PushSubSize, u256("0x" + value)};
|
||||
}
|
||||
else if (name == "PUSHSIZE")
|
||||
{
|
||||
requireValueUndefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::PushProgramSize, 0};
|
||||
}
|
||||
else if (name == "PUSHLIB")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::PushLibraryAddress, storeLibraryHash(value)};
|
||||
}
|
||||
else if (name == "PUSHDEPLOYADDRESS")
|
||||
{
|
||||
requireValueUndefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::PushDeployTimeAddress, 0};
|
||||
}
|
||||
else if (name == "PUSHIMMUTABLE")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::PushImmutable, storeImmutableHash(value)};
|
||||
}
|
||||
else if (name == "ASSIGNIMMUTABLE")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::AssignImmutable, storeImmutableHash(value)};
|
||||
}
|
||||
else if (name == "tag")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::Tag, updateUsedTags(u256(value))};
|
||||
}
|
||||
else if (name == "PUSH data")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
result = {AssemblyItemType::PushData, u256("0x" + value)};
|
||||
}
|
||||
else if (name == "VERBATIM")
|
||||
{
|
||||
requireValueDefinedForInstruction(name, value);
|
||||
AssemblyItem item(fromHex(value), 0, 0);
|
||||
result = item;
|
||||
}
|
||||
else
|
||||
solThrow(InvalidOpcode, "Invalid opcode: " + name);
|
||||
}
|
||||
result.setLocation(location);
|
||||
result.m_modifierDepth = modifierDepth;
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -221,7 +427,7 @@ std::string Assembly::assemblyString(
|
||||
return tmp.str();
|
||||
}
|
||||
|
||||
Json::Value Assembly::assemblyJSON(std::map<std::string, unsigned> const& _sourceIndices, bool _includeSourceList) const
|
||||
Json::Value Assembly::assemblyJSON(std::vector<std::string> const& _sources, bool _includeSourceList) const
|
||||
{
|
||||
Json::Value root;
|
||||
root[".code"] = Json::arrayValue;
|
||||
@ -230,11 +436,12 @@ Json::Value Assembly::assemblyJSON(std::map<std::string, unsigned> const& _sourc
|
||||
{
|
||||
int sourceIndex = -1;
|
||||
if (item.location().sourceName)
|
||||
{
|
||||
auto iter = _sourceIndices.find(*item.location().sourceName);
|
||||
if (iter != _sourceIndices.end())
|
||||
sourceIndex = static_cast<int>(iter->second);
|
||||
}
|
||||
for (size_t index = 0; index < _sources.size(); ++index)
|
||||
if (_sources[index] == *item.location().sourceName)
|
||||
{
|
||||
sourceIndex = static_cast<int>(index);
|
||||
break;
|
||||
}
|
||||
|
||||
auto [name, data] = item.nameAndData(m_evmVersion);
|
||||
Json::Value jsonItem;
|
||||
@ -267,12 +474,12 @@ Json::Value Assembly::assemblyJSON(std::map<std::string, unsigned> const& _sourc
|
||||
code.append(std::move(jumpdest));
|
||||
}
|
||||
}
|
||||
if (_includeSourceList)
|
||||
if (!_sources.empty() && _includeSourceList)
|
||||
{
|
||||
root["sourceList"] = Json::arrayValue;
|
||||
Json::Value& jsonSourceList = root["sourceList"];
|
||||
for (auto const& [name, index]: _sourceIndices)
|
||||
jsonSourceList[index] = name;
|
||||
for (int index = 0; index < static_cast<int>(_sources.size()); ++index)
|
||||
jsonSourceList[index] = _sources[static_cast<size_t>(index)];
|
||||
}
|
||||
|
||||
if (!m_data.empty() || !m_subs.empty())
|
||||
@ -287,7 +494,8 @@ Json::Value Assembly::assemblyJSON(std::map<std::string, unsigned> const& _sourc
|
||||
{
|
||||
std::stringstream hexStr;
|
||||
hexStr << std::hex << i;
|
||||
data[hexStr.str()] = m_subs[i]->assemblyJSON(_sourceIndices, /*_includeSourceList = */false);
|
||||
data[hexStr.str()] = m_subs[i]->assemblyJSON(_sources, false);
|
||||
data[hexStr.str()]["index"] = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -297,6 +505,130 @@ Json::Value Assembly::assemblyJSON(std::map<std::string, unsigned> const& _sourc
|
||||
return root;
|
||||
}
|
||||
|
||||
std::pair<std::shared_ptr<Assembly>, std::vector<std::string>> Assembly::fromJSON(Json::Value const& _json, std::vector<std::string> const& _sourceList, int _level)
|
||||
{
|
||||
solRequire(_json.isObject(), AssemblyImportException, "Supplied JSON is not an object.");
|
||||
static std::set<std::string> const validMembers{".code", ".data", ".auxdata", "sourceList", "index"};
|
||||
for (auto const& attribute: _json.getMemberNames())
|
||||
solRequire(validMembers.count(attribute), AssemblyImportException, "Unknown attribute '" + attribute + "'.");
|
||||
solRequire(_json.isMember(".code"), AssemblyImportException, "Member '.code' does not exist.");
|
||||
solRequire(_json[".code"].isArray(), AssemblyImportException, "Member '.code' is not an array.");
|
||||
for (auto const& codeItem: _json[".code"])
|
||||
solRequire(codeItem.isObject(), AssemblyImportException, "Item of '.code' array is not an object.");
|
||||
|
||||
if (_level == 0)
|
||||
{
|
||||
if (_json.isMember("sourceList"))
|
||||
{
|
||||
solRequire(_json["sourceList"].isArray(), AssemblyImportException, "Optional member 'sourceList' is not an array.");
|
||||
for (auto const& sourceListItem: _json["sourceList"])
|
||||
solRequire(sourceListItem.isString(), AssemblyImportException, "Item of 'sourceList' array is not of type string.");
|
||||
}
|
||||
} else
|
||||
solRequire(
|
||||
!_json.isMember("sourceList"),
|
||||
AssemblyImportException,
|
||||
"Member 'sourceList' is only allowed in root JSON object."
|
||||
);
|
||||
|
||||
std::shared_ptr<Assembly> result = std::make_shared<Assembly>(langutil::EVMVersion(), _level == 0, "");
|
||||
std::vector<std::string> sourceList;
|
||||
if (_json.isMember("sourceList"))
|
||||
{
|
||||
solAssert(_level == 0);
|
||||
for (auto const& it: _json["sourceList"])
|
||||
{
|
||||
solRequire(
|
||||
std::find(sourceList.begin(), sourceList.end(), it.asString()) == sourceList.end(),
|
||||
AssemblyImportException,
|
||||
"Items in 'sourceList' array are not unique."
|
||||
);
|
||||
sourceList.emplace_back(it.asString());
|
||||
}
|
||||
} else
|
||||
sourceList = _sourceList;
|
||||
|
||||
result->importAssemblyItemsFromJSON(_json[".code"], sourceList);
|
||||
if (_json[".auxdata"])
|
||||
{
|
||||
solRequire(_json[".auxdata"].isString(), AssemblyImportException, "Optional member '.auxdata' is not of type string.");
|
||||
bytes auxdata{fromHex(_json[".auxdata"].asString())};
|
||||
solRequire(!auxdata.empty(), AssemblyImportException, "Optional member '.auxdata' is not a valid hexadecimal string.");
|
||||
result->m_auxiliaryData = auxdata;
|
||||
}
|
||||
|
||||
if (_json.isMember(".data"))
|
||||
{
|
||||
solRequire(_json[".data"].isObject(), AssemblyImportException, "Optional member '.data' is not an object.");
|
||||
Json::Value const& data = _json[".data"];
|
||||
for (Json::ValueConstIterator dataIter = data.begin(); dataIter != data.end(); dataIter++)
|
||||
{
|
||||
solRequire(dataIter.key().isString(), AssemblyImportException, "Key inside '.data' is not of type string.");
|
||||
std::string dataItemID = dataIter.key().asString();
|
||||
Json::Value const& code = data[dataItemID];
|
||||
if (code.isString())
|
||||
{
|
||||
if (!code.asString().empty())
|
||||
{
|
||||
bytes data_value{fromHex(code.asString())};
|
||||
solRequire(
|
||||
!data_value.empty(),
|
||||
AssemblyImportException,
|
||||
"Member '.data' contains a value for '" + dataItemID + "' that is not a valid hexadecimal string.");
|
||||
}
|
||||
result->m_data[h256(fromHex(dataItemID))] = fromHex(code.asString());
|
||||
}
|
||||
else if (code.isObject())
|
||||
{
|
||||
solAssert(code.isMember("index"));
|
||||
size_t index = static_cast<size_t>(code["index"].asInt());
|
||||
if (result->m_subs.size() <= index)
|
||||
result->m_subs.resize(index + 1);
|
||||
std::shared_ptr<Assembly> subassembly(Assembly::fromJSON(code, sourceList, _level + 1).first);
|
||||
solAssert(subassembly);
|
||||
result->m_subs[index] = subassembly;
|
||||
}
|
||||
else
|
||||
solThrow(AssemblyImportException, "Key inside '.data' '" + dataItemID + "' can only be a valid hex-string or an object.");
|
||||
}
|
||||
}
|
||||
if (_level == 0)
|
||||
result->updatePaths();
|
||||
return std::make_pair(result, sourceList);
|
||||
}
|
||||
|
||||
void Assembly::updatePaths(std::vector<Assembly*> const& _parents, std::vector<size_t> const& _absolutePathFromRoot)
|
||||
{
|
||||
size_t subId = 0;
|
||||
for (auto& assembly: this->m_subs)
|
||||
{
|
||||
std::vector<Assembly*> parents{_parents};
|
||||
parents.push_back(this);
|
||||
|
||||
std::vector<size_t> absolutePathFromRoot{_absolutePathFromRoot};
|
||||
absolutePathFromRoot.emplace_back(subId);
|
||||
|
||||
int pindex = 0;
|
||||
for (auto& parent: parents)
|
||||
{
|
||||
if (pindex == 0)
|
||||
parent->encodeSubPath(absolutePathFromRoot);
|
||||
else
|
||||
{
|
||||
std::vector<size_t> relativePath{absolutePathFromRoot};
|
||||
for (int i = 0; i < pindex; ++i)
|
||||
relativePath.erase(relativePath.begin());
|
||||
parent->encodeSubPath(relativePath);
|
||||
}
|
||||
++pindex;
|
||||
}
|
||||
|
||||
assembly->updatePaths(parents, absolutePathFromRoot);
|
||||
|
||||
++subId;
|
||||
}
|
||||
}
|
||||
|
||||
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.");
|
||||
|
@ -150,10 +150,18 @@ public:
|
||||
) const;
|
||||
|
||||
/// Create a JSON representation of the assembly.
|
||||
Json::Value assemblyJSON(
|
||||
std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>(),
|
||||
bool _includeSourceList = true
|
||||
) const;
|
||||
Json::Value assemblyJSON(std::vector<std::string> const& _sources, bool _includeSourceList = true) const;
|
||||
|
||||
/// Loads the JSON representation of assembly.
|
||||
/// @param _json JSON object containing assembly in the format produced by assemblyJSON().
|
||||
/// @param _sourceList list of source names (used to supply the source-list from the root-assembly object to sub-assemblies).
|
||||
/// @param _level this function might be called recursively, _level reflects the nesting level.
|
||||
/// @returns Resulting Assembly object loaded from given json.
|
||||
static std::pair<std::shared_ptr<Assembly>, std::vector<std::string>> fromJSON(
|
||||
Json::Value const& _json,
|
||||
std::vector<std::string> const& _sourceList = {},
|
||||
int _level = 0
|
||||
);
|
||||
|
||||
/// Mark this assembly as invalid. Calling ``assemble`` on it will throw.
|
||||
void markAsInvalid() { m_invalid = true; }
|
||||
@ -171,11 +179,25 @@ protected:
|
||||
|
||||
unsigned codeSize(unsigned subTagSize) const;
|
||||
|
||||
/// Add all assembly items from given JSON array. This function imports the items by iterating through
|
||||
/// the code array. This method only works on clean Assembly objects that don't have any items defined yet.
|
||||
/// @param _json JSON array that contains assembly items (e.g. json['.code'])
|
||||
/// @param _sourceList list of source names.
|
||||
void importAssemblyItemsFromJSON(Json::Value const& _code, std::vector<std::string> const& _sourceList);
|
||||
|
||||
/// Creates an AssemblyItem from a given JSON representation.
|
||||
/// @param _json JSON object that consists a single assembly item
|
||||
/// @param _sourceList list of source names.
|
||||
/// @returns AssemblyItem of _json argument.
|
||||
AssemblyItem createAssemblyItemFromJSON(Json::Value const& _json, std::vector<std::string> const& _sourceList);
|
||||
|
||||
private:
|
||||
bool m_invalid = false;
|
||||
|
||||
Assembly const* subAssemblyById(size_t _subId) const;
|
||||
|
||||
void updatePaths(std::vector<Assembly *> const& _parents = {}, std::vector<size_t> const& _absolutePathFromRoot = {});
|
||||
|
||||
protected:
|
||||
/// 0 is reserved for exception
|
||||
unsigned m_usedTags = 1;
|
||||
@ -217,7 +239,6 @@ protected:
|
||||
/// Internal name of the assembly object, only used with the Yul backend
|
||||
/// currently
|
||||
std::string m_name;
|
||||
|
||||
langutil::SourceLocation m_currentSourceLocation;
|
||||
|
||||
public:
|
||||
|
@ -247,6 +247,18 @@ std::string AssemblyItem::getJumpTypeAsString() const
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyItem::setJumpType(std::string const& _jumpType)
|
||||
{
|
||||
if (_jumpType == "[in]")
|
||||
m_jumpType = JumpType::IntoFunction;
|
||||
else if (_jumpType == "[out]")
|
||||
m_jumpType = JumpType::OutOfFunction;
|
||||
else if (_jumpType.empty())
|
||||
m_jumpType = JumpType::Ordinary;
|
||||
else
|
||||
solThrow(AssemblyImportException, "Invalid jump type.");
|
||||
}
|
||||
|
||||
std::string AssemblyItem::toAssemblyText(Assembly const& _assembly) const
|
||||
{
|
||||
std::string text;
|
||||
|
@ -174,6 +174,7 @@ public:
|
||||
langutil::SourceLocation const& location() const { return m_location; }
|
||||
|
||||
void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; }
|
||||
void setJumpType(std::string const& _jumpType);
|
||||
JumpType getJumpType() const { return m_jumpType; }
|
||||
std::string getJumpTypeAsString() const;
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
set(sources
|
||||
AbstractAssemblyStack.h
|
||||
Assembly.cpp
|
||||
Assembly.h
|
||||
AssemblyItem.cpp
|
||||
AssemblyItem.h
|
||||
EVMAssemblyStack.cpp
|
||||
EVMAssemblyStack.h
|
||||
BlockDeduplicator.cpp
|
||||
BlockDeduplicator.h
|
||||
CommonSubexpressionEliminator.cpp
|
||||
|
126
libevmasm/EVMAssemblyStack.cpp
Normal file
126
libevmasm/EVMAssemblyStack.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#include <libevmasm/EVMAssemblyStack.h>
|
||||
|
||||
#include <libsolutil/JSON.h>
|
||||
#include <liblangutil/Exceptions.h>
|
||||
#include <libsolidity/codegen/CompilerContext.h>
|
||||
|
||||
using namespace solidity::util;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
|
||||
namespace solidity::evmasm
|
||||
{
|
||||
|
||||
void EVMAssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string const& _source)
|
||||
{
|
||||
solAssert(!m_evmAssembly);
|
||||
m_name = _sourceName;
|
||||
solRequire(jsonParseStrict(_source, m_json), AssemblyImportException, "Could not parse JSON file.");
|
||||
auto result = evmasm::Assembly::fromJSON(m_json);
|
||||
m_evmAssembly = result.first;
|
||||
m_sourceList = result.second;
|
||||
solRequire(m_evmAssembly != nullptr, AssemblyImportException, "Could not create evm assembly object.");
|
||||
}
|
||||
|
||||
void EVMAssemblyStack::assemble()
|
||||
{
|
||||
solAssert(m_evmAssembly);
|
||||
solAssert(m_evmAssembly->isCreation());
|
||||
solAssert(!m_evmRuntimeAssembly);
|
||||
|
||||
m_object = m_evmAssembly->assemble();
|
||||
m_sourceMapping = AssemblyItem::computeSourceMapping(m_evmAssembly->items(), sourceIndices());
|
||||
if (m_evmAssembly->numSubs() > 0)
|
||||
{
|
||||
m_evmRuntimeAssembly = std::make_shared<evmasm::Assembly>(m_evmAssembly->sub(0));
|
||||
solAssert(m_evmRuntimeAssembly && !m_evmRuntimeAssembly->isCreation());
|
||||
m_runtimeSourceMapping = AssemblyItem::computeSourceMapping(m_evmRuntimeAssembly->items(), sourceIndices());
|
||||
m_runtimeObject = m_evmRuntimeAssembly->assemble();
|
||||
}
|
||||
}
|
||||
|
||||
LinkerObject const& EVMAssemblyStack::object(std::string const& _contractName) const
|
||||
{
|
||||
solAssert(_contractName == m_name);
|
||||
return m_object;
|
||||
}
|
||||
|
||||
LinkerObject const& EVMAssemblyStack::runtimeObject(std::string const& _contractName) const
|
||||
{
|
||||
solAssert(_contractName == m_name);
|
||||
return m_runtimeObject;
|
||||
}
|
||||
|
||||
std::map<std::string, unsigned> EVMAssemblyStack::sourceIndices() const
|
||||
{
|
||||
solAssert(m_evmAssembly);
|
||||
std::map<std::string, unsigned> indices;
|
||||
unsigned index = 0;
|
||||
for (auto const& s: m_sourceList)
|
||||
if (s != CompilerContext::yulUtilityFileName())
|
||||
indices[s] = index++;
|
||||
|
||||
if (indices.find(CompilerContext::yulUtilityFileName()) == indices.end())
|
||||
indices[CompilerContext::yulUtilityFileName()] = index++;
|
||||
return indices;
|
||||
}
|
||||
|
||||
std::string const* EVMAssemblyStack::sourceMapping(std::string const& _contractName) const
|
||||
{
|
||||
solAssert(_contractName == m_name);
|
||||
return &m_sourceMapping;
|
||||
}
|
||||
|
||||
std::string const* EVMAssemblyStack::runtimeSourceMapping(std::string const& _contractName) const
|
||||
{
|
||||
solAssert(_contractName == m_name);
|
||||
return &m_runtimeSourceMapping;
|
||||
}
|
||||
|
||||
Json::Value EVMAssemblyStack::assemblyJSON(std::string const& _contractName) const
|
||||
{
|
||||
solAssert(_contractName == m_name);
|
||||
solAssert(m_evmAssembly);
|
||||
std::vector<std::string> sources = sourceNames();
|
||||
if (find(sources.begin(), sources.end(), CompilerContext::yulUtilityFileName()) == sources.end())
|
||||
sources.emplace_back(CompilerContext::yulUtilityFileName());
|
||||
return m_evmAssembly->assemblyJSON(sources);
|
||||
}
|
||||
|
||||
std::string EVMAssemblyStack::assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const
|
||||
{
|
||||
solAssert(_contractName == m_name);
|
||||
solAssert(m_evmAssembly);
|
||||
return m_evmAssembly->assemblyString(m_debugInfoSelection, _sourceCodes);
|
||||
}
|
||||
|
||||
std::string const EVMAssemblyStack::filesystemFriendlyName(std::string const& _contractName) const
|
||||
{
|
||||
solAssert(_contractName == m_name);
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::vector<std::string> EVMAssemblyStack::sourceNames() const
|
||||
{
|
||||
return m_sourceList;
|
||||
}
|
||||
|
||||
} // namespace solidity::evmasm
|
86
libevmasm/EVMAssemblyStack.h
Normal file
86
libevmasm/EVMAssemblyStack.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libevmasm/AbstractAssemblyStack.h>
|
||||
#include <libevmasm/Assembly.h>
|
||||
#include <libevmasm/LinkerObject.h>
|
||||
|
||||
#include <libsolutil/JSON.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace solidity::evmasm
|
||||
{
|
||||
|
||||
class EVMAssemblyStack: public AbstractAssemblyStack
|
||||
{
|
||||
public:
|
||||
explicit EVMAssemblyStack(langutil::EVMVersion _evmVersion): m_evmVersion(_evmVersion) {}
|
||||
|
||||
/// Runs parsing and analysis steps.
|
||||
/// Multiple calls overwrite the previous state.
|
||||
/// @throws AssemblyImportException, if JSON could not be validated.
|
||||
void parseAndAnalyze(std::string const& _sourceName, std::string const& _source);
|
||||
|
||||
void assemble();
|
||||
|
||||
std::string const& name() const { return m_name; }
|
||||
|
||||
virtual LinkerObject const& object(std::string const& _contractName) const override;
|
||||
virtual LinkerObject const& runtimeObject(std::string const& _contractName) const override;
|
||||
|
||||
std::shared_ptr<evmasm::Assembly> const& evmAssembly() const { return m_evmAssembly; }
|
||||
std::shared_ptr<evmasm::Assembly> const& evmRuntimeAssembly() const { return m_evmRuntimeAssembly; }
|
||||
|
||||
virtual std::string const* sourceMapping(std::string const& _contractName) const override;
|
||||
virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const override;
|
||||
|
||||
virtual Json::Value assemblyJSON(std::string const& _contractName) const override;
|
||||
virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override;
|
||||
|
||||
virtual std::string const filesystemFriendlyName(std::string const& _contractName) const override;
|
||||
|
||||
virtual std::vector<std::string> contractNames() const override { return {m_name}; }
|
||||
virtual std::vector<std::string> sourceNames() const override;
|
||||
std::map<std::string, unsigned> sourceIndices() const;
|
||||
|
||||
virtual bool compilationSuccessful() const override { return m_evmAssembly != nullptr; }
|
||||
|
||||
void selectDebugInfo(langutil::DebugInfoSelection _debugInfoSelection)
|
||||
{
|
||||
m_debugInfoSelection = _debugInfoSelection;
|
||||
}
|
||||
|
||||
private:
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
std::string m_name;
|
||||
Json::Value m_json;
|
||||
std::shared_ptr<evmasm::Assembly> m_evmAssembly;
|
||||
std::shared_ptr<evmasm::Assembly> m_evmRuntimeAssembly;
|
||||
evmasm::LinkerObject m_object; ///< Deployment object (includes the runtime sub-object).
|
||||
evmasm::LinkerObject m_runtimeObject; ///< Runtime object.
|
||||
std::vector<std::string> m_sourceList;
|
||||
langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default();
|
||||
std::string m_sourceMapping;
|
||||
std::string m_runtimeSourceMapping;
|
||||
};
|
||||
|
||||
} // namespace solidity::evmasm
|
@ -28,6 +28,7 @@ namespace solidity::evmasm
|
||||
{
|
||||
|
||||
struct AssemblyException: virtual util::Exception {};
|
||||
struct AssemblyImportException: virtual AssemblyException {};
|
||||
struct OptimizerException: virtual AssemblyException {};
|
||||
struct StackTooDeepException: virtual OptimizerException {};
|
||||
struct ItemNotAvailableException: virtual OptimizerException {};
|
||||
|
@ -74,7 +74,6 @@
|
||||
#include <liblangutil/SemVerHandler.h>
|
||||
#include <liblangutil/SourceReferenceFormatter.h>
|
||||
|
||||
#include <libevmasm/Exceptions.h>
|
||||
|
||||
#include <libsolutil/SwarmHash.h>
|
||||
#include <libsolutil/IpfsHash.h>
|
||||
@ -702,6 +701,7 @@ bool CompilerStack::isRequestedContract(ContractDefinition const& _contract) con
|
||||
|
||||
bool CompilerStack::compile(State _stopAfter)
|
||||
{
|
||||
solAssert(m_compilationSourceType != CompilationSourceType::EvmAssemblyJSON);
|
||||
m_stopAfter = _stopAfter;
|
||||
if (m_stackState < AnalysisSuccessful)
|
||||
if (!parseAndAnalyze(_stopAfter))
|
||||
@ -986,7 +986,12 @@ Json::Value CompilerStack::assemblyJSON(std::string const& _contractName) const
|
||||
|
||||
Contract const& currentContract = contract(_contractName);
|
||||
if (currentContract.evmAssembly)
|
||||
return currentContract.evmAssembly->assemblyJSON(sourceIndices());
|
||||
{
|
||||
std::vector<std::string> sources = sourceNames();
|
||||
if (find(sources.begin(), sources.end(), CompilerContext::yulUtilityFileName()) == sources.end())
|
||||
sources.emplace_back(CompilerContext::yulUtilityFileName());
|
||||
return currentContract.evmAssembly->assemblyJSON(sources);
|
||||
}
|
||||
else
|
||||
return Json::Value();
|
||||
}
|
||||
@ -1001,9 +1006,11 @@ std::map<std::string, unsigned> CompilerStack::sourceIndices() const
|
||||
std::map<std::string, unsigned> indices;
|
||||
unsigned index = 0;
|
||||
for (auto const& s: m_sources)
|
||||
indices[s.first] = index++;
|
||||
solAssert(!indices.count(CompilerContext::yulUtilityFileName()), "");
|
||||
indices[CompilerContext::yulUtilityFileName()] = index++;
|
||||
if (s.first != CompilerContext::yulUtilityFileName())
|
||||
indices[s.first] = index++;
|
||||
|
||||
if (indices.find(CompilerContext::yulUtilityFileName()) == indices.end())
|
||||
indices[CompilerContext::yulUtilityFileName()] = index++;
|
||||
return indices;
|
||||
}
|
||||
|
||||
@ -1611,6 +1618,11 @@ std::string CompilerStack::createMetadata(Contract const& _contract, bool _forIR
|
||||
case CompilationSourceType::SolidityAST:
|
||||
sourceType = "SolidityAST";
|
||||
break;
|
||||
case CompilationSourceType::EvmAssemblyJSON:
|
||||
sourceType = "EvmAssemblyJson";
|
||||
break;
|
||||
default:
|
||||
solAssert(false);
|
||||
}
|
||||
meta["language"] = sourceType;
|
||||
meta["compiler"]["version"] = VersionStringStrict;
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
#include <liblangutil/SourceLocation.h>
|
||||
|
||||
#include <libevmasm/AbstractAssemblyStack.h>
|
||||
#include <libevmasm/LinkerObject.h>
|
||||
|
||||
#include <libsolutil/Common.h>
|
||||
@ -91,7 +92,7 @@ class Analysis;
|
||||
* It holds state and can be used to either step through the compilation stages (and abort e.g.
|
||||
* before compilation to bytecode) or run the whole compilation in one call.
|
||||
*/
|
||||
class CompilerStack: public langutil::CharStreamProvider
|
||||
class CompilerStack: public langutil::CharStreamProvider, public evmasm::AbstractAssemblyStack
|
||||
{
|
||||
public:
|
||||
/// Noncopyable.
|
||||
@ -123,7 +124,9 @@ public:
|
||||
/// Regular compilation from Solidity source files.
|
||||
Solidity,
|
||||
/// Compilation from an imported Solidity AST.
|
||||
SolidityAST
|
||||
SolidityAST,
|
||||
/// Compilation from an imported EVM Assembly JSON.
|
||||
EvmAssemblyJSON
|
||||
};
|
||||
|
||||
/// Creates a new compiler stack.
|
||||
@ -139,6 +142,8 @@ public:
|
||||
/// @returns the current state.
|
||||
State state() const { return m_stackState; }
|
||||
|
||||
virtual bool compilationSuccessful() const override { return m_stackState >= CompilationSuccessful; }
|
||||
|
||||
/// Resets the compiler to an empty state. Unless @a _keepSettings is set to true,
|
||||
/// all settings are reset as well.
|
||||
void reset(bool _keepSettings = false);
|
||||
@ -234,7 +239,7 @@ public:
|
||||
bool compile(State _stopAfter = State::CompilationSuccessful);
|
||||
|
||||
/// @returns the list of sources (paths) used
|
||||
std::vector<std::string> sourceNames() const;
|
||||
virtual std::vector<std::string> sourceNames() const override;
|
||||
|
||||
/// @returns a mapping assigning each source name its index inside the vector returned
|
||||
/// by sourceNames().
|
||||
@ -255,13 +260,13 @@ public:
|
||||
std::vector<std::string> const& unhandledSMTLib2Queries() const { return m_unhandledSMTLib2Queries; }
|
||||
|
||||
/// @returns a list of the contract names in the sources.
|
||||
std::vector<std::string> contractNames() const;
|
||||
virtual std::vector<std::string> contractNames() const override;
|
||||
|
||||
/// @returns the name of the last contract. If _sourceName is defined the last contract of that source will be returned.
|
||||
std::string const lastContractName(std::optional<std::string> const& _sourceName = std::nullopt) const;
|
||||
|
||||
/// @returns either the contract's name or a mixture of its name and source file, sanitized for filesystem use
|
||||
std::string const filesystemFriendlyName(std::string const& _contractName) const;
|
||||
virtual std::string const filesystemFriendlyName(std::string const& _contractName) const override;
|
||||
|
||||
/// @returns the IR representation of a contract.
|
||||
std::string const& yulIR(std::string const& _contractName) const;
|
||||
@ -276,10 +281,10 @@ public:
|
||||
Json::Value const& yulIROptimizedAst(std::string const& _contractName) const;
|
||||
|
||||
/// @returns the assembled object for a contract.
|
||||
evmasm::LinkerObject const& object(std::string const& _contractName) const;
|
||||
virtual evmasm::LinkerObject const& object(std::string const& _contractName) const override;
|
||||
|
||||
/// @returns the runtime object for the contract.
|
||||
evmasm::LinkerObject const& runtimeObject(std::string const& _contractName) const;
|
||||
virtual evmasm::LinkerObject const& runtimeObject(std::string const& _contractName) const override;
|
||||
|
||||
/// @returns normal contract assembly items
|
||||
evmasm::AssemblyItems const* assemblyItems(std::string const& _contractName) const;
|
||||
@ -293,21 +298,21 @@ public:
|
||||
|
||||
/// @returns the string that provides a mapping between bytecode and sourcecode or a nullptr
|
||||
/// if the contract does not (yet) have bytecode.
|
||||
std::string const* sourceMapping(std::string const& _contractName) const;
|
||||
virtual std::string const* sourceMapping(std::string const& _contractName) const override;
|
||||
|
||||
/// @returns the string that provides a mapping between runtime bytecode and sourcecode.
|
||||
/// if the contract does not (yet) have bytecode.
|
||||
std::string const* runtimeSourceMapping(std::string const& _contractName) const;
|
||||
virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const override;
|
||||
|
||||
/// @return a verbose text representation of the assembly.
|
||||
/// @arg _sourceCodes is the map of input files to source code strings
|
||||
/// Prerequisite: Successful compilation.
|
||||
std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes = StringMap()) const;
|
||||
virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes = StringMap()) const override;
|
||||
|
||||
/// @returns a JSON representation of the assembly.
|
||||
/// @arg _sourceCodes is the map of input files to source code strings
|
||||
/// Prerequisite: Successful compilation.
|
||||
Json::Value assemblyJSON(std::string const& _contractName) const;
|
||||
virtual Json::Value assemblyJSON(std::string const& _contractName) const override;
|
||||
|
||||
/// @returns a JSON representing the contract ABI.
|
||||
/// Prerequisite: Successful call to parse or compile.
|
||||
|
@ -23,13 +23,30 @@
|
||||
# ast import/export tests:
|
||||
# - first exporting a .sol file to JSON, then loading it into the compiler
|
||||
# and exporting it again. The second JSON should be identical to the first.
|
||||
#
|
||||
# evm-assembly import/export tests:
|
||||
# - first a .sol file will be exported to a combined json file, containing outputs
|
||||
# for "asm" "bin" "bin-runtime" "opcodes" "srcmap" and "srcmap-runtime" (expected output).
|
||||
# The "asm" output will then be used as import, where its output "bin" "bin-runtime"
|
||||
# "opcodes" "srcmap" "srcmap-runtime" (obtained output) will be compared with the expected output.
|
||||
# The expected output needs to be identical with the obtained output.
|
||||
#
|
||||
# Additionally to this, the direct import/export is tested by importing an
|
||||
# evm-assembly json with --import-asm-json and directly exporting it again with
|
||||
# --asm-json using the same solc invocation. The original asm json file used for the
|
||||
# import and the resulting exported asm json file need to be identical.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
READLINK=readlink
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
READLINK=greadlink
|
||||
READLINK="readlink"
|
||||
if [[ "${OSTYPE}" == "darwin"* ]]; then
|
||||
READLINK="greadlink"
|
||||
fi
|
||||
EXPR="expr"
|
||||
if [[ "${OSTYPE}" == "darwin"* ]]; then
|
||||
EXPR="gexpr"
|
||||
fi
|
||||
|
||||
REPO_ROOT=$(${READLINK} -f "$(dirname "$0")"/..)
|
||||
SOLIDITY_BUILD_DIR=${SOLIDITY_BUILD_DIR:-${REPO_ROOT}/build}
|
||||
SOLC="${SOLIDITY_BUILD_DIR}/solc/solc"
|
||||
@ -40,7 +57,7 @@ source "${REPO_ROOT}/scripts/common.sh"
|
||||
|
||||
function print_usage
|
||||
{
|
||||
echo "Usage: ${0} ast [--exit-on-error|--help]."
|
||||
echo "Usage: ${0} ast|evm-assembly [--exit-on-error|--help]."
|
||||
}
|
||||
|
||||
function print_used_commands
|
||||
@ -48,6 +65,7 @@ function print_used_commands
|
||||
local test_directory="$1"
|
||||
local export_command="$2"
|
||||
local import_command="$3"
|
||||
echo
|
||||
printError "You can find the files used for this test here: ${test_directory}"
|
||||
printError "Used commands for test:"
|
||||
printError "# export"
|
||||
@ -61,34 +79,38 @@ function print_stderr_stdout
|
||||
local error_message="$1"
|
||||
local stderr_file="$2"
|
||||
local stdout_file="$3"
|
||||
printError "$error_message"
|
||||
printError "${error_message}"
|
||||
printError ""
|
||||
printError "stderr:"
|
||||
cat "$stderr_file" >&2
|
||||
cat "${stderr_file}" >&2
|
||||
printError ""
|
||||
printError "stdout:"
|
||||
cat "$stdout_file" >&2
|
||||
cat "${stdout_file}" >&2
|
||||
}
|
||||
|
||||
function check_import_test_type_unset
|
||||
{
|
||||
[[ -z "$IMPORT_TEST_TYPE" ]] || fail "ERROR: Import test type can only be set once. Aborting."
|
||||
[[ -z "${IMPORT_TEST_TYPE}" ]] || fail "ERROR: Import test type can only be set once. Aborting."
|
||||
}
|
||||
|
||||
IMPORT_TEST_TYPE=
|
||||
EXIT_ON_ERROR=0
|
||||
for PARAM in "$@"
|
||||
do
|
||||
case "$PARAM" in
|
||||
case "${PARAM}" in
|
||||
ast) check_import_test_type_unset ; IMPORT_TEST_TYPE="ast" ;;
|
||||
evm-assembly) check_import_test_type_unset ; IMPORT_TEST_TYPE="evm-assembly" ;;
|
||||
--help) print_usage ; exit 0 ;;
|
||||
--exit-on-error) EXIT_ON_ERROR=1 ;;
|
||||
*) fail "Unknown option '$PARAM'. Aborting. $(print_usage)" ;;
|
||||
*) fail "Unknown option '${PARAM}'. Aborting. $(print_usage || true)" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
SYNTAXTESTS_DIR="${REPO_ROOT}/test/libsolidity/syntaxTests"
|
||||
ASTJSONTESTS_DIR="${REPO_ROOT}/test/libsolidity/ASTJSON"
|
||||
SEMANTICTESTS_DIR="${REPO_ROOT}/test/libsolidity/semanticTests"
|
||||
YULTESTS_DIR="${REPO_ROOT}/test/libyul"
|
||||
|
||||
|
||||
FAILED=0
|
||||
UNCOMPILABLE=0
|
||||
@ -153,6 +175,281 @@ function test_ast_import_export_equivalence
|
||||
TESTED=$((TESTED + 1))
|
||||
}
|
||||
|
||||
function split_combined_json
|
||||
{
|
||||
local json_file="$1"
|
||||
local output_path="$2"
|
||||
local prefix="${3:-}"
|
||||
for path_with_contract in $(jq '.contracts | keys | .[]' "${json_file}" 2> /dev/null)
|
||||
do
|
||||
local path=${path_with_contract}
|
||||
local contract=""
|
||||
local delimiter
|
||||
delimiter=$("${EXPR}" index "${path}" ":") || true
|
||||
if [[ -z "${prefix}" ]]
|
||||
then
|
||||
path=${path_with_contract:0:((${delimiter} - 1))}
|
||||
contract=${path_with_contract:((${delimiter})):((${#path_with_contract} - ${delimiter} - 1))}
|
||||
else
|
||||
path=${path_with_contract}
|
||||
contract=""
|
||||
fi
|
||||
for type in $(jq --raw-output ".contracts.${path_with_contract} | keys | .[]" "${json_file}" 2> /dev/null)
|
||||
do
|
||||
local output
|
||||
output=$(jq --raw-output ".contracts.${path_with_contract}.\"${type}\"" "${json_file}")
|
||||
if [[ -n "${output}" ]]
|
||||
then
|
||||
echo "${output}" > "${output_path}/${prefix}${contract}.${type}"
|
||||
fi
|
||||
done
|
||||
done
|
||||
rm "${json_file}"
|
||||
}
|
||||
|
||||
function run_solc
|
||||
{
|
||||
local parameters=( "${@}" )
|
||||
|
||||
if ! "${SOLC}" "${parameters[@]}" > /dev/null 2> solc_stderr
|
||||
then
|
||||
printError "ERROR: ${parameters[*]}"
|
||||
printError "${PWD}"
|
||||
local SOLC_STDERR
|
||||
SOLC_STDERR=$(cat "solc_stderr")
|
||||
printError "${SOLC_STDERR}"
|
||||
exit 1
|
||||
fi
|
||||
rm -f solc_stderr
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function run_solc_store_stdout
|
||||
{
|
||||
local output_file=$1
|
||||
local parameters=( "${@:2}" )
|
||||
|
||||
if ! "${SOLC}" "${parameters[@]}" > "${output_file}" 2> "${output_file}.error"
|
||||
then
|
||||
printError "ERROR: ${parameters[*]}"
|
||||
printError "${PWD}"
|
||||
local SOLC_STDERR
|
||||
SOLC_STDERR=$(cat "${output_file}.error")
|
||||
printError "${SOLC_STDERR}"
|
||||
exit 1
|
||||
fi
|
||||
rm -f "${output_file}.error"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function test_evmjson_via_ir_and_yul_import_export
|
||||
{
|
||||
local sol_file="$1"
|
||||
local input_files=( "${@:2}" )
|
||||
|
||||
mkdir yul
|
||||
# export found solidity contracts to yul.
|
||||
run_solc --optimize --via-ir --ir-optimized "${input_files[@]}" --no-optimize-yul -o yul/
|
||||
for filename in yul/*
|
||||
do
|
||||
if [[ -s "${filename}" ]]
|
||||
then
|
||||
# remove '_opt' part of '<contract-name>_opt.yul'
|
||||
mv "${filename}" "${filename/_opt/}"
|
||||
else
|
||||
# if file was empty, delete it.
|
||||
rm -f "${filename}"
|
||||
fi
|
||||
done
|
||||
|
||||
local export_command
|
||||
local import_command
|
||||
|
||||
mkdir sol
|
||||
# create from a combined json from the supplied solidity contracts.
|
||||
export_command=("${SOLC}" --combined-json "bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime" --optimize --via-ir --pretty-json --json-indent 4 --no-optimize-yul "${input_files[@]}" -o sol/)
|
||||
run_solc --combined-json "bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime" --optimize --via-ir --pretty-json --json-indent 4 "${input_files[@]}" --no-optimize-yul -o sol/
|
||||
mkdir input
|
||||
|
||||
# save the original supplied solidity contract sources for potential debugging purposes.
|
||||
for file in "${input_files[@]}"
|
||||
do
|
||||
cat "${file}" >> "input/$(basename "${file}")"
|
||||
done
|
||||
# split the combined json into different files.
|
||||
split_combined_json sol/combined.json sol/
|
||||
|
||||
# iterate through all yul files.
|
||||
for yulfile in yul/*
|
||||
do
|
||||
# take the yul file and export it as evm assembly json. save the result in "$yulfile.asm.json".
|
||||
run_solc_store_stdout "${yulfile}.asm.json" --strict-assembly "${yulfile}" --optimize --asm-json --pretty-json --json-indent 4 --no-optimize-yul
|
||||
# remove the lines containing '=======', so that we just have a nice json file.
|
||||
grep -v '^=======' "${yulfile}.asm.json" > tmpfile && mv tmpfile "${yulfile}.asm.json"
|
||||
# import_command will just contain the last file in yul/*.asm - but it's still a good starting point ;)
|
||||
import_command=("${SOLC}" --combined-json "bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime" --pretty-json --json-indent 4 --import-asm-json "${yulfile}.asm.json")
|
||||
# import the created evm assembly json file and create a combined json out of it.
|
||||
run_solc_store_stdout "${yulfile}.combined.json" --combined-json "bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime" --pretty-json --json-indent 4 --import-asm-json "${yulfile}.asm.json"
|
||||
# split the combined json into different files.
|
||||
split_combined_json "${yulfile}.combined.json" . "${yulfile}"
|
||||
done
|
||||
|
||||
# now iterate over all files in the sol/ output folder.
|
||||
# the files stored here will normally look like e.g. "sol/C.asm", "sol/C.bin"
|
||||
# they were generated by the split_combined_json call above and contain the contract
|
||||
# name and the type (e.g. bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime) in the
|
||||
# file-name.
|
||||
for file in sol/*
|
||||
do
|
||||
local type
|
||||
local delimiter
|
||||
local yul
|
||||
|
||||
# first just remove all path parts from the file and put it in the type.
|
||||
# - "sol/C.asm" -> "C.asm"
|
||||
type="$(basename "${file}")"
|
||||
|
||||
# delimiter is just the position of that dot that is delimiting the contract
|
||||
# name from it's type.
|
||||
delimiter=$("${EXPR}" index "${type}" ".")
|
||||
|
||||
# extract the type: for e.g. "C.asm" -> type will be "asm".
|
||||
type=${type:((${delimiter})):((${#type} - ${delimiter}))}
|
||||
|
||||
# now we want to know which is the corresponding yul file, that should have exactly
|
||||
# the same content. e.g. file="sol/C.srcmap-runtime" -> yul="yul/C.yul.srcmap-runtime"
|
||||
yul=${file/sol/yul}
|
||||
yul=${yul/${type}/yul.${type}}
|
||||
|
||||
# remember that we first exported the yul file from solidity contract files.
|
||||
# then we generated and split the corresponding combined-json of that exported yul file.
|
||||
# we also generated and split another combined-json file from the original
|
||||
# solidity contract files. if the yul export to asm evm json and it's re-import
|
||||
# will lead to the same content of the combined-json of the original solidity file,
|
||||
# the yul export to asm evm json and it's reimport seem to work correctly.
|
||||
|
||||
# we can ignore "asm" and "json" files here. "asm" is the exported evm asm json.
|
||||
# between the yul and the sol assembly jsons we may have some subtile differences,
|
||||
# e.g. in the source-lists.
|
||||
# however, if the yul/sol outputs of e.g. bin,bin-runtime,opcodes,srcmap,srcmap-runtime
|
||||
# is matching, we consider that the reimport was done correctly.
|
||||
if [[ "${type}" == "asm" ]] || [[ "${type}" == "json" ]]
|
||||
then
|
||||
continue
|
||||
fi
|
||||
|
||||
# compare the files. e.g. "sol/C.srcmap-runtime" with "yul/C.yul.srcmap-runtime"
|
||||
if ! diff_files "${file}" "${yul}" > diff_error
|
||||
then
|
||||
local diff_error
|
||||
diff_error=$(cat diff_error)
|
||||
printError "ERROR: diff failed ${file} ${yul}:\n ${diff_error}"
|
||||
if (( EXIT_ON_ERROR == 1 ))
|
||||
then
|
||||
print_used_commands "${PWD}" "${export_command[*]}" "${import_command[*]}"
|
||||
exit 1
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
rm -rf sol
|
||||
rm -rf yul
|
||||
rm -rf input
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function test_evmjson_sol_import_export
|
||||
{
|
||||
local sol_file="$1"
|
||||
local input_files=( "${@:2}" )
|
||||
|
||||
mkdir -p sol
|
||||
# create from a combined json from the supplied solidity contracts.
|
||||
local export_command
|
||||
local import_command
|
||||
export_command=("${SOLC}" --combined-json "bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime" --pretty-json --json-indent 4 "${input_files[@]}" -o sol/)
|
||||
|
||||
run_solc --combined-json "bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime" --pretty-json --json-indent 4 "${input_files[@]}" -o sol/
|
||||
mkdir input
|
||||
# save the original supplied solidity contract sources for potential debugging purposes.
|
||||
for file in "${input_files[@]}"
|
||||
do
|
||||
cat "${file}" >> "input/$(basename "${file}")"
|
||||
done
|
||||
# split the combined json into different files.
|
||||
split_combined_json sol/combined.json sol/
|
||||
|
||||
mkdir -p imported-from-sol
|
||||
for file in sol/*.asm
|
||||
do
|
||||
name=$(basename "${file}" .asm)
|
||||
# import_command will just contain the last file in sol/*.asm - but it's still a good starting point ;)
|
||||
import_command=("${SOLC}" --import-ast --combined-json "bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime" --pretty-json --json-indent 4 --import-asm-json "${file}")
|
||||
run_solc_store_stdout "imported-from-sol/combined.json" --combined-json "bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime" --pretty-json --json-indent 4 --import-asm-json "${file}"
|
||||
split_combined_json imported-from-sol/combined.json imported-from-sol/ "${name}"
|
||||
done
|
||||
|
||||
for file in sol/*
|
||||
do
|
||||
local imported
|
||||
imported=${file/sol/imported-from-sol}
|
||||
if ! diff_files "${file}" "${imported}" > diff_error
|
||||
then
|
||||
local diff_error
|
||||
diff_error=$(cat diff_error)
|
||||
printError "ERROR: diff failed ${file} ${imported}:\n ${diff_error}"
|
||||
if (( EXIT_ON_ERROR == 1 ))
|
||||
then
|
||||
print_used_commands "${PWD}" "${export_command[*]}" "${import_command[*]}"
|
||||
exit 1
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
rm -rf sol
|
||||
rm -rf imported-from-sol
|
||||
rm -rf input
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function test_evmjson_import_export_equivalence
|
||||
{
|
||||
local sol_file="$1"
|
||||
local input_files=( "${@:2}" )
|
||||
local success=1
|
||||
|
||||
# export sol to yul. generate artefacts from sol and convert yul to asm json.
|
||||
# import the yul asm json and check whether the sol artefacts are the same as for yul.
|
||||
if ! test_evmjson_via_ir_and_yul_import_export "${sol_file}" "${input_files[@]}"
|
||||
then
|
||||
success=0
|
||||
fi
|
||||
|
||||
# only run the next test-step, if the previous test was run correctly.
|
||||
if (( success == 1 ))
|
||||
then
|
||||
# generate artefacts from sol. export sol to asm json. import that asm json and
|
||||
# check whether the sol artefacts are the same as created by the asm json import.
|
||||
if ! test_evmjson_sol_import_export "${sol_file}" "${input_files[@]}"
|
||||
then
|
||||
success=0
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( success == 1 ))
|
||||
then
|
||||
TESTED=$((TESTED + 1))
|
||||
else
|
||||
FAILED=$((FAILED + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
# function tests whether exporting and importing again is equivalent.
|
||||
# Results are recorded by incrementing the FAILED or UNCOMPILABLE global variable.
|
||||
# Also, in case of a mismatch a diff is printed
|
||||
@ -166,21 +463,23 @@ function test_import_export_equivalence {
|
||||
local solc_return_code
|
||||
local compile_test
|
||||
|
||||
case "$IMPORT_TEST_TYPE" in
|
||||
case "${IMPORT_TEST_TYPE}" in
|
||||
ast) compile_test="--ast-compact-json" ;;
|
||||
evm-assembly) compile_test="--bin" ;;
|
||||
*) assertFail "Unknown import test type '${IMPORT_TEST_TYPE}'. Aborting." ;;
|
||||
esac
|
||||
|
||||
set +e
|
||||
output=$("$SOLC" "${compile_test}" "${input_files[@]}" 2>&1)
|
||||
output=$("${SOLC}" "${compile_test}" "${input_files[@]}" 2>&1)
|
||||
solc_return_code=$?
|
||||
set -e
|
||||
|
||||
# if input files where compilable with success
|
||||
if (( solc_return_code == 0 ))
|
||||
then
|
||||
case "$IMPORT_TEST_TYPE" in
|
||||
case "${IMPORT_TEST_TYPE}" in
|
||||
ast) test_ast_import_export_equivalence "${sol_file}" "${input_files[@]}" ;;
|
||||
evm-assembly) test_evmjson_import_export_equivalence "${sol_file}" "${input_files[@]}" ;;
|
||||
*) assertFail "Unknown import test type '${IMPORT_TEST_TYPE}'. Aborting." ;;
|
||||
esac
|
||||
else
|
||||
@ -191,70 +490,163 @@ function test_import_export_equivalence {
|
||||
# and print some details about the corresponding solc invocation.
|
||||
if (( solc_return_code == 2 ))
|
||||
then
|
||||
fail "\n\nERROR: Uncaught Exception while executing '$SOLC ${compile_test} ${input_files[*]}':\n${output}\n"
|
||||
# For the evm-assembly import/export tests, this script uses only the
|
||||
# old code generator. Some semantic test can only be compiled with
|
||||
# --via-ir (some need to be additionally compiled with --optimize).
|
||||
# The tests that are meant to be compiled with --via-ir are throwing
|
||||
# an UnimplementedFeatureError exception (e.g. Copying of type struct C.S
|
||||
# memory[] memory to storage not yet supported, Copying nested calldata
|
||||
# dynamic arrays to storage is not implemented in the old code generator.)
|
||||
# We will just ignore these kind of exceptions for now.
|
||||
# However, any other exception will be treated as a fatal error and the
|
||||
# script execution will be terminated with an error.
|
||||
if [[ "${output}" != *"UnimplementedFeatureError"* ]]
|
||||
then
|
||||
fail "\n\nERROR: Uncaught Exception while executing '${SOLC} ${compile_test} ${input_files[*]}':\n${output}\n"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
WORKINGDIR=$PWD
|
||||
function test_evmjson_import_from_yul_export
|
||||
{
|
||||
local files="${*}"
|
||||
for yulfile in $files
|
||||
do
|
||||
local export_command
|
||||
local import_command
|
||||
echo -n "·"
|
||||
|
||||
command_available "$SOLC" --version
|
||||
# create a temporary sub-directory
|
||||
FILETMP=$(mktemp -d)
|
||||
cd "${FILETMP}"
|
||||
|
||||
set +e
|
||||
output=$("${SOLC}" "--strict-assembly" "${yulfile}" "--bin" "--optimize" 2>/dev/null)
|
||||
solc_return_code=$?
|
||||
set -e
|
||||
|
||||
# if yul file got compiled with success.
|
||||
if (( solc_return_code == 0 ))
|
||||
then
|
||||
yul_bin="$(basename "$yulfile").bin"
|
||||
yul_json="$(basename "$yulfile").asm.json"
|
||||
echo "$output" > "${yul_bin}"
|
||||
# remove all lines starting with '=======' and 'Binary representation:'.
|
||||
grep -v -e '^=======' -e '^Binary representation:' "${yul_bin}" > tmpfile && mv tmpfile "${yul_bin}"
|
||||
# remove all white-spaces. we only want the binary.
|
||||
tr -d '[:space:]' < "${yul_bin}" > tmpfile && mv tmpfile "${yul_bin}"
|
||||
# only compare bytecode, if bytecode got generated.
|
||||
if [[ -s "${yul_bin}" ]]
|
||||
then
|
||||
# take the yul file and export it as evm assembly json. save the result in "$yul_json".
|
||||
export_command=("${SOLC}" --strict-assembly "${yulfile}" --optimize --asm-json --pretty-json --json-indent 4)
|
||||
run_solc_store_stdout "${yul_json}" --strict-assembly "${yulfile}" --optimize --asm-json --pretty-json --json-indent 4
|
||||
# remove the lines containing '=======', so that we just have a nice json file.
|
||||
grep -v '^=======' "${yul_json}" > tmpfile && mv tmpfile "${yul_json}"
|
||||
|
||||
# import the created evm assembly json file and create a combined json out of it.
|
||||
import_command=("${SOLC}" --combined-json "bin" --pretty-json --json-indent 4 --import-asm-json "${yul_json}")
|
||||
run_solc_store_stdout "${yul_json}.combined.json" --combined-json "bin" --pretty-json --json-indent 4 --import-asm-json "${yul_json}"
|
||||
# split the combined json into different files.
|
||||
split_combined_json "${yul_json}.combined.json" . "compiled"
|
||||
tr -d '[:space:]' < "compiled.bin" > tmpfile && mv tmpfile "compiled.bin"
|
||||
|
||||
if ! diff_files compiled.bin "${yul_bin}" > diff_error
|
||||
then
|
||||
diff_error=$(cat diff_error)
|
||||
printError "ERROR: diff failed ${yulfile}:\n ${diff_error}"
|
||||
if (( EXIT_ON_ERROR == 1 ))
|
||||
then
|
||||
print_used_commands "${PWD}" "${export_command[*]}" "${import_command[*]}"
|
||||
exit 1
|
||||
fi
|
||||
FAILED=$((FAILED + 1))
|
||||
else
|
||||
TESTED=$((TESTED + 1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
cd "${WORKINGDIR}"
|
||||
# Delete temporary files
|
||||
rm -rf "${FILETMP}"
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
WORKINGDIR=${PWD}
|
||||
|
||||
command_available "${SOLC}" --version
|
||||
command_available jq --version
|
||||
command_available "${EXPR}" --version
|
||||
command_available "${READLINK}" --version
|
||||
|
||||
case "$IMPORT_TEST_TYPE" in
|
||||
case "${IMPORT_TEST_TYPE}" in
|
||||
ast) TEST_DIRS=("${SYNTAXTESTS_DIR}" "${ASTJSONTESTS_DIR}") ;;
|
||||
*) assertFail "Import test type not defined. $(print_usage)" ;;
|
||||
evm-assembly) TEST_DIRS=("${SEMANTICTESTS_DIR}") ;;
|
||||
*) assertFail "Import test type not defined. $(print_usage || true)}" ;;
|
||||
esac
|
||||
|
||||
YUL_NSOURCES=0
|
||||
if [[ "${IMPORT_TEST_TYPE}" == "evm-assembly" ]]
|
||||
then
|
||||
IMPORT_TEST_FILES=$(find "${YULTESTS_DIR}" -name "*.yul")
|
||||
YUL_NSOURCES="$(echo "${IMPORT_TEST_FILES}" | wc -l)"
|
||||
echo "Looking at ${YUL_NSOURCES} .yul files..."
|
||||
test_evmjson_import_from_yul_export "${IMPORT_TEST_FILES[@]}"
|
||||
fi
|
||||
|
||||
# boost_filesystem_bug specifically tests a local fix for a boost::filesystem
|
||||
# bug. Since the test involves a malformed path, there is no point in running
|
||||
# tests on it. See https://github.com/boostorg/filesystem/issues/176
|
||||
IMPORT_TEST_FILES=$(find "${TEST_DIRS[@]}" -name "*.sol" -and -not -name "boost_filesystem_bug.sol" -not -path "*/experimental/*")
|
||||
|
||||
NSOURCES="$(echo "${IMPORT_TEST_FILES}" | wc -l)"
|
||||
echo "Looking at ${NSOURCES} .sol files..."
|
||||
SOL_NSOURCES="$(echo "${IMPORT_TEST_FILES}" | wc -l)"
|
||||
echo "Looking at ${SOL_NSOURCES} .sol files..."
|
||||
|
||||
for solfile in $IMPORT_TEST_FILES
|
||||
NSOURCES=$(( YUL_NSOURCES + SOL_NSOURCES ))
|
||||
|
||||
for solfile in ${IMPORT_TEST_FILES}
|
||||
do
|
||||
echo -n "·"
|
||||
# create a temporary sub-directory
|
||||
FILETMP=$(mktemp -d)
|
||||
cd "$FILETMP"
|
||||
cd "${FILETMP}"
|
||||
|
||||
set +e
|
||||
OUTPUT=$("$SPLITSOURCES" "$solfile")
|
||||
OUTPUT=$("${SPLITSOURCES}" "${solfile}")
|
||||
SPLITSOURCES_RC=$?
|
||||
set -e
|
||||
|
||||
if (( SPLITSOURCES_RC == 0 ))
|
||||
then
|
||||
IFS=' ' read -ra OUTPUT_ARRAY <<< "$OUTPUT"
|
||||
test_import_export_equivalence "$solfile" "${OUTPUT_ARRAY[@]}"
|
||||
IFS=' ' read -ra OUTPUT_ARRAY <<< "${OUTPUT}"
|
||||
test_import_export_equivalence "${solfile}" "${OUTPUT_ARRAY[@]}"
|
||||
elif (( SPLITSOURCES_RC == 1 ))
|
||||
then
|
||||
test_import_export_equivalence "$solfile" "$solfile"
|
||||
test_import_export_equivalence "${solfile}" "${solfile}"
|
||||
elif (( SPLITSOURCES_RC == 2 ))
|
||||
then
|
||||
# The script will exit with return code 2, if an UnicodeDecodeError occurred.
|
||||
# This is the case if e.g. some tests are using invalid utf-8 sequences. We will ignore
|
||||
# these errors, but print the actual output of the script.
|
||||
printError "\n\n${OUTPUT}\n\n"
|
||||
test_import_export_equivalence "$solfile" "$solfile"
|
||||
test_import_export_equivalence "${solfile}" "${solfile}"
|
||||
else
|
||||
# All other return codes will be treated as critical errors. The script will exit.
|
||||
printError "\n\nGot unexpected return code ${SPLITSOURCES_RC} from '${SPLITSOURCES} ${solfile}'. Aborting."
|
||||
printError "\n\n${OUTPUT}\n\n"
|
||||
|
||||
cd "$WORKINGDIR"
|
||||
cd "${WORKINGDIR}"
|
||||
# Delete temporary files
|
||||
rm -rf "$FILETMP"
|
||||
rm -rf "${FILETMP}"
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$WORKINGDIR"
|
||||
cd "${WORKINGDIR}"
|
||||
# Delete temporary files
|
||||
rm -rf "$FILETMP"
|
||||
rm -rf "${FILETMP}"
|
||||
done
|
||||
|
||||
echo
|
||||
|
@ -92,6 +92,7 @@ namespace
|
||||
std::set<frontend::InputMode> const CompilerInputModes{
|
||||
frontend::InputMode::Compiler,
|
||||
frontend::InputMode::CompilerWithASTImport,
|
||||
frontend::InputMode::EVMAssemblerJSON
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
@ -166,42 +167,77 @@ static bool coloredOutput(CommandLineOptions const& _options)
|
||||
(_options.formatting.coloredOutput.has_value() && _options.formatting.coloredOutput.value());
|
||||
}
|
||||
|
||||
void CommandLineInterface::handleEVMAssembly(std::string const& _contract)
|
||||
{
|
||||
solAssert(m_assemblyStack);
|
||||
solAssert(CompilerInputModes.count(m_options.input.mode) == 1);
|
||||
|
||||
if (m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson)
|
||||
{
|
||||
std::string assembly;
|
||||
if (m_options.compiler.outputs.asmJson)
|
||||
assembly = util::jsonPrint(removeNullMembers(m_assemblyStack->assemblyJSON(_contract)), m_options.formatting.json);
|
||||
else
|
||||
assembly = m_assemblyStack->assemblyString(_contract, m_fileReader.sourceUnits());
|
||||
|
||||
if (!m_options.output.dir.empty())
|
||||
createFile(
|
||||
m_compiler->filesystemFriendlyName(_contract) +
|
||||
(m_options.compiler.outputs.asmJson ? "_evm.json" : ".evm"),
|
||||
assembly
|
||||
);
|
||||
else
|
||||
sout() << "EVM assembly:" << std::endl << assembly << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLineInterface::handleBinary(std::string const& _contract)
|
||||
{
|
||||
solAssert(m_assemblyStack);
|
||||
solAssert(CompilerInputModes.count(m_options.input.mode) == 1);
|
||||
|
||||
std::string binary;
|
||||
std::string binaryRuntime;
|
||||
if (m_options.compiler.outputs.binary)
|
||||
binary = objectWithLinkRefsHex(m_assemblyStack->object(_contract));
|
||||
if (m_options.compiler.outputs.binaryRuntime)
|
||||
binaryRuntime = objectWithLinkRefsHex(m_assemblyStack->runtimeObject(_contract));
|
||||
|
||||
if (m_options.compiler.outputs.binary)
|
||||
{
|
||||
if (!m_options.output.dir.empty())
|
||||
createFile(m_compiler->filesystemFriendlyName(_contract) + ".bin", objectWithLinkRefsHex(m_compiler->object(_contract)));
|
||||
createFile(m_assemblyStack->filesystemFriendlyName(_contract) + ".bin", binary);
|
||||
else
|
||||
{
|
||||
sout() << "Binary:" << std::endl;
|
||||
sout() << objectWithLinkRefsHex(m_compiler->object(_contract)) << std::endl;
|
||||
sout() << binary << std::endl;
|
||||
}
|
||||
}
|
||||
if (m_options.compiler.outputs.binaryRuntime)
|
||||
{
|
||||
if (!m_options.output.dir.empty())
|
||||
createFile(m_compiler->filesystemFriendlyName(_contract) + ".bin-runtime", objectWithLinkRefsHex(m_compiler->runtimeObject(_contract)));
|
||||
createFile(m_assemblyStack->filesystemFriendlyName(_contract) + ".bin-runtime", binaryRuntime);
|
||||
else
|
||||
{
|
||||
sout() << "Binary of the runtime part:" << std::endl;
|
||||
sout() << objectWithLinkRefsHex(m_compiler->runtimeObject(_contract)) << std::endl;
|
||||
sout() << binaryRuntime << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLineInterface::handleOpcode(std::string const& _contract)
|
||||
{
|
||||
solAssert(m_assemblyStack);
|
||||
solAssert(CompilerInputModes.count(m_options.input.mode) == 1);
|
||||
|
||||
std::string opcodes{evmasm::disassemble(m_assemblyStack->object(_contract).bytecode, m_options.output.evmVersion)};
|
||||
|
||||
if (!m_options.output.dir.empty())
|
||||
createFile(m_compiler->filesystemFriendlyName(_contract) + ".opcode", evmasm::disassemble(m_compiler->object(_contract).bytecode, m_options.output.evmVersion));
|
||||
createFile(m_assemblyStack->filesystemFriendlyName(_contract) + ".opcode", opcodes);
|
||||
else
|
||||
{
|
||||
sout() << "Opcodes:" << std::endl;
|
||||
sout() << std::uppercase << evmasm::disassemble(m_compiler->object(_contract).bytecode, m_options.output.evmVersion);
|
||||
sout() << std::uppercase << opcodes;
|
||||
sout() << std::endl;
|
||||
}
|
||||
}
|
||||
@ -701,6 +737,12 @@ void CommandLineInterface::processInput()
|
||||
compile();
|
||||
outputCompilationResults();
|
||||
break;
|
||||
case InputMode::EVMAssemblerJSON:
|
||||
assembleFromEvmAssemblyJson();
|
||||
handleCombinedJSON();
|
||||
handleBytecode(m_assemblyStack->contractNames().front());
|
||||
handleEVMAssembly(m_assemblyStack->contractNames().front());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -717,11 +759,38 @@ void CommandLineInterface::printLicense()
|
||||
sout() << licenseText << std::endl;
|
||||
}
|
||||
|
||||
void CommandLineInterface::assembleFromEvmAssemblyJson()
|
||||
{
|
||||
solAssert(m_options.input.mode == InputMode::EVMAssemblerJSON);
|
||||
solAssert(!m_assemblyStack);
|
||||
solAssert(!m_evmAssemblyStack && !m_compiler);
|
||||
std::unique_ptr<evmasm::EVMAssemblyStack> evmAssemblyStack;
|
||||
solAssert(m_fileReader.sourceUnits().size() == 1);
|
||||
auto&& [sourceUnitName, source] = *m_fileReader.sourceUnits().begin();
|
||||
try
|
||||
{
|
||||
evmAssemblyStack = std::make_unique<evmasm::EVMAssemblyStack>(m_options.output.evmVersion);
|
||||
evmAssemblyStack->parseAndAnalyze(sourceUnitName, source);
|
||||
if (m_options.output.debugInfoSelection.has_value())
|
||||
evmAssemblyStack->selectDebugInfo(m_options.output.debugInfoSelection.value());
|
||||
evmAssemblyStack->assemble();
|
||||
m_evmAssemblyStack = std::move(evmAssemblyStack);
|
||||
m_assemblyStack = m_evmAssemblyStack.get();
|
||||
}
|
||||
catch (evmasm::AssemblyImportException const& _exception)
|
||||
{
|
||||
solThrow(CommandLineExecutionError, "Assembly Import Error: "s + _exception.what());
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLineInterface::compile()
|
||||
{
|
||||
solAssert(CompilerInputModes.count(m_options.input.mode) == 1);
|
||||
solAssert(!m_assemblyStack);
|
||||
solAssert(!m_evmAssemblyStack && !m_compiler);
|
||||
|
||||
m_compiler = std::make_unique<CompilerStack>(m_universalCallback.callback());
|
||||
m_assemblyStack = m_compiler.get();
|
||||
|
||||
SourceReferenceFormatter formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
|
||||
|
||||
@ -831,6 +900,7 @@ void CommandLineInterface::compile()
|
||||
|
||||
void CommandLineInterface::handleCombinedJSON()
|
||||
{
|
||||
solAssert(m_assemblyStack);
|
||||
solAssert(CompilerInputModes.count(m_options.input.mode) == 1);
|
||||
|
||||
if (!m_options.compiler.combinedJsonRequests.has_value())
|
||||
@ -839,63 +909,59 @@ void CommandLineInterface::handleCombinedJSON()
|
||||
Json::Value output(Json::objectValue);
|
||||
|
||||
output[g_strVersion] = frontend::VersionString;
|
||||
std::vector<std::string> contracts = m_compiler->contractNames();
|
||||
|
||||
// NOTE: The state checks here are more strict that in Standard JSON. There we allow
|
||||
// requesting certain outputs even if compilation fails as long as analysis went ok.
|
||||
bool compilationSuccess = m_compiler->state() >= CompilerStack::State::CompilationSuccessful;
|
||||
std::vector<std::string> contracts = m_assemblyStack->contractNames();
|
||||
|
||||
if (!contracts.empty())
|
||||
output[g_strContracts] = Json::Value(Json::objectValue);
|
||||
for (std::string const& contractName: contracts)
|
||||
{
|
||||
Json::Value& contractData = output[g_strContracts][contractName] = Json::objectValue;
|
||||
if (m_options.compiler.combinedJsonRequests->abi && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->abi && m_compiler->compilationSuccessful())
|
||||
contractData[g_strAbi] = m_compiler->contractABI(contractName);
|
||||
if (m_options.compiler.combinedJsonRequests->metadata && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->metadata && m_compiler->compilationSuccessful())
|
||||
contractData["metadata"] = m_compiler->metadata(contractName);
|
||||
if (m_options.compiler.combinedJsonRequests->binary && compilationSuccess)
|
||||
contractData[g_strBinary] = m_compiler->object(contractName).toHex();
|
||||
if (m_options.compiler.combinedJsonRequests->binaryRuntime && compilationSuccess)
|
||||
contractData[g_strBinaryRuntime] = m_compiler->runtimeObject(contractName).toHex();
|
||||
if (m_options.compiler.combinedJsonRequests->opcodes && compilationSuccess)
|
||||
contractData[g_strOpcodes] = evmasm::disassemble(m_compiler->object(contractName).bytecode, m_options.output.evmVersion);
|
||||
if (m_options.compiler.combinedJsonRequests->asm_ && compilationSuccess)
|
||||
contractData[g_strAsm] = m_compiler->assemblyJSON(contractName);
|
||||
if (m_options.compiler.combinedJsonRequests->storageLayout && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->binary && m_assemblyStack->compilationSuccessful())
|
||||
contractData[g_strBinary] = m_assemblyStack->object(contractName).toHex();
|
||||
if (m_options.compiler.combinedJsonRequests->binaryRuntime && m_assemblyStack->compilationSuccessful())
|
||||
contractData[g_strBinaryRuntime] = m_assemblyStack->runtimeObject(contractName).toHex();
|
||||
if (m_options.compiler.combinedJsonRequests->opcodes && m_assemblyStack->compilationSuccessful())
|
||||
contractData[g_strOpcodes] = evmasm::disassemble(m_assemblyStack->object(contractName).bytecode, m_options.output.evmVersion);
|
||||
if (m_options.compiler.combinedJsonRequests->asm_ && m_assemblyStack->compilationSuccessful())
|
||||
contractData[g_strAsm] = m_assemblyStack->assemblyJSON(contractName);
|
||||
|
||||
if (m_options.compiler.combinedJsonRequests->storageLayout && m_compiler->compilationSuccessful())
|
||||
contractData[g_strStorageLayout] = m_compiler->storageLayout(contractName);
|
||||
if (m_options.compiler.combinedJsonRequests->generatedSources && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->generatedSources && m_compiler->compilationSuccessful())
|
||||
contractData[g_strGeneratedSources] = m_compiler->generatedSources(contractName, false);
|
||||
if (m_options.compiler.combinedJsonRequests->generatedSourcesRuntime && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->generatedSourcesRuntime && m_compiler->compilationSuccessful())
|
||||
contractData[g_strGeneratedSourcesRuntime] = m_compiler->generatedSources(contractName, true);
|
||||
if (m_options.compiler.combinedJsonRequests->srcMap && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->srcMap && m_assemblyStack->compilationSuccessful())
|
||||
{
|
||||
auto map = m_compiler->sourceMapping(contractName);
|
||||
auto map = m_assemblyStack->sourceMapping(contractName);
|
||||
contractData[g_strSrcMap] = map ? *map : "";
|
||||
}
|
||||
if (m_options.compiler.combinedJsonRequests->srcMapRuntime && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->srcMapRuntime && m_assemblyStack->compilationSuccessful())
|
||||
{
|
||||
auto map = m_compiler->runtimeSourceMapping(contractName);
|
||||
auto map = m_assemblyStack->runtimeSourceMapping(contractName);
|
||||
contractData[g_strSrcMapRuntime] = map ? *map : "";
|
||||
}
|
||||
if (m_options.compiler.combinedJsonRequests->funDebug && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->funDebug && m_assemblyStack->compilationSuccessful())
|
||||
contractData[g_strFunDebug] = StandardCompiler::formatFunctionDebugData(
|
||||
m_compiler->object(contractName).functionDebugData
|
||||
m_assemblyStack->object(contractName).functionDebugData
|
||||
);
|
||||
if (m_options.compiler.combinedJsonRequests->funDebugRuntime && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->funDebugRuntime && m_assemblyStack->compilationSuccessful())
|
||||
contractData[g_strFunDebugRuntime] = StandardCompiler::formatFunctionDebugData(
|
||||
m_compiler->runtimeObject(contractName).functionDebugData
|
||||
m_assemblyStack->runtimeObject(contractName).functionDebugData
|
||||
);
|
||||
if (m_options.compiler.combinedJsonRequests->signatureHashes && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->signatureHashes && m_compiler->compilationSuccessful())
|
||||
contractData[g_strSignatureHashes] = m_compiler->interfaceSymbols(contractName)["methods"];
|
||||
if (m_options.compiler.combinedJsonRequests->natspecDev && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->natspecDev && m_compiler->compilationSuccessful())
|
||||
contractData[g_strNatspecDev] = m_compiler->natspecDev(contractName);
|
||||
if (m_options.compiler.combinedJsonRequests->natspecUser && compilationSuccess)
|
||||
if (m_options.compiler.combinedJsonRequests->natspecUser && m_compiler->compilationSuccessful())
|
||||
contractData[g_strNatspecUser] = m_compiler->natspecUser(contractName);
|
||||
}
|
||||
|
||||
bool needsSourceList =
|
||||
m_options.compiler.combinedJsonRequests->ast ||
|
||||
bool needsSourceList = m_options.compiler.combinedJsonRequests->ast ||
|
||||
m_options.compiler.combinedJsonRequests->srcMap ||
|
||||
m_options.compiler.combinedJsonRequests->srcMapRuntime;
|
||||
if (needsSourceList)
|
||||
@ -903,7 +969,7 @@ void CommandLineInterface::handleCombinedJSON()
|
||||
// Indices into this array are used to abbreviate source names in source locations.
|
||||
output[g_strSourceList] = Json::Value(Json::arrayValue);
|
||||
|
||||
for (auto const& source: m_compiler->sourceNames())
|
||||
for (auto const& source: m_assemblyStack->sourceNames())
|
||||
output[g_strSourceList].append(source);
|
||||
}
|
||||
|
||||
@ -1152,6 +1218,55 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
|
||||
else
|
||||
serr() << "No text representation found." << std::endl;
|
||||
}
|
||||
|
||||
if (m_options.compiler.outputs.asmJson)
|
||||
{
|
||||
std::shared_ptr<evmasm::Assembly> assembly{stack.assembleEVMWithDeployed().first};
|
||||
if (assembly)
|
||||
{
|
||||
std::function<std::map<std::string, unsigned>(yul::Object const&)> collectSourceIndices =
|
||||
[&](yul::Object const& _object) -> std::map<std::string, unsigned> {
|
||||
std::map<std::string, unsigned> sourceIndices;
|
||||
if (_object.debugData && _object.debugData->sourceNames.has_value())
|
||||
for (auto const& iter: *_object.debugData->sourceNames)
|
||||
sourceIndices[*iter.second] = iter.first;
|
||||
for (auto const& sub: _object.subObjects)
|
||||
{
|
||||
auto subObject = dynamic_cast<yul::Object const*>(sub.get());
|
||||
if (subObject)
|
||||
for (auto const& [name, index]: collectSourceIndices(*subObject))
|
||||
sourceIndices[name] = index;
|
||||
}
|
||||
return sourceIndices;
|
||||
};
|
||||
if (stack.parserResult() && stack.parserResult()->debugData)
|
||||
{
|
||||
std::map<std::string, unsigned> sourceIndices = collectSourceIndices(*stack.parserResult());
|
||||
// if sourceIndices are empty here, there were no source locations annotated in the yul source.
|
||||
// in this case, we just add the filename of the yul file itself here.
|
||||
if (sourceIndices.empty())
|
||||
sourceIndices[src.first] = 0;
|
||||
size_t max_index = 0;
|
||||
for (auto const& [name, index]: sourceIndices)
|
||||
if (max_index < index)
|
||||
max_index = index;
|
||||
std::vector<std::string> sourceList(max_index + 1);
|
||||
uint32_t counter{0};
|
||||
for (auto& source: sourceList)
|
||||
source = "unknown-source-" + std::to_string(counter++);
|
||||
for (auto const& [name, index]: sourceIndices)
|
||||
sourceList[index] = name;
|
||||
sout() << util::jsonPrint(
|
||||
removeNullMembers(
|
||||
assembly->assemblyJSON(sourceList)
|
||||
),
|
||||
m_options.formatting.json
|
||||
) << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
serr() << "Could not create Assembly JSON representation." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1177,20 +1292,7 @@ void CommandLineInterface::outputCompilationResults()
|
||||
if (needsHumanTargetedStdout(m_options))
|
||||
sout() << std::endl << "======= " << contract << " =======" << std::endl;
|
||||
|
||||
// do we need EVM assembly?
|
||||
if (m_options.compiler.outputs.asm_ || m_options.compiler.outputs.asmJson)
|
||||
{
|
||||
std::string ret;
|
||||
if (m_options.compiler.outputs.asmJson)
|
||||
ret = util::jsonPrint(removeNullMembers(m_compiler->assemblyJSON(contract)), m_options.formatting.json);
|
||||
else
|
||||
ret = m_compiler->assemblyString(contract, m_fileReader.sourceUnits());
|
||||
|
||||
if (!m_options.output.dir.empty())
|
||||
createFile(m_compiler->filesystemFriendlyName(contract) + (m_options.compiler.outputs.asmJson ? "_evm.json" : ".evm"), ret);
|
||||
else
|
||||
sout() << "EVM assembly:" << std::endl << ret << std::endl;
|
||||
}
|
||||
handleEVMAssembly(contract);
|
||||
|
||||
if (m_options.compiler.estimateGas)
|
||||
handleGasEstimation(contract);
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <solc/CommandLineParser.h>
|
||||
|
||||
#include <libevmasm/EVMAssemblyStack.h>
|
||||
#include <libsolidity/interface/CompilerStack.h>
|
||||
#include <libsolidity/interface/DebugSettings.h>
|
||||
#include <libsolidity/interface/FileReader.h>
|
||||
@ -84,6 +85,7 @@ private:
|
||||
void printVersion();
|
||||
void printLicense();
|
||||
void compile();
|
||||
void assembleFromEvmAssemblyJson();
|
||||
void serveLSP();
|
||||
void link();
|
||||
void writeLinkedFiles();
|
||||
@ -98,6 +100,7 @@ private:
|
||||
|
||||
void handleCombinedJSON();
|
||||
void handleAst();
|
||||
void handleEVMAssembly(std::string const& _contract);
|
||||
void handleBinary(std::string const& _contract);
|
||||
void handleOpcode(std::string const& _contract);
|
||||
void handleIR(std::string const& _contract);
|
||||
@ -145,6 +148,8 @@ private:
|
||||
UniversalCallback m_universalCallback{m_fileReader, m_solverCommand};
|
||||
std::optional<std::string> m_standardJsonInput;
|
||||
std::unique_ptr<frontend::CompilerStack> m_compiler;
|
||||
std::unique_ptr<evmasm::EVMAssemblyStack> m_evmAssemblyStack;
|
||||
evmasm::AbstractAssemblyStack* m_assemblyStack = nullptr;
|
||||
CommandLineOptions m_options;
|
||||
};
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <range/v3/view/filter.hpp>
|
||||
#include <range/v3/range/conversion.hpp>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
using namespace solidity::langutil;
|
||||
|
||||
namespace po = boost::program_options;
|
||||
@ -50,6 +52,7 @@ static std::string const g_strExperimentalViaIR = "experimental-via-ir";
|
||||
static std::string const g_strGas = "gas";
|
||||
static std::string const g_strHelp = "help";
|
||||
static std::string const g_strImportAst = "import-ast";
|
||||
static std::string const g_strImportEvmAssemblerJson = "import-asm-json";
|
||||
static std::string const g_strInputFile = "input-file";
|
||||
static std::string const g_strYul = "yul";
|
||||
static std::string const g_strYulDialect = "yul-dialect";
|
||||
@ -140,6 +143,7 @@ static std::map<InputMode, std::string> const g_inputModeName = {
|
||||
{InputMode::StandardJson, "standard JSON"},
|
||||
{InputMode::Linker, "linker"},
|
||||
{InputMode::LanguageServer, "language server (LSP)"},
|
||||
{InputMode::EVMAssemblerJSON, "EVM assembler (JSON format)"},
|
||||
};
|
||||
|
||||
void CommandLineParser::checkMutuallyExclusive(std::vector<std::string> const& _optionNames)
|
||||
@ -465,8 +469,15 @@ void CommandLineParser::parseOutputSelection()
|
||||
CompilerOutputs::componentName(&CompilerOutputs::binary),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::irOptimized),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::astCompactJson),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::asmJson),
|
||||
};
|
||||
static std::set<std::string> const evmAssemblyJsonImportModeOutputs = {
|
||||
CompilerOutputs::componentName(&CompilerOutputs::asm_),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::binary),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::binaryRuntime),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::opcodes),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::asmJson),
|
||||
};
|
||||
|
||||
switch (_mode)
|
||||
{
|
||||
case InputMode::Help:
|
||||
@ -477,6 +488,8 @@ void CommandLineParser::parseOutputSelection()
|
||||
case InputMode::Compiler:
|
||||
case InputMode::CompilerWithASTImport:
|
||||
return util::contains(compilerModeOutputs, _outputName);
|
||||
case InputMode::EVMAssemblerJSON:
|
||||
return util::contains(evmAssemblyJsonImportModeOutputs, _outputName);
|
||||
case InputMode::Assembler:
|
||||
return util::contains(assemblerModeOutputs, _outputName);
|
||||
case InputMode::StandardJson:
|
||||
@ -657,6 +670,10 @@ General Information)").c_str(),
|
||||
"Supported Inputs is the output of the --" + g_strStandardJSON + " or the one produced by "
|
||||
"--" + g_strCombinedJson + " " + CombinedJsonRequests::componentName(&CombinedJsonRequests::ast)).c_str()
|
||||
)
|
||||
(
|
||||
g_strImportEvmAssemblerJson.c_str(),
|
||||
"Import EVM assembly from JSON. Assumes input is in the format used by --asm-json."
|
||||
)
|
||||
(
|
||||
g_strLSP.c_str(),
|
||||
"Switch to language server mode (\"LSP\"). Allows the compiler to be used as an analysis backend "
|
||||
@ -925,6 +942,7 @@ void CommandLineParser::processArgs()
|
||||
g_strYul,
|
||||
g_strImportAst,
|
||||
g_strLSP,
|
||||
g_strImportEvmAssemblerJson,
|
||||
});
|
||||
|
||||
if (m_args.count(g_strHelp) > 0)
|
||||
@ -943,6 +961,8 @@ void CommandLineParser::processArgs()
|
||||
m_options.input.mode = InputMode::Linker;
|
||||
else if (m_args.count(g_strImportAst) > 0)
|
||||
m_options.input.mode = InputMode::CompilerWithASTImport;
|
||||
else if (m_args.count(g_strImportEvmAssemblerJson) > 0)
|
||||
m_options.input.mode = InputMode::EVMAssemblerJSON;
|
||||
else
|
||||
m_options.input.mode = InputMode::Compiler;
|
||||
|
||||
@ -1002,9 +1022,39 @@ void CommandLineParser::processArgs()
|
||||
if (option != CompilerOutputs::componentName(&CompilerOutputs::astCompactJson))
|
||||
checkMutuallyExclusive({g_strStopAfter, option});
|
||||
|
||||
if (m_options.input.mode == InputMode::EVMAssemblerJSON)
|
||||
{
|
||||
static std::set<std::string> const supportedByEvmAsmJsonImport{
|
||||
g_strImportEvmAssemblerJson,
|
||||
CompilerOutputs::componentName(&CompilerOutputs::asm_),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::binary),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::binaryRuntime),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::asmJson),
|
||||
CompilerOutputs::componentName(&CompilerOutputs::opcodes),
|
||||
g_strCombinedJson,
|
||||
g_strInputFile,
|
||||
g_strJsonIndent,
|
||||
g_strPrettyJson,
|
||||
"srcmap",
|
||||
"srcmap-runtime",
|
||||
};
|
||||
|
||||
for (auto const& option: m_args)
|
||||
if (!option.second.defaulted() && !supportedByEvmAsmJsonImport.count(option.first))
|
||||
solThrow(
|
||||
CommandLineValidationError,
|
||||
fmt::format(
|
||||
"Option --{} is not supported with --{}.",
|
||||
option.first,
|
||||
g_strImportEvmAssemblerJson
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
m_options.input.mode != InputMode::Compiler &&
|
||||
m_options.input.mode != InputMode::CompilerWithASTImport &&
|
||||
m_options.input.mode != InputMode::EVMAssemblerJSON &&
|
||||
m_options.input.mode != InputMode::Assembler
|
||||
)
|
||||
{
|
||||
@ -1362,7 +1412,11 @@ void CommandLineParser::processArgs()
|
||||
m_args.count(g_strModelCheckerTimeout);
|
||||
m_options.output.viaIR = (m_args.count(g_strExperimentalViaIR) > 0 || m_args.count(g_strViaIR) > 0);
|
||||
|
||||
solAssert(m_options.input.mode == InputMode::Compiler || m_options.input.mode == InputMode::CompilerWithASTImport);
|
||||
solAssert(
|
||||
m_options.input.mode == InputMode::Compiler ||
|
||||
m_options.input.mode == InputMode::CompilerWithASTImport ||
|
||||
m_options.input.mode == InputMode::EVMAssemblerJSON
|
||||
);
|
||||
}
|
||||
|
||||
void CommandLineParser::parseCombinedJsonOption()
|
||||
@ -1378,6 +1432,35 @@ void CommandLineParser::parseCombinedJsonOption()
|
||||
m_options.compiler.combinedJsonRequests = CombinedJsonRequests{};
|
||||
for (auto&& [componentName, component]: CombinedJsonRequests::componentMap())
|
||||
m_options.compiler.combinedJsonRequests.value().*component = (requests.count(componentName) > 0);
|
||||
|
||||
if (m_options.input.mode == InputMode::EVMAssemblerJSON && m_options.compiler.combinedJsonRequests.has_value())
|
||||
{
|
||||
static bool CombinedJsonRequests::* invalidOptions[]{
|
||||
&CombinedJsonRequests::abi,
|
||||
&CombinedJsonRequests::ast,
|
||||
&CombinedJsonRequests::funDebug,
|
||||
&CombinedJsonRequests::funDebugRuntime,
|
||||
&CombinedJsonRequests::generatedSources,
|
||||
&CombinedJsonRequests::generatedSourcesRuntime,
|
||||
&CombinedJsonRequests::metadata,
|
||||
&CombinedJsonRequests::natspecDev,
|
||||
&CombinedJsonRequests::natspecUser,
|
||||
&CombinedJsonRequests::signatureHashes,
|
||||
&CombinedJsonRequests::storageLayout
|
||||
};
|
||||
|
||||
for (auto const invalidOption: invalidOptions)
|
||||
if (m_options.compiler.combinedJsonRequests.value().*invalidOption)
|
||||
solThrow(
|
||||
CommandLineValidationError,
|
||||
fmt::format(
|
||||
"Invalid option to --{}: {} for --{}",
|
||||
g_strCombinedJson,
|
||||
CombinedJsonRequests::componentName(invalidOption),
|
||||
g_strImportEvmAssemblerJson
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
size_t CommandLineParser::countEnabledOptions(std::vector<std::string> const& _optionNames) const
|
||||
|
@ -57,6 +57,7 @@ enum class InputMode
|
||||
Linker,
|
||||
Assembler,
|
||||
LanguageServer,
|
||||
EVMAssemblerJSON
|
||||
};
|
||||
|
||||
struct CompilerOutputs
|
||||
|
@ -1567,7 +1567,8 @@ EVM assembly:
|
||||
"name": "JUMP",
|
||||
"source": 1
|
||||
}
|
||||
]
|
||||
],
|
||||
"index": 0
|
||||
}
|
||||
},
|
||||
"sourceList":
|
||||
|
@ -0,0 +1 @@
|
||||
--strict-assembly - --asm-json --pretty-json
|
388
test/cmdlineTests/asm_json_export_yul_more_subobjects/output
Normal file
388
test/cmdlineTests/asm_json_export_yul_more_subobjects/output
Normal file
@ -0,0 +1,388 @@
|
||||
|
||||
======= <stdin> (EVM) =======
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 37,
|
||||
"end": 51,
|
||||
"name": "PUSHSIZE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 34,
|
||||
"end": 35,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"begin": 27,
|
||||
"end": 52,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 67,
|
||||
"end": 81,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 64,
|
||||
"end": 65,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"begin": 57,
|
||||
"end": 82,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 97,
|
||||
"end": 114,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 94,
|
||||
"end": 95,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "2"
|
||||
},
|
||||
{
|
||||
"begin": 87,
|
||||
"end": 115,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 130,
|
||||
"end": 152,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffe"
|
||||
},
|
||||
{
|
||||
"begin": 127,
|
||||
"end": 128,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "3"
|
||||
},
|
||||
{
|
||||
"begin": 120,
|
||||
"end": 153,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 168,
|
||||
"end": 190,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffd"
|
||||
},
|
||||
{
|
||||
"begin": 165,
|
||||
"end": 166,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "4"
|
||||
},
|
||||
{
|
||||
"begin": 158,
|
||||
"end": 191,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 206,
|
||||
"end": 228,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffc"
|
||||
},
|
||||
{
|
||||
"begin": 203,
|
||||
"end": 204,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "5"
|
||||
},
|
||||
{
|
||||
"begin": 196,
|
||||
"end": 229,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 21,
|
||||
"end": 233,
|
||||
"name": "STOP",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 278,
|
||||
"end": 292,
|
||||
"name": "PUSHSIZE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 275,
|
||||
"end": 276,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "6"
|
||||
},
|
||||
{
|
||||
"begin": 268,
|
||||
"end": 293,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 310,
|
||||
"end": 324,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 307,
|
||||
"end": 308,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "7"
|
||||
},
|
||||
{
|
||||
"begin": 300,
|
||||
"end": 325,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 342,
|
||||
"end": 361,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 339,
|
||||
"end": 340,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "8"
|
||||
},
|
||||
{
|
||||
"begin": 332,
|
||||
"end": 362,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 379,
|
||||
"end": 398,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffe"
|
||||
},
|
||||
{
|
||||
"begin": 376,
|
||||
"end": 377,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "9"
|
||||
},
|
||||
{
|
||||
"begin": 369,
|
||||
"end": 399,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 417,
|
||||
"end": 436,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffd"
|
||||
},
|
||||
{
|
||||
"begin": 413,
|
||||
"end": 415,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "A"
|
||||
},
|
||||
{
|
||||
"begin": 406,
|
||||
"end": 437,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 260,
|
||||
"end": 443,
|
||||
"name": "STOP",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 494,
|
||||
"end": 508,
|
||||
"name": "PUSHSIZE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 490,
|
||||
"end": 492,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "B"
|
||||
},
|
||||
{
|
||||
"begin": 483,
|
||||
"end": 509,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 529,
|
||||
"end": 545,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 525,
|
||||
"end": 527,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "C"
|
||||
},
|
||||
{
|
||||
"begin": 518,
|
||||
"end": 546,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 566,
|
||||
"end": 582,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000001"
|
||||
},
|
||||
{
|
||||
"begin": 562,
|
||||
"end": 564,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "D"
|
||||
},
|
||||
{
|
||||
"begin": 555,
|
||||
"end": 583,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 603,
|
||||
"end": 619,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000002"
|
||||
},
|
||||
{
|
||||
"begin": 599,
|
||||
"end": 601,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "E"
|
||||
},
|
||||
{
|
||||
"begin": 592,
|
||||
"end": 620,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 473,
|
||||
"end": 628,
|
||||
"name": "STOP",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 676,
|
||||
"end": 685,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 0
|
||||
},
|
||||
"1":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 751,
|
||||
"end": 760,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 1
|
||||
},
|
||||
"2":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 826,
|
||||
"end": 835,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 2
|
||||
}
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
},
|
||||
"sourceList":
|
||||
[
|
||||
"<stdin>"
|
||||
]
|
||||
}
|
43
test/cmdlineTests/asm_json_export_yul_more_subobjects/stdin
Normal file
43
test/cmdlineTests/asm_json_export_yul_more_subobjects/stdin
Normal file
@ -0,0 +1,43 @@
|
||||
object "L0" {
|
||||
code {
|
||||
sstore(0, datasize("L0"))
|
||||
sstore(1, datasize("L1"))
|
||||
sstore(2, datasize("L1.L2"))
|
||||
sstore(3, datasize("L1.L2.L2_0"))
|
||||
sstore(4, datasize("L1.L2.L2_1"))
|
||||
sstore(5, datasize("L1.L2.L2_2"))
|
||||
}
|
||||
|
||||
object "L1" {
|
||||
code {
|
||||
sstore(6, datasize("L1"))
|
||||
sstore(7, datasize("L2"))
|
||||
sstore(8, datasize("L2.L2_0"))
|
||||
sstore(9, datasize("L2.L2_1"))
|
||||
sstore(10, datasize("L2.L2_2"))
|
||||
}
|
||||
object "L2" {
|
||||
code {
|
||||
sstore(11, datasize("L2"))
|
||||
sstore(12, datasize("L2_0"))
|
||||
sstore(13, datasize("L2_1"))
|
||||
sstore(14, datasize("L2_2"))
|
||||
}
|
||||
object "L2_0" {
|
||||
code {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
object "L2_1" {
|
||||
code {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
object "L2_2" {
|
||||
code {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
test/cmdlineTests/asm_json_export_yul_subobjects/args
Normal file
1
test/cmdlineTests/asm_json_export_yul_subobjects/args
Normal file
@ -0,0 +1 @@
|
||||
--strict-assembly - --asm-json --pretty-json
|
437
test/cmdlineTests/asm_json_export_yul_subobjects/output
Normal file
437
test/cmdlineTests/asm_json_export_yul_subobjects/output
Normal file
@ -0,0 +1,437 @@
|
||||
|
||||
======= <stdin> (EVM) =======
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 36,
|
||||
"end": 51,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"begin": 33,
|
||||
"end": 34,
|
||||
"name": "DUP1",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 26,
|
||||
"end": 52,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 67,
|
||||
"end": 80,
|
||||
"name": "PUSHSIZE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 64,
|
||||
"end": 65,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"begin": 57,
|
||||
"end": 81,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 96,
|
||||
"end": 111,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 93,
|
||||
"end": 94,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "2"
|
||||
},
|
||||
{
|
||||
"begin": 86,
|
||||
"end": 112,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 127,
|
||||
"end": 140,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 124,
|
||||
"end": 125,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "3"
|
||||
},
|
||||
{
|
||||
"begin": 117,
|
||||
"end": 141,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 156,
|
||||
"end": 173,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 153,
|
||||
"end": 154,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "4"
|
||||
},
|
||||
{
|
||||
"begin": 146,
|
||||
"end": 174,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 189,
|
||||
"end": 204,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 186,
|
||||
"end": 187,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "5"
|
||||
},
|
||||
{
|
||||
"begin": 179,
|
||||
"end": 205,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 220,
|
||||
"end": 237,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffe"
|
||||
},
|
||||
{
|
||||
"begin": 217,
|
||||
"end": 218,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "6"
|
||||
},
|
||||
{
|
||||
"begin": 210,
|
||||
"end": 238,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 253,
|
||||
"end": 268,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffe"
|
||||
},
|
||||
{
|
||||
"begin": 250,
|
||||
"end": 251,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "7"
|
||||
},
|
||||
{
|
||||
"begin": 243,
|
||||
"end": 269,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 284,
|
||||
"end": 303,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffd"
|
||||
},
|
||||
{
|
||||
"begin": 281,
|
||||
"end": 282,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "8"
|
||||
},
|
||||
{
|
||||
"begin": 274,
|
||||
"end": 304,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 319,
|
||||
"end": 336,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffd"
|
||||
},
|
||||
{
|
||||
"begin": 316,
|
||||
"end": 317,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "9"
|
||||
},
|
||||
{
|
||||
"begin": 309,
|
||||
"end": 337,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 20,
|
||||
"end": 341,
|
||||
"name": "STOP",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 418,
|
||||
"end": 433,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 414,
|
||||
"end": 416,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "A"
|
||||
},
|
||||
{
|
||||
"begin": 407,
|
||||
"end": 434,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 452,
|
||||
"end": 465,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 448,
|
||||
"end": 450,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "B"
|
||||
},
|
||||
{
|
||||
"begin": 441,
|
||||
"end": 466,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 484,
|
||||
"end": 499,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000001"
|
||||
},
|
||||
{
|
||||
"begin": 480,
|
||||
"end": 482,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "C"
|
||||
},
|
||||
{
|
||||
"begin": 473,
|
||||
"end": 500,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 518,
|
||||
"end": 531,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000001"
|
||||
},
|
||||
{
|
||||
"begin": 514,
|
||||
"end": 516,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "D"
|
||||
},
|
||||
{
|
||||
"begin": 507,
|
||||
"end": 532,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 550,
|
||||
"end": 567,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 546,
|
||||
"end": 548,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "E"
|
||||
},
|
||||
{
|
||||
"begin": 539,
|
||||
"end": 568,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 586,
|
||||
"end": 601,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 582,
|
||||
"end": 584,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "F"
|
||||
},
|
||||
{
|
||||
"begin": 575,
|
||||
"end": 602,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 399,
|
||||
"end": 608,
|
||||
"name": "STOP",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 658,
|
||||
"end": 673,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 654,
|
||||
"end": 656,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "10"
|
||||
},
|
||||
{
|
||||
"begin": 647,
|
||||
"end": 674,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 694,
|
||||
"end": 707,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 690,
|
||||
"end": 692,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "11"
|
||||
},
|
||||
{
|
||||
"begin": 683,
|
||||
"end": 708,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 637,
|
||||
"end": 716,
|
||||
"name": "STOP",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 761,
|
||||
"end": 770,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 0
|
||||
}
|
||||
},
|
||||
"index": 0
|
||||
},
|
||||
"1":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 833,
|
||||
"end": 842,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 1
|
||||
}
|
||||
},
|
||||
"index": 0
|
||||
},
|
||||
"ACAF3289D7B601CBD114FB36C4D29C85BBFD5E133F14CB355C3FD8D99367964F": "48656c6c6f2c20576f726c6421"
|
||||
},
|
||||
"sourceList":
|
||||
[
|
||||
"<stdin>"
|
||||
]
|
||||
}
|
43
test/cmdlineTests/asm_json_export_yul_subobjects/stdin
Normal file
43
test/cmdlineTests/asm_json_export_yul_subobjects/stdin
Normal file
@ -0,0 +1,43 @@
|
||||
object "A" {
|
||||
code {
|
||||
sstore(0, dataoffset("A"))
|
||||
sstore(1, datasize("A"))
|
||||
sstore(2, dataoffset("B"))
|
||||
sstore(3, datasize("B"))
|
||||
sstore(4, dataoffset("B.C"))
|
||||
sstore(5, datasize("B.C"))
|
||||
sstore(6, dataoffset("B.E"))
|
||||
sstore(7, datasize("B.E"))
|
||||
sstore(8, dataoffset("B.C.D"))
|
||||
sstore(9, datasize("B.C.D"))
|
||||
}
|
||||
|
||||
data "data1" "Hello, World!"
|
||||
|
||||
object "B" {
|
||||
code {
|
||||
sstore(10, dataoffset("C"))
|
||||
sstore(11, datasize("C"))
|
||||
sstore(12, dataoffset("E"))
|
||||
sstore(13, datasize("E"))
|
||||
sstore(14, dataoffset("C.D"))
|
||||
sstore(15, datasize("C.D"))
|
||||
}
|
||||
object "C" {
|
||||
code {
|
||||
sstore(16, dataoffset("D"))
|
||||
sstore(17, datasize("D"))
|
||||
}
|
||||
object "D" {
|
||||
code {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
}
|
||||
object "E" {
|
||||
code {
|
||||
invalid()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
test/cmdlineTests/asm_json_export_yul_verbatim/args
Normal file
1
test/cmdlineTests/asm_json_export_yul_verbatim/args
Normal file
@ -0,0 +1 @@
|
||||
--strict-assembly - --asm-json
|
3
test/cmdlineTests/asm_json_export_yul_verbatim/output
Normal file
3
test/cmdlineTests/asm_json_export_yul_verbatim/output
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
======= <stdin> (EVM) =======
|
||||
{".code":[{"begin":28,"end":29,"name":"PUSH","source":0,"value":"0"},{"begin":15,"end":30,"name":"CALLDATALOAD","source":0},{"begin":44,"end":46,"name":"PUSH","source":0,"value":"14"},{"begin":61,"end":62,"name":"DUP1","source":0},{"begin":58,"end":59,"name":"DUP3","source":0},{"begin":51,"end":63,"name":"SSTORE","source":0},{"begin":84,"end":86,"name":"PUSH","source":0,"value":"20"},{"begin":71,"end":87,"name":"CALLDATALOAD","source":0},{"begin":68,"end":188,"name":"ISZERO","source":0},{"begin":68,"end":188,"name":"PUSH [tag]","source":0,"value":"1"},{"begin":68,"end":188,"name":"JUMPI","source":0},{"begin":108,"end":109,"name":"DUP1","source":0},{"begin":105,"end":106,"name":"DUP3","source":0},{"begin":98,"end":110,"name":"SSTORE","source":0},{"begin":149,"end":150,"name":"PUSH","source":0,"value":"0"},{"begin":146,"end":147,"name":"DUP1","source":0},{"begin":143,"end":144,"name":"PUSH","source":0,"value":"0"},{"begin":140,"end":141,"name":"DUP1","source":0},{"begin":137,"end":138,"name":"PUSH","source":0,"value":"0"},{"begin":134,"end":135,"name":"DUP1","source":0},{"begin":123,"end":151,"name":"STATICCALL","source":0},{"begin":119,"end":152,"name":"POP","source":0},{"begin":161,"end":182,"name":"VERBATIM","source":0,"value":"78797a"},{"begin":68,"end":188,"name":"tag","source":0,"value":"1"},{"begin":68,"end":188,"name":"JUMPDEST","source":0},{"begin":203,"end":204,"name":"DUP1","source":0},{"begin":200,"end":201,"name":"DUP3","source":0},{"begin":193,"end":205,"name":"SSTORE","source":0},{"begin":0,"end":207,"name":"POP","source":0},{"begin":0,"end":207,"name":"POP","source":0}],"sourceList":["<stdin>"]}
|
11
test/cmdlineTests/asm_json_export_yul_verbatim/stdin
Normal file
11
test/cmdlineTests/asm_json_export_yul_verbatim/stdin
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
let a := calldataload(0)
|
||||
let b := 20
|
||||
sstore(a, b)
|
||||
if calldataload(32) {
|
||||
sstore(a, b)
|
||||
pop(staticcall(0, 0, 0, 0, 0, 0))
|
||||
verbatim_0i_0o("xyz")
|
||||
}
|
||||
sstore(a, b)
|
||||
}
|
1
test/cmdlineTests/asm_json_export_yul_with_debug/args
Normal file
1
test/cmdlineTests/asm_json_export_yul_with_debug/args
Normal file
@ -0,0 +1 @@
|
||||
--strict-assembly - --asm-json
|
3
test/cmdlineTests/asm_json_export_yul_with_debug/output
Normal file
3
test/cmdlineTests/asm_json_export_yul_with_debug/output
Normal file
File diff suppressed because one or more lines are too long
50
test/cmdlineTests/asm_json_export_yul_with_debug/stdin
Normal file
50
test/cmdlineTests/asm_json_export_yul_with_debug/stdin
Normal file
@ -0,0 +1,50 @@
|
||||
/// @use-src 0:"state_var_initialization.sol"
|
||||
object "C_23" {
|
||||
code {
|
||||
{
|
||||
/// @src 0:0:125 "contract C {..."
|
||||
let _1 := memoryguard(0x80)
|
||||
mstore(64, _1)
|
||||
if callvalue() { revert(0, 0) }
|
||||
sstore(/** @src 0:33:34 "1" */ 0x00, /** @src 0:56:57 "2" */ 0x02)
|
||||
/// @src 0:0:125 "contract C {..."
|
||||
sstore(/** @src 0:33:34 "1" */ 0x01, 0x00)
|
||||
/// @src 0:0:125 "contract C {..."
|
||||
let _2 := datasize("C_23_deployed")
|
||||
codecopy(_1, dataoffset("C_23_deployed"), _2)
|
||||
return(_1, _2)
|
||||
}
|
||||
}
|
||||
/// @use-src 0:"state_var_initialization.sol"
|
||||
object "C_23_deployed" {
|
||||
code {
|
||||
{
|
||||
/// @src 0:0:125 "contract C {..."
|
||||
let _1 := memoryguard(0x80)
|
||||
mstore(64, _1)
|
||||
if iszero(lt(calldatasize(), 4))
|
||||
{
|
||||
let _2 := 0
|
||||
switch shr(224, calldataload(_2))
|
||||
case 0xb4f40c61 {
|
||||
if callvalue() { revert(_2, _2) }
|
||||
if slt(add(calldatasize(), not(3)), _2) { revert(_2, _2) }
|
||||
mstore(_1, sload(/** @src 0:40:57 "uint public k = 2" */ 1))
|
||||
/// @src 0:0:125 "contract C {..."
|
||||
return(_1, 32)
|
||||
}
|
||||
case 0xe5aa3d58 {
|
||||
if callvalue() { revert(_2, _2) }
|
||||
if slt(add(calldatasize(), not(3)), _2) { revert(_2, _2) }
|
||||
let _3 := sload(_2)
|
||||
let memPos := mload(64)
|
||||
mstore(memPos, _3)
|
||||
return(memPos, 32)
|
||||
}
|
||||
}
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
data ".metadata" hex"a2646970667358221220f04f800086d1bd95dea7e66c53d041963124c118e4dc70bc4b39a50865c2483f64736f6c63430008130033"
|
||||
}
|
||||
}
|
1
test/cmdlineTests/asm_json_export_yul_without_debug/args
Normal file
1
test/cmdlineTests/asm_json_export_yul_without_debug/args
Normal file
@ -0,0 +1 @@
|
||||
--strict-assembly - --asm-json
|
File diff suppressed because one or more lines are too long
43
test/cmdlineTests/asm_json_export_yul_without_debug/stdin
Normal file
43
test/cmdlineTests/asm_json_export_yul_without_debug/stdin
Normal file
@ -0,0 +1,43 @@
|
||||
object "C_23" {
|
||||
code {
|
||||
{
|
||||
let _1 := memoryguard(0x80)
|
||||
mstore(64, _1)
|
||||
if callvalue() { revert(0, 0) }
|
||||
sstore(0x00, 0x02)
|
||||
sstore(0x01, 0x00)
|
||||
let _2 := datasize("C_23_deployed")
|
||||
codecopy(_1, dataoffset("C_23_deployed"), _2)
|
||||
return(_1, _2)
|
||||
}
|
||||
}
|
||||
object "C_23_deployed" {
|
||||
code {
|
||||
{
|
||||
let _1 := memoryguard(0x80)
|
||||
mstore(64, _1)
|
||||
if iszero(lt(calldatasize(), 4))
|
||||
{
|
||||
let _2 := 0
|
||||
switch shr(224, calldataload(_2))
|
||||
case 0xb4f40c61 {
|
||||
if callvalue() { revert(_2, _2) }
|
||||
if slt(add(calldatasize(), not(3)), _2) { revert(_2, _2) }
|
||||
mstore(_1, sload(/** @src 0:40:57 "uint public k = 2" */ 1))
|
||||
return(_1, 32)
|
||||
}
|
||||
case 0xe5aa3d58 {
|
||||
if callvalue() { revert(_2, _2) }
|
||||
if slt(add(calldatasize(), not(3)), _2) { revert(_2, _2) }
|
||||
let _3 := sload(_2)
|
||||
let memPos := mload(64)
|
||||
mstore(memPos, _3)
|
||||
return(memPos, 32)
|
||||
}
|
||||
}
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
data ".metadata" hex"a2646970667358221220f04f800086d1bd95dea7e66c53d041963124c118e4dc70bc4b39a50865c2483f64736f6c63430008130033"
|
||||
}
|
||||
}
|
1
test/cmdlineTests/asm_json_import_all_valid_flags/args
Normal file
1
test/cmdlineTests/asm_json_import_all_valid_flags/args
Normal file
@ -0,0 +1 @@
|
||||
--pretty-json --json-indent 4 --combined-json bin,bin-runtime,opcodes,asm,srcmap,srcmap-runtime --asm --bin --bin-runtime --asm-json --import-asm-json -
|
93
test/cmdlineTests/asm_json_import_all_valid_flags/output
Normal file
93
test/cmdlineTests/asm_json_import_all_valid_flags/output
Normal file
@ -0,0 +1,93 @@
|
||||
{
|
||||
"contracts":
|
||||
{
|
||||
"<stdin>":
|
||||
{
|
||||
"asm":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 0,
|
||||
"end": 0,
|
||||
"name": "PUSH",
|
||||
"source": -1,
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 0,
|
||||
"end": 0,
|
||||
"name": "PUSH",
|
||||
"source": -1,
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"index": 0
|
||||
}
|
||||
},
|
||||
"sourceList":
|
||||
[
|
||||
"contract.sol",
|
||||
"#utility.yul"
|
||||
]
|
||||
},
|
||||
"bin": "5ffe",
|
||||
"bin-runtime": "6001",
|
||||
"opcodes": "PUSH0 INVALID ",
|
||||
"srcmap": "0:0::-:0",
|
||||
"srcmap-runtime": "0:0::-:0"
|
||||
}
|
||||
},
|
||||
"sourceList":
|
||||
[
|
||||
"contract.sol",
|
||||
"#utility.yul"
|
||||
],
|
||||
"version": "<VERSION REMOVED>"
|
||||
}
|
||||
Binary:
|
||||
5ffe
|
||||
Binary of the runtime part:
|
||||
6001
|
||||
EVM assembly:
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 0,
|
||||
"end": 0,
|
||||
"name": "PUSH",
|
||||
"source": -1,
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 0,
|
||||
"end": 0,
|
||||
"name": "PUSH",
|
||||
"source": -1,
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"index": 0
|
||||
}
|
||||
},
|
||||
"sourceList":
|
||||
[
|
||||
"contract.sol",
|
||||
"#utility.yul"
|
||||
]
|
||||
}
|
23
test/cmdlineTests/asm_json_import_all_valid_flags/stdin
Normal file
23
test/cmdlineTests/asm_json_import_all_valid_flags/stdin
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
".code": [
|
||||
{
|
||||
"name": "PUSH",
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
".data": {
|
||||
"0": {
|
||||
".code": [
|
||||
{
|
||||
"name": "PUSH",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"index": 0
|
||||
}
|
||||
},
|
||||
"sourceList": [
|
||||
"contract.sol",
|
||||
"#utility.yul"
|
||||
]
|
||||
}
|
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes --asm
|
@ -0,0 +1,6 @@
|
||||
Opcodes:
|
||||
PREVRANDAO PREVRANDAO
|
||||
EVM assembly:
|
||||
/* */
|
||||
prevrandao
|
||||
prevrandao
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
".code": [
|
||||
{ "name": "DIFFICULTY" },
|
||||
{ "name": "PREVRANDAO" }
|
||||
]
|
||||
}
|
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes --asm
|
@ -0,0 +1 @@
|
||||
Assembly Import Error: Member '.data' contains a value for '0' that is not a valid hexadecimal string.
|
@ -0,0 +1 @@
|
||||
1
|
11
test/cmdlineTests/asm_json_import_invalid_data_no_hex/stdin
Normal file
11
test/cmdlineTests/asm_json_import_invalid_data_no_hex/stdin
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
".code": [
|
||||
{
|
||||
"name": "PUSH",
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
".data": {
|
||||
"0": "no-hex-string"
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes --asm
|
@ -0,0 +1 @@
|
||||
Assembly Import Error: Key inside '.data' '0' can only be a valid hex-string or an object.
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
".code": [
|
||||
{
|
||||
"name": "PUSH",
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
".data": {
|
||||
"0": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes --asm
|
@ -0,0 +1 @@
|
||||
Assembly Import Error: Member 'jumpType' set on instruction different from JUMP or JUMPI (was set on instruction 'PUSH')
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
".code": [
|
||||
{
|
||||
"name": "PUSH",
|
||||
"value": "0",
|
||||
"jumpType": "[in]"
|
||||
}
|
||||
]
|
||||
}
|
1
test/cmdlineTests/asm_json_import_invalid_value/args
Normal file
1
test/cmdlineTests/asm_json_import_invalid_value/args
Normal file
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes --asm
|
1
test/cmdlineTests/asm_json_import_invalid_value/err
Normal file
1
test/cmdlineTests/asm_json_import_invalid_value/err
Normal file
@ -0,0 +1 @@
|
||||
Assembly Import Error: Member 'value' defined for instruction 'DIFFICULTY', but the instruction does not need a value.
|
1
test/cmdlineTests/asm_json_import_invalid_value/exit
Normal file
1
test/cmdlineTests/asm_json_import_invalid_value/exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
8
test/cmdlineTests/asm_json_import_invalid_value/stdin
Normal file
8
test/cmdlineTests/asm_json_import_invalid_value/stdin
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
".code": [
|
||||
{
|
||||
"name": "DIFFICULTY",
|
||||
"value": "0"
|
||||
}
|
||||
]
|
||||
}
|
1
test/cmdlineTests/asm_json_import_no_optimiser/args
Normal file
1
test/cmdlineTests/asm_json_import_no_optimiser/args
Normal file
@ -0,0 +1 @@
|
||||
--optimize --import-asm-json - --opcodes --asm
|
1
test/cmdlineTests/asm_json_import_no_optimiser/err
Normal file
1
test/cmdlineTests/asm_json_import_no_optimiser/err
Normal file
@ -0,0 +1 @@
|
||||
Option --optimize is not supported with --import-asm-json.
|
1
test/cmdlineTests/asm_json_import_no_optimiser/exit
Normal file
1
test/cmdlineTests/asm_json_import_no_optimiser/exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
6
test/cmdlineTests/asm_json_import_no_optimiser/stdin
Normal file
6
test/cmdlineTests/asm_json_import_no_optimiser/stdin
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
".code": [
|
||||
{ "name": "DIFFICULTY" },
|
||||
{ "name": "PREVRANDAO" }
|
||||
]
|
||||
}
|
1
test/cmdlineTests/asm_json_import_no_value/args
Normal file
1
test/cmdlineTests/asm_json_import_no_value/args
Normal file
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes --asm
|
1
test/cmdlineTests/asm_json_import_no_value/err
Normal file
1
test/cmdlineTests/asm_json_import_no_value/err
Normal file
@ -0,0 +1 @@
|
||||
Assembly Import Error: Member 'value' was not defined for instruction 'PUSH', but the instruction needs a value.
|
1
test/cmdlineTests/asm_json_import_no_value/exit
Normal file
1
test/cmdlineTests/asm_json_import_no_value/exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
5
test/cmdlineTests/asm_json_import_no_value/stdin
Normal file
5
test/cmdlineTests/asm_json_import_no_value/stdin
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
".code": [
|
||||
{ "name": "PUSH" }
|
||||
]
|
||||
}
|
@ -0,0 +1 @@
|
||||
--asm-json --import-asm-json -
|
1
test/cmdlineTests/asm_json_import_non_unique_sources/err
Normal file
1
test/cmdlineTests/asm_json_import_non_unique_sources/err
Normal file
@ -0,0 +1 @@
|
||||
Assembly Import Error: Items in 'sourceList' array are not unique.
|
@ -0,0 +1 @@
|
||||
1
|
23
test/cmdlineTests/asm_json_import_non_unique_sources/stdin
Normal file
23
test/cmdlineTests/asm_json_import_non_unique_sources/stdin
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
".code": [
|
||||
{
|
||||
"name": "PUSH",
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
".data": {
|
||||
"0": {
|
||||
".code": [
|
||||
{
|
||||
"name": "PUSH",
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sourceList": [
|
||||
"contract.sol",
|
||||
"contract.sol",
|
||||
"#utility.yul"
|
||||
]
|
||||
}
|
1
test/cmdlineTests/asm_json_import_other_fields/args
Normal file
1
test/cmdlineTests/asm_json_import_other_fields/args
Normal file
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes --asm
|
1
test/cmdlineTests/asm_json_import_other_fields/err
Normal file
1
test/cmdlineTests/asm_json_import_other_fields/err
Normal file
@ -0,0 +1 @@
|
||||
Assembly Import Error: Unknown member '_name'. Valid members are begin, end, jumpType, modifierDepth, name, source, value.
|
1
test/cmdlineTests/asm_json_import_other_fields/exit
Normal file
1
test/cmdlineTests/asm_json_import_other_fields/exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
5
test/cmdlineTests/asm_json_import_other_fields/stdin
Normal file
5
test/cmdlineTests/asm_json_import_other_fields/stdin
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
".code": [
|
||||
{ "_name": "DIFFICULTY" }
|
||||
]
|
||||
}
|
1
test/cmdlineTests/asm_json_import_untagged_jumpdest/args
Normal file
1
test/cmdlineTests/asm_json_import_untagged_jumpdest/args
Normal file
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes --asm
|
1
test/cmdlineTests/asm_json_import_untagged_jumpdest/err
Normal file
1
test/cmdlineTests/asm_json_import_untagged_jumpdest/err
Normal file
@ -0,0 +1 @@
|
||||
Assembly Import Error: JUMPDEST instruction without a tag
|
1
test/cmdlineTests/asm_json_import_untagged_jumpdest/exit
Normal file
1
test/cmdlineTests/asm_json_import_untagged_jumpdest/exit
Normal file
@ -0,0 +1 @@
|
||||
1
|
10
test/cmdlineTests/asm_json_import_untagged_jumpdest/stdin
Normal file
10
test/cmdlineTests/asm_json_import_untagged_jumpdest/stdin
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
".code": [
|
||||
{
|
||||
"name": "tag",
|
||||
"value": "0x00"
|
||||
},
|
||||
{ "name": "JUMPDEST" },
|
||||
{ "name": "JUMPDEST" }
|
||||
]
|
||||
}
|
1
test/cmdlineTests/asm_json_import_verbatim/args
Normal file
1
test/cmdlineTests/asm_json_import_verbatim/args
Normal file
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes --asm
|
58
test/cmdlineTests/asm_json_import_verbatim/output
Normal file
58
test/cmdlineTests/asm_json_import_verbatim/output
Normal file
@ -0,0 +1,58 @@
|
||||
Opcodes:
|
||||
PUSH0 CALLDATALOAD PUSH1 0x14 DUP1 DUP3 SSTORE PUSH1 0x20 CALLDATALOAD ISZERO PUSH1 0x1C JUMPI DUP1 DUP3 SSTORE PUSH0 DUP1 PUSH0 DUP1 PUSH0 DUP1 STATICCALL POP PUSH25 0x797A5B80825550500000000000000000000000000000000000
|
||||
EVM assembly:
|
||||
/* "<stdin>":28:29 b */
|
||||
0x00
|
||||
/* "<stdin>":15:30 {... */
|
||||
calldataload
|
||||
/* "<stdin>":44:46 */
|
||||
0x14
|
||||
/* "<stdin>":61:62 */
|
||||
dup1
|
||||
/* "<stdin>":58:59 */
|
||||
dup3
|
||||
/* "<stdin>":51:63 : 29,... */
|
||||
sstore
|
||||
/* "<stdin>":84:86 " */
|
||||
0x20
|
||||
/* "<stdin>":71:87 "PUSH",... */
|
||||
calldataload
|
||||
/* "<stdin>":68:188 ": "PUSH",... */
|
||||
iszero
|
||||
tag_1
|
||||
jumpi
|
||||
/* "<stdin>":108:109 u */
|
||||
dup1
|
||||
/* "<stdin>":105:106 v */
|
||||
dup3
|
||||
/* "<stdin>":98:110 "value */
|
||||
sstore
|
||||
/* "<stdin>":149:150 */
|
||||
0x00
|
||||
/* "<stdin>":146:147 5 */
|
||||
dup1
|
||||
/* "<stdin>":143:144 : */
|
||||
0x00
|
||||
/* "<stdin>":140:141 i */
|
||||
dup1
|
||||
/* "<stdin>":137:138 b */
|
||||
0x00
|
||||
/* "<stdin>":134:135 */
|
||||
dup1
|
||||
/* "<stdin>":123:151 ... */
|
||||
staticcall
|
||||
/* "<stdin>":119:152 },... */
|
||||
pop
|
||||
/* "<stdin>":161:182 30,... */
|
||||
verbatimbytecode_78797a
|
||||
/* "<stdin>":68:188 ": "PUSH",... */
|
||||
tag_1:
|
||||
/* "<stdin>":203:204 s */
|
||||
dup1
|
||||
/* "<stdin>":200:201 */
|
||||
dup3
|
||||
/* "<stdin>":193:205 ",... */
|
||||
sstore
|
||||
/* "<stdin>":0:207 {... */
|
||||
pop
|
||||
pop
|
196
test/cmdlineTests/asm_json_import_verbatim/stdin
Normal file
196
test/cmdlineTests/asm_json_import_verbatim/stdin
Normal file
@ -0,0 +1,196 @@
|
||||
{
|
||||
".code": [
|
||||
{
|
||||
"begin": 28,
|
||||
"end": 29,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"begin": 15,
|
||||
"end": 30,
|
||||
"name": "CALLDATALOAD",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 44,
|
||||
"end": 46,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "14"
|
||||
},
|
||||
{
|
||||
"begin": 61,
|
||||
"end": 62,
|
||||
"name": "DUP1",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 58,
|
||||
"end": 59,
|
||||
"name": "DUP3",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 51,
|
||||
"end": 63,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 84,
|
||||
"end": 86,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "20"
|
||||
},
|
||||
{
|
||||
"begin": 71,
|
||||
"end": 87,
|
||||
"name": "CALLDATALOAD",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 68,
|
||||
"end": 188,
|
||||
"name": "ISZERO",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 68,
|
||||
"end": 188,
|
||||
"name": "PUSH [tag]",
|
||||
"source": 0,
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"begin": 68,
|
||||
"end": 188,
|
||||
"name": "JUMPI",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 108,
|
||||
"end": 109,
|
||||
"name": "DUP1",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 105,
|
||||
"end": 106,
|
||||
"name": "DUP3",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 98,
|
||||
"end": 110,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 149,
|
||||
"end": 150,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"begin": 146,
|
||||
"end": 147,
|
||||
"name": "DUP1",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 143,
|
||||
"end": 144,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"begin": 140,
|
||||
"end": 141,
|
||||
"name": "DUP1",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 137,
|
||||
"end": 138,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"begin": 134,
|
||||
"end": 135,
|
||||
"name": "DUP1",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 123,
|
||||
"end": 151,
|
||||
"name": "STATICCALL",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 119,
|
||||
"end": 152,
|
||||
"name": "POP",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 161,
|
||||
"end": 182,
|
||||
"name": "VERBATIM",
|
||||
"source": 0,
|
||||
"value": "78797a"
|
||||
},
|
||||
{
|
||||
"begin": 68,
|
||||
"end": 188,
|
||||
"name": "tag",
|
||||
"source": 0,
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"begin": 68,
|
||||
"end": 188,
|
||||
"name": "JUMPDEST",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 203,
|
||||
"end": 204,
|
||||
"name": "DUP1",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 200,
|
||||
"end": 201,
|
||||
"name": "DUP3",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 193,
|
||||
"end": 205,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 0,
|
||||
"end": 207,
|
||||
"name": "POP",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 0,
|
||||
"end": 207,
|
||||
"name": "POP",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"sourceList": [
|
||||
"<stdin>"
|
||||
]
|
||||
}
|
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes
|
@ -0,0 +1,2 @@
|
||||
Opcodes:
|
||||
PUSH1 0x1E PUSH0 SSTORE PUSH1 0x1A PUSH1 0x1 SSTORE PUSH1 0x15 PUSH1 0x2 SSTORE PUSH1 0x1 PUSH1 0x3 SSTORE PUSH1 0x1 PUSH1 0x4 SSTORE PUSH1 0x1 PUSH1 0x5 SSTORE INVALID
|
368
test/cmdlineTests/asm_json_import_yul_more_subobjects/stdin
Normal file
368
test/cmdlineTests/asm_json_import_yul_more_subobjects/stdin
Normal file
@ -0,0 +1,368 @@
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 37,
|
||||
"end": 51,
|
||||
"name": "PUSHSIZE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 34,
|
||||
"end": 35,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"begin": 27,
|
||||
"end": 52,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 67,
|
||||
"end": 81,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 64,
|
||||
"end": 65,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"begin": 57,
|
||||
"end": 82,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 97,
|
||||
"end": 114,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 94,
|
||||
"end": 95,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "2"
|
||||
},
|
||||
{
|
||||
"begin": 87,
|
||||
"end": 115,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 130,
|
||||
"end": 152,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffe"
|
||||
},
|
||||
{
|
||||
"begin": 127,
|
||||
"end": 128,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "3"
|
||||
},
|
||||
{
|
||||
"begin": 120,
|
||||
"end": 153,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 168,
|
||||
"end": 190,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffd"
|
||||
},
|
||||
{
|
||||
"begin": 165,
|
||||
"end": 166,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "4"
|
||||
},
|
||||
{
|
||||
"begin": 158,
|
||||
"end": 191,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 206,
|
||||
"end": 228,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffc"
|
||||
},
|
||||
{
|
||||
"begin": 203,
|
||||
"end": 204,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "5"
|
||||
},
|
||||
{
|
||||
"begin": 196,
|
||||
"end": 229,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 278,
|
||||
"end": 292,
|
||||
"name": "PUSHSIZE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 275,
|
||||
"end": 276,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "6"
|
||||
},
|
||||
{
|
||||
"begin": 268,
|
||||
"end": 293,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 310,
|
||||
"end": 324,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 307,
|
||||
"end": 308,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "7"
|
||||
},
|
||||
{
|
||||
"begin": 300,
|
||||
"end": 325,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 342,
|
||||
"end": 361,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 339,
|
||||
"end": 340,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "8"
|
||||
},
|
||||
{
|
||||
"begin": 332,
|
||||
"end": 362,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 379,
|
||||
"end": 398,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffe"
|
||||
},
|
||||
{
|
||||
"begin": 376,
|
||||
"end": 377,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "9"
|
||||
},
|
||||
{
|
||||
"begin": 369,
|
||||
"end": 399,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 417,
|
||||
"end": 436,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffd"
|
||||
},
|
||||
{
|
||||
"begin": 413,
|
||||
"end": 415,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "A"
|
||||
},
|
||||
{
|
||||
"begin": 406,
|
||||
"end": 437,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 0,
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 494,
|
||||
"end": 508,
|
||||
"name": "PUSHSIZE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 490,
|
||||
"end": 492,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "B"
|
||||
},
|
||||
{
|
||||
"begin": 483,
|
||||
"end": 509,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 529,
|
||||
"end": 545,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 525,
|
||||
"end": 527,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "C"
|
||||
},
|
||||
{
|
||||
"begin": 518,
|
||||
"end": 546,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 566,
|
||||
"end": 582,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000001"
|
||||
},
|
||||
{
|
||||
"begin": 562,
|
||||
"end": 564,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "D"
|
||||
},
|
||||
{
|
||||
"begin": 555,
|
||||
"end": 583,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 603,
|
||||
"end": 619,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000002"
|
||||
},
|
||||
{
|
||||
"begin": 599,
|
||||
"end": 601,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "E"
|
||||
},
|
||||
{
|
||||
"begin": 592,
|
||||
"end": 620,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 0,
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 676,
|
||||
"end": 685,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 0
|
||||
},
|
||||
"1":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 751,
|
||||
"end": 760,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 1
|
||||
},
|
||||
"2":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 826,
|
||||
"end": 835,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceList":
|
||||
[
|
||||
"<stdin>"
|
||||
]
|
||||
}
|
1
test/cmdlineTests/asm_json_import_yul_subobjects/args
Normal file
1
test/cmdlineTests/asm_json_import_yul_subobjects/args
Normal file
@ -0,0 +1 @@
|
||||
--import-asm-json - --opcodes
|
2
test/cmdlineTests/asm_json_import_yul_subobjects/output
Normal file
2
test/cmdlineTests/asm_json_import_yul_subobjects/output
Normal file
@ -0,0 +1,2 @@
|
||||
Opcodes:
|
||||
PUSH0 DUP1 SSTORE PUSH1 0x6A PUSH1 0x1 SSTORE PUSH1 0x31 PUSH1 0x2 SSTORE PUSH1 0x2C PUSH1 0x3 SSTORE PUSH1 0x5E PUSH1 0x4 SSTORE PUSH1 0xC PUSH1 0x5 SSTORE PUSH1 0x5D PUSH1 0x6 SSTORE PUSH1 0x1 PUSH1 0x7 SSTORE PUSH1 0x5D PUSH1 0x8 SSTORE PUSH1 0x1 PUSH1 0x9 SSTORE INVALID PUSH1 0x1F PUSH1 0xA SSTORE PUSH1 0xC PUSH1 0xB SSTORE PUSH1 0x2B PUSH1 0xC SSTORE PUSH1 0x1 PUSH1 0xD SSTORE PUSH1 0x2B PUSH1 0xE SSTORE PUSH1 0x1 PUSH1 0xF SSTORE INVALID PUSH1 0xB PUSH1 0x10 SSTORE PUSH1 0x1 PUSH1 0x11 SSTORE INVALID INVALID INVALID INVALID PUSH1 0xB PUSH1 0x10 SSTORE PUSH1 0x1 PUSH1 0x11 SSTORE INVALID INVALID
|
417
test/cmdlineTests/asm_json_import_yul_subobjects/stdin
Normal file
417
test/cmdlineTests/asm_json_import_yul_subobjects/stdin
Normal file
@ -0,0 +1,417 @@
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 36,
|
||||
"end": 51,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"begin": 33,
|
||||
"end": 34,
|
||||
"name": "DUP1",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 26,
|
||||
"end": 52,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 67,
|
||||
"end": 80,
|
||||
"name": "PUSHSIZE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 64,
|
||||
"end": 65,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"begin": 57,
|
||||
"end": 81,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 96,
|
||||
"end": 111,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 93,
|
||||
"end": 94,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "2"
|
||||
},
|
||||
{
|
||||
"begin": 86,
|
||||
"end": 112,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 127,
|
||||
"end": 140,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 124,
|
||||
"end": 125,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "3"
|
||||
},
|
||||
{
|
||||
"begin": 117,
|
||||
"end": 141,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 156,
|
||||
"end": 173,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 153,
|
||||
"end": 154,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "4"
|
||||
},
|
||||
{
|
||||
"begin": 146,
|
||||
"end": 174,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 189,
|
||||
"end": 204,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 186,
|
||||
"end": 187,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "5"
|
||||
},
|
||||
{
|
||||
"begin": 179,
|
||||
"end": 205,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 220,
|
||||
"end": 237,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffe"
|
||||
},
|
||||
{
|
||||
"begin": 217,
|
||||
"end": 218,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "6"
|
||||
},
|
||||
{
|
||||
"begin": 210,
|
||||
"end": 238,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 253,
|
||||
"end": 268,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffe"
|
||||
},
|
||||
{
|
||||
"begin": 250,
|
||||
"end": 251,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "7"
|
||||
},
|
||||
{
|
||||
"begin": 243,
|
||||
"end": 269,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 284,
|
||||
"end": 303,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffd"
|
||||
},
|
||||
{
|
||||
"begin": 281,
|
||||
"end": 282,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "8"
|
||||
},
|
||||
{
|
||||
"begin": 274,
|
||||
"end": 304,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 319,
|
||||
"end": 336,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000fffffffffffffffd"
|
||||
},
|
||||
{
|
||||
"begin": 316,
|
||||
"end": 317,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "9"
|
||||
},
|
||||
{
|
||||
"begin": 309,
|
||||
"end": 337,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 418,
|
||||
"end": 433,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 414,
|
||||
"end": 416,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "A"
|
||||
},
|
||||
{
|
||||
"begin": 407,
|
||||
"end": 434,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 452,
|
||||
"end": 465,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 448,
|
||||
"end": 450,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "B"
|
||||
},
|
||||
{
|
||||
"begin": 441,
|
||||
"end": 466,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 484,
|
||||
"end": 499,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000001"
|
||||
},
|
||||
{
|
||||
"begin": 480,
|
||||
"end": 482,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "C"
|
||||
},
|
||||
{
|
||||
"begin": 473,
|
||||
"end": 500,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 518,
|
||||
"end": 531,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000001"
|
||||
},
|
||||
{
|
||||
"begin": 514,
|
||||
"end": 516,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "D"
|
||||
},
|
||||
{
|
||||
"begin": 507,
|
||||
"end": 532,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 550,
|
||||
"end": 567,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 546,
|
||||
"end": 548,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "E"
|
||||
},
|
||||
{
|
||||
"begin": 539,
|
||||
"end": 568,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 586,
|
||||
"end": 601,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "000000000000000000000000000000000000000000000000ffffffffffffffff"
|
||||
},
|
||||
{
|
||||
"begin": 582,
|
||||
"end": 584,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "F"
|
||||
},
|
||||
{
|
||||
"begin": 575,
|
||||
"end": 602,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 0,
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 658,
|
||||
"end": 673,
|
||||
"name": "PUSH [$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 654,
|
||||
"end": 656,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "10"
|
||||
},
|
||||
{
|
||||
"begin": 647,
|
||||
"end": 674,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
},
|
||||
{
|
||||
"begin": 694,
|
||||
"end": 707,
|
||||
"name": "PUSH #[$]",
|
||||
"source": 0,
|
||||
"value": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
{
|
||||
"begin": 690,
|
||||
"end": 692,
|
||||
"name": "PUSH",
|
||||
"source": 0,
|
||||
"value": "11"
|
||||
},
|
||||
{
|
||||
"begin": 683,
|
||||
"end": 708,
|
||||
"name": "SSTORE",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 0,
|
||||
".data":
|
||||
{
|
||||
"0":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 761,
|
||||
"end": 770,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"1":
|
||||
{
|
||||
".code":
|
||||
[
|
||||
{
|
||||
"begin": 833,
|
||||
"end": 842,
|
||||
"name": "INVALID",
|
||||
"source": 0
|
||||
}
|
||||
],
|
||||
"index": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"ACAF3289D7B601CBD114FB36C4D29C85BBFD5E133F14CB355C3FD8D99367964F": "48656c6c6f2c20576f726c6421"
|
||||
},
|
||||
"sourceList":
|
||||
[
|
||||
"<stdin>"
|
||||
]
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
The following outputs are not supported in assembler mode: --abi, --asm-json, --bin-runtime, --devdoc, --hashes, --ir, --metadata, --opcodes, --storage-layout, --userdoc.
|
||||
The following outputs are not supported in assembler mode: --abi, --bin-runtime, --devdoc, --hashes, --ir, --metadata, --opcodes, --storage-layout, --userdoc.
|
||||
|
16
test/cmdlineTests/~evmasm_import_export/test.sh
Executable file
16
test/cmdlineTests/~evmasm_import_export/test.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# shellcheck source=scripts/common.sh
|
||||
source "${REPO_ROOT}/scripts/common.sh"
|
||||
|
||||
SOLTMPDIR=$(mktemp -d -t "cmdline-test-evmasm-import-export-XXXXXX")
|
||||
(
|
||||
cd "$SOLTMPDIR"
|
||||
if ! "$REPO_ROOT/scripts/ASTImportTest.sh" evm-assembly
|
||||
then
|
||||
rm -r "$SOLTMPDIR"
|
||||
fail
|
||||
fi
|
||||
)
|
||||
rm -r "$SOLTMPDIR"
|
@ -55,11 +55,6 @@ BOOST_AUTO_TEST_SUITE(Assembler)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(all_assembly_items)
|
||||
{
|
||||
std::map<std::string, unsigned> indices = {
|
||||
{ "root.asm", 0 },
|
||||
{ "sub.asm", 1 },
|
||||
{ "verbatim.asm", 2 }
|
||||
};
|
||||
EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
||||
Assembly _assembly{evmVersion, false, {}};
|
||||
auto root_asm = std::make_shared<std::string>("root.asm");
|
||||
@ -203,16 +198,16 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
|
||||
"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"},"
|
||||
"{\"begin\":6,\"end\":8,\"name\":\"PUSH [ErrorTag]\",\"source\":1},"
|
||||
"{\"begin\":6,\"end\":8,\"name\":\"INVALID\",\"source\":1}"
|
||||
"]},"
|
||||
"],\"index\":0},"
|
||||
"\"1\":{\".code\":["
|
||||
"{\"begin\":8,\"end\":18,\"name\":\"VERBATIM\",\"source\":2,\"value\":\"ffff\"},"
|
||||
"{\"begin\":8,\"end\":18,\"name\":\"VERBATIM\",\"source\":2,\"value\":\"74657374\"},"
|
||||
"{\"begin\":8,\"end\":18,\"name\":\"MSTORE\",\"source\":2}"
|
||||
"]},\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"},\"sourceList\":[\"root.asm\",\"sub.asm\",\"verbatim.asm\"]}"
|
||||
"],\"index\":1},\"A6885B3731702DA62E8E4A8F584AC46A7F6822F4E2BA50FBA902F67B1588D23B\":\"01020304\"},\"sourceList\":[\"root.asm\",\"sub.asm\",\"verbatim.asm\"]}"
|
||||
};
|
||||
Json::Value jsonValue;
|
||||
BOOST_CHECK(util::jsonParseStrict(json, jsonValue));
|
||||
BOOST_CHECK_EQUAL(util::jsonCompactPrint(_assembly.assemblyJSON(indices)), util::jsonCompactPrint(jsonValue));
|
||||
BOOST_CHECK_EQUAL(util::jsonCompactPrint(_assembly.assemblyJSON({"root.asm", "sub.asm", "verbatim.asm"})), util::jsonCompactPrint(jsonValue));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps)
|
||||
@ -301,10 +296,6 @@ BOOST_AUTO_TEST_CASE(immutables_and_its_source_maps)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(immutable)
|
||||
{
|
||||
std::map<std::string, unsigned> indices = {
|
||||
{ "root.asm", 0 },
|
||||
{ "sub.asm", 1 }
|
||||
};
|
||||
EVMVersion evmVersion = solidity::test::CommonOptions::get().evmVersion();
|
||||
Assembly _assembly{evmVersion, true, {}};
|
||||
auto root_asm = std::make_shared<std::string>("root.asm");
|
||||
@ -383,7 +374,7 @@ BOOST_AUTO_TEST_CASE(immutable)
|
||||
"}\n"
|
||||
);
|
||||
BOOST_CHECK_EQUAL(
|
||||
util::jsonCompactPrint(_assembly.assemblyJSON(indices)),
|
||||
util::jsonCompactPrint(_assembly.assemblyJSON({"root.asm", "sub.asm"})),
|
||||
"{\".code\":["
|
||||
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"2A\"},"
|
||||
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"0\"},"
|
||||
@ -397,7 +388,7 @@ BOOST_AUTO_TEST_CASE(immutable)
|
||||
"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"},"
|
||||
"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someOtherImmutable\"},"
|
||||
"{\"begin\":6,\"end\":8,\"name\":\"PUSHIMMUTABLE\",\"source\":1,\"value\":\"someImmutable\"}"
|
||||
"]}},\"sourceList\":[\"root.asm\",\"sub.asm\"]}"
|
||||
"],\"index\":0}},\"sourceList\":[\"root.asm\",\"sub.asm\"]}"
|
||||
);
|
||||
}
|
||||
|
||||
|
475
test/libyul/objectCompiler/manySubObjects.yul
Normal file
475
test/libyul/objectCompiler/manySubObjects.yul
Normal file
@ -0,0 +1,475 @@
|
||||
object "root" {
|
||||
code {
|
||||
sstore(0, datasize("root"))
|
||||
sstore(1, datasize("0"))
|
||||
sstore(2, datasize("1"))
|
||||
sstore(3, datasize("2"))
|
||||
sstore(4, datasize("3"))
|
||||
sstore(5, datasize("4"))
|
||||
sstore(6, datasize("5"))
|
||||
sstore(7, datasize("6"))
|
||||
sstore(8, datasize("7"))
|
||||
sstore(9, datasize("8"))
|
||||
sstore(10, datasize("9"))
|
||||
sstore(11, datasize("a"))
|
||||
sstore(12, datasize("b"))
|
||||
sstore(13, datasize("c"))
|
||||
sstore(14, datasize("d"))
|
||||
sstore(15, datasize("e"))
|
||||
sstore(16, datasize("f"))
|
||||
sstore(17, datasize("10"))
|
||||
}
|
||||
|
||||
object "0" {
|
||||
code {
|
||||
sstore(100, 0)
|
||||
sstore(200, datasize("sub0"))
|
||||
}
|
||||
object "sub0" {
|
||||
code {
|
||||
sstore(300, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object "1" {
|
||||
code {
|
||||
sstore(100, 1)
|
||||
}
|
||||
}
|
||||
|
||||
object "2" {
|
||||
code {
|
||||
sstore(101, 2)
|
||||
}
|
||||
}
|
||||
|
||||
object "3" {
|
||||
code {
|
||||
sstore(102, 3)
|
||||
}
|
||||
}
|
||||
|
||||
object "4" {
|
||||
code {
|
||||
sstore(103, 4)
|
||||
}
|
||||
}
|
||||
|
||||
object "5" {
|
||||
code {
|
||||
sstore(104, 5)
|
||||
}
|
||||
}
|
||||
|
||||
object "6" {
|
||||
code {
|
||||
sstore(105, 6)
|
||||
}
|
||||
}
|
||||
|
||||
object "7" {
|
||||
code {
|
||||
sstore(106, 7)
|
||||
}
|
||||
}
|
||||
|
||||
object "8" {
|
||||
code {
|
||||
sstore(107, 8)
|
||||
}
|
||||
}
|
||||
|
||||
object "9" {
|
||||
code {
|
||||
sstore(108, 9)
|
||||
}
|
||||
}
|
||||
|
||||
object "a" {
|
||||
code {
|
||||
sstore(109, 10)
|
||||
}
|
||||
}
|
||||
|
||||
object "b" {
|
||||
code {
|
||||
sstore(110, 11)
|
||||
}
|
||||
}
|
||||
|
||||
object "c" {
|
||||
code {
|
||||
sstore(111, 12)
|
||||
}
|
||||
}
|
||||
|
||||
object "d" {
|
||||
code {
|
||||
sstore(112, 13)
|
||||
}
|
||||
}
|
||||
|
||||
object "e" {
|
||||
code {
|
||||
sstore(113, 14)
|
||||
}
|
||||
}
|
||||
|
||||
object "f" {
|
||||
code {
|
||||
sstore(114, 15)
|
||||
}
|
||||
}
|
||||
|
||||
object "10" {
|
||||
code {
|
||||
sstore(115, 16)
|
||||
sstore(201, datasize("sub10"))
|
||||
}
|
||||
object "sub10" {
|
||||
code {
|
||||
sstore(300, 16)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Assembly:
|
||||
// /* "source":41:57 */
|
||||
// bytecodeSize
|
||||
// /* "source":38:39 */
|
||||
// 0x00
|
||||
// /* "source":31:58 */
|
||||
// sstore
|
||||
// /* "source":75:88 */
|
||||
// dataSize(sub_0)
|
||||
// /* "source":72:73 */
|
||||
// 0x01
|
||||
// /* "source":65:89 */
|
||||
// sstore
|
||||
// /* "source":106:119 */
|
||||
// dataSize(sub_1)
|
||||
// /* "source":103:104 */
|
||||
// 0x02
|
||||
// /* "source":96:120 */
|
||||
// sstore
|
||||
// /* "source":137:150 */
|
||||
// dataSize(sub_2)
|
||||
// /* "source":134:135 */
|
||||
// 0x03
|
||||
// /* "source":127:151 */
|
||||
// sstore
|
||||
// /* "source":168:181 */
|
||||
// dataSize(sub_3)
|
||||
// /* "source":165:166 */
|
||||
// 0x04
|
||||
// /* "source":158:182 */
|
||||
// sstore
|
||||
// /* "source":199:212 */
|
||||
// dataSize(sub_4)
|
||||
// /* "source":196:197 */
|
||||
// 0x05
|
||||
// /* "source":189:213 */
|
||||
// sstore
|
||||
// /* "source":230:243 */
|
||||
// dataSize(sub_5)
|
||||
// /* "source":227:228 */
|
||||
// 0x06
|
||||
// /* "source":220:244 */
|
||||
// sstore
|
||||
// /* "source":261:274 */
|
||||
// dataSize(sub_6)
|
||||
// /* "source":258:259 */
|
||||
// 0x07
|
||||
// /* "source":251:275 */
|
||||
// sstore
|
||||
// /* "source":292:305 */
|
||||
// dataSize(sub_7)
|
||||
// /* "source":289:290 */
|
||||
// 0x08
|
||||
// /* "source":282:306 */
|
||||
// sstore
|
||||
// /* "source":323:336 */
|
||||
// dataSize(sub_8)
|
||||
// /* "source":320:321 */
|
||||
// 0x09
|
||||
// /* "source":313:337 */
|
||||
// sstore
|
||||
// /* "source":355:368 */
|
||||
// dataSize(sub_9)
|
||||
// /* "source":351:353 */
|
||||
// 0x0a
|
||||
// /* "source":344:369 */
|
||||
// sstore
|
||||
// /* "source":387:400 */
|
||||
// dataSize(sub_10)
|
||||
// /* "source":383:385 */
|
||||
// 0x0b
|
||||
// /* "source":376:401 */
|
||||
// sstore
|
||||
// /* "source":419:432 */
|
||||
// dataSize(sub_11)
|
||||
// /* "source":415:417 */
|
||||
// 0x0c
|
||||
// /* "source":408:433 */
|
||||
// sstore
|
||||
// /* "source":451:464 */
|
||||
// dataSize(sub_12)
|
||||
// /* "source":447:449 */
|
||||
// 0x0d
|
||||
// /* "source":440:465 */
|
||||
// sstore
|
||||
// /* "source":483:496 */
|
||||
// dataSize(sub_13)
|
||||
// /* "source":479:481 */
|
||||
// 0x0e
|
||||
// /* "source":472:497 */
|
||||
// sstore
|
||||
// /* "source":515:528 */
|
||||
// dataSize(sub_14)
|
||||
// /* "source":511:513 */
|
||||
// 0x0f
|
||||
// /* "source":504:529 */
|
||||
// sstore
|
||||
// /* "source":547:560 */
|
||||
// dataSize(sub_15)
|
||||
// /* "source":543:545 */
|
||||
// 0x10
|
||||
// /* "source":536:561 */
|
||||
// sstore
|
||||
// /* "source":579:593 */
|
||||
// dataSize(sub_16)
|
||||
// /* "source":575:577 */
|
||||
// 0x11
|
||||
// /* "source":568:594 */
|
||||
// sstore
|
||||
// /* "source":23:598 */
|
||||
// stop
|
||||
// stop
|
||||
//
|
||||
// sub_0: assembly {
|
||||
// /* "source":644:645 */
|
||||
// 0x00
|
||||
// /* "source":639:642 */
|
||||
// 0x64
|
||||
// /* "source":632:646 */
|
||||
// sstore
|
||||
// /* "source":665:681 */
|
||||
// dataSize(sub_0)
|
||||
// /* "source":660:663 */
|
||||
// 0xc8
|
||||
// /* "source":653:682 */
|
||||
// sstore
|
||||
// /* "source":624:688 */
|
||||
// stop
|
||||
// stop
|
||||
//
|
||||
// sub_0: assembly {
|
||||
// /* "source":742:743 */
|
||||
// 0x00
|
||||
// /* "source":737:740 */
|
||||
// 0x012c
|
||||
// /* "source":730:744 */
|
||||
// sstore
|
||||
// /* "source":720:752 */
|
||||
// stop
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// sub_1: assembly {
|
||||
// /* "source":808:809 */
|
||||
// 0x01
|
||||
// /* "source":803:806 */
|
||||
// 0x64
|
||||
// /* "source":796:810 */
|
||||
// sstore
|
||||
// /* "source":788:816 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_2: assembly {
|
||||
// /* "source":866:867 */
|
||||
// 0x02
|
||||
// /* "source":861:864 */
|
||||
// 0x65
|
||||
// /* "source":854:868 */
|
||||
// sstore
|
||||
// /* "source":846:874 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_3: assembly {
|
||||
// /* "source":924:925 */
|
||||
// 0x03
|
||||
// /* "source":919:922 */
|
||||
// 0x66
|
||||
// /* "source":912:926 */
|
||||
// sstore
|
||||
// /* "source":904:932 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_4: assembly {
|
||||
// /* "source":982:983 */
|
||||
// 0x04
|
||||
// /* "source":977:980 */
|
||||
// 0x67
|
||||
// /* "source":970:984 */
|
||||
// sstore
|
||||
// /* "source":962:990 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_5: assembly {
|
||||
// /* "source":1040:1041 */
|
||||
// 0x05
|
||||
// /* "source":1035:1038 */
|
||||
// 0x68
|
||||
// /* "source":1028:1042 */
|
||||
// sstore
|
||||
// /* "source":1020:1048 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_6: assembly {
|
||||
// /* "source":1098:1099 */
|
||||
// 0x06
|
||||
// /* "source":1093:1096 */
|
||||
// 0x69
|
||||
// /* "source":1086:1100 */
|
||||
// sstore
|
||||
// /* "source":1078:1106 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_7: assembly {
|
||||
// /* "source":1156:1157 */
|
||||
// 0x07
|
||||
// /* "source":1151:1154 */
|
||||
// 0x6a
|
||||
// /* "source":1144:1158 */
|
||||
// sstore
|
||||
// /* "source":1136:1164 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_8: assembly {
|
||||
// /* "source":1214:1215 */
|
||||
// 0x08
|
||||
// /* "source":1209:1212 */
|
||||
// 0x6b
|
||||
// /* "source":1202:1216 */
|
||||
// sstore
|
||||
// /* "source":1194:1222 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_9: assembly {
|
||||
// /* "source":1272:1273 */
|
||||
// 0x09
|
||||
// /* "source":1267:1270 */
|
||||
// 0x6c
|
||||
// /* "source":1260:1274 */
|
||||
// sstore
|
||||
// /* "source":1252:1280 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_10: assembly {
|
||||
// /* "source":1330:1332 */
|
||||
// 0x0a
|
||||
// /* "source":1325:1328 */
|
||||
// 0x6d
|
||||
// /* "source":1318:1333 */
|
||||
// sstore
|
||||
// /* "source":1310:1339 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_11: assembly {
|
||||
// /* "source":1389:1391 */
|
||||
// 0x0b
|
||||
// /* "source":1384:1387 */
|
||||
// 0x6e
|
||||
// /* "source":1377:1392 */
|
||||
// sstore
|
||||
// /* "source":1369:1398 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_12: assembly {
|
||||
// /* "source":1448:1450 */
|
||||
// 0x0c
|
||||
// /* "source":1443:1446 */
|
||||
// 0x6f
|
||||
// /* "source":1436:1451 */
|
||||
// sstore
|
||||
// /* "source":1428:1457 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_13: assembly {
|
||||
// /* "source":1507:1509 */
|
||||
// 0x0d
|
||||
// /* "source":1502:1505 */
|
||||
// 0x70
|
||||
// /* "source":1495:1510 */
|
||||
// sstore
|
||||
// /* "source":1487:1516 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_14: assembly {
|
||||
// /* "source":1566:1568 */
|
||||
// 0x0e
|
||||
// /* "source":1561:1564 */
|
||||
// 0x71
|
||||
// /* "source":1554:1569 */
|
||||
// sstore
|
||||
// /* "source":1546:1575 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_15: assembly {
|
||||
// /* "source":1625:1627 */
|
||||
// 0x0f
|
||||
// /* "source":1620:1623 */
|
||||
// 0x72
|
||||
// /* "source":1613:1628 */
|
||||
// sstore
|
||||
// /* "source":1605:1634 */
|
||||
// stop
|
||||
// }
|
||||
//
|
||||
// sub_16: assembly {
|
||||
// /* "source":1685:1687 */
|
||||
// 0x10
|
||||
// /* "source":1680:1683 */
|
||||
// 0x73
|
||||
// /* "source":1673:1688 */
|
||||
// sstore
|
||||
// /* "source":1707:1724 */
|
||||
// dataSize(sub_0)
|
||||
// /* "source":1702:1705 */
|
||||
// 0xc9
|
||||
// /* "source":1695:1725 */
|
||||
// sstore
|
||||
// /* "source":1665:1731 */
|
||||
// stop
|
||||
// stop
|
||||
//
|
||||
// sub_0: assembly {
|
||||
// /* "source":1786:1788 */
|
||||
// 0x10
|
||||
// /* "source":1781:1784 */
|
||||
// 0x012c
|
||||
// /* "source":1774:1789 */
|
||||
// sstore
|
||||
// /* "source":1764:1797 */
|
||||
// stop
|
||||
// }
|
||||
// }
|
||||
// Bytecode: 61005c5f55600b600155600660025560066003556006600455600660055560066006556006600755600660085560066009556006600a556006600b556006600c556006600d556006600e556006600f556006601055600c60115500fe
|
||||
// Opcodes: PUSH2 0x5C PUSH0 SSTORE PUSH1 0xB PUSH1 0x1 SSTORE PUSH1 0x6 PUSH1 0x2 SSTORE PUSH1 0x6 PUSH1 0x3 SSTORE PUSH1 0x6 PUSH1 0x4 SSTORE PUSH1 0x6 PUSH1 0x5 SSTORE PUSH1 0x6 PUSH1 0x6 SSTORE PUSH1 0x6 PUSH1 0x7 SSTORE PUSH1 0x6 PUSH1 0x8 SSTORE PUSH1 0x6 PUSH1 0x9 SSTORE PUSH1 0x6 PUSH1 0xA SSTORE PUSH1 0x6 PUSH1 0xB SSTORE PUSH1 0x6 PUSH1 0xC SSTORE PUSH1 0x6 PUSH1 0xD SSTORE PUSH1 0x6 PUSH1 0xE SSTORE PUSH1 0x6 PUSH1 0xF SSTORE PUSH1 0x6 PUSH1 0x10 SSTORE PUSH1 0xC PUSH1 0x11 SSTORE STOP INVALID
|
||||
// SourceMappings: 41:16:0:-:0;38:1;31:27;75:13;72:1;65:24;106:13;103:1;96:24;137:13;134:1;127:24;168:13;165:1;158:24;199:13;196:1;189:24;230:13;227:1;220:24;261:13;258:1;251:24;292:13;289:1;282:24;323:13;320:1;313:24;355:13;351:2;344:25;387:13;383:2;376:25;419:13;415:2;408:25;451:13;447:2;440:25;483:13;479:2;472:25;515:13;511:2;504:25;547:13;543:2;536:25;579:14;575:2;568:26;23:575
|
@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(version)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(multiple_input_modes)
|
||||
{
|
||||
array<string, 9> inputModeOptions = {
|
||||
array<string, 10> inputModeOptions = {
|
||||
"--help",
|
||||
"--license",
|
||||
"--version",
|
||||
@ -159,10 +159,11 @@ BOOST_AUTO_TEST_CASE(multiple_input_modes)
|
||||
"--strict-assembly",
|
||||
"--yul",
|
||||
"--import-ast",
|
||||
"--import-asm-json",
|
||||
};
|
||||
string expectedMessage =
|
||||
"The following options are mutually exclusive: "
|
||||
"--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast, --lsp. "
|
||||
"--help, --license, --version, --standard-json, --link, --assemble, --strict-assembly, --yul, --import-ast, --lsp, --import-asm-json. "
|
||||
"Select at most one.";
|
||||
|
||||
for (string const& mode1: inputModeOptions)
|
||||
|
Loading…
Reference in New Issue
Block a user