From f1528e166a5840a12de21f76ae38f427dafc2a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 21 Apr 2023 21:50:16 +0200 Subject: [PATCH] Make EVMAssemblyStack impolement AbstractAssemblyStack --- libevmasm/EVMAssemblyStack.cpp | 93 ++++++++++++++++++++++++++++++++++ libevmasm/EVMAssemblyStack.h | 29 ++++++++++- 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/libevmasm/EVMAssemblyStack.cpp b/libevmasm/EVMAssemblyStack.cpp index dc0a0b273..49cee91b4 100644 --- a/libevmasm/EVMAssemblyStack.cpp +++ b/libevmasm/EVMAssemblyStack.cpp @@ -59,4 +59,97 @@ void EVMAssemblyStack::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; +} + +// TODO: Review implementation here +map EVMAssemblyStack::sourceIndices() const +{ + solAssert(m_evmAssembly); + + map indices; + unsigned index = 0; + for (auto const& s: m_evmAssembly->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); + solAssert(m_evmAssembly); + + if (!m_sourceMapping.has_value()) + { + // TODO: Should this be already pre-computed in assemble() and only returned here? + AssemblyItems const& items = m_evmAssembly->items(); + m_sourceMapping.emplace(AssemblyItem::computeSourceMapping(items, sourceIndices())); + } + + return m_sourceMapping.has_value() ? &m_sourceMapping.value() : nullptr; +} + +string const* EVMAssemblyStack::runtimeSourceMapping(string const& _contractName) const +{ + solAssert(_contractName == m_name); + solAssert(m_evmRuntimeAssembly); + + if (!m_sourceMapping.has_value()) + { + // TODO: Should this be already pre-computed in assemble() and only returned here? + AssemblyItems const& items = m_evmRuntimeAssembly->items(); + m_sourceMapping.emplace(AssemblyItem::computeSourceMapping(items, sourceIndices())); + } + + return m_sourceMapping.has_value() ? &m_sourceMapping.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()); + m_evmAssembly->setSourceList(sources); + return m_evmAssembly->assemblyJSON(); +} + +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); + + // We have only one contract so there are no conflicts possible and no need to sanitize the name + return m_name; +} + +vector EVMAssemblyStack::sourceNames() const +{ + solAssert(m_evmAssembly); + + return m_evmAssembly->sourceList(); +} + } // namespace solidity::evmasm diff --git a/libevmasm/EVMAssemblyStack.h b/libevmasm/EVMAssemblyStack.h index dfd828857..bd026643a 100644 --- a/libevmasm/EVMAssemblyStack.h +++ b/libevmasm/EVMAssemblyStack.h @@ -19,17 +19,22 @@ #pragma once #include +#include #include +#include + #include #include +#include #include +#include namespace solidity::evmasm { -class EVMAssemblyStack +class EVMAssemblyStack: public AbstractAssemblyStack { public: explicit EVMAssemblyStack(langutil::EVMVersion _evmVersion): m_evmVersion(_evmVersion) {} @@ -44,19 +49,41 @@ public: 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; + + // TODO: This should depend on whether assemble() was successful + virtual bool compilationSuccessful() const override { return true; } + + void selectDebugInfo(langutil::DebugInfoSelection _debugInfoSelection) { m_debugInfoSelection = _debugInfoSelection; } private: langutil::EVMVersion m_evmVersion; + langutil::DebugInfoSelection m_debugInfoSelection = langutil::DebugInfoSelection::Default(); + std::string m_name; Json::Value m_json; std::shared_ptr m_evmAssembly; std::shared_ptr m_evmRuntimeAssembly; evmasm::LinkerObject m_object; ///< Deployment object (includes the runtime sub-object). evmasm::LinkerObject m_runtimeObject; ///< Runtime object. + mutable std::optional m_sourceMapping; + mutable std::optional m_runtimeSourceMapping; }; } // namespace solidity::evmasm