aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/codegen')
-rw-r--r--libsolidity/codegen/AsmCodeGen.cpp194
-rw-r--r--libsolidity/codegen/AsmCodeGen.h93
-rw-r--r--libsolidity/codegen/CompilerContext.cpp7
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp4
4 files changed, 292 insertions, 6 deletions
diff --git a/libsolidity/codegen/AsmCodeGen.cpp b/libsolidity/codegen/AsmCodeGen.cpp
new file mode 100644
index 00000000..dfcc900b
--- /dev/null
+++ b/libsolidity/codegen/AsmCodeGen.cpp
@@ -0,0 +1,194 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Adaptor between the abstract assembly and eth assembly.
+ */
+
+#include <libsolidity/codegen/AsmCodeGen.h>
+
+#include <libyul/AsmData.h>
+#include <libyul/AsmAnalysisInfo.h>
+
+#include <libyul/backends/evm/AbstractAssembly.h>
+#include <libyul/backends/evm/EVMCodeTransform.h>
+
+#include <libevmasm/Assembly.h>
+#include <libevmasm/AssemblyItem.h>
+#include <libevmasm/Instruction.h>
+
+#include <liblangutil/SourceLocation.h>
+
+#include <libdevcore/FixedHash.h>
+
+#include <memory>
+#include <functional>
+
+using namespace std;
+using namespace dev;
+using namespace langutil;
+using namespace yul;
+using namespace dev::solidity;
+
+EthAssemblyAdapter::EthAssemblyAdapter(eth::Assembly& _assembly):
+ m_assembly(_assembly)
+{
+}
+
+void EthAssemblyAdapter::setSourceLocation(SourceLocation const& _location)
+{
+ m_assembly.setSourceLocation(_location);
+}
+
+int EthAssemblyAdapter::stackHeight() const
+{
+ return m_assembly.deposit();
+}
+
+void EthAssemblyAdapter::appendInstruction(solidity::Instruction _instruction)
+{
+ m_assembly.append(_instruction);
+}
+
+void EthAssemblyAdapter::appendConstant(u256 const& _constant)
+{
+ m_assembly.append(_constant);
+}
+
+void EthAssemblyAdapter::appendLabel(LabelID _labelId)
+{
+ m_assembly.append(eth::AssemblyItem(eth::Tag, _labelId));
+}
+
+void EthAssemblyAdapter::appendLabelReference(LabelID _labelId)
+{
+ m_assembly.append(eth::AssemblyItem(eth::PushTag, _labelId));
+}
+
+size_t EthAssemblyAdapter::newLabelId()
+{
+ return assemblyTagToIdentifier(m_assembly.newTag());
+}
+
+size_t EthAssemblyAdapter::namedLabel(std::string const& _name)
+{
+ return assemblyTagToIdentifier(m_assembly.namedTag(_name));
+}
+
+void EthAssemblyAdapter::appendLinkerSymbol(std::string const& _linkerSymbol)
+{
+ m_assembly.appendLibraryAddress(_linkerSymbol);
+}
+
+void EthAssemblyAdapter::appendJump(int _stackDiffAfter)
+{
+ appendInstruction(solidity::Instruction::JUMP);
+ m_assembly.adjustDeposit(_stackDiffAfter);
+}
+
+void EthAssemblyAdapter::appendJumpTo(LabelID _labelId, int _stackDiffAfter)
+{
+ appendLabelReference(_labelId);
+ appendJump(_stackDiffAfter);
+}
+
+void EthAssemblyAdapter::appendJumpToIf(LabelID _labelId)
+{
+ appendLabelReference(_labelId);
+ appendInstruction(solidity::Instruction::JUMPI);
+}
+
+void EthAssemblyAdapter::appendBeginsub(LabelID, int)
+{
+ // TODO we could emulate that, though
+ solAssert(false, "BEGINSUB not implemented for EVM 1.0");
+}
+
+void EthAssemblyAdapter::appendJumpsub(LabelID, int, int)
+{
+ // TODO we could emulate that, though
+ solAssert(false, "JUMPSUB not implemented for EVM 1.0");
+}
+
+void EthAssemblyAdapter::appendReturnsub(int, int)
+{
+ // TODO we could emulate that, though
+ solAssert(false, "RETURNSUB not implemented for EVM 1.0");
+}
+
+void EthAssemblyAdapter::appendAssemblySize()
+{
+ m_assembly.appendProgramSize();
+}
+
+pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly()
+{
+ shared_ptr<eth::Assembly> assembly{make_shared<eth::Assembly>()};
+ auto sub = m_assembly.newSub(assembly);
+ return {make_shared<EthAssemblyAdapter>(*assembly), size_t(sub.data())};
+}
+
+void EthAssemblyAdapter::appendDataOffset(AbstractAssembly::SubID _sub)
+{
+ auto it = m_dataHashBySubId.find(_sub);
+ if (it == m_dataHashBySubId.end())
+ m_assembly.pushSubroutineOffset(size_t(_sub));
+ else
+ m_assembly << eth::AssemblyItem(eth::PushData, it->second);
+}
+
+void EthAssemblyAdapter::appendDataSize(AbstractAssembly::SubID _sub)
+{
+ auto it = m_dataHashBySubId.find(_sub);
+ if (it == m_dataHashBySubId.end())
+ m_assembly.pushSubroutineSize(size_t(_sub));
+ else
+ m_assembly << u256(m_assembly.data(h256(it->second)).size());
+}
+
+AbstractAssembly::SubID EthAssemblyAdapter::appendData(bytes const& _data)
+{
+ eth::AssemblyItem pushData = m_assembly.newData(_data);
+ SubID subID = m_nextDataCounter++;
+ m_dataHashBySubId[subID] = pushData.data();
+ return subID;
+}
+
+EthAssemblyAdapter::LabelID EthAssemblyAdapter::assemblyTagToIdentifier(eth::AssemblyItem const& _tag)
+{
+ u256 id = _tag.data();
+ solAssert(id <= std::numeric_limits<LabelID>::max(), "Tag id too large.");
+ return LabelID(id);
+}
+
+void CodeGenerator::assemble(
+ Block const& _parsedData,
+ AsmAnalysisInfo& _analysisInfo,
+ eth::Assembly& _assembly,
+ ExternalIdentifierAccess const& _identifierAccess,
+ bool _useNamedLabelsForFunctions
+)
+{
+ EthAssemblyAdapter assemblyAdapter(_assembly);
+ CodeTransform(
+ assemblyAdapter,
+ _analysisInfo,
+ false,
+ false,
+ _identifierAccess,
+ _useNamedLabelsForFunctions
+ )(_parsedData);
+}
diff --git a/libsolidity/codegen/AsmCodeGen.h b/libsolidity/codegen/AsmCodeGen.h
new file mode 100644
index 00000000..4c6d97f4
--- /dev/null
+++ b/libsolidity/codegen/AsmCodeGen.h
@@ -0,0 +1,93 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Adaptor between the abstract assembly and eth assembly.
+ */
+
+#pragma once
+
+#include <libyul/AsmAnalysis.h>
+#include <libyul/backends/evm/AbstractAssembly.h>
+
+#include <liblangutil/SourceLocation.h>
+
+#include <functional>
+
+namespace yul
+{
+struct Block;
+}
+
+namespace dev
+{
+namespace eth
+{
+class Assembly;
+class AssemblyItem;
+}
+
+namespace solidity
+{
+
+class EthAssemblyAdapter: public yul::AbstractAssembly
+{
+public:
+ explicit EthAssemblyAdapter(eth::Assembly& _assembly);
+ void setSourceLocation(langutil::SourceLocation const& _location) override;
+ int stackHeight() const override;
+ void appendInstruction(solidity::Instruction _instruction) override;
+ void appendConstant(u256 const& _constant) override;
+ void appendLabel(LabelID _labelId) override;
+ void appendLabelReference(LabelID _labelId) override;
+ size_t newLabelId() override;
+ size_t namedLabel(std::string const& _name) override;
+ void appendLinkerSymbol(std::string const& _linkerSymbol) override;
+ void appendJump(int _stackDiffAfter) override;
+ void appendJumpTo(LabelID _labelId, int _stackDiffAfter) override;
+ void appendJumpToIf(LabelID _labelId) override;
+ void appendBeginsub(LabelID, int) override;
+ void appendJumpsub(LabelID, int, int) override;
+ void appendReturnsub(int, int) override;
+ void appendAssemblySize() override;
+ std::pair<std::shared_ptr<AbstractAssembly>, SubID> createSubAssembly() override;
+ void appendDataOffset(SubID _sub) override;
+ void appendDataSize(SubID _sub) override;
+ SubID appendData(dev::bytes const& _data) override;
+
+private:
+ static LabelID assemblyTagToIdentifier(eth::AssemblyItem const& _tag);
+
+ eth::Assembly& m_assembly;
+ std::map<SubID, dev::u256> m_dataHashBySubId;
+ size_t m_nextDataCounter = std::numeric_limits<size_t>::max() / 2;
+};
+
+class CodeGenerator
+{
+public:
+ /// Performs code generation and appends generated to _assembly.
+ static void assemble(
+ yul::Block const& _parsedData,
+ yul::AsmAnalysisInfo& _analysisInfo,
+ dev::eth::Assembly& _assembly,
+ yul::ExternalIdentifierAccess const& _identifierAccess = yul::ExternalIdentifierAccess(),
+ bool _useNamedLabelsForFunctions = false
+ );
+};
+
+}
+}
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index 039738a6..dac09c2e 100644
--- a/libsolidity/codegen/CompilerContext.cpp
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -24,10 +24,10 @@
#include <libsolidity/codegen/CompilerUtils.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/codegen/Compiler.h>
+#include <libsolidity/codegen/AsmCodeGen.h>
#include <libsolidity/interface/Version.h>
#include <liblangutil/SourceReferenceFormatter.h>
#include <libyul/AsmParser.h>
-#include <libyul/AsmCodeGen.h>
#include <libyul/AsmAnalysis.h>
#include <libyul/AsmAnalysisInfo.h>
#include <libyul/YulString.h>
@@ -386,8 +386,7 @@ void CompilerContext::appendInlineAssembly(
for (auto const& error: errorReporter.errors())
message += SourceReferenceFormatter::formatExceptionInformation(
*error,
- (error->type() == Error::Type::Warning) ? "Warning" : "Error",
- [&](string const&) -> Scanner const& { return *scanner; }
+ (error->type() == Error::Type::Warning) ? "Warning" : "Error"
);
message += "-------------------------------------------\n";
@@ -395,7 +394,7 @@ void CompilerContext::appendInlineAssembly(
}
solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block.");
- yul::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, identifierAccess, _system);
+ CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, identifierAccess, _system);
// Reset the source location to the one of the node (instead of the CODEGEN source location)
updateSourceLocation();
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index aabdbb79..ec55ae9b 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -23,8 +23,8 @@
#include <libsolidity/codegen/ContractCompiler.h>
#include <libsolidity/codegen/ExpressionCompiler.h>
#include <libsolidity/codegen/CompilerUtils.h>
+#include <libsolidity/codegen/AsmCodeGen.h>
#include <libsolidity/ast/AST.h>
-#include <libyul/AsmCodeGen.h>
#include <liblangutil/ErrorReporter.h>
#include <libevmasm/Instruction.h>
@@ -618,7 +618,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
}
};
solAssert(_inlineAssembly.annotation().analysisInfo, "");
- yul::CodeGenerator::assemble(
+ CodeGenerator::assemble(
_inlineAssembly.operations(),
*_inlineAssembly.annotation().analysisInfo,
m_context.nonConstAssembly(),