From 52f2d4b6e0d3dc75690f0ce8f8c4026488d4c15b Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Wed, 26 Apr 2023 20:02:22 -0500 Subject: [PATCH] [evmasm::EVMAssemblyStack] Implement AbstractAssemblyStack. --- libevmasm/EVMAssemblyStack.cpp | 76 ++++++++++++++++++++++++++++++++-- libevmasm/EVMAssemblyStack.h | 31 +++++++++++--- 2 files changed, 99 insertions(+), 8 deletions(-) diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index dc0a0b273..f34884f49 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -22,8 +22,6 @@ #include #include -#include - using namespace solidity::util; using namespace solidity::langutil; using namespace solidity::frontend; @@ -40,7 +38,10 @@ bool EVMAssemblyStack::parseAndAnalyze(string const& _sourceName, string const& if (!jsonParseStrict(_source, m_json)) return false; - m_evmAssembly = evmasm::Assembly::fromJSON(m_json); + auto result = evmasm::Assembly::fromJSON(m_json); + m_evmAssembly = result.first; + m_sourceList = result.second; + return m_evmAssembly != nullptr; } @@ -51,12 +52,81 @@ void EVMAssemblyStack::assemble() solAssert(!m_evmRuntimeAssembly); m_object = m_evmAssembly->assemble(); + m_sourceMapping.emplace(AssemblyItem::computeSourceMapping(m_evmAssembly->items(), sourceIndices())); if (m_evmAssembly->numSubs() > 0) { m_evmRuntimeAssembly = make_shared(m_evmAssembly->sub(0)); solAssert(m_evmRuntimeAssembly && !m_evmRuntimeAssembly->isCreation()); + m_runtimeSourceMapping.emplace(AssemblyItem::computeSourceMapping(m_evmRuntimeAssembly->items(), sourceIndices())); m_runtimeObject = m_evmRuntimeAssembly->assemble(); } } + +LinkerObject const& EVMAssemblyStack::object(string const& _contractName) const +{ + solAssert(_contractName == m_name); + return m_object; +} + +LinkerObject const& EVMAssemblyStack::runtimeObject(string const& _contractName) const +{ + solAssert(_contractName == m_name); + return m_runtimeObject; +} + +map EVMAssemblyStack::sourceIndices() const +{ + solAssert(m_evmAssembly); + map indices; + unsigned index = 0; + for (auto const& s: m_sourceList) + if (s != CompilerContext::yulUtilityFileName()) + indices[s] = index++; + + if (indices.find(CompilerContext::yulUtilityFileName()) == indices.end()) + indices[CompilerContext::yulUtilityFileName()] = index++; + return indices; +} + +string const* EVMAssemblyStack::sourceMapping(string const& _contractName) const +{ + solAssert(_contractName == m_name); + return m_sourceMapping.has_value() ? &m_sourceMapping.value() : nullptr; +} + +string const* EVMAssemblyStack::runtimeSourceMapping(string const& _contractName) const +{ + solAssert(_contractName == m_name); + return m_runtimeSourceMapping.has_value() ? &m_runtimeSourceMapping.value() : nullptr; +} + +Json::Value EVMAssemblyStack::assemblyJSON(string const& _contractName) const +{ + solAssert(_contractName == m_name); + solAssert(m_evmAssembly); + vector sources = sourceNames(); + if (find(sources.begin(), sources.end(), CompilerContext::yulUtilityFileName()) == sources.end()) + sources.emplace_back(CompilerContext::yulUtilityFileName()); + return m_evmAssembly->assemblyJSON(sources); +} + +string EVMAssemblyStack::assemblyString(string const& _contractName, StringMap const& _sourceCodes) const +{ + solAssert(_contractName == m_name); + solAssert(m_evmAssembly); + return m_evmAssembly->assemblyString(m_debugInfoSelection, _sourceCodes); +} + +string const EVMAssemblyStack::filesystemFriendlyName(string const& _contractName) const +{ + solAssert(_contractName == m_name); + return m_name; +} + +vector EVMAssemblyStack::sourceNames() const +{ + return m_sourceList; +} + } // namespace solidity::evmasm diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index dfd828857..e9e4a9a4f 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -18,6 +18,7 @@ #pragma once +#include #include #include @@ -29,25 +30,41 @@ namespace solidity::evmasm { -class EVMAssemblyStack +class EVMAssemblyStack: public AbstractAssemblyStack { public: explicit EVMAssemblyStack(langutil::EVMVersion _evmVersion): m_evmVersion(_evmVersion) {} - /// Runs parsing and analysis, returns false if input cannot be assembled. - /// Multiple calls overwrite the previous state. bool parseAndAnalyze(std::string const& _sourceName, std::string const& _source); void assemble(); std::string const& name() const { return m_name; } - evmasm::LinkerObject const& object() const { return m_object; } - evmasm::LinkerObject const& runtimeObject() const { return m_runtimeObject; } + virtual LinkerObject const& object(std::string const& _contractName) const override; + virtual LinkerObject const& runtimeObject(std::string const& _contractName) const override; std::shared_ptr const& evmAssembly() const { return m_evmAssembly; } std::shared_ptr const& evmRuntimeAssembly() const { return m_evmRuntimeAssembly; } + virtual std::string const* sourceMapping(std::string const& _contractName) const override; + virtual std::string const* runtimeSourceMapping(std::string const& _contractName) const override; + + virtual Json::Value assemblyJSON(std::string const& _contractName) const override; + virtual std::string assemblyString(std::string const& _contractName, StringMap const& _sourceCodes) const override; + + virtual std::string const filesystemFriendlyName(std::string const& _contractName) const override; + + virtual std::vector contractNames() const override { return {m_name}; } + virtual std::vector sourceNames() const override; + std::map sourceIndices() const; + + virtual bool compilationSuccessful() const override { return m_evmAssembly != nullptr; } + + void selectDebugInfo(langutil::DebugInfoSelection _debugInfoSelection) + { + m_debugInfoSelection = _debugInfoSelection; + } private: langutil::EVMVersion m_evmVersion; @@ -57,6 +74,10 @@ private: std::shared_ptr m_evmRuntimeAssembly; evmasm::LinkerObject m_object; ///< Deployment object (includes the runtime sub-object). evmasm::LinkerObject m_runtimeObject; ///< Runtime object. + std::vector m_sourceList; + langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default(); + std::optional m_sourceMapping; + std::optional m_runtimeSourceMapping; }; } // namespace solidity::evmasm