aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-02-23 18:42:53 +0800
committerchriseth <chris@ethereum.org>2018-03-02 00:19:35 +0800
commitdc317a44e031d45ebf745b47248bf06bc92d58bf (patch)
treed03753c0d0ff0672669e0e8ecb70db84f73f6a7f
parenta53d6b499d5cc5c45fc096cea6393dc285581f90 (diff)
downloaddexon-solidity-dc317a44e031d45ebf745b47248bf06bc92d58bf.tar.gz
dexon-solidity-dc317a44e031d45ebf745b47248bf06bc92d58bf.tar.zst
dexon-solidity-dc317a44e031d45ebf745b47248bf06bc92d58bf.zip
Provide EVM version to assembly analysis.
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp3
-rw-r--r--libsolidity/analysis/TypeChecker.cpp1
-rw-r--r--libsolidity/codegen/CompilerContext.cpp1
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp32
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.h5
-rw-r--r--libsolidity/interface/AssemblyStack.cpp2
-rw-r--r--libsolidity/interface/AssemblyStack.h7
-rw-r--r--solc/CommandLineInterface.cpp31
-rw-r--r--solc/CommandLineInterface.h2
-rw-r--r--test/ExecutionFramework.cpp8
-rw-r--r--test/TestHelper.cpp16
-rw-r--r--test/TestHelper.h5
-rw-r--r--test/libjulia/Common.cpp9
-rw-r--r--test/libjulia/Parser.cpp7
-rw-r--r--test/libsolidity/InlineAssembly.cpp6
15 files changed, 91 insertions, 44 deletions
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index 985c44d0..296a39c2 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -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;
}
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 2914472a..04185b38 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -875,6 +875,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
assembly::AsmAnalyzer analyzer(
*_inlineAssembly.annotation().analysisInfo,
m_errorReporter,
+ m_evmVersion,
assembly::AsmFlavour::Loose,
identifierAccess
);
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index 0198a107..ebf0213a 100644
--- a/libsolidity/codegen/CompilerContext.cpp
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -329,6 +329,7 @@ void CompilerContext::appendInlineAssembly(
analyzerResult = assembly::AsmAnalyzer(
analysisInfo,
errorReporter,
+ m_evmVersion,
assembly::AsmFlavour::Strict,
identifierAccess.resolve
).analyze(*parserResult);
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index 1030523a..efa0410d 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -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{
diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h
index 7a81dbf8..867711c7 100644
--- a/libsolidity/inlineasm/AsmAnalysis.h
+++ b/libsolidity/inlineasm/AsmAnalysis.h
@@ -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;
};
diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp
index c9e534c7..7a9fffbf 100644
--- a/libsolidity/interface/AssemblyStack.cpp
+++ b/libsolidity/interface/AssemblyStack.cpp
@@ -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;
}
diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h
index 6ae7e8d1..720220ab 100644
--- a/libsolidity/interface/AssemblyStack.h
+++ b/libsolidity/interface/AssemblyStack.h
@@ -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;
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 04d6d1a8..8ccb04ee 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -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))
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index 4768c9d8..81117fdc 100644
--- a/solc/CommandLineInterface.h
+++ b/solc/CommandLineInterface.h
@@ -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();
diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp
index adf514e2..a24f78fb 100644
--- a/test/ExecutionFramework.cpp
+++ b/test/ExecutionFramework.cpp
@@ -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);
}
diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp
index fbf2dc90..e0d4423d 100644
--- a/test/TestHelper.cpp
+++ b/test/TestHelper.cpp
@@ -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();
+}
diff --git a/test/TestHelper.h b/test/TestHelper.h
index 69ac458a..8c2eec36 100644
--- a/test/TestHelper.h
+++ b/test/TestHelper.h
@@ -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();
};
diff --git a/test/libjulia/Common.cpp b/test/libjulia/Common.cpp
index 7053a68d..d8cd20b6 100644
--- a/test/libjulia/Common.cpp
+++ b/test/libjulia/Common.cpp
@@ -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());
diff --git a/test/libjulia/Parser.cpp b/test/libjulia/Parser.cpp
index ff9474c1..6476c4d4 100644
--- a/test/libjulia/Parser.cpp
+++ b/test/libjulia/Parser.cpp
@@ -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&)
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index ea120657..16ab611a 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -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);