diff options
author | chriseth <chris@ethereum.org> | 2018-12-12 07:37:20 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-12 07:37:20 +0800 |
commit | e74d9df20d1d1e8253cf51ef8d4191e9a0f51e14 (patch) | |
tree | 72a8593bf822032ecf50dbc8e1c78e899a5befd4 /libyul/backends/evm/EVMDialect.cpp | |
parent | 9f86ede32d4aa3e53bf82d0e4c64dbea3661791b (diff) | |
parent | fb3a0ac1c7d2c4624df6ae62d290a2de7768d036 (diff) | |
download | dexon-solidity-e74d9df20d1d1e8253cf51ef8d4191e9a0f51e14.tar dexon-solidity-e74d9df20d1d1e8253cf51ef8d4191e9a0f51e14.tar.gz dexon-solidity-e74d9df20d1d1e8253cf51ef8d4191e9a0f51e14.tar.bz2 dexon-solidity-e74d9df20d1d1e8253cf51ef8d4191e9a0f51e14.tar.lz dexon-solidity-e74d9df20d1d1e8253cf51ef8d4191e9a0f51e14.tar.xz dexon-solidity-e74d9df20d1d1e8253cf51ef8d4191e9a0f51e14.tar.zst dexon-solidity-e74d9df20d1d1e8253cf51ef8d4191e9a0f51e14.zip |
Merge pull request #5616 from ethereum/codegenForObjectsAccess
[Yul] Codegen for objects access
Diffstat (limited to 'libyul/backends/evm/EVMDialect.cpp')
-rw-r--r-- | libyul/backends/evm/EVMDialect.cpp | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp new file mode 100644 index 00000000..33ee19d4 --- /dev/null +++ b/libyul/backends/evm/EVMDialect.cpp @@ -0,0 +1,141 @@ +/* + 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/>. +*/ +/** + * Yul dialects for EVM. + */ + +#include <libyul/backends/evm/EVMDialect.h> + +#include <libyul/AsmAnalysisInfo.h> +#include <libyul/AsmData.h> +#include <libyul/Object.h> +#include <libyul/backends/evm/AbstractAssembly.h> + +#include <liblangutil/Exceptions.h> + +#include <libyul/Exceptions.h> + +#include <boost/range/adaptor/reversed.hpp> + +using namespace std; +using namespace dev; +using namespace yul; +using namespace dev::solidity; + + +EVMDialect::EVMDialect(AsmFlavour _flavour, bool _objectAccess): + Dialect(_flavour), m_objectAccess(_objectAccess) +{ + // The EVM instructions will be moved to builtins at some point. + if (!m_objectAccess) + return; + + addFunction("datasize", 1, 1, true, [this]( + FunctionCall const& _call, + AbstractAssembly& _assembly, + std::function<void()> + ) { + yulAssert(m_currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulString dataName = boost::get<Literal>(arg).value; + if (m_currentObject->name == dataName) + _assembly.appendAssemblySize(); + else + _assembly.appendDataSize(m_subIDs.at(dataName)); + }); + addFunction("dataoffset", 1, 1, true, [this]( + FunctionCall const& _call, + AbstractAssembly& _assembly, + std::function<void()> + ) { + yulAssert(m_currentObject, "No object available."); + yulAssert(_call.arguments.size() == 1, ""); + Expression const& arg = _call.arguments.front(); + YulString dataName = boost::get<Literal>(arg).value; + if (m_currentObject->name == dataName) + _assembly.appendConstant(0); + else + _assembly.appendDataOffset(m_subIDs.at(dataName)); + }); + addFunction("datacopy", 3, 0, false, []( + FunctionCall const&, + AbstractAssembly& _assembly, + std::function<void()> _visitArguments + ) { + _visitArguments(); + _assembly.appendInstruction(solidity::Instruction::CODECOPY); + }); +} + +BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const +{ + auto it = m_functions.find(_name); + if (it != m_functions.end()) + return &it->second; + else + return nullptr; +} + +shared_ptr<EVMDialect> EVMDialect::looseAssemblyForEVM() +{ + return make_shared<EVMDialect>(AsmFlavour::Loose, false); +} + +shared_ptr<EVMDialect> EVMDialect::strictAssemblyForEVM() +{ + return make_shared<EVMDialect>(AsmFlavour::Strict, false); +} + +shared_ptr<EVMDialect> EVMDialect::strictAssemblyForEVMObjects() +{ + return make_shared<EVMDialect>(AsmFlavour::Strict, true); +} + +shared_ptr<yul::EVMDialect> EVMDialect::yulForEVM() +{ + return make_shared<EVMDialect>(AsmFlavour::Yul, false); +} + +void EVMDialect::setSubIDs(map<YulString, AbstractAssembly::SubID> _subIDs) +{ + yulAssert(m_objectAccess, "Sub IDs set with dialect that does not support object access."); + m_subIDs = std::move(_subIDs); +} + +void EVMDialect::setCurrentObject(Object const* _object) +{ + yulAssert(m_objectAccess, "Current object set with dialect that does not support object access."); + m_currentObject = _object; +} + +void EVMDialect::addFunction( + string _name, + size_t _params, + size_t _returns, + bool _movable, + std::function<void(FunctionCall const&, AbstractAssembly&, std::function<void()>)> _generateCode +) +{ + YulString name{std::move(_name)}; + BuiltinFunctionForEVM& f = m_functions[name]; + f.name = name; + f.parameters.resize(_params); + f.returns.resize(_returns); + f.movable = _movable; + f.generateCode = std::move(_generateCode); +} |