Merge pull request #5989 from ethereum/moveAssemblyStack

[REF] Move assembly stack
This commit is contained in:
chriseth 2019-02-13 14:15:27 +01:00 committed by GitHub
commit 10888b21d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 73 additions and 78 deletions

View File

@ -80,8 +80,6 @@ set(sources
formal/VariableUsage.h formal/VariableUsage.h
interface/ABI.cpp interface/ABI.cpp
interface/ABI.h interface/ABI.h
interface/AssemblyStack.cpp
interface/AssemblyStack.h
interface/CompilerStack.cpp interface/CompilerStack.cpp
interface/CompilerStack.h interface/CompilerStack.h
interface/GasEstimator.cpp interface/GasEstimator.cpp

View File

@ -20,10 +20,7 @@
*/ */
#include <libsolidity/interface/AssemblyStack.h> #include <libyul/AssemblyStack.h>
#include <libevmasm/Assembly.h>
#include <liblangutil/Scanner.h>
#include <libyul/AsmAnalysis.h> #include <libyul/AsmAnalysis.h>
#include <libyul/AsmAnalysisInfo.h> #include <libyul/AsmAnalysisInfo.h>
@ -37,26 +34,28 @@
#include <libyul/ObjectParser.h> #include <libyul/ObjectParser.h>
#include <libyul/optimiser/Suite.h> #include <libyul/optimiser/Suite.h>
#include <libevmasm/Assembly.h>
#include <liblangutil/Scanner.h>
using namespace std; using namespace std;
using namespace dev;
using namespace langutil; using namespace langutil;
using namespace dev::solidity; using namespace yul;
namespace namespace
{ {
shared_ptr<yul::Dialect> languageToDialect(AssemblyStack::Language _language) shared_ptr<Dialect> languageToDialect(AssemblyStack::Language _language)
{ {
switch (_language) switch (_language)
{ {
case AssemblyStack::Language::Assembly: case AssemblyStack::Language::Assembly:
return yul::EVMDialect::looseAssemblyForEVM(); return EVMDialect::looseAssemblyForEVM();
case AssemblyStack::Language::StrictAssembly: case AssemblyStack::Language::StrictAssembly:
return yul::EVMDialect::strictAssemblyForEVMObjects(); return EVMDialect::strictAssemblyForEVMObjects();
case AssemblyStack::Language::Yul: case AssemblyStack::Language::Yul:
return yul::Dialect::yul(); return Dialect::yul();
} }
solAssert(false, ""); solAssert(false, "");
return yul::Dialect::yul(); return Dialect::yul();
} }
} }
@ -73,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 = yul::ObjectParser(m_errorReporter, languageToDialect(m_language)).parse(m_scanner, false); m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language)).parse(m_scanner, false);
if (!m_errorReporter.errors().empty()) if (!m_errorReporter.errors().empty())
return false; return false;
solAssert(m_parserResult, ""); solAssert(m_parserResult, "");
@ -99,43 +98,43 @@ bool AssemblyStack::analyzeParsed()
return m_analysisSuccessful; return m_analysisSuccessful;
} }
bool AssemblyStack::analyzeParsed(yul::Object& _object) bool AssemblyStack::analyzeParsed(Object& _object)
{ {
solAssert(_object.code, ""); solAssert(_object.code, "");
_object.analysisInfo = make_shared<yul::AsmAnalysisInfo>(); _object.analysisInfo = make_shared<AsmAnalysisInfo>();
yul::AsmAnalyzer analyzer(*_object.analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToDialect(m_language)); AsmAnalyzer analyzer(*_object.analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToDialect(m_language));
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<yul::Object*>(subNode.get())) if (auto subObject = dynamic_cast<Object*>(subNode.get()))
if (!analyzeParsed(*subObject)) if (!analyzeParsed(*subObject))
success = false; success = false;
return success; return success;
} }
void AssemblyStack::compileEVM(yul::AbstractAssembly& _assembly, bool _evm15, bool _optimize) const void AssemblyStack::compileEVM(AbstractAssembly& _assembly, bool _evm15, bool _optimize) const
{ {
shared_ptr<yul::EVMDialect> dialect; shared_ptr<EVMDialect> dialect;
if (m_language == Language::Assembly) if (m_language == Language::Assembly)
dialect = yul::EVMDialect::looseAssemblyForEVM(); dialect = EVMDialect::looseAssemblyForEVM();
else if (m_language == AssemblyStack::Language::StrictAssembly) else if (m_language == AssemblyStack::Language::StrictAssembly)
dialect = yul::EVMDialect::strictAssemblyForEVMObjects(); dialect = EVMDialect::strictAssemblyForEVMObjects();
else if (m_language == AssemblyStack::Language::Yul) else if (m_language == AssemblyStack::Language::Yul)
dialect = yul::EVMDialect::yulForEVM(); dialect = EVMDialect::yulForEVM();
else else
solAssert(false, "Invalid language."); solAssert(false, "Invalid language.");
yul::EVMObjectCompiler::compile(*m_parserResult, _assembly, *dialect, _evm15, _optimize); EVMObjectCompiler::compile(*m_parserResult, _assembly, *dialect, _evm15, _optimize);
} }
void AssemblyStack::optimize(yul::Object& _object) void AssemblyStack::optimize(Object& _object)
{ {
solAssert(_object.code, ""); solAssert(_object.code, "");
solAssert(_object.analysisInfo, ""); solAssert(_object.analysisInfo, "");
for (auto& subNode: _object.subObjects) for (auto& subNode: _object.subObjects)
if (auto subObject = dynamic_cast<yul::Object*>(subNode.get())) if (auto subObject = dynamic_cast<Object*>(subNode.get()))
optimize(*subObject); optimize(*subObject);
yul::OptimiserSuite::run(languageToDialect(m_language), *_object.code, *_object.analysisInfo); OptimiserSuite::run(languageToDialect(m_language), *_object.code, *_object.analysisInfo);
} }
MachineAssemblyObject AssemblyStack::assemble(Machine _machine, bool _optimize) const MachineAssemblyObject AssemblyStack::assemble(Machine _machine, bool _optimize) const
@ -150,19 +149,19 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine, bool _optimize)
case Machine::EVM: case Machine::EVM:
{ {
MachineAssemblyObject object; MachineAssemblyObject object;
eth::Assembly assembly; dev::eth::Assembly assembly;
yul::EthAssemblyAdapter adapter(assembly); EthAssemblyAdapter adapter(assembly);
compileEVM(adapter, false, _optimize); compileEVM(adapter, false, _optimize);
object.bytecode = make_shared<eth::LinkerObject>(assembly.assemble()); object.bytecode = make_shared<dev::eth::LinkerObject>(assembly.assemble());
object.assembly = assembly.assemblyString(); object.assembly = assembly.assemblyString();
return object; return object;
} }
case Machine::EVM15: case Machine::EVM15:
{ {
MachineAssemblyObject object; MachineAssemblyObject object;
yul::EVMAssembly assembly(true); EVMAssembly assembly(true);
compileEVM(assembly, true, _optimize); compileEVM(assembly, true, _optimize);
object.bytecode = make_shared<eth::LinkerObject>(assembly.finalize()); object.bytecode = make_shared<dev::eth::LinkerObject>(assembly.finalize());
/// TODO: fill out text representation /// TODO: fill out text representation
return object; return object;
} }

