Merge pull request #10348 from ethereum/simplify-compiler

Simplify abstraction of Compiler/CompilerContext/CompilerStack
This commit is contained in:
Leonardo 2020-12-11 17:42:36 +01:00 committed by GitHub
commit da9cede0fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 25 additions and 52 deletions

View File

@ -51,28 +51,12 @@ public:
); );
/// @returns Entire assembly. /// @returns Entire assembly.
evmasm::Assembly const& assembly() const { return m_context.assembly(); } evmasm::Assembly const& assembly() const { return m_context.assembly(); }
/// @returns Runtime assembly.
evmasm::Assembly const& runtimeAssembly() const { return m_context.assembly().sub(m_runtimeSub); }
/// @returns Entire assembly as a shared pointer to non-const. /// @returns Entire assembly as a shared pointer to non-const.
std::shared_ptr<evmasm::Assembly> assemblyPtr() const { return m_context.assemblyPtr(); } std::shared_ptr<evmasm::Assembly> assemblyPtr() const { return m_context.assemblyPtr(); }
/// @returns Runtime assembly. /// @returns Runtime assembly as a shared pointer.
std::shared_ptr<evmasm::Assembly> runtimeAssemblyPtr() const; std::shared_ptr<evmasm::Assembly> runtimeAssemblyPtr() const;
/// @returns The entire assembled object (with constructor).
evmasm::LinkerObject assembledObject() const { return m_context.assembledObject(); }
/// @returns Only the runtime object (without constructor).
evmasm::LinkerObject runtimeObject() const { return m_context.assembledRuntimeObject(m_runtimeSub); }
/// @arg _sourceCodes is the map of input files to source code strings
std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const
{
return m_context.assemblyString(_sourceCodes);
}
/// @arg _sourceCodes is the map of input files to source code strings
Json::Value assemblyJSON(std::map<std::string, unsigned> const& _indices = std::map<std::string, unsigned>()) const
{
return m_context.assemblyJSON(_indices);
}
/// @returns Assembly items of the normal compiler context
evmasm::AssemblyItems const& assemblyItems() const { return m_context.assembly().items(); }
/// @returns Assembly items of the runtime compiler context
evmasm::AssemblyItems const& runtimeAssemblyItems() const { return m_context.assembly().sub(m_runtimeSub).items(); }
std::string generatedYulUtilityCode() const { return m_context.generatedYulUtilityCode(); } std::string generatedYulUtilityCode() const { return m_context.generatedYulUtilityCode(); }
std::string runtimeGeneratedYulUtilityCode() const { return m_runtimeContext.generatedYulUtilityCode(); } std::string runtimeGeneratedYulUtilityCode() const { return m_runtimeContext.generatedYulUtilityCode(); }

View File

@ -548,13 +548,6 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _
#endif #endif
} }
LinkerObject const& CompilerContext::assembledObject() const
{
LinkerObject const& object = m_asm->assemble();
solAssert(object.immutableReferences.empty(), "Leftover immutables.");
return object;
}
string CompilerContext::revertReasonIfDebug(string const& _message) string CompilerContext::revertReasonIfDebug(string const& _message)
{ {
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message); return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message);

View File

@ -287,21 +287,6 @@ public:
/// Should be avoided except when adding sub-assemblies. /// Should be avoided except when adding sub-assemblies.
std::shared_ptr<evmasm::Assembly> assemblyPtr() const { return m_asm; } std::shared_ptr<evmasm::Assembly> assemblyPtr() const { return m_asm; }
/// @arg _sourceCodes is the map of input files to source code strings
std::string assemblyString(StringMap const& _sourceCodes = StringMap()) const
{
return m_asm->assemblyString(_sourceCodes);
}
/// @arg _sourceCodes is the map of input files to source code strings
Json::Value assemblyJSON(std::map<std::string, unsigned> const& _indicies = std::map<std::string, unsigned>()) const
{
return m_asm->assemblyJSON(_indicies);
}
evmasm::LinkerObject const& assembledObject() const;
evmasm::LinkerObject const& assembledRuntimeObject(size_t _subIndex) const { return m_asm->sub(_subIndex).assemble(); }
/** /**
* Helper class to pop the visited nodes stack when a scope closes * Helper class to pop the visited nodes stack when a scope closes
*/ */

View File

