diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.cpp | 9 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 2 | ||||
-rw-r--r-- | libsolidity/codegen/AsmCodeGen.cpp | 152 | ||||
-rw-r--r-- | libsolidity/codegen/AsmCodeGen.h | 56 | ||||
-rw-r--r-- | libsolidity/codegen/CompilerContext.cpp | 8 | ||||
-rw-r--r-- | libsolidity/codegen/ContractCompiler.cpp | 4 | ||||
-rw-r--r-- | libsolidity/interface/AssemblyStack.cpp | 19 |
8 files changed, 234 insertions, 17 deletions
diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index dc4c6d15..43d61c86 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -23,6 +23,7 @@ set(sources ast/Types.cpp codegen/ABIFunctions.cpp codegen/ArrayUtils.cpp + codegen/AsmCodeGen.cpp codegen/Compiler.cpp codegen/CompilerContext.cpp codegen/CompilerUtils.cpp diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index c4931d98..ac88a052 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -316,7 +316,14 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) // We use the latest EVM version because we will re-run it anyway. yul::AsmAnalysisInfo analysisInfo; boost::optional<Error::Type> errorTypeForLoose = Error::Type::SyntaxError; - yul::AsmAnalyzer(analysisInfo, errorsIgnored, EVMVersion(), errorTypeForLoose, yul::AsmFlavour::Loose, resolver).analyze(_inlineAssembly.operations()); + yul::AsmAnalyzer( + analysisInfo, + errorsIgnored, + EVMVersion(), + errorTypeForLoose, + yul::Dialect::looseAssemblyForEVM(), + resolver + ).analyze(_inlineAssembly.operations()); return false; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9350df05..5c8e0c6c 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -658,7 +658,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) m_errorReporter, m_evmVersion, Error::Type::SyntaxError, - yul::AsmFlavour::Loose, + yul::Dialect::looseAssemblyForEVM(), identifierAccess ); if (!analyzer.analyze(_inlineAssembly.operations())) diff --git a/libsolidity/codegen/AsmCodeGen.cpp b/libsolidity/codegen/AsmCodeGen.cpp new file mode 100644 index 00000000..83dd08fb --- /dev/null +++ b/libsolidity/codegen/AsmCodeGen.cpp @@ -0,0 +1,152 @@ +/* + 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/Instruction.h> + +#include <liblangutil/SourceLocation.h> + +#include <memory> +#include <functional> + +using namespace std; +using namespace dev; +using namespace langutil; +using namespace yul; +using namespace dev::solidity; + +class EthAssemblyAdapter: public AbstractAssembly +{ +public: + explicit EthAssemblyAdapter(eth::Assembly& _assembly): + m_assembly(_assembly) + { + } + virtual void setSourceLocation(SourceLocation const& _location) override + { + m_assembly.setSourceLocation(_location); + } + virtual int stackHeight() const override { return m_assembly.deposit(); } + virtual void appendInstruction(solidity::Instruction _instruction) override + { + m_assembly.append(_instruction); + } + virtual void appendConstant(u256 const& _constant) override + { + m_assembly.append(_constant); + } + /// Append a label. + virtual void appendLabel(LabelID _labelId) override + { + m_assembly.append(eth::AssemblyItem(eth::Tag, _labelId)); + } + /// Append a label reference. + virtual void appendLabelReference(LabelID _labelId) override + { + m_assembly.append(eth::AssemblyItem(eth::PushTag, _labelId)); + } + virtual size_t newLabelId() override + { + return assemblyTagToIdentifier(m_assembly.newTag()); + } + virtual size_t namedLabel(std::string const& _name) override + { + return assemblyTagToIdentifier(m_assembly.namedTag(_name)); + } + virtual void appendLinkerSymbol(std::string const& _linkerSymbol) override + { + m_assembly.appendLibraryAddress(_linkerSymbol); + } + virtual void appendJump(int _stackDiffAfter) override + { + appendInstruction(solidity::Instruction::JUMP); + m_assembly.adjustDeposit(_stackDiffAfter); + } + virtual void appendJumpTo(LabelID _labelId, int _stackDiffAfter) override + { + appendLabelReference(_labelId); + appendJump(_stackDiffAfter); + } + virtual void appendJumpToIf(LabelID _labelId) override + { + appendLabelReference(_labelId); + appendInstruction(solidity::Instruction::JUMPI); + } + virtual void appendBeginsub(LabelID, int) override + { + // TODO we could emulate that, though + solAssert(false, "BEGINSUB not implemented for EVM 1.0"); + } + /// Call a subroutine. + virtual void appendJumpsub(LabelID, int, int) override + { + // TODO we could emulate that, though + solAssert(false, "JUMPSUB not implemented for EVM 1.0"); + } + + /// Return from a subroutine. + virtual void appendReturnsub(int, int) override + { + // TODO we could emulate that, though + solAssert(false, "RETURNSUB not implemented for EVM 1.0"); + } + + virtual void appendAssemblySize() override + { + m_assembly.appendProgramSize(); + } + +private: + static LabelID assemblyTagToIdentifier(eth::AssemblyItem const& _tag) + { + u256 id = _tag.data(); + solAssert(id <= std::numeric_limits<LabelID>::max(), "Tag id too large."); + return LabelID(id); + } + + eth::Assembly& m_assembly; +}; + +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..dc529e10 --- /dev/null +++ b/libsolidity/codegen/AsmCodeGen.h @@ -0,0 +1,56 @@ +/* + 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 <functional> + +namespace yul +{ +struct Block; +} + +namespace dev +{ +namespace eth +{ +class Assembly; +} + +namespace solidity +{ + +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 5a3a233c..5ccdac37 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> @@ -361,7 +361,7 @@ void CompilerContext::appendInlineAssembly( ErrorList errors; ErrorReporter errorReporter(errors); auto scanner = make_shared<langutil::Scanner>(langutil::CharStream(_assembly, "--CODEGEN--")); - auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Strict).parse(scanner, false); + auto parserResult = yul::Parser(errorReporter, yul::Dialect::strictAssemblyForEVM()).parse(scanner, false); #ifdef SOL_OUTPUT_ASM cout << yul::AsmPrinter()(*parserResult) << endl; #endif @@ -373,7 +373,7 @@ void CompilerContext::appendInlineAssembly( errorReporter, m_evmVersion, boost::none, - yul::AsmFlavour::Strict, + yul::Dialect::strictAssemblyForEVM(), identifierAccess.resolve ).analyze(*parserResult); if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) @@ -395,7 +395,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(), diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index f5eb7e41..c15a192a 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -22,12 +22,13 @@ #include <libsolidity/interface/AssemblyStack.h> +#include <libsolidity/codegen/AsmCodeGen.h> + #include <liblangutil/Scanner.h> #include <libyul/AsmPrinter.h> #include <libyul/AsmParser.h> #include <libyul/AsmAnalysis.h> #include <libyul/AsmAnalysisInfo.h> -#include <libyul/AsmCodeGen.h> #include <libyul/backends/evm/EVMCodeTransform.h> #include <libyul/backends/evm/EVMAssembly.h> #include <libyul/ObjectParser.h> @@ -43,19 +44,19 @@ using namespace dev::solidity; namespace { -yul::AsmFlavour languageToAsmFlavour(AssemblyStack::Language _language) +yul::Dialect languageToDialect(AssemblyStack::Language _language) { switch (_language) { case AssemblyStack::Language::Assembly: - return yul::AsmFlavour::Loose; + return yul::Dialect::looseAssemblyForEVM(); case AssemblyStack::Language::StrictAssembly: - return yul::AsmFlavour::Strict; + return yul::Dialect::strictAssemblyForEVM(); case AssemblyStack::Language::Yul: - return yul::AsmFlavour::Yul; + return yul::Dialect::yul(); } solAssert(false, ""); - return yul::AsmFlavour::Yul; + return yul::Dialect::yul(); } } @@ -72,7 +73,7 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string m_errors.clear(); m_analysisSuccessful = false; m_scanner = make_shared<Scanner>(CharStream(_source, _sourceName)); - m_parserResult = yul::ObjectParser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); + m_parserResult = yul::ObjectParser(m_errorReporter, languageToDialect(m_language)).parse(m_scanner, false); if (!m_errorReporter.errors().empty()) return false; solAssert(m_parserResult, ""); @@ -93,7 +94,7 @@ bool AssemblyStack::analyzeParsed() solAssert(m_parserResult, ""); solAssert(m_parserResult->code, ""); m_parserResult->analysisInfo = make_shared<yul::AsmAnalysisInfo>(); - yul::AsmAnalyzer analyzer(*m_parserResult->analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToAsmFlavour(m_language)); + yul::AsmAnalyzer analyzer(*m_parserResult->analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToDialect(m_language)); m_analysisSuccessful = analyzer.analyze(*m_parserResult->code); return m_analysisSuccessful; } @@ -111,7 +112,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const { MachineAssemblyObject object; eth::Assembly assembly; - yul::CodeGenerator::assemble(*m_parserResult->code, *m_parserResult->analysisInfo, assembly); + CodeGenerator::assemble(*m_parserResult->code, *m_parserResult->analysisInfo, assembly); object.bytecode = make_shared<eth::LinkerObject>(assembly.assemble()); object.assembly = assembly.assemblyString(); return object; |