Make EVM version part of EVM dialect.

This commit is contained in:
chriseth 2019-02-21 21:56:30 +01:00
parent 773a3ff880
commit 7f5b335b47
20 changed files with 51 additions and 48 deletions

View File

@ -324,9 +324,8 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
yul::AsmAnalyzer( yul::AsmAnalyzer(
analysisInfo, analysisInfo,
errorsIgnored, errorsIgnored,
EVMVersion(),
errorTypeForLoose, errorTypeForLoose,
yul::EVMDialect::looseAssemblyForEVM(), yul::EVMDialect::looseAssemblyForEVM(EVMVersion::constantinople()),
resolver resolver
).analyze(_inlineAssembly.operations()); ).analyze(_inlineAssembly.operations());
return false; return false;

View File

@ -713,9 +713,8 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
yul::AsmAnalyzer analyzer( yul::AsmAnalyzer analyzer(
*_inlineAssembly.annotation().analysisInfo, *_inlineAssembly.annotation().analysisInfo,
m_errorReporter, m_errorReporter,
m_evmVersion,
Error::Type::SyntaxError, Error::Type::SyntaxError,
yul::EVMDialect::looseAssemblyForEVM(), yul::EVMDialect::looseAssemblyForEVM(m_evmVersion),
identifierAccess identifierAccess
); );
if (!analyzer.analyze(_inlineAssembly.operations())) if (!analyzer.analyze(_inlineAssembly.operations()))

View File

@ -376,7 +376,7 @@ void CompilerContext::appendInlineAssembly(
ErrorList errors; ErrorList errors;
ErrorReporter errorReporter(errors); ErrorReporter errorReporter(errors);
auto scanner = make_shared<langutil::Scanner>(langutil::CharStream(_assembly, "--CODEGEN--")); auto scanner = make_shared<langutil::Scanner>(langutil::CharStream(_assembly, "--CODEGEN--"));
auto parserResult = yul::Parser(errorReporter, yul::EVMDialect::strictAssemblyForEVM()).parse(scanner, false); auto parserResult = yul::Parser(errorReporter, yul::EVMDialect::strictAssemblyForEVM(m_evmVersion)).parse(scanner, false);
#ifdef SOL_OUTPUT_ASM #ifdef SOL_OUTPUT_ASM
cout << yul::AsmPrinter()(*parserResult) << endl; cout << yul::AsmPrinter()(*parserResult) << endl;
#endif #endif
@ -386,9 +386,8 @@ void CompilerContext::appendInlineAssembly(
analyzerResult = yul::AsmAnalyzer( analyzerResult = yul::AsmAnalyzer(
analysisInfo, analysisInfo,
errorReporter, errorReporter,
m_evmVersion,
boost::none, boost::none,
yul::EVMDialect::strictAssemblyForEVM(), yul::EVMDialect::strictAssemblyForEVM(m_evmVersion),
identifierAccess.resolve identifierAccess.resolve
).analyze(*parserResult); ).analyze(*parserResult);
if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) if (!parserResult || !errorReporter.errors().empty() || !analyzerResult)
@ -409,7 +408,7 @@ void CompilerContext::appendInlineAssembly(
} }
solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block."); solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block.");
yul::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, identifierAccess, _system); yul::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, m_evmVersion, identifierAccess, _system);
// Reset the source location to the one of the node (instead of the CODEGEN source location) // Reset the source location to the one of the node (instead of the CODEGEN source location)
updateSourceLocation(); updateSourceLocation();

View File

@ -719,6 +719,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
_inlineAssembly.operations(), _inlineAssembly.operations(),
*_inlineAssembly.annotation().analysisInfo, *_inlineAssembly.annotation().analysisInfo,
*m_context.assemblyPtr(), *m_context.assemblyPtr(),
m_context.evmVersion(),
identifierAccess identifierAccess
); );
m_context.setStackOffset(startStackHeight); m_context.setStackOffset(startStackHeight);

View File

@ -1041,7 +1041,8 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
m_scanner->next(); m_scanner->next();
} }
yul::Parser asmParser(m_errorReporter, yul::EVMDialect::looseAssemblyForEVM()); // Using latest EVM Version for now, it will be run again later.
yul::Parser asmParser(m_errorReporter, yul::EVMDialect::looseAssemblyForEVM(EVMVersion::constantinople()));
shared_ptr<yul::Block> block = asmParser.parse(m_scanner, true); shared_ptr<yul::Block> block = asmParser.parse(m_scanner, true);
if (block == nullptr) if (block == nullptr)
BOOST_THROW_EXCEPTION(FatalError()); BOOST_THROW_EXCEPTION(FatalError());

