From 25c41546ee03f9567d67068dcc636c09367e9a32 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 3 Nov 2021 11:08:45 +0100 Subject: [PATCH] Function reference resolver. --- libyul/CMakeLists.txt | 2 + libyul/FunctionReferenceResolver.cpp | 60 ++++++++++++++++++++++++++++ libyul/FunctionReferenceResolver.h | 48 ++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 libyul/FunctionReferenceResolver.cpp create mode 100644 libyul/FunctionReferenceResolver.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 3c980fbb8..039e24ea9 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -40,6 +40,8 @@ add_library(yul Dialect.cpp Dialect.h Exceptions.h + FunctionReferenceResolver.cpp + FunctionReferenceResolver.h Object.cpp Object.h ObjectParser.cpp diff --git a/libyul/FunctionReferenceResolver.cpp b/libyul/FunctionReferenceResolver.cpp new file mode 100644 index 000000000..5df94237a --- /dev/null +++ b/libyul/FunctionReferenceResolver.cpp @@ -0,0 +1,60 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#include + +#include +#include + +#include + +using namespace std; +using namespace solidity::yul; +using namespace solidity::util; + +FunctionReferenceResolver::FunctionReferenceResolver(Block const& _ast) +{ + (*this)(_ast); + yulAssert(m_scopes.empty()); +} + +void FunctionReferenceResolver::operator()(FunctionCall const& _functionCall) +{ + for (auto&& scope: m_scopes | ranges::views::reverse) + if (FunctionDefinition const** function = util::valueOrNullptr(scope, _functionCall.functionName.name)) + { + m_functionReferences[&_functionCall] = *function; + break; + } + + // If we did not find anything, it was a builtin call. + + ASTWalker::operator()(_functionCall); +} + +void FunctionReferenceResolver::operator()(Block const& _block) +{ + m_scopes.emplace_back(); + for (auto const& statement: _block.statements) + if (auto const* function = get_if(&statement)) + m_scopes.back()[function->name] = function; + + ASTWalker::operator()(_block); + + m_scopes.pop_back(); +} diff --git a/libyul/FunctionReferenceResolver.h b/libyul/FunctionReferenceResolver.h new file mode 100644 index 000000000..8c1385adb --- /dev/null +++ b/libyul/FunctionReferenceResolver.h @@ -0,0 +1,48 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#pragma once + +#include + +namespace solidity::yul +{ + +/** + * Resolves references to user-defined functions in function calls. + * Assumes the code is correct, i.e. does not check for references to be valid or unique. + * + * Be careful not to iterate over the result - it is not deterministic. + */ +class FunctionReferenceResolver: private ASTWalker +{ +public: + explicit FunctionReferenceResolver(Block const& _ast); + std::map const& references() const { return m_functionReferences; } + +private: + using ASTWalker::operator(); + void operator()(FunctionCall const& _functionCall) override; + void operator()(Block const& _block) override; + + std::map m_functionReferences; + std::vector> m_scopes; +}; + + +}