mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Provide EVM version to assembly analysis.
This commit is contained in:
parent
a53d6b499d
commit
dc317a44e0
@ -278,8 +278,9 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
|
||||
};
|
||||
|
||||
// Will be re-generated later with correct information
|
||||
// We use the latest EVM version because we will re-run it anyway.
|
||||
assembly::AsmAnalysisInfo analysisInfo;
|
||||
assembly::AsmAnalyzer(analysisInfo, errorsIgnored, assembly::AsmFlavour::Loose, resolver).analyze(_inlineAssembly.operations());
|
||||
assembly::AsmAnalyzer(analysisInfo, errorsIgnored, EVMVersion(), assembly::AsmFlavour::Loose, resolver).analyze(_inlineAssembly.operations());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -875,6 +875,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
assembly::AsmAnalyzer analyzer(
|
||||
*_inlineAssembly.annotation().analysisInfo,
|
||||
m_errorReporter,
|
||||
m_evmVersion,
|
||||
assembly::AsmFlavour::Loose,
|
||||
identifierAccess
|
||||
);
|
||||
|
@ -329,6 +329,7 @@ void CompilerContext::appendInlineAssembly(
|
||||
analyzerResult = assembly::AsmAnalyzer(
|
||||
analysisInfo,
|
||||
errorReporter,
|
||||
m_evmVersion,
|
||||
assembly::AsmFlavour::Strict,
|
||||
identifierAccess.resolve
|
||||
).analyze(*parserResult);
|
||||
|
@ -533,19 +533,33 @@ void AsmAnalyzer::expectValidType(string const& type, SourceLocation const& _loc
|
||||
|
||||
void AsmAnalyzer::warnOnInstructions(solidity::Instruction _instr, SourceLocation const& _location)
|
||||
{
|
||||
static set<solidity::Instruction> futureInstructions{
|
||||
solidity::Instruction::CREATE2,
|
||||
solidity::Instruction::RETURNDATACOPY,
|
||||
solidity::Instruction::RETURNDATASIZE,
|
||||
solidity::Instruction::STATICCALL
|
||||
};
|
||||
if (futureInstructions.count(_instr))
|
||||
// We assume that returndatacopy, returndatasize and staticcall are either all available
|
||||
// or all not available.
|
||||
solAssert(m_evmVersion.supportsReturndata() == m_evmVersion.hasStaticCall(), "");
|
||||
|
||||
if (_instr == solidity::Instruction::CREATE2)
|
||||
m_errorReporter.warning(
|
||||
_location,
|
||||
"The \"" +
|
||||
boost::to_lower_copy(instructionInfo(_instr).name)
|
||||
+ "\" instruction is only available after " +
|
||||
"the Metropolis hard fork. Before that it acts as an invalid instruction."
|
||||
+ "\" instruction is not supported by the VM version \"" +
|
||||
"" + m_evmVersion.name() +
|
||||
"\" you are currently compiling for. " +
|
||||
"It will be interpreted as an invalid instruction on this VM."
|
||||
);
|
||||
else if ((
|
||||
_instr == solidity::Instruction::RETURNDATACOPY ||
|
||||
_instr == solidity::Instruction::RETURNDATASIZE ||
|
||||
_instr == solidity::Instruction::STATICCALL
|
||||
) && !m_evmVersion.supportsReturndata())
|
||||
m_errorReporter.warning(
|
||||
_location,
|
||||
"The \"" +
|
||||
boost::to_lower_copy(instructionInfo(_instr).name)
|
||||
+ "\" instruction is only available for Byzantium-compatible VMs. " +
|
||||
"You are currently compiling for \"" +
|
||||
m_evmVersion.name() +
|
||||
"\", where it will be interpreted as an invalid instruction."
|
||||
);
|
||||
|
||||
static set<solidity::Instruction> experimentalInstructions{
|
||||
|
@ -21,6 +21,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/interface/Exceptions.h>
|
||||
#include <libsolidity/interface/EVMVersion.h>
|
||||
|
||||
#include <libsolidity/inlineasm/AsmScope.h>
|
||||
|
||||
@ -54,9 +55,10 @@ public:
|
||||
explicit AsmAnalyzer(
|
||||
AsmAnalysisInfo& _analysisInfo,
|
||||
ErrorReporter& _errorReporter,
|
||||
EVMVersion _evmVersion,
|
||||
AsmFlavour _flavour = AsmFlavour::Loose,
|
||||
julia::ExternalIdentifierAccess::Resolver const& _resolver = julia::ExternalIdentifierAccess::Resolver()
|
||||
): m_resolver(_resolver), m_info(_analysisInfo), m_errorReporter(_errorReporter), m_flavour(_flavour) {}
|
||||
): m_resolver(_resolver), m_info(_analysisInfo), m_errorReporter(_errorReporter), m_evmVersion(_evmVersion), m_flavour(_flavour) {}
|
||||
|
||||
bool analyze(assembly::Block const& _block);
|
||||
|
||||
@ -97,6 +99,7 @@ private:
|
||||
std::set<Scope::Variable const*> m_activeVariables;
|
||||
AsmAnalysisInfo& m_info;
|
||||
ErrorReporter& m_errorReporter;
|
||||
EVMVersion m_evmVersion;
|
||||
AsmFlavour m_flavour = AsmFlavour::Loose;
|
||||
};
|
||||
|
||||
|
@ -91,7 +91,7 @@ bool AssemblyStack::analyze(assembly::Block const& _block, Scanner const* _scann
|
||||
bool AssemblyStack::analyzeParsed()
|
||||
{
|
||||
m_analysisInfo = make_shared<assembly::AsmAnalysisInfo>();
|
||||
assembly::AsmAnalyzer analyzer(*m_analysisInfo, m_errorReporter, languageToAsmFlavour(m_language));
|
||||
assembly::AsmAnalyzer analyzer(*m_analysisInfo, m_errorReporter, m_evmVersion, languageToAsmFlavour(m_language));
|
||||
m_analysisSuccessful = analyzer.analyze(*m_parserResult);
|
||||
return m_analysisSuccessful;
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <libsolidity/interface/ErrorReporter.h>
|
||||
#include <libsolidity/interface/EVMVersion.h>
|
||||
|
||||
#include <libevmasm/LinkerObject.h>
|
||||
|
||||
#include <string>
|
||||
@ -54,8 +56,8 @@ public:
|
||||
enum class Language { JULIA, Assembly, StrictAssembly };
|
||||
enum class Machine { EVM, EVM15, eWasm };
|
||||
|
||||
explicit AssemblyStack(Language _language = Language::Assembly):
|
||||
m_language(_language), m_errorReporter(m_errors)
|
||||
explicit AssemblyStack(EVMVersion _evmVersion = EVMVersion(), Language _language = Language::Assembly):
|
||||
m_language(_language), m_evmVersion(_evmVersion), m_errorReporter(m_errors)
|
||||
{}
|
||||
|
||||
/// @returns the scanner used during parsing
|
||||
@ -82,6 +84,7 @@ private:
|
||||
bool analyzeParsed();
|
||||
|
||||
Language m_language = Language::Assembly;
|
||||
EVMVersion m_evmVersion;
|
||||
|
||||
std::shared_ptr<Scanner> m_scanner;
|
||||
|
||||
|
@ -748,6 +748,19 @@ bool CommandLineInterface::processInput()
|
||||
if (!parseLibraryOption(library))
|
||||
return false;
|
||||
|
||||
EVMVersion evmVersion;
|
||||
if (m_args.count(g_strEVMVersion))
|
||||
{
|
||||
string versionOptionStr = m_args[g_strEVMVersion].as<string>();
|
||||
boost::optional<EVMVersion> versionOption = EVMVersion::fromString(versionOptionStr);
|
||||
if (!versionOption)
|
||||
{
|
||||
cerr << "Invalid option for --evm-version: " << versionOptionStr << endl;
|
||||
return false;
|
||||
}
|
||||
evmVersion = *versionOption;
|
||||
}
|
||||
|
||||
if (m_args.count(g_argAssemble) || m_args.count(g_argStrictAssembly) || m_args.count(g_argJulia))
|
||||
{
|
||||
// switch to assembly mode
|
||||
@ -771,7 +784,7 @@ bool CommandLineInterface::processInput()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return assemble(inputLanguage, targetMachine);
|
||||
return assemble(evmVersion, inputLanguage, targetMachine);
|
||||
}
|
||||
if (m_args.count(g_argLink))
|
||||
{
|
||||
@ -782,19 +795,6 @@ bool CommandLineInterface::processInput()
|
||||
|
||||
m_compiler.reset(new CompilerStack(fileReader));
|
||||
|
||||
EVMVersion evmVersion;
|
||||
if (m_args.count(g_strEVMVersion))
|
||||
{
|
||||
string versionOptionStr = m_args[g_strEVMVersion].as<string>();
|
||||
boost::optional<EVMVersion> versionOption = EVMVersion::fromString(versionOptionStr);
|
||||
if (!versionOption)
|
||||
{
|
||||
cerr << "Invalid option for --evm-version: " << versionOptionStr << endl;
|
||||
return false;
|
||||
}
|
||||
evmVersion = *versionOption;
|
||||
}
|
||||
|
||||
auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compiler->scanner(_sourceName); };
|
||||
SourceReferenceFormatter formatter(cerr, scannerFromSourceName);
|
||||
|
||||
@ -1081,6 +1081,7 @@ void CommandLineInterface::writeLinkedFiles()
|
||||
}
|
||||
|
||||
bool CommandLineInterface::assemble(
|
||||
EVMVersion _evmVersion,
|
||||
AssemblyStack::Language _language,
|
||||
AssemblyStack::Machine _targetMachine
|
||||
)
|
||||
@ -1089,7 +1090,7 @@ bool CommandLineInterface::assemble(
|
||||
map<string, AssemblyStack> assemblyStacks;
|
||||
for (auto const& src: m_sourceCodes)
|
||||
{
|
||||
auto& stack = assemblyStacks[src.first] = AssemblyStack(_language);
|
||||
auto& stack = assemblyStacks[src.first] = AssemblyStack(_evmVersion, _language);
|
||||
try
|
||||
{
|
||||
if (!stack.parseAndAnalyze(src.first, src.second))
|
||||
|
@ -54,7 +54,7 @@ private:
|
||||
bool link();
|
||||
void writeLinkedFiles();
|
||||
|
||||
bool assemble(AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine);
|
||||
bool assemble(EVMVersion _evmVersion, AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine);
|
||||
|
||||
void outputCompilationResults();
|
||||
|
||||
|
@ -51,17 +51,11 @@ string getIPCSocketPath()
|
||||
|
||||
ExecutionFramework::ExecutionFramework() :
|
||||
m_rpc(RPCSession::instance(getIPCSocketPath())),
|
||||
m_evmVersion(dev::test::Options::get().evmVersion()),
|
||||
m_optimize(dev::test::Options::get().optimize),
|
||||
m_showMessages(dev::test::Options::get().showMessages),
|
||||
m_sender(m_rpc.account(0))
|
||||
{
|
||||
if (!dev::test::Options::get().evmVersion.empty())
|
||||
{
|
||||
auto version = solidity::EVMVersion::fromString(dev::test::Options::get().evmVersion);
|
||||
BOOST_REQUIRE_MESSAGE(version, "Invalid EVM version: " + dev::test::Options::get().evmVersion);
|
||||
m_evmVersion = *version;
|
||||
}
|
||||
|
||||
m_rpc.test_rewindToBlock(0);
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ Options::Options()
|
||||
optimize = true;
|
||||
else if (string(suite.argv[i]) == "--evm-version")
|
||||
{
|
||||
evmVersion = i + 1 < suite.argc ? suite.argv[i + 1] : "INVALID";
|
||||
evmVersionString = i + 1 < suite.argc ? suite.argv[i + 1] : "INVALID";
|
||||
++i;
|
||||
}
|
||||
else if (string(suite.argv[i]) == "--show-messages")
|
||||
@ -61,3 +61,17 @@ Options::Options()
|
||||
if (auto path = getenv("ETH_TEST_IPC"))
|
||||
ipcPath = path;
|
||||
}
|
||||
|
||||
dev::solidity::EVMVersion Options::evmVersion() const
|
||||
{
|
||||
if (!evmVersionString.empty())
|
||||
{
|
||||
// We do this check as opposed to in the constructor because the BOOST_REQUIRE
|
||||
// macros cannot yet be used in the constructor.
|
||||
auto version = solidity::EVMVersion::fromString(evmVersionString);
|
||||
BOOST_REQUIRE_MESSAGE(version, "Invalid EVM version: " + evmVersionString);
|
||||
return *version;
|
||||
}
|
||||
else
|
||||
return dev::solidity::EVMVersion();
|
||||
}
|
||||
|
@ -36,14 +36,17 @@ struct Options: boost::noncopyable
|
||||
{
|
||||
std::string ipcPath;
|
||||
bool showMessages = false;
|
||||
std::string evmVersion;
|
||||
bool optimize = false;
|
||||
bool disableIPC = false;
|
||||
bool disableSMT = false;
|
||||
|
||||
solidity::EVMVersion evmVersion() const;
|
||||
|
||||
static Options const& get();
|
||||
|
||||
private:
|
||||
std::string evmVersionString;
|
||||
|
||||
Options();
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include <test/libjulia/Common.h>
|
||||
|
||||
#include <test/TestHelper.h>
|
||||
|
||||
#include <libjulia/optimiser/Disambiguator.h>
|
||||
|
||||
#include <libsolidity/parsing/Scanner.h>
|
||||
@ -61,7 +63,12 @@ pair<shared_ptr<Block>, shared_ptr<assembly::AsmAnalysisInfo>> dev::julia::test:
|
||||
{
|
||||
BOOST_REQUIRE(errorReporter.errors().empty());
|
||||
auto analysisInfo = make_shared<assembly::AsmAnalysisInfo>();
|
||||
assembly::AsmAnalyzer analyzer(*analysisInfo, errorReporter, flavour);
|
||||
assembly::AsmAnalyzer analyzer(
|
||||
*analysisInfo,
|
||||
errorReporter,
|
||||
dev::test::Options::get().evmVersion(),
|
||||
flavour
|
||||
);
|
||||
if (analyzer.analyze(*parserResult))
|
||||
{
|
||||
BOOST_REQUIRE(errorReporter.errors().empty());
|
||||
|
@ -56,7 +56,12 @@ bool parse(string const& _source, ErrorReporter& errorReporter)
|
||||
if (parserResult)
|
||||
{
|
||||
assembly::AsmAnalysisInfo analysisInfo;
|
||||
return (assembly::AsmAnalyzer(analysisInfo, errorReporter, assembly::AsmFlavour::IULIA)).analyze(*parserResult);
|
||||
return (assembly::AsmAnalyzer(
|
||||
analysisInfo,
|
||||
errorReporter,
|
||||
dev::test::Options::get().evmVersion(),
|
||||
assembly::AsmFlavour::IULIA
|
||||
)).analyze(*parserResult);
|
||||
}
|
||||
}
|
||||
catch (FatalError const&)
|
||||
|
@ -55,7 +55,7 @@ boost::optional<Error> parseAndReturnFirstError(
|
||||
AssemblyStack::Machine _machine = AssemblyStack::Machine::EVM
|
||||
)
|
||||
{
|
||||
AssemblyStack stack(_language);
|
||||
AssemblyStack stack(dev::test::Options::get().evmVersion(), _language);
|
||||
bool success = false;
|
||||
try
|
||||
{
|
||||
@ -117,7 +117,7 @@ Error expectError(
|
||||
|
||||
void parsePrintCompare(string const& _source, bool _canWarn = false)
|
||||
{
|
||||
AssemblyStack stack;
|
||||
AssemblyStack stack(dev::test::Options::get().evmVersion());
|
||||
BOOST_REQUIRE(stack.parseAndAnalyze("", _source));
|
||||
if (_canWarn)
|
||||
BOOST_REQUIRE(Error::containsOnlyWarnings(stack.errors()));
|
||||
@ -567,7 +567,7 @@ BOOST_AUTO_TEST_CASE(print_string_literal_unicode)
|
||||
{
|
||||
string source = "{ let x := \"\\u1bac\" }";
|
||||
string parsed = "{\n let x := \"\\xe1\\xae\\xac\"\n}";
|
||||
AssemblyStack stack;
|
||||
AssemblyStack stack(dev::test::Options::get().evmVersion());
|
||||
BOOST_REQUIRE(stack.parseAndAnalyze("", source));
|
||||
BOOST_REQUIRE(stack.errors().empty());
|
||||
BOOST_CHECK_EQUAL(stack.print(), parsed);
|
||||
|
Loading…
Reference in New Issue
Block a user