@ -627,7 +627,7 @@ evmasm::AssemblyItems const* CompilerStack::assemblyItems(string const& _contrac
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
Contract const& currentContract = contract(_contractName); Contract const& currentContract = contract(_contractName);
return currentContract.compiler ? &contract(_contractName).compiler->assemblyItems() : nullptr; return currentContract.evmAssembly ? &currentContract.evmAssembly->items() : nullptr;
} }
evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _contractName) const evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _contractName) const
@ -636,7 +636,7 @@ evmasm::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
Contract const& currentContract = contract(_contractName); Contract const& currentContract = contract(_contractName);
return currentContract.compiler ? &contract(_contractName).compiler->runtimeAssemblyItems() : nullptr; return currentContract.evmRuntimeAssembly ? &currentContract.evmRuntimeAssembly->items() : nullptr;
} }
Json::Value CompilerStack::generatedSources(string const& _contractName, bool _runtime) const Json::Value CompilerStack::generatedSources(string const& _contractName, bool _runtime) const
@ -790,8 +790,8 @@ string CompilerStack::assemblyString(string const& _contractName, StringMap _sou
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
Contract const& currentContract = contract(_contractName); Contract const& currentContract = contract(_contractName);
if (currentContract.compiler) if (currentContract.evmAssembly)
return currentContract.compiler->assemblyString(_sourceCodes); return currentContract.evmAssembly->assemblyString(_sourceCodes);
else else
return string(); return string();
} }
@ -803,8 +803,8 @@ Json::Value CompilerStack::assemblyJSON(string const& _contractName) const
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful.")); BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
Contract const& currentContract = contract(_contractName); Contract const& currentContract = contract(_contractName);
if (currentContract.compiler) if (currentContract.evmAssembly)
return currentContract.compiler->assemblyJSON(sourceIndices()); return currentContract.evmAssembly->assemblyJSON(sourceIndices());
else else
return Json::Value(); return Json::Value();
} }
@ -977,7 +977,7 @@ size_t CompilerStack::functionEntryPoint(
evmasm::AssemblyItem tag = compiler->functionEntryLabel(_function); evmasm::AssemblyItem tag = compiler->functionEntryLabel(_function);
if (tag.type() == evmasm::UndefinedItem) if (tag.type() == evmasm::UndefinedItem)
return 0; return 0;
evmasm::AssemblyItems const& items = compiler->runtimeAssemblyItems(); evmasm::AssemblyItems const& items = compiler->runtimeAssembly().items();
for (size_t i = 0; i < items.size(); ++i) for (size_t i = 0; i < items.size(); ++i)
if (items.at(i).type() == evmasm::Tag && items.at(i).data() == tag.data()) if (items.at(i).type() == evmasm::Tag && items.at(i).data() == tag.data())
return i; return i;
@ -1200,20 +1200,25 @@ void CompilerStack::compileContract(
solAssert(false, "Optimizer exception during compilation"); solAssert(false, "Optimizer exception during compilation");
} }
compiledContract.evmAssembly = compiler->assemblyPtr();
solAssert(compiledContract.evmAssembly, "");
try try
{ {
// Assemble deployment (incl. runtime) object. // Assemble deployment (incl. runtime) object.
compiledContract.object = compiler->assembledObject(); compiledContract.object = compiledContract.evmAssembly->assemble();
} }
catch(evmasm::AssemblyException const&) catch(evmasm::AssemblyException const&)
{ {
solAssert(false, "Assembly exception for bytecode"); solAssert(false, "Assembly exception for bytecode");
} }
solAssert(compiledContract.object.immutableReferences.empty(), "Leftover immutables.");
compiledContract.evmRuntimeAssembly = compiler->runtimeAssemblyPtr();
solAssert(compiledContract.evmRuntimeAssembly, "");
try try
{ {
// Assemble runtime object. // Assemble runtime object.
compiledContract.runtimeObject = compiler->runtimeObject(); compiledContract.runtimeObject = compiledContract.evmRuntimeAssembly->assemble();
} }
catch(evmasm::AssemblyException const&) catch(evmasm::AssemblyException const&)
{ {

View File

@ -358,6 +358,8 @@ private:
{ {
ContractDefinition const* contract = nullptr; ContractDefinition const* contract = nullptr;
std::shared_ptr<Compiler> compiler; std::shared_ptr<Compiler> compiler;
std::shared_ptr<evmasm::Assembly> evmAssembly;
std::shared_ptr<evmasm::Assembly> evmRuntimeAssembly;
evmasm::LinkerObject object; ///< Deployment object (includes the runtime sub-object). evmasm::LinkerObject object; ///< Deployment object (includes the runtime sub-object).
evmasm::LinkerObject runtimeObject; ///< Runtime object. evmasm::LinkerObject runtimeObject; ///< Runtime object.
std::string yulIR; ///< Experimental Yul IR code. std::string yulIR; ///< Experimental Yul IR code.

View File

@ -91,7 +91,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode)
); );
compiler.compileContract(*contract, map<ContractDefinition const*, shared_ptr<Compiler const>>{}, bytes()); compiler.compileContract(*contract, map<ContractDefinition const*, shared_ptr<Compiler const>>{}, bytes());
return compiler.runtimeAssemblyItems(); return compiler.runtimeAssembly().items();
} }
BOOST_FAIL("No contract found in source."); BOOST_FAIL("No contract found in source.");
return AssemblyItems(); return AssemblyItems();

View File

@ -35,6 +35,7 @@
#include <libsolidity/ast/TypeProvider.h> #include <libsolidity/ast/TypeProvider.h>
#include <libsolidity/analysis/TypeChecker.h> #include <libsolidity/analysis/TypeChecker.h>
#include <liblangutil/ErrorReporter.h> #include <liblangutil/ErrorReporter.h>
#include <libevmasm/LinkerObject.h>
#include <test/Common.h> #include <test/Common.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
@ -160,7 +161,10 @@ bytes compileFirstExpression(
context << context.functionEntryLabel(dynamic_cast<FunctionDefinition const&>( context << context.functionEntryLabel(dynamic_cast<FunctionDefinition const&>(
resolveDeclaration(*sourceUnit, function, resolver) resolveDeclaration(*sourceUnit, function, resolver)
)); ));
bytes instructions = context.assembledObject().bytecode; BOOST_REQUIRE(context.assemblyPtr());
LinkerObject const& object = context.assemblyPtr()->assemble();
BOOST_REQUIRE(object.immutableReferences.empty());
bytes instructions = object.bytecode;
// debug // debug
// cout << evmasm::disassemble(instructions) << endl; // cout << evmasm::disassemble(instructions) << endl;
return instructions; return instructions;