From dd5b43741ce58bc4326a2cec1a68aa3f28e84766 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 28 Jan 2019 18:11:58 +0100 Subject: [PATCH] No-output Assembly. --- libyul/CMakeLists.txt | 2 + libyul/backends/evm/NoOutputAssembly.cpp | 143 +++++++++++++++++++++++ libyul/backends/evm/NoOutputAssembly.h | 75 ++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 libyul/backends/evm/NoOutputAssembly.cpp create mode 100644 libyul/backends/evm/NoOutputAssembly.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 259f43f85..edae65552 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -32,6 +32,8 @@ add_library(yul backends/evm/EVMDialect.h backends/evm/EVMObjectCompiler.cpp backends/evm/EVMObjectCompiler.h + backends/evm/NoOutputAssembly.h + backends/evm/NoOutputAssembly.cpp optimiser/ASTCopier.cpp optimiser/ASTCopier.h optimiser/ASTWalker.cpp diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp new file mode 100644 index 000000000..81c67a5e4 --- /dev/null +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -0,0 +1,143 @@ +/* + 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 . +*/ +/** + * Assembly interface that ignores everything. Can be used as a backend for a compilation dry-run. + */ + +#include + +#include + +#include + +using namespace std; +using namespace dev; +using namespace langutil; +using namespace yul; + + +void NoOutputAssembly::appendInstruction(solidity::Instruction _instr) +{ + m_stackHeight += solidity::instructionInfo(_instr).ret - solidity::instructionInfo(_instr).args; +} + +void NoOutputAssembly::appendConstant(u256 const&) +{ + appendInstruction(solidity::pushInstruction(1)); +} + +void NoOutputAssembly::appendLabel(LabelID) +{ + appendInstruction(solidity::Instruction::JUMPDEST); +} + +void NoOutputAssembly::appendLabelReference(LabelID) +{ + solAssert(!m_evm15, "Cannot use plain label references in EMV1.5 mode."); + appendInstruction(solidity::pushInstruction(1)); +} + +NoOutputAssembly::LabelID NoOutputAssembly::newLabelId() +{ + return 1; +} + +AbstractAssembly::LabelID NoOutputAssembly::namedLabel(string const&) +{ + return 1; +} + +void NoOutputAssembly::appendLinkerSymbol(string const&) +{ + solAssert(false, "Linker symbols not yet implemented."); +} + +void NoOutputAssembly::appendJump(int _stackDiffAfter) +{ + solAssert(!m_evm15, "Plain JUMP used for EVM 1.5"); + appendInstruction(solidity::Instruction::JUMP); + m_stackHeight += _stackDiffAfter; +} + +void NoOutputAssembly::appendJumpTo(LabelID _labelId, int _stackDiffAfter) +{ + if (m_evm15) + m_stackHeight += _stackDiffAfter; + else + { + appendLabelReference(_labelId); + appendJump(_stackDiffAfter); + } +} + +void NoOutputAssembly::appendJumpToIf(LabelID _labelId) +{ + if (m_evm15) + m_stackHeight--; + else + { + appendLabelReference(_labelId); + appendInstruction(solidity::Instruction::JUMPI); + } +} + +void NoOutputAssembly::appendBeginsub(LabelID, int _arguments) +{ + solAssert(m_evm15, "BEGINSUB used for EVM 1.0"); + solAssert(_arguments >= 0, ""); + m_stackHeight += _arguments; +} + +void NoOutputAssembly::appendJumpsub(LabelID, int _arguments, int _returns) +{ + solAssert(m_evm15, "JUMPSUB used for EVM 1.0"); + solAssert(_arguments >= 0 && _returns >= 0, ""); + m_stackHeight += _returns - _arguments; +} + +void NoOutputAssembly::appendReturnsub(int _returns, int _stackDiffAfter) +{ + solAssert(m_evm15, "RETURNSUB used for EVM 1.0"); + solAssert(_returns >= 0, ""); + m_stackHeight += _stackDiffAfter - _returns; +} + +void NoOutputAssembly::appendAssemblySize() +{ + appendInstruction(solidity::Instruction::PUSH1); +} + +pair, AbstractAssembly::SubID> NoOutputAssembly::createSubAssembly() +{ + solAssert(false, "Sub assemblies not implemented."); + return {}; +} + +void NoOutputAssembly::appendDataOffset(AbstractAssembly::SubID) +{ + appendInstruction(solidity::Instruction::PUSH1); +} + +void NoOutputAssembly::appendDataSize(AbstractAssembly::SubID) +{ + appendInstruction(solidity::Instruction::PUSH1); +} + +AbstractAssembly::SubID NoOutputAssembly::appendData(bytes const&) +{ + return 1; +} diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h new file mode 100644 index 000000000..b07569439 --- /dev/null +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -0,0 +1,75 @@ +/* + 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 . +*/ +/** + * Assembly interface that ignores everything. Can be used as a backend for a compilation dry-run. + */ + +#pragma once + +#include + +#include + +#include + +namespace langutil +{ +struct SourceLocation; +} + +namespace yul +{ + +/** + * Assembly class that just ignores everything and only performs stack counting. + * The purpose is to use this assembly for compilation dry-runs. + */ +class NoOutputAssembly: public AbstractAssembly +{ +public: + explicit NoOutputAssembly(bool _evm15 = false): m_evm15(_evm15) { } + virtual ~NoOutputAssembly() = default; + + void setSourceLocation(langutil::SourceLocation const&) override {} + int stackHeight() const override { return m_stackHeight; } + void appendInstruction(dev::solidity::Instruction _instruction) override; + void appendConstant(dev::u256 const& _constant) override; + void appendLabel(LabelID _labelId) override; + void appendLabelReference(LabelID _labelId) override; + LabelID newLabelId() override; + LabelID namedLabel(std::string const& _name) override; + void appendLinkerSymbol(std::string const& _name) override; + + void appendJump(int _stackDiffAfter) override; + void appendJumpTo(LabelID _labelId, int _stackDiffAfter) override; + void appendJumpToIf(LabelID _labelId) override; + void appendBeginsub(LabelID _labelId, int _arguments) override; + void appendJumpsub(LabelID _labelId, int _arguments, int _returns) override; + void appendReturnsub(int _returns, int _stackDiffAfter) override; + + void appendAssemblySize() override; + std::pair, SubID> createSubAssembly() override; + void appendDataOffset(SubID _sub) override; + void appendDataSize(SubID _sub) override; + SubID appendData(dev::bytes const& _data) override; + +private: + bool m_evm15 = false; ///< if true, switch to evm1.5 mode + int m_stackHeight = 0; +}; + +}