From c9ed11662106276efaddbc18f1b2f14caf49c7fa Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 28 Dec 2020 22:49:14 +0100 Subject: [PATCH] Scoper: Walks Yul AST and assigns scopes This is taken from DataFlowAnalyzer and will be used in the optimizer step MemoryLoadResolver. --- libyul/CMakeLists.txt | 2 + libyul/optimiser/Scoper.cpp | 88 +++++++++++++++++++++++++++++++++++++ libyul/optimiser/Scoper.h | 56 +++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 libyul/optimiser/Scoper.cpp create mode 100644 libyul/optimiser/Scoper.h diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index df7f087e1..a02b3d592 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -160,6 +160,8 @@ add_library(yul optimiser/RedundantAssignEliminator.h optimiser/Rematerialiser.cpp optimiser/Rematerialiser.h + optimiser/Scoper.h + optimiser/Scoper.cpp optimiser/SSAReverser.cpp optimiser/SSAReverser.h optimiser/SSATransform.cpp diff --git a/libyul/optimiser/Scoper.cpp b/libyul/optimiser/Scoper.cpp new file mode 100644 index 000000000..48647ce32 --- /dev/null +++ b/libyul/optimiser/Scoper.cpp @@ -0,0 +1,88 @@ +/* + 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 + +#include + +#include + +using namespace solidity::yul; +using namespace solidity::util; +using namespace std; + +void Scoper::operator()(VariableDeclaration& _varDecl) +{ + set names; + for (auto const& var: _varDecl.variables) + names.emplace(var.name); + m_variableScopes.back().variables += names; + + ASTModifier::operator()(_varDecl); +} + +void Scoper::operator()(FunctionDefinition& _fun) +{ + pushScope(true); + for (auto const& parameter: _fun.parameters) + m_variableScopes.back().variables.emplace(parameter.name); + for (auto const& var: _fun.returnVariables) + { + m_variableScopes.back().variables.emplace(var.name); + } + + ASTModifier::operator()(_fun); + + popScope(); +} + +void Scoper::operator()(Block& _block) +{ + size_t numScopes = m_variableScopes.size(); + pushScope(false); + ASTModifier::operator()(_block); + popScope(); + yulAssert(numScopes == m_variableScopes.size(), ""); +} + +void Scoper::pushScope(bool _functionScope) +{ + m_variableScopes.emplace_back(_functionScope); +} + +void Scoper::popScope() +{ + m_variableScopes.pop_back(); +} + +bool Scoper::inScope(YulString _variableName) const +{ + for (auto const& scope: m_variableScopes | boost::adaptors::reversed) + { + if (scope.variables.count(_variableName)) + return true; + if (scope.isFunction) + return false; + } + return false; +} diff --git a/libyul/optimiser/Scoper.h b/libyul/optimiser/Scoper.h new file mode 100644 index 000000000..a5dd679a1 --- /dev/null +++ b/libyul/optimiser/Scoper.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 . +*/ +// SPDX-License-Identifier: GPL-3.0 +/** + * Base class that assigns scope to Yul AST + */ +#include + +#include + +namespace solidity::yul +{ + +class Scoper: public ASTModifier +{ +public: + using ASTModifier::operator(); + + void operator()(VariableDeclaration& _varDecl) override; + void operator()(FunctionDefinition& _fun) override; + void operator()(Block& _block) override; + +protected: + /// Returns true iff the variable is in scope. + bool inScope(YulString _variableName) const; + + /// Creates a new inner scope. + void pushScope(bool _functionScope); + /// Removes the innermost scope and clears all variables in it. + virtual void popScope(); + + struct Scope + { + explicit Scope(bool _isFunction): isFunction(_isFunction) {} + std::set variables; + bool isFunction; + }; + + std::vector m_variableScopes; +}; + +}