View File

@ -36,19 +36,15 @@ namespace langutil
{ {
class Scanner; class Scanner;
} }
namespace yul namespace yul
{ {
class AbstractAssembly; class AbstractAssembly;
}
namespace dev
{
namespace solidity
{
struct MachineAssemblyObject struct MachineAssemblyObject
{ {
std::shared_ptr<eth::LinkerObject> bytecode; std::shared_ptr<dev::eth::LinkerObject> bytecode;
std::string assembly; std::string assembly;
}; };
@ -62,7 +58,7 @@ public:
enum class Language { Yul, Assembly, StrictAssembly }; enum class Language { Yul, Assembly, StrictAssembly };
enum class Machine { EVM, EVM15, eWasm }; enum class Machine { EVM, EVM15, eWasm };
explicit AssemblyStack(EVMVersion _evmVersion = EVMVersion(), Language _language = Language::Assembly): explicit AssemblyStack(dev::solidity::EVMVersion _evmVersion = dev::solidity::EVMVersion(), Language _language = Language::Assembly):
m_language(_language), m_evmVersion(_evmVersion), m_errorReporter(m_errors) m_language(_language), m_evmVersion(_evmVersion), m_errorReporter(m_errors)
{} {}
@ -95,7 +91,7 @@ private:
void optimize(yul::Object& _object); void optimize(yul::Object& _object);
Language m_language = Language::Assembly; Language m_language = Language::Assembly;
EVMVersion m_evmVersion; dev::solidity::EVMVersion m_evmVersion;
std::shared_ptr<langutil::Scanner> m_scanner; std::shared_ptr<langutil::Scanner> m_scanner;
@ -106,4 +102,3 @@ private:
}; };
} }
}