View File

@ -60,7 +60,6 @@ bool AsmAnalyzer::analyze(Block const& _block)
AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(
shared_ptr<Dialect> _dialect, shared_ptr<Dialect> _dialect,
EVMVersion _evmVersion,
Block const& _ast Block const& _ast
) )
{ {
@ -70,7 +69,6 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(
bool success = yul::AsmAnalyzer( bool success = yul::AsmAnalyzer(
analysisInfo, analysisInfo,
errors, errors,
_evmVersion,
Error::Type::SyntaxError, Error::Type::SyntaxError,
_dialect _dialect
).analyze(_ast); ).analyze(_ast);

View File

@ -28,6 +28,7 @@
#include <libyul/AsmDataForward.h> #include <libyul/AsmDataForward.h>
#include <libyul/backends/evm/AbstractAssembly.h> #include <libyul/backends/evm/AbstractAssembly.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <boost/variant.hpp> #include <boost/variant.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -57,7 +58,6 @@ public:
explicit AsmAnalyzer( explicit AsmAnalyzer(
AsmAnalysisInfo& _analysisInfo, AsmAnalysisInfo& _analysisInfo,
langutil::ErrorReporter& _errorReporter, langutil::ErrorReporter& _errorReporter,
dev::solidity::EVMVersion _evmVersion,
boost::optional<langutil::Error::Type> _errorTypeForLoose, boost::optional<langutil::Error::Type> _errorTypeForLoose,
std::shared_ptr<Dialect> _dialect, std::shared_ptr<Dialect> _dialect,
ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver() ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver()
@ -65,16 +65,17 @@ public:
m_resolver(_resolver), m_resolver(_resolver),
m_info(_analysisInfo), m_info(_analysisInfo),
m_errorReporter(_errorReporter), m_errorReporter(_errorReporter),
m_evmVersion(_evmVersion),
m_dialect(std::move(_dialect)), m_dialect(std::move(_dialect)),
m_errorTypeForLoose(_errorTypeForLoose) m_errorTypeForLoose(_errorTypeForLoose)
{} {
if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(m_dialect.get()))
m_evmVersion = evmDialect->evmVersion();
}
bool analyze(Block const& _block); bool analyze(Block const& _block);
static AsmAnalysisInfo analyzeStrictAssertCorrect( static AsmAnalysisInfo analyzeStrictAssertCorrect(
std::shared_ptr<Dialect> _dialect, std::shared_ptr<Dialect> _dialect,
dev::solidity::EVMVersion _evmVersion,
Block const& _ast Block const& _ast
); );

View File

@ -43,14 +43,14 @@ using namespace yul;
namespace namespace
{ {
shared_ptr<Dialect> languageToDialect(AssemblyStack::Language _language) shared_ptr<Dialect> languageToDialect(AssemblyStack::Language _language, EVMVersion _version)
{ {
switch (_language) switch (_language)
{ {
case AssemblyStack::Language::Assembly: case AssemblyStack::Language::Assembly:
return EVMDialect::looseAssemblyForEVM(); return EVMDialect::looseAssemblyForEVM(_version);
case AssemblyStack::Language::StrictAssembly: case AssemblyStack::Language::StrictAssembly:
return EVMDialect::strictAssemblyForEVMObjects(); return EVMDialect::strictAssemblyForEVMObjects(_version);
case AssemblyStack::Language::Yul: case AssemblyStack::Language::Yul:
return Dialect::yul(); return Dialect::yul();
} }
@ -72,7 +72,7 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string
m_errors.clear(); m_errors.clear();
m_analysisSuccessful = false; m_analysisSuccessful = false;
m_scanner = make_shared<Scanner>(CharStream(_source, _sourceName)); m_scanner = make_shared<Scanner>(CharStream(_source, _sourceName));
m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language)).parse(m_scanner, false); m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion)).parse(m_scanner, false);
if (!m_errorReporter.errors().empty()) if (!m_errorReporter.errors().empty())
return false; return false;
solAssert(m_parserResult, ""); solAssert(m_parserResult, "");
@ -103,7 +103,7 @@ bool AssemblyStack::analyzeParsed(Object& _object)
{ {
solAssert(_object.code, ""); solAssert(_object.code, "");
_object.analysisInfo = make_shared<AsmAnalysisInfo>(); _object.analysisInfo = make_shared<AsmAnalysisInfo>();
AsmAnalyzer analyzer(*_object.analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToDialect(m_language)); AsmAnalyzer analyzer(*_object.analysisInfo, m_errorReporter, boost::none, languageToDialect(m_language, m_evmVersion));
bool success = analyzer.analyze(*_object.code); bool success = analyzer.analyze(*_object.code);
for (auto& subNode: _object.subObjects) for (auto& subNode: _object.subObjects)
if (auto subObject = dynamic_cast<Object*>(subNode.get())) if (auto subObject = dynamic_cast<Object*>(subNode.get()))
@ -117,11 +117,11 @@ void AssemblyStack::compileEVM(AbstractAssembly& _assembly, bool _evm15, bool _o
shared_ptr<EVMDialect> dialect; shared_ptr<EVMDialect> dialect;
if (m_language == Language::Assembly) if (m_language == Language::Assembly)
dialect = EVMDialect::looseAssemblyForEVM(); dialect = EVMDialect::looseAssemblyForEVM(m_evmVersion);
else if (m_language == AssemblyStack::Language::StrictAssembly) else if (m_language == AssemblyStack::Language::StrictAssembly)
dialect = EVMDialect::strictAssemblyForEVMObjects(); dialect = EVMDialect::strictAssemblyForEVMObjects(m_evmVersion);
else if (m_language == AssemblyStack::Language::Yul) else if (m_language == AssemblyStack::Language::Yul)
dialect = EVMDialect::yulForEVM(); dialect = EVMDialect::yulForEVM(m_evmVersion);
else else
solAssert(false, "Invalid language."); solAssert(false, "Invalid language.");
@ -135,7 +135,7 @@ void AssemblyStack::optimize(Object& _object)
for (auto& subNode: _object.subObjects) for (auto& subNode: _object.subObjects)
if (auto subObject = dynamic_cast<Object*>(subNode.get())) if (auto subObject = dynamic_cast<Object*>(subNode.get()))
optimize(*subObject); optimize(*subObject);
OptimiserSuite::run(languageToDialect(m_language), *_object.code, *_object.analysisInfo); OptimiserSuite::run(languageToDialect(m_language, m_evmVersion), *_object.code, *_object.analysisInfo);
} }
MachineAssemblyObject AssemblyStack::assemble(Machine _machine, bool _optimize) const MachineAssemblyObject AssemblyStack::assemble(Machine _machine, bool _optimize) const

View File

@ -45,7 +45,7 @@ std::map<YulString, int> CompilabilityChecker::run(std::shared_ptr<Dialect> _dia
bool optimize = true; bool optimize = true;
yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalysisInfo analysisInfo =
yul::AsmAnalyzer::analyzeStrictAssertCorrect(noOutputDialect, EVMVersion(), _ast); yul::AsmAnalyzer::analyzeStrictAssertCorrect(noOutputDialect, _ast);
NoOutputAssembly assembly; NoOutputAssembly assembly;
CodeTransform transform(assembly, analysisInfo, _ast, *noOutputDialect, optimize); CodeTransform transform(assembly, analysisInfo, _ast, *noOutputDialect, optimize);

View File

@ -177,13 +177,14 @@ void CodeGenerator::assemble(
Block const& _parsedData, Block const& _parsedData,
AsmAnalysisInfo& _analysisInfo, AsmAnalysisInfo& _analysisInfo,
eth::Assembly& _assembly, eth::Assembly& _assembly,
dev::solidity::EVMVersion _evmVersion,
ExternalIdentifierAccess const& _identifierAccess, ExternalIdentifierAccess const& _identifierAccess,
bool _useNamedLabelsForFunctions, bool _useNamedLabelsForFunctions,
bool _optimize bool _optimize
) )
{ {
EthAssemblyAdapter assemblyAdapter(_assembly); EthAssemblyAdapter assemblyAdapter(_assembly);
shared_ptr<EVMDialect> dialect = EVMDialect::strictAssemblyForEVM(); shared_ptr<EVMDialect> dialect = EVMDialect::strictAssemblyForEVM(_evmVersion);
CodeTransform transform( CodeTransform transform(
assemblyAdapter, assemblyAdapter,
_analysisInfo, _analysisInfo,

View File

@ -79,6 +79,7 @@ public:
Block const& _parsedData, Block const& _parsedData,
AsmAnalysisInfo& _analysisInfo, AsmAnalysisInfo& _analysisInfo,
dev::eth::Assembly& _assembly, dev::eth::Assembly& _assembly,
dev::solidity::EVMVersion _evmVersion,
ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess(), ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess(),
bool _useNamedLabelsForFunctions = false, bool _useNamedLabelsForFunctions = false,
bool _optimize = false bool _optimize = false

View File

@ -37,8 +37,8 @@ using namespace yul;
using namespace dev::solidity; using namespace dev::solidity;
EVMDialect::EVMDialect(AsmFlavour _flavour, bool _objectAccess): EVMDialect::EVMDialect(AsmFlavour _flavour, bool _objectAccess, EVMVersion _evmVersion):
Dialect{_flavour}, m_objectAccess(_objectAccess) Dialect{_flavour}, m_objectAccess(_objectAccess), m_evmVersion(_evmVersion)
{ {
// The EVM instructions will be moved to builtins at some point. // The EVM instructions will be moved to builtins at some point.
if (!m_objectAccess) if (!m_objectAccess)
@ -91,24 +91,24 @@ BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const
return nullptr; return nullptr;
} }
shared_ptr<EVMDialect> EVMDialect::looseAssemblyForEVM() shared_ptr<EVMDialect> EVMDialect::looseAssemblyForEVM(EVMVersion _version)
{ {
return make_shared<EVMDialect>(AsmFlavour::Loose, false); return make_shared<EVMDialect>(AsmFlavour::Loose, false, _version);
} }
shared_ptr<EVMDialect> EVMDialect::strictAssemblyForEVM() shared_ptr<EVMDialect> EVMDialect::strictAssemblyForEVM(EVMVersion _version)
{ {
return make_shared<EVMDialect>(AsmFlavour::Strict, false); return make_shared<EVMDialect>(AsmFlavour::Strict, false, _version);
} }
shared_ptr<EVMDialect> EVMDialect::strictAssemblyForEVMObjects() shared_ptr<EVMDialect> EVMDialect::strictAssemblyForEVMObjects(EVMVersion _version)
{ {
return make_shared<EVMDialect>(AsmFlavour::Strict, true); return make_shared<EVMDialect>(AsmFlavour::Strict, true, _version);
} }
shared_ptr<yul::EVMDialect> EVMDialect::yulForEVM() shared_ptr<yul::EVMDialect> EVMDialect::yulForEVM(EVMVersion _version)
{ {
return make_shared<EVMDialect>(AsmFlavour::Yul, false); return make_shared<EVMDialect>(AsmFlavour::Yul, false, _version);
} }
void EVMDialect::setSubIDs(map<YulString, AbstractAssembly::SubID> _subIDs) void EVMDialect::setSubIDs(map<YulString, AbstractAssembly::SubID> _subIDs)

View File

@ -23,6 +23,7 @@
#include <libyul/Dialect.h> #include <libyul/Dialect.h>
#include <libyul/backends/evm/AbstractAssembly.h> #include <libyul/backends/evm/AbstractAssembly.h>
#include <liblangutil/EVMVersion.h>
#include <map> #include <map>
@ -49,15 +50,17 @@ struct BuiltinFunctionForEVM: BuiltinFunction
*/ */
struct EVMDialect: public Dialect struct EVMDialect: public Dialect
{ {
EVMDialect(AsmFlavour _flavour, bool _objectAccess); EVMDialect(AsmFlavour _flavour, bool _objectAccess, dev::solidity::EVMVersion _evmVersion);
/// @returns the builtin function of the given name or a nullptr if it is not a builtin function. /// @returns the builtin function of the given name or a nullptr if it is not a builtin function.
BuiltinFunctionForEVM const* builtin(YulString _name) const override; BuiltinFunctionForEVM const* builtin(YulString _name) const override;
static std::shared_ptr<EVMDialect> looseAssemblyForEVM(); static std::shared_ptr<EVMDialect> looseAssemblyForEVM(dev::solidity::EVMVersion _version);
static std::shared_ptr<EVMDialect> strictAssemblyForEVM(); static std::shared_ptr<EVMDialect> strictAssemblyForEVM(dev::solidity::EVMVersion _version);
static std::shared_ptr<EVMDialect> strictAssemblyForEVMObjects(); static std::shared_ptr<EVMDialect> strictAssemblyForEVMObjects(dev::solidity::EVMVersion _version);
static std::shared_ptr<EVMDialect> yulForEVM(); static std::shared_ptr<EVMDialect> yulForEVM(dev::solidity::EVMVersion _version);
dev::solidity::EVMVersion evmVersion() const { return m_evmVersion; }
bool providesObjectAccess() const { return m_objectAccess; } bool providesObjectAccess() const { return m_objectAccess; }
@ -77,6 +80,7 @@ protected:
); );
bool m_objectAccess; bool m_objectAccess;
dev::solidity::EVMVersion m_evmVersion;
Object const* m_currentObject = nullptr; Object const* m_currentObject = nullptr;
/// Mapping from named objects to abstract assembly sub IDs. /// Mapping from named objects to abstract assembly sub IDs.
std::map<YulString, AbstractAssembly::SubID> m_subIDs; std::map<YulString, AbstractAssembly::SubID> m_subIDs;

View File

@ -143,7 +143,7 @@ AbstractAssembly::SubID NoOutputAssembly::appendData(bytes const&)
} }
NoOutputEVMDialect::NoOutputEVMDialect(shared_ptr<EVMDialect> const& _copyFrom): NoOutputEVMDialect::NoOutputEVMDialect(shared_ptr<EVMDialect> const& _copyFrom):
EVMDialect(_copyFrom->flavour, _copyFrom->providesObjectAccess()) EVMDialect(_copyFrom->flavour, _copyFrom->providesObjectAccess(), _copyFrom->evmVersion())
{ {
for (auto& fun: m_functions) for (auto& fun: m_functions)
{ {

View File

@ -22,6 +22,7 @@
#include <libyul/AsmDataForward.h> #include <libyul/AsmDataForward.h>
#include <libyul/YulString.h> #include <libyul/YulString.h>
#include <liblangutil/EVMVersion.h>
#include <set> #include <set>

View File

@ -46,7 +46,7 @@ namespace
{ {
shared_ptr<Dialect> defaultDialect(bool _yul) shared_ptr<Dialect> defaultDialect(bool _yul)
{ {
return _yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM(); return _yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM(dev::test::Options::get().evmVersion());
} }
} }

View File

@ -39,7 +39,7 @@ string check(string const& _input)
{ {
shared_ptr<Block> ast = yul::test::parse(_input, false).first; shared_ptr<Block> ast = yul::test::parse(_input, false).first;
BOOST_REQUIRE(ast); BOOST_REQUIRE(ast);
map<YulString, int> functions = CompilabilityChecker::run(EVMDialect::strictAssemblyForEVM(), *ast); map<YulString, int> functions = CompilabilityChecker::run(EVMDialect::strictAssemblyForEVM(dev::test::Options::get().evmVersion()), *ast);
string out; string out;
for (auto const& function: functions) for (auto const& function: functions)
out += function.first.str() + ": " + to_string(function.second) + " "; out += function.first.str() + ": " + to_string(function.second) + " ";

View File

@ -61,7 +61,6 @@ bool parse(string const& _source, std::shared_ptr<Dialect> _dialect, ErrorReport
return (yul::AsmAnalyzer( return (yul::AsmAnalyzer(
analysisInfo, analysisInfo,
errorReporter, errorReporter,
dev::test::Options::get().evmVersion(),
boost::none, boost::none,
_dialect _dialect
)).analyze(*parserResult); )).analyze(*parserResult);

View File

@ -300,7 +300,7 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c
printErrors(_stream, stack.errors()); printErrors(_stream, stack.errors());
return false; return false;
} }
m_dialect = m_yul ? Dialect::yul() : EVMDialect::strictAssemblyForEVMObjects(); m_dialect = m_yul ? Dialect::yul() : EVMDialect::strictAssemblyForEVMObjects(dev::test::Options::get().evmVersion());
m_ast = stack.parserResult()->code; m_ast = stack.parserResult()->code;
m_analysisInfo = stack.parserResult()->analysisInfo; m_analysisInfo = stack.parserResult()->analysisInfo;
return true; return true;

View File

@ -99,7 +99,6 @@ public:
AsmAnalyzer analyzer( AsmAnalyzer analyzer(
*m_analysisInfo, *m_analysisInfo,
errorReporter, errorReporter,
EVMVersion::byzantium(),
langutil::Error::Type::SyntaxError, langutil::Error::Type::SyntaxError,
m_dialect m_dialect
); );
@ -207,7 +206,7 @@ public:
private: private:
ErrorList m_errors; ErrorList m_errors;
shared_ptr<yul::Block> m_ast; shared_ptr<yul::Block> m_ast;
shared_ptr<Dialect> m_dialect{EVMDialect::strictAssemblyForEVMObjects()}; shared_ptr<Dialect> m_dialect{EVMDialect::strictAssemblyForEVMObjects(EVMVersion::constantinople())};
shared_ptr<AsmAnalysisInfo> m_analysisInfo; shared_ptr<AsmAnalysisInfo> m_analysisInfo;
shared_ptr<NameDispenser> m_nameDispenser; shared_ptr<NameDispenser> m_nameDispenser;
}; };