diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 12d2866c2..65269e9e0 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -154,6 +154,8 @@ add_library(yul optimiser/Suite.h optimiser/SyntacticalEquality.cpp optimiser/SyntacticalEquality.h + optimiser/TypeInfo.cpp + optimiser/TypeInfo.h optimiser/UnusedPruner.cpp optimiser/UnusedPruner.h optimiser/VarDeclInitializer.cpp diff --git a/libyul/optimiser/TypeInfo.cpp b/libyul/optimiser/TypeInfo.cpp new file mode 100644 index 000000000..4b5715baa --- /dev/null +++ b/libyul/optimiser/TypeInfo.cpp @@ -0,0 +1,98 @@ +/* + 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 . +*/ +/** + * Helper class that keeps track of the types while performing optimizations. + */ + +#include + +#include + +#include +#include + +#include + +using namespace std; +using namespace solidity::yul; +using namespace solidity::util; + +class TypeInfo::TypeCollector: public ASTWalker +{ +public: + explicit TypeCollector(Block const& _block) + { + (*this)(_block); + } + + using ASTWalker::operator(); + void operator()(VariableDeclaration const& _varDecl) override + { + for (auto const& var: _varDecl.variables) + variableTypes[var.name] = var.type; + } + void operator()(FunctionDefinition const& _funDef) override + { + ASTWalker::operator()(_funDef); + + auto& funType = functionTypes[_funDef.name]; + for (auto const arg: _funDef.parameters) + { + funType.parameters.emplace_back(arg.type); + variableTypes[arg.name] = arg.type; + } + for (auto const ret: _funDef.returnVariables) + { + funType.returns.emplace_back(ret.type); + variableTypes[ret.name] = ret.type; + } + } + + std::map variableTypes; + std::map functionTypes; +}; + + +TypeInfo::TypeInfo(Dialect const& _dialect, Block const& _ast): + m_dialect(_dialect) +{ + TypeCollector types(_ast); + m_functionTypes = std::move(types.functionTypes); + m_variableTypes = std::move(types.variableTypes); +} + +YulString TypeInfo::typeOf(Expression const& _expression) const +{ + return std::visit(GenericVisitor{ + [&](FunctionCall const& _funCall) { + YulString name = _funCall.functionName.name; + vector const* retTypes = nullptr; + if (BuiltinFunction const* fun = m_dialect.builtin(name)) + retTypes = &fun->returns; + else + retTypes = &m_functionTypes.at(name).returns; + yulAssert(retTypes && retTypes->size() == 1, "Call to typeOf for non-single-value expression."); + return retTypes->front(); + }, + [&](Identifier const& _identifier) { + return m_variableTypes.at(_identifier.name); + }, + [&](Literal const& _literal) { + return _literal.type; + } + }, _expression); +} diff --git a/libyul/optimiser/TypeInfo.h b/libyul/optimiser/TypeInfo.h new file mode 100644 index 000000000..deb537ea3 --- /dev/null +++ b/libyul/optimiser/TypeInfo.h @@ -0,0 +1,61 @@ +/* + 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 . +*/ +/** + * Helper class that keeps track of the types while performing optimizations. + */ +#pragma once + +#include +#include + +#include +#include + +namespace solidity::yul +{ +struct Dialect; + +/** + * Helper class that keeps track of the types while performing optimizations. + * + * Only works on disambiguated sources! + */ +class TypeInfo +{ +public: + TypeInfo(Dialect const& _dialect, Block const& _ast); + + void setVariableType(YulString _name, YulString _type) { m_variableTypes[_name] = _type; } + + /// @returns the type of an expression that is assumed to return exactly one value. + YulString typeOf(Expression const& _expression) const; + +private: + class TypeCollector; + + struct FunctionType + { + std::vector parameters; + std::vector returns; + }; + + Dialect const& m_dialect; + std::map m_variableTypes; + std::map m_functionTypes; +}; + +}