View File

@ -13,6 +13,8 @@ add_library(yul
AsmScope.h AsmScope.h
AsmScopeFiller.cpp AsmScopeFiller.cpp
AsmScopeFiller.h AsmScopeFiller.h
AssemblyStack.h
AssemblyStack.cpp
CompilabilityChecker.cpp CompilabilityChecker.cpp
CompilabilityChecker.h CompilabilityChecker.h
Dialect.cpp Dialect.cpp

View File

@ -20,28 +20,30 @@
* @date 2014 * @date 2014
* Solidity command line interface. * Solidity command line interface.
*/ */
#include "CommandLineInterface.h" #include <solc/CommandLineInterface.h>
#include "solidity/BuildInfo.h" #include "solidity/BuildInfo.h"
#include "license.h" #include "license.h"
#include <libsolidity/interface/Version.h> #include <libsolidity/interface/Version.h>
#include <liblangutil/Scanner.h>
#include <libsolidity/parsing/Parser.h> #include <libsolidity/parsing/Parser.h>
#include <libsolidity/ast/ASTPrinter.h> #include <libsolidity/ast/ASTPrinter.h>
#include <libsolidity/ast/ASTJsonConverter.h> #include <libsolidity/ast/ASTJsonConverter.h>
#include <libsolidity/analysis/NameAndTypeResolver.h> #include <libsolidity/analysis/NameAndTypeResolver.h>
#include <liblangutil/Exceptions.h>
#include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/CompilerStack.h>
#include <libsolidity/interface/StandardCompiler.h> #include <libsolidity/interface/StandardCompiler.h>
#include <liblangutil/SourceReferenceFormatter.h>
#include <liblangutil/SourceReferenceFormatterHuman.h>
#include <libsolidity/interface/GasEstimator.h> #include <libsolidity/interface/GasEstimator.h>
#include <libsolidity/interface/AssemblyStack.h>
#include <libyul/AssemblyStack.h>
#include <libevmasm/Instruction.h> #include <libevmasm/Instruction.h>
#include <libevmasm/GasMeter.h> #include <libevmasm/GasMeter.h>
#include <liblangutil/Exceptions.h>
#include <liblangutil/Scanner.h>
#include <liblangutil/SourceReferenceFormatter.h>
#include <liblangutil/SourceReferenceFormatterHuman.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
@ -841,8 +843,8 @@ bool CommandLineInterface::processInput()
{ {
// switch to assembly mode // switch to assembly mode
m_onlyAssemble = true; m_onlyAssemble = true;
using Input = AssemblyStack::Language; using Input = yul::AssemblyStack::Language;
using Machine = AssemblyStack::Machine; using Machine = yul::AssemblyStack::Machine;
Input inputLanguage = m_args.count(g_argYul) ? Input::Yul : (m_args.count(g_argStrictAssembly) ? Input::StrictAssembly : Input::Assembly); Input inputLanguage = m_args.count(g_argYul) ? Input::Yul : (m_args.count(g_argStrictAssembly) ? Input::StrictAssembly : Input::Assembly);
Machine targetMachine = Machine::EVM; Machine targetMachine = Machine::EVM;
bool optimize = m_args.count(g_argOptimize); bool optimize = m_args.count(g_argOptimize);
@ -1216,16 +1218,16 @@ string CommandLineInterface::objectWithLinkRefsHex(eth::LinkerObject const& _obj
} }
bool CommandLineInterface::assemble( bool CommandLineInterface::assemble(
AssemblyStack::Language _language, yul::AssemblyStack::Language _language,
AssemblyStack::Machine _targetMachine, yul::AssemblyStack::Machine _targetMachine,
bool _optimize bool _optimize
) )
{ {
bool successful = true; bool successful = true;
map<string, AssemblyStack> assemblyStacks; map<string, yul::AssemblyStack> assemblyStacks;
for (auto const& src: m_sourceCodes) for (auto const& src: m_sourceCodes)
{ {
auto& stack = assemblyStacks[src.first] = AssemblyStack(m_evmVersion, _language); auto& stack = assemblyStacks[src.first] = yul::AssemblyStack(m_evmVersion, _language);
try try
{ {
if (!stack.parseAndAnalyze(src.first, src.second)) if (!stack.parseAndAnalyze(src.first, src.second))
@ -1272,16 +1274,16 @@ bool CommandLineInterface::assemble(
for (auto const& src: m_sourceCodes) for (auto const& src: m_sourceCodes)
{ {
string machine = string machine =
_targetMachine == AssemblyStack::Machine::EVM ? "EVM" : _targetMachine == yul::AssemblyStack::Machine::EVM ? "EVM" :
_targetMachine == AssemblyStack::Machine::EVM15 ? "EVM 1.5" : _targetMachine == yul::AssemblyStack::Machine::EVM15 ? "EVM 1.5" :
"eWasm"; "eWasm";
sout() << endl << "======= " << src.first << " (" << machine << ") =======" << endl; sout() << endl << "======= " << src.first << " (" << machine << ") =======" << endl;
AssemblyStack& stack = assemblyStacks[src.first]; yul::AssemblyStack& stack = assemblyStacks[src.first];
sout() << endl << "Pretty printed source:" << endl; sout() << endl << "Pretty printed source:" << endl;
sout() << stack.print() << endl; sout() << stack.print() << endl;
MachineAssemblyObject object; yul::MachineAssemblyObject object;
try try
{ {
object = stack.assemble(_targetMachine); object = stack.assemble(_targetMachine);

View File

@ -22,7 +22,7 @@
#pragma once #pragma once
#include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/CompilerStack.h>
#include <libsolidity/interface/AssemblyStack.h> #include <libyul/AssemblyStack.h>
#include <liblangutil/EVMVersion.h> #include <liblangutil/EVMVersion.h>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
@ -57,7 +57,7 @@ private:
/// @returns the full object with library placeholder hints in hex. /// @returns the full object with library placeholder hints in hex.
static std::string objectWithLinkRefsHex(eth::LinkerObject const& _obj); static std::string objectWithLinkRefsHex(eth::LinkerObject const& _obj);
bool assemble(AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine, bool _optimize); bool assemble(yul::AssemblyStack::Language _language, yul::AssemblyStack::Machine _targetMachine, bool _optimize);
void outputCompilationResults(); void outputCompilationResults();

View File

@ -22,11 +22,15 @@
#include <test/Options.h> #include <test/Options.h>
#include <libsolidity/interface/AssemblyStack.h> #include <test/libsolidity/ErrorCheck.h>
#include <libsolidity/ast/AST.h>
#include <libyul/AssemblyStack.h>
#include <liblangutil/Scanner.h> #include <liblangutil/Scanner.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
#include <libsolidity/ast/AST.h>
#include <test/libsolidity/ErrorCheck.h>
#include <libevmasm/Assembly.h> #include <libevmasm/Assembly.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -37,6 +41,7 @@
using namespace std; using namespace std;
using namespace langutil; using namespace langutil;
using namespace yul;
namespace dev namespace dev
{ {

View File

@ -19,7 +19,7 @@
#include <libdevcore/AnsiColorized.h> #include <libdevcore/AnsiColorized.h>
#include <libsolidity/interface/AssemblyStack.h> #include <libyul/AssemblyStack.h>
#include <libevmasm/Instruction.h> #include <libevmasm/Instruction.h>

View File

@ -23,7 +23,7 @@
#include <test/libsolidity/ErrorCheck.h> #include <test/libsolidity/ErrorCheck.h>
#include <libsolidity/interface/AssemblyStack.h> #include <libyul/AssemblyStack.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
@ -34,8 +34,6 @@
using namespace std; using namespace std;
using namespace langutil; using namespace langutil;
namespace dev
{
namespace yul namespace yul
{ {
namespace test namespace test
@ -48,9 +46,9 @@ std::pair<bool, ErrorList> parse(string const& _source)
{ {
try try
{ {
solidity::AssemblyStack asmStack( AssemblyStack asmStack(
dev::test::Options::get().evmVersion(), dev::test::Options::get().evmVersion(),
solidity::AssemblyStack::Language::StrictAssembly AssemblyStack::Language::StrictAssembly
); );
bool success = asmStack.parseAndAnalyze("source", _source); bool success = asmStack.parseAndAnalyze("source", _source);
return {success, asmStack.errors()}; return {success, asmStack.errors()};
@ -107,7 +105,7 @@ do \
{ \ { \
Error err = expectError((text), false); \ Error err = expectError((text), false); \
BOOST_CHECK(err.type() == (Error::Type::typ)); \ BOOST_CHECK(err.type() == (Error::Type::typ)); \
BOOST_CHECK(solidity::searchErrorMessage(err, (substring))); \ BOOST_CHECK(dev::solidity::searchErrorMessage(err, (substring))); \
} while(0) } while(0)
BOOST_AUTO_TEST_SUITE(YulObjectParser) BOOST_AUTO_TEST_SUITE(YulObjectParser)
@ -242,9 +240,9 @@ BOOST_AUTO_TEST_CASE(to_string)
} }
)"; )";
expectation = boost::replace_all_copy(expectation, "\t", " "); expectation = boost::replace_all_copy(expectation, "\t", " ");
solidity::AssemblyStack asmStack( AssemblyStack asmStack(
dev::test::Options::get().evmVersion(), dev::test::Options::get().evmVersion(),
solidity::AssemblyStack::Language::StrictAssembly AssemblyStack::Language::StrictAssembly
); );
BOOST_REQUIRE(asmStack.parseAndAnalyze("source", code)); BOOST_REQUIRE(asmStack.parseAndAnalyze("source", code));
BOOST_CHECK_EQUAL(asmStack.print(), expectation); BOOST_CHECK_EQUAL(asmStack.print(), expectation);
@ -284,4 +282,3 @@ BOOST_AUTO_TEST_SUITE_END()
} }
} }
} // end namespaces

View File

@ -20,13 +20,11 @@
#include <test/Options.h> #include <test/Options.h>
#include <libsolidity/interface/AssemblyStack.h> #include <libyul/AssemblyStack.h>
#include <libevmasm/Instruction.h> #include <libevmasm/Instruction.h>
using namespace std; using namespace std;
namespace dev
{
namespace yul namespace yul
{ {
namespace test namespace test
@ -36,9 +34,9 @@ namespace
{ {
string assemble(string const& _input) string assemble(string const& _input)
{ {
solidity::AssemblyStack asmStack; AssemblyStack asmStack;
BOOST_REQUIRE_MESSAGE(asmStack.parseAndAnalyze("", _input), "Source did not parse: " + _input); BOOST_REQUIRE_MESSAGE(asmStack.parseAndAnalyze("", _input), "Source did not parse: " + _input);
return solidity::disassemble(asmStack.assemble(solidity::AssemblyStack::Machine::EVM, true).bytecode->bytecode); return dev::solidity::disassemble(asmStack.assemble(AssemblyStack::Machine::EVM, true).bytecode->bytecode);
} }
} }
@ -350,4 +348,3 @@ BOOST_AUTO_TEST_SUITE_END()
} }
} }
}