From fc7518e399d4285c560e32ac2ba41706bf067a5b Mon Sep 17 00:00:00 2001 From: clonker Date: Fri, 5 Jul 2024 10:24:59 +0200 Subject: [PATCH 01/15] Yul: YulNameRepository proxying a dialect --- libyul/CMakeLists.txt | 2 + libyul/Dialect.h | 2 + libyul/YulName.cpp | 432 +++++++++++++++++++++++++++++ libyul/YulName.h | 202 ++++++++++++++ libyul/backends/evm/EVMDialect.cpp | 9 + libyul/backends/evm/EVMDialect.h | 2 + test/CMakeLists.txt | 1 + test/libyul/YulName.cpp | 164 +++++++++++ 8 files changed, 814 insertions(+) create mode 100644 libyul/YulName.cpp create mode 100644 libyul/YulName.h create mode 100644 test/libyul/YulName.cpp diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 92b03facfe93..b074fc4853a8 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -38,6 +38,8 @@ add_library(yul Utilities.cpp Utilities.h YulString.h + YulName.cpp + YulName.h backends/evm/AbstractAssembly.h backends/evm/AsmCodeGen.cpp backends/evm/AsmCodeGen.h diff --git a/libyul/Dialect.h b/libyul/Dialect.h index e3f270357f91..9f3cd22d1f24 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -91,6 +91,8 @@ struct Dialect virtual Literal zeroLiteralForType(YulString _type) const; virtual Literal trueLiteral() const; + virtual std::set builtinNames() const { return {}; } + virtual std::set fixedFunctionNames() const { return {}; } Dialect() = default; diff --git a/libyul/YulName.cpp b/libyul/YulName.cpp new file mode 100644 index 000000000000..faec03b2bb79 --- /dev/null +++ b/libyul/YulName.cpp @@ -0,0 +1,432 @@ +/* + 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 + +#include + +namespace solidity::yul +{ + +YulNameRepository::YulNameRepository(solidity::yul::Dialect const& _dialect): + m_dialect(_dialect) +{ + { + auto const emptyName = defineName(""); + yulAssert(emptyName == YulNameRepository::emptyName()); + } + + for (auto const& type: _dialect.types) + if (type.empty()) + { + m_indexBoundaries.beginTypes = 0; + m_dialectTypes.emplace_back(emptyName(), type.str()); + } + else + { + m_indexBoundaries.beginTypes = 1; + m_dialectTypes.emplace_back(defineName(type.str()), type.str()); + } + m_indexBoundaries.endTypes = m_index; + m_indexBoundaries.beginBuiltins = m_index; + + auto const& builtinNames = _dialect.builtinNames(); + m_predefined.verbatim = defineName("@ verbatim"); + for (auto const& label: builtinNames) + if (!label.empty()) + { + auto const name = defineName(label); + if (auto const* function = m_dialect.get().builtin(YulString(label))) + m_builtinFunctions[name] = convertBuiltinFunction(name, *function); + } + m_indexBoundaries.endBuiltins = m_index; + + m_predefined.boolType = nameOfType(_dialect.boolType.str()); + m_predefined.defaultType = nameOfType(_dialect.defaultType.str()); + + auto const predefinedName = [&](std::string const& label) + { + if (builtinNames.count(label) > 0) + return nameOfBuiltin(label); + else + return defineName(label); + }; + m_predefined.dataoffset = predefinedName("dataoffset"); + m_predefined.datasize = predefinedName("datasize"); + m_predefined.selfdestruct = predefinedName("selfdestruct"); + m_predefined.tstore = predefinedName("tstore"); + m_predefined.memoryguard = predefinedName("memoryguard"); + m_predefined.eq = predefinedName("eq"); + m_predefined.add = predefinedName("add"); + m_predefined.sub = predefinedName("sub"); + + { + auto types = m_dialectTypes; + if (types.empty()) + types.emplace_back(0, ""); + + for (auto const& [typeName, typeLabel]: types) + { + if (auto const* discardFunction = m_dialect.get().discardFunction(YulString(typeLabel))) + m_predefinedBuiltinFunctions.discardFunctions.emplace_back(nameOfBuiltin(discardFunction->name.str())); + else + m_predefinedBuiltinFunctions.discardFunctions.emplace_back(std::nullopt); + + if (auto const* equalityFunction = m_dialect.get().equalityFunction(YulString(typeLabel))) + m_predefinedBuiltinFunctions.equalityFunctions.emplace_back(nameOfBuiltin(equalityFunction->name.str())); + else + m_predefinedBuiltinFunctions.equalityFunctions.emplace_back(std::nullopt); + + if (auto const* booleanNegationFunction = m_dialect.get().booleanNegationFunction()) + m_predefinedBuiltinFunctions.booleanNegationFunction = nameOfBuiltin(booleanNegationFunction->name.str()); + else + m_predefinedBuiltinFunctions.booleanNegationFunction = std::nullopt; + + if (auto const* memStoreFunction = m_dialect.get().memoryStoreFunction(YulString(typeLabel))) + m_predefinedBuiltinFunctions.memoryStoreFunctions.emplace_back(nameOfBuiltin(memStoreFunction->name.str())); + else + m_predefinedBuiltinFunctions.memoryStoreFunctions.emplace_back(std::nullopt); + + if (auto const* memLoadFunction = m_dialect.get().memoryLoadFunction(YulString(typeLabel))) + m_predefinedBuiltinFunctions.memoryLoadFunctions.emplace_back(nameOfBuiltin(memLoadFunction->name.str())); + else + m_predefinedBuiltinFunctions.memoryLoadFunctions.emplace_back(std::nullopt); + + if (auto const* storageStoreFunction = m_dialect.get().storageStoreFunction(YulString(typeLabel))) + m_predefinedBuiltinFunctions.storageStoreFunctions.emplace_back(nameOfBuiltin(storageStoreFunction->name.str())); + else + m_predefinedBuiltinFunctions.storageStoreFunctions.emplace_back(std::nullopt); + + if (auto const* storageLoadFunction = m_dialect.get().storageLoadFunction(YulString(typeLabel))) + m_predefinedBuiltinFunctions.storageLoadFunctions.emplace_back(nameOfBuiltin(storageLoadFunction->name.str())); + else + m_predefinedBuiltinFunctions.storageLoadFunctions.emplace_back(std::nullopt); + + m_predefinedBuiltinFunctions.hashFunctions.emplace_back(nameOfBuiltin(m_dialect.get().hashFunction(YulString(typeLabel)).str())); + } + } + + m_predefined.placeholder_zero = defineName("@ 0"); + m_predefined.placeholder_one = defineName("@ 1"); + m_predefined.placeholder_thirtytwo = defineName("@ 32"); +} + +YulNameRepository::BuiltinFunction const* YulNameRepository::builtin(YulName const _name) const +{ + yulAssert(nameWithinBounds(_name), "YulName exceeds repository size, probably stems from another instance."); + auto const baseName = baseNameOf(_name); + if (isBuiltinName(baseName)) + { + auto const it = m_builtinFunctions.find(_name); + if (it != m_builtinFunctions.end()) + return &it->second; + } + return nullptr; +} + +std::optional YulNameRepository::labelOf(YulName const _name) const +{ + yulAssert(nameWithinBounds(_name), "YulName exceeds repository size, probably stems from another instance."); + if (!isDerivedName(_name)) + { + // if the parent is directly a defined label, we take that one + yulAssert(std::get<0>(m_names[_name]) < m_definedLabels.size()); + return m_definedLabels[std::get<0>(m_names[_name])]; + } + if (isVerbatimFunction(_name)) + { + auto const* builtinFun = builtin(_name); + yulAssert(builtinFun); + return builtinFun->data->name.str(); + } + return std::nullopt; +} + +YulNameRepository::YulName YulNameRepository::baseNameOf(YulName _name) const +{ + yulAssert(nameWithinBounds(_name), "YulName exceeds repository size, probably stems from another instance."); + while (isDerivedName(_name)) + _name = std::get<0>(m_names[_name]); + return _name; +} + +std::string_view YulNameRepository::baseLabelOf(YulName const _name) const +{ + yulAssert(nameWithinBounds(_name), "YulName exceeds repository size, probably stems from another instance."); + return m_definedLabels[std::get<0>(m_names[baseNameOf(_name)])]; +} + +YulNameRepository::BuiltinFunction const* YulNameRepository::fetchTypedPredefinedFunction(YulName const _type, std::vector> const& _functions) const +{ + yulAssert(nameWithinBounds(_type), "Type exceeds repository size, probably stems from another instance."); + auto const typeIndex = indexOfType(_type); + yulAssert(typeIndex < _functions.size()); + auto const& functionName = _functions[typeIndex]; + if (!functionName) + return nullptr; + return builtin(*functionName); +} + +YulNameRepository::BuiltinFunction const* YulNameRepository::discardFunction(YulName const _type) const +{ + return fetchTypedPredefinedFunction(_type, m_predefinedBuiltinFunctions.discardFunctions); +} + +YulNameRepository::BuiltinFunction const* YulNameRepository::equalityFunction(YulName const _type) const +{ + return fetchTypedPredefinedFunction(_type, m_predefinedBuiltinFunctions.equalityFunctions); +} + +YulNameRepository::BuiltinFunction const* YulNameRepository::booleanNegationFunction() const +{ + if (!m_predefinedBuiltinFunctions.booleanNegationFunction) + return nullptr; + return builtin(*m_predefinedBuiltinFunctions.booleanNegationFunction); +} + +YulNameRepository::BuiltinFunction const* YulNameRepository::memoryLoadFunction(YulName const _type) const +{ + return fetchTypedPredefinedFunction(_type, m_predefinedBuiltinFunctions.memoryLoadFunctions); +} + +YulNameRepository::BuiltinFunction const* YulNameRepository::memoryStoreFunction(YulName const _type) const +{ + return fetchTypedPredefinedFunction(_type, m_predefinedBuiltinFunctions.memoryStoreFunctions); +} + +YulNameRepository::BuiltinFunction const* YulNameRepository::storageLoadFunction(YulName _type) const +{ + return fetchTypedPredefinedFunction(_type, m_predefinedBuiltinFunctions.storageLoadFunctions); +} + +YulNameRepository::BuiltinFunction const* YulNameRepository::storageStoreFunction(YulName const _type) const +{ + return fetchTypedPredefinedFunction(_type, m_predefinedBuiltinFunctions.storageStoreFunctions); +} + +YulName YulNameRepository::hashFunction(YulName const _type) const +{ + yulAssert(nameWithinBounds(_type), "Type exceeds repository size, probably stems from another instance."); + auto const typeIndex = indexOfType(_type); + return m_predefinedBuiltinFunctions.hashFunctions[typeIndex]; +} + +bool YulNameRepository::isBuiltinName(YulName const _name) const +{ + yulAssert(nameWithinBounds(_name), "YulName exceeds repository size, probably stems from another instance."); + auto const baseName = baseNameOf(_name); + return baseName >= m_indexBoundaries.beginBuiltins && baseName < m_indexBoundaries.endBuiltins; +} + +YulNameRepository::BuiltinFunction YulNameRepository::convertBuiltinFunction(YulName const _name, yul::BuiltinFunction const& _builtin) const +{ + yulAssert(nameWithinBounds(_name), "YulName exceeds repository size, probably stems from another instance."); + BuiltinFunction result; + result.name = _name; + for (auto const& type: _builtin.parameters) + result.parameters.push_back(nameOfType(type.str())); + for (auto const& type: _builtin.returns) + result.returns.push_back(nameOfType(type.str())); + result.data = &_builtin; + return result; +} + +YulName YulNameRepository::nameOfLabel(std::string_view const label) const +{ + auto const it = std::find(m_definedLabels.begin(), m_definedLabels.end(), label); + if (it != m_definedLabels.end()) + { + auto const labelIndex = static_cast(std::distance(m_definedLabels.begin(), it)); + // mostly it'll be iota + if (!isDerivedName(labelIndex) && std::get<0>(m_names[labelIndex]) == static_cast(labelIndex)) + return labelIndex; + // if not iota, we have to search + auto itName = std::find(m_names.rbegin(), m_names.rend(), std::make_tuple(labelIndex, YulNameState::DEFINED)); + if (itName != m_names.rend()) + return YulName{static_cast(std::distance(itName, m_names.rend())) - 1}; + } + return emptyName(); +} + +YulName YulNameRepository::nameOfBuiltin(std::string_view const builtin) const +{ + for (size_t i = m_indexBoundaries.beginBuiltins; i < m_indexBoundaries.endBuiltins; ++i) + if (baseLabelOf(std::get<0>(m_names[i])) == builtin) + return i; + return emptyName(); +} + +YulName YulNameRepository::nameOfType(std::string_view const _type) const +{ + if (!m_dialectTypes.empty()) + { + for (auto const& m_dialectType: m_dialectTypes) + if (std::get<1>(m_dialectType) == _type) + return std::get<0>(m_dialectType); + yulAssert(false, "only defined for (some) dialect types"); + } + else + return emptyName(); +} + +size_t YulNameRepository::indexOfType(YulName const _type) const +{ + if (m_dialectTypes.empty()) + return 0; + auto const it = std::find_if(m_dialectTypes.begin(), m_dialectTypes.end(), [&](auto const& element) { return std::get<0>(element) == _type; }); + yulAssert(it != m_dialectTypes.end(), "tried to get index of unknown type"); + return static_cast(std::distance(m_dialectTypes.begin(), it)); +} + +Dialect const& YulNameRepository::dialect() const +{ + return m_dialect; +} + +bool YulNameRepository::isVerbatimFunction(YulName const _name) const +{ + yulAssert(nameWithinBounds(_name), "YulName exceeds repository size, probably stems from another instance."); + return baseNameOf(_name) == predefined().verbatim; +} + +YulName YulNameRepository::defineName(std::string_view const _label) +{ + if (auto const* builtin = m_dialect.get().builtin(YulString(std::string(_label)))) + { + if (builtin->name.str().substr(0, std::string_view("verbatim").size()) == "verbatim") + { + auto const key = std::make_tuple(builtin->parameters.size(), builtin->returns.size()); + auto [it, emplaced] = m_verbatimNames.try_emplace(key); + if (emplaced) + { + it->second = deriveName(predefined().verbatim); + m_builtinFunctions[it->second] = convertBuiltinFunction(it->second, *builtin); + } + return it->second; + } + else + { + auto const builtinName = nameOfBuiltin(_label); + if (builtinName == emptyName()) + { + m_definedLabels.emplace_back(_label); + m_names.emplace_back(m_definedLabels.size() - 1, YulNameState::DEFINED); + return m_index++; + } + else + return builtinName; + } + } + else + { + if (auto const name = nameOfLabel(_label); name != emptyName()) + return name; + + m_definedLabels.emplace_back(_label); + m_names.emplace_back(m_definedLabels.size() - 1, YulNameState::DEFINED); + return m_index++; + } +} + +YulName YulNameRepository::deriveName(YulName const _name) +{ + yulAssert(nameWithinBounds(_name), "YulName exceeds repository size, probably stems from another instance."); + m_names.emplace_back(_name, YulNameState::DERIVED); + return m_index++; +} + +YulName YulNameRepository::addGhost() +{ + return defineName(fmt::format(FMT_COMPILE("GHOST[{}]"), m_nGhosts++)); +} + +bool YulNameRepository::isType(YulName const _name) const { + return _name >= m_indexBoundaries.beginTypes && _name < m_indexBoundaries.endTypes; +} + +size_t YulNameRepository::nTypes() const +{ + return m_indexBoundaries.endTypes - m_indexBoundaries.beginTypes; +} + +bool YulNameRepository::isEvmDialect() const { return dynamic_cast(&m_dialect.get()) != nullptr; } + +void YulNameRepository::generateLabels(std::set const& _usedNames, std::set const& _illegal) +{ + std::set used (m_definedLabels.begin(), m_definedLabels.begin() + static_cast(m_indexBoundaries.endBuiltins)); + std::set toDerive; + for (auto const name: _usedNames) + if (!isDerivedName(name) || isVerbatimFunction(name)) + { + auto const label = labelOf(name); + yulAssert(label.has_value()); + auto const [_, emplaced] = used.emplace(*label); + if (!emplaced) + { + // there's been a clash (eg by calling generate labels twice), let's remove this name and derive + // it instead + toDerive.insert(name); + } + } + + std::vector> generated; + auto namesIt = _usedNames.begin(); + for (size_t name = m_indexBoundaries.endBuiltins; name < m_names.size(); ++name) + { + if (namesIt != _usedNames.end() && name == *namesIt) + { + if ((isDerivedName(name) && !isVerbatimFunction(name)) || toDerive.find(name) != toDerive.end()) + { + std::string const baseLabel(baseLabelOf(name)); + std::string label (baseLabel); + size_t bump = 1; + while (used.count(label) > 0 || _illegal.count(label) > 0) + { + label = fmt::format(FMT_COMPILE("{}_{}"), baseLabel, bump++); + } + if (auto const existingDefinedName = nameOfLabel(label); existingDefinedName != emptyName() || name == emptyName()) + m_names[name] = m_names[existingDefinedName]; + else + generated.emplace_back(label, name); + used.insert(label); + } + ++namesIt; + } + } + + for (auto const& [label, name] : generated) + { + m_definedLabels.emplace_back(label); + std::get<0>(m_names[name]) = m_definedLabels.size() - 1; + std::get<1>(m_names[name]) = YulNameState::DEFINED; + } +} + +// commented out for the time being until the AST is refactored to use YulName over YulString +// void YulNameRepository::generateLabels(Block const& _ast, std::set const& _illegal) +// { +// generateLabels(NameCollector(_ast).names(), _illegal); +// } + +} diff --git a/libyul/YulName.h b/libyul/YulName.h new file mode 100644 index 000000000000..7d8a6c0ff9f9 --- /dev/null +++ b/libyul/YulName.h @@ -0,0 +1,202 @@ +/* + 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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace solidity::yul +{ + +enum class LiteralKind; +struct Dialect; +struct Block; +struct BuiltinFunction; + +class YulNameRepository +{ +public: + using YulName = size_t; + + /// Decorating a yul dialect builtin function with `YulName`s. + struct BuiltinFunction + { + YulName name; + std::vector parameters; + std::vector returns; + + yul::BuiltinFunction const* data; + }; + + struct PredefinedHandles + { + YulName empty {}; + YulName verbatim {}; + YulName boolType {}; + YulName hashFunction {}; + YulName datasize {}; + YulName dataoffset {}; + YulName selfdestruct {}; + YulName memoryguard {}; + YulName eq {}; + YulName add {}; + YulName sub {}; + YulName tstore {}; + YulName defaultType {}; + YulName placeholder_zero {}; + YulName placeholder_one {}; + YulName placeholder_thirtytwo {}; + }; + + /// Construct via dialect. It is important that the dialect instance lives at least as long as the name repository + /// instance. + explicit YulNameRepository(Dialect const& _dialect); + ~YulNameRepository() = default; + YulNameRepository(YulNameRepository&&) = default; + YulNameRepository& operator=(YulNameRepository&&) = default; + YulNameRepository(YulNameRepository const&) = default; + YulNameRepository& operator=(YulNameRepository const&) = default; + + /// Defines a new name based on a label. If the label already was defined, it returns the corresponding YulName + /// instead of a new one. + YulName defineName(std::string_view _label); + + /// Defines a new name based on a parent name. When generating labels, the generated label will be based on the + /// parent's. + YulName deriveName(YulName _id); + + /// Adds a ghost name. + YulName addGhost(); + + /// The empty name. + static constexpr YulName emptyName() { return 0; } + + /// Yields the label of a yul name. The name must have been added via ``defineName``, a label must have been + /// generated with ``generateLabels``, or it is a builtin. + std::optional labelOf(YulName _name) const; + + /// Yields the name that the provided name was based on - or the name itself, if the name was directly "defined". + YulName baseNameOf(YulName _name) const; + + /// Yields the label of the base name of the provided name. Opposed to ``labelOf``, this must always exist. + std::string_view baseLabelOf(YulName _name) const; + + /// Whether a name is considered derived, i.e., has no label but a parent name. + bool isDerivedName(YulName const _name) const { return std::get<1>(m_names[_name]) == YulNameState::DERIVED; } + + /// Whether a name corresponds to a verbatim builtin function. + bool isVerbatimFunction(YulName _name) const; + + /// A couple of predefined names. + PredefinedHandles const& predefined() const { return m_predefined; } + + /// Functionality that decorates a yul dialect based on YulNames (ids). + [[nodiscard]] BuiltinFunction const* builtin(YulName _name) const; + bool isBuiltinName(YulName _name) const; + + BuiltinFunction const* discardFunction(YulName _type) const; + BuiltinFunction const* equalityFunction(YulName _type) const; + BuiltinFunction const* booleanNegationFunction() const; + + BuiltinFunction const* memoryStoreFunction(YulName _type) const; + BuiltinFunction const* memoryLoadFunction(YulName _type) const; + BuiltinFunction const* storageStoreFunction(YulName _type) const; + BuiltinFunction const* storageLoadFunction(YulName _type) const; + YulName hashFunction(YulName _type) const; + + /// Tries to find the label in the defined names and returns the corresponding name. If not found, ``emptyName``. + YulName nameOfLabel(std::string_view label) const; + + /// Same as nameOfLabel, but restricted to builtins and therefore computationally more efficient. + YulName nameOfBuiltin(std::string_view builtin) const; + + /// Same as nameOfLabel, but restricted to types and therefore computationally more efficient. + YulName nameOfType(std::string_view type) const; + + /// Whether the name is corresponding to a type. + bool isType(YulName _name) const; + + /// Number of types. If the dialect is untyped, there is still one type (the "empty type" type) + size_t nTypes() const; + + Dialect const& dialect() const; + + bool isEvmDialect() const; + + /// Generates labels for derived names over the set of _usedNames, respecting a set of _illegal labels. + /// This will change the state of all derived names in _usedNames to "not derived" with a label associated to them. + void generateLabels(std::set const& _usedNames, std::set const& _illegal = {}); + + // commented out for the time being, as it requires AST refactoring to be YulName-based + // void generateLabels(Block const& _ast, std::set const& _illegal = {}); + +private: + struct PredefinedBuiltinFunctions + { + std::vector> discardFunctions; + std::vector> equalityFunctions; + std::optional booleanNegationFunction; + std::vector> memoryStoreFunctions; + std::vector> memoryLoadFunctions; + std::vector> storageStoreFunctions; + std::vector> storageLoadFunctions; + std::vector hashFunctions; + }; + struct IndexBoundaries + { + size_t beginTypes {}; + size_t endTypes {}; + size_t beginBuiltins {}; + size_t endBuiltins {}; + }; + enum class YulNameState { DERIVED, DEFINED }; + bool nameWithinBounds(YulName const _name) const { return _name < m_index; } + + size_t indexOfType(YulName _type) const; + BuiltinFunction convertBuiltinFunction(YulName _name, yul::BuiltinFunction const& _builtin) const; + BuiltinFunction const* fetchTypedPredefinedFunction(YulName _type, std::vector> const& _functions) const; + + std::reference_wrapper m_dialect; + std::vector> m_dialectTypes; + std::map m_builtinFunctions; + + PredefinedBuiltinFunctions m_predefinedBuiltinFunctions; + + size_t m_index {0}; + size_t m_nGhosts {0}; + std::vector m_definedLabels {}; + std::vector> m_names {}; + std::map, YulName> m_verbatimNames {}; + PredefinedHandles m_predefined{}; + IndexBoundaries m_indexBoundaries; +}; +using YulName = YulNameRepository::YulName; + +} diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 856689c91ad4..463bd458837f 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -35,6 +35,8 @@ #include #include +#include +#include #include @@ -462,6 +464,13 @@ BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, siz return function.get(); } +std::set EVMDialect::builtinNames() const { + static std::array verbatim {YulString("verbatim")}; + auto const keys = ranges::views::concat(ranges::views::keys(m_functions), verbatim) + | ranges::views::transform([](auto const& name) { return name.str(); }); + return { keys.begin(), keys.end() }; +} + EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess): EVMDialect(_evmVersion, _objectAccess) { diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 28649f3e5e90..3ae23b7a1674 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -93,6 +93,8 @@ struct EVMDialect: public Dialect static SideEffects sideEffectsOfInstruction(evmasm::Instruction _instruction); + std::set builtinNames() const override; + protected: BuiltinFunctionForEVM const* verbatimFunction(size_t _arguments, size_t _returnVariables) const; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d5435237ec7b..7bd4b4fb2989 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -158,6 +158,7 @@ set(libyul_sources libyul/SyntaxTest.cpp libyul/YulInterpreterTest.cpp libyul/YulInterpreterTest.h + libyul/YulName.cpp libyul/YulOptimizerTest.cpp libyul/YulOptimizerTest.h libyul/YulOptimizerTestCommon.cpp diff --git a/test/libyul/YulName.cpp b/test/libyul/YulName.cpp new file mode 100644 index 000000000000..6c7238799853 --- /dev/null +++ b/test/libyul/YulName.cpp @@ -0,0 +1,164 @@ +/* + 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 + +using namespace solidity; +using namespace solidity::yul; + +namespace solidity::yul::test +{ + +BOOST_AUTO_TEST_SUITE(YulName) + +BOOST_AUTO_TEST_CASE(repository_with_blank_dialect) +{ + Dialect dialect{}; + YulNameRepository nameRepository(dialect); + BOOST_CHECK(!nameRepository.isEvmDialect()); + BOOST_CHECK(nameRepository.nTypes() == 1); + nameRepository.isType(YulNameRepository::emptyName()); + BOOST_CHECK(nameRepository.labelOf(nameRepository.predefined().empty).value().empty()); + BOOST_CHECK(nameRepository.labelOf(nameRepository.predefined().datasize) == "datasize"); + BOOST_CHECK(nameRepository.labelOf(nameRepository.predefined().dataoffset) == "dataoffset"); + BOOST_CHECK(nameRepository.labelOf(nameRepository.predefined().selfdestruct) == "selfdestruct"); + BOOST_CHECK(nameRepository.labelOf(nameRepository.predefined().memoryguard) == "memoryguard"); + BOOST_CHECK(nameRepository.labelOf(nameRepository.predefined().eq) == "eq"); + BOOST_CHECK(nameRepository.labelOf(nameRepository.predefined().add) == "add"); + BOOST_CHECK(nameRepository.labelOf(nameRepository.predefined().sub) == "sub"); +} + +BOOST_AUTO_TEST_CASE(repository_generate_labels_for_derived_types) +{ + Dialect dialect{}; + YulNameRepository nameRepository(dialect); + auto const test1 = nameRepository.defineName("test1"); + BOOST_CHECK(!nameRepository.isDerivedName(test1)); + auto const test1_1 = nameRepository.deriveName(test1); + BOOST_CHECK(nameRepository.isDerivedName(test1_1)); + auto const test1_2 = nameRepository.deriveName(test1); + BOOST_CHECK(nameRepository.isDerivedName(test1_2)); + auto const test1_2_1 = nameRepository.deriveName(test1_2); + BOOST_CHECK(nameRepository.isDerivedName(test1_2_1)); + auto const test2 = nameRepository.defineName("test2_1"); + auto const test2_1 = nameRepository.deriveName(test2); + auto const test3 = nameRepository.defineName("test3"); + auto const test3_1 = nameRepository.deriveName(test3); + nameRepository.generateLabels({test1, test1_1, test1_2, test1_2_1, test2_1, test3, test3_1}); + + BOOST_CHECK(nameRepository.labelOf(test1) == "test1"); + BOOST_CHECK(nameRepository.labelOf(test1_1) == "test1_1"); + BOOST_CHECK(nameRepository.labelOf(test1_2) == "test1_2"); + BOOST_CHECK(nameRepository.labelOf(test1_2_1) == "test1_3"); + + BOOST_CHECK(nameRepository.labelOf(test2) == "test2_1"); + // the label of test2 is reused as it's not in the used names when generating labels + BOOST_CHECK(nameRepository.labelOf(test2_1) == "test2_1"); + + BOOST_CHECK(nameRepository.labelOf(test3) == "test3"); + BOOST_CHECK(nameRepository.labelOf(test3_1) == "test3_1"); + + // derive a name from the (now labelled) test2_1 name + auto const test2_1_1 = nameRepository.deriveName(test2_1); + // but we have a conflict with an already defined/labelled name, expectation is that we get test2_1_2 + auto const conflict = nameRepository.defineName("test2_1_1"); + nameRepository.generateLabels({test1, test1_1, test1_2, test1_2_1, test2_1, test2_1_1, test3, test3_1, conflict}); + // test2_1 is in the list, so produce a new name + BOOST_CHECK(nameRepository.labelOf(test2_1_1) == "test2_1_2"); + BOOST_CHECK(nameRepository.labelOf(conflict) == "test2_1_1"); + + nameRepository.generateLabels({test2, test2_1, test2_1_1, conflict}); + BOOST_CHECK(nameRepository.labelOf(test2) == "test2_1"); + // this label gets reassigned, as test2_1 is back in the game + BOOST_CHECK(nameRepository.labelOf(test2_1) == "test2_1_3"); + BOOST_CHECK(nameRepository.labelOf(test2_1_1) == "test2_1_2"); + BOOST_CHECK(nameRepository.labelOf(conflict) == "test2_1_1"); + +} + +BOOST_AUTO_TEST_CASE(repository_with_evm_dialect) +{ + auto const& dialect = EVMDialect::strictAssemblyForEVM({}); + YulNameRepository nameRepository(dialect); + BOOST_CHECK(nameRepository.isEvmDialect()); + BOOST_CHECK(nameRepository.nTypes() == 1); + BOOST_CHECK(nameRepository.isType(YulNameRepository::emptyName())); + + auto const extractEVMFunction = [](auto const* function) { return function ? function->data : nullptr; }; + auto const type = YulNameRepository::emptyName(); + YulString typeLabel(std::string(nameRepository.labelOf(type).value())); + BOOST_CHECK(extractEVMFunction(nameRepository.discardFunction(type)) == dialect.discardFunction(typeLabel)); + BOOST_CHECK(extractEVMFunction(nameRepository.equalityFunction(type)) == dialect.equalityFunction(typeLabel));; + BOOST_CHECK(extractEVMFunction(nameRepository.booleanNegationFunction()) == dialect.booleanNegationFunction()); + BOOST_CHECK(extractEVMFunction(nameRepository.memoryStoreFunction(type)) == dialect.memoryStoreFunction(typeLabel)); + BOOST_CHECK(extractEVMFunction(nameRepository.memoryLoadFunction(type)) == dialect.memoryLoadFunction(typeLabel)); + BOOST_CHECK(extractEVMFunction(nameRepository.storageStoreFunction(type)) == dialect.storageStoreFunction(typeLabel)); + BOOST_CHECK(extractEVMFunction(nameRepository.storageLoadFunction(type)) == dialect.storageLoadFunction(typeLabel)); + BOOST_CHECK(nameRepository.labelOf(nameRepository.hashFunction(type)) == dialect.hashFunction(typeLabel).str()); +} + +BOOST_AUTO_TEST_CASE(repository_with_typed_evm_dialect) +{ + auto const& dialect = EVMDialectTyped::instance({}); + YulNameRepository nameRepository(dialect); + BOOST_CHECK(nameRepository.isEvmDialect()); + auto const wordType = nameRepository.nameOfType("u256"); + auto const boolType = nameRepository.nameOfType("bool"); + BOOST_CHECK(nameRepository.labelOf(wordType) == "u256"); + BOOST_CHECK(nameRepository.labelOf(boolType) == "bool"); + BOOST_CHECK(nameRepository.isType(wordType)); + BOOST_CHECK(nameRepository.isType(boolType)); + BOOST_CHECK(!nameRepository.isType(YulNameRepository::emptyName())); + BOOST_CHECK(nameRepository.nTypes() == 2); + + auto const extractEVMFunction = [](auto const* function) { return function ? function->data : nullptr; }; + + for (auto const type : {wordType, boolType}) + { + YulString typeLabel(std::string(nameRepository.labelOf(type).value())); + BOOST_CHECK(extractEVMFunction(nameRepository.discardFunction(type)) == dialect.discardFunction(typeLabel)); + BOOST_CHECK(extractEVMFunction(nameRepository.equalityFunction(type)) == dialect.equalityFunction(typeLabel)); + BOOST_CHECK(extractEVMFunction(nameRepository.booleanNegationFunction()) == dialect.booleanNegationFunction()); + BOOST_CHECK(extractEVMFunction(nameRepository.memoryStoreFunction(type)) == dialect.memoryStoreFunction(typeLabel)); + BOOST_CHECK(extractEVMFunction(nameRepository.memoryLoadFunction(type)) == dialect.memoryLoadFunction(typeLabel)); + BOOST_CHECK(extractEVMFunction(nameRepository.storageStoreFunction(type)) == dialect.storageStoreFunction(typeLabel)); + BOOST_CHECK(extractEVMFunction(nameRepository.storageLoadFunction(type)) == dialect.storageLoadFunction(typeLabel)); + BOOST_CHECK(nameRepository.labelOf(nameRepository.hashFunction(type)) == dialect.hashFunction(typeLabel).str()); + } +} + +BOOST_AUTO_TEST_CASE(verbatim_functions) +{ + auto const& dialect = EVMDialect::strictAssemblyForEVMObjects({}); + YulNameRepository nameRepository(dialect); + auto const verbatimName = nameRepository.defineName("verbatim_5i_3o"); + BOOST_CHECK(verbatimName != YulNameRepository::emptyName()); + BOOST_CHECK(nameRepository.isBuiltinName(verbatimName)); + BOOST_CHECK(nameRepository.isDerivedName(verbatimName)); + BOOST_CHECK(nameRepository.baseNameOf(verbatimName) == nameRepository.predefined().verbatim); + BOOST_CHECK(nameRepository.builtin(verbatimName)->data == dialect.builtin(YulString{"verbatim_5i_3o"})); +} + +BOOST_AUTO_TEST_SUITE_END() + +} From a2cb5f4ee961921ccfff18f2b94a0adadbc15a23 Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 19 Jun 2024 13:31:57 +0200 Subject: [PATCH 02/15] YulNameRepository with node id handles --- Changelog.md | 1 + libsolidity/analysis/ControlFlowBuilder.cpp | 8 +- libsolidity/analysis/PostTypeChecker.cpp | 8 +- libsolidity/analysis/ReferencesResolver.cpp | 37 +-- libsolidity/analysis/ReferencesResolver.h | 3 +- libsolidity/analysis/SyntaxChecker.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/analysis/ViewPureChecker.cpp | 16 +- libsolidity/ast/AST.cpp | 20 ++ libsolidity/ast/AST.h | 16 +- libsolidity/ast/ASTJsonExporter.cpp | 6 +- libsolidity/ast/ASTJsonImporter.cpp | 5 +- libsolidity/codegen/CompilerContext.cpp | 38 +-- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/codegen/ContractCompiler.cpp | 7 +- .../codegen/ir/IRGeneratorForStatements.cpp | 18 +- .../experimental/analysis/TypeInference.cpp | 2 +- .../codegen/IRGeneratorForStatements.cpp | 18 +- libsolidity/formal/SMTEncoder.cpp | 2 +- libsolidity/interface/CompilerStack.cpp | 5 +- libsolidity/interface/CompilerStack.h | 5 + libsolidity/lsp/RenameSymbol.cpp | 4 +- libsolidity/parsing/Parser.cpp | 5 +- libsolutil/StringUtils.h | 2 +- libyul/AST.h | 11 +- libyul/ASTForward.h | 1 + libyul/AsmAnalysis.cpp | 222 +++++++++-------- libyul/AsmAnalysis.h | 30 +-- libyul/AsmJsonConverter.cpp | 20 +- libyul/AsmJsonConverter.h | 3 +- libyul/AsmJsonImporter.cpp | 11 +- libyul/AsmJsonImporter.h | 7 +- libyul/AsmParser.cpp | 40 ++-- libyul/AsmParser.h | 12 +- libyul/AsmPrinter.cpp | 26 +- libyul/AsmPrinter.h | 28 ++- libyul/CMakeLists.txt | 6 +- libyul/CompilabilityChecker.cpp | 7 +- libyul/CompilabilityChecker.h | 6 +- libyul/ControlFlowSideEffectsCollector.cpp | 12 +- libyul/ControlFlowSideEffectsCollector.h | 6 +- libyul/Dialect.cpp | 48 ++-- libyul/Dialect.h | 50 ++-- libyul/Exceptions.h | 9 +- libyul/FunctionReferenceResolver.h | 2 +- libyul/Object.cpp | 20 +- libyul/Object.h | 19 +- libyul/ObjectParser.cpp | 2 +- libyul/ObjectParser.h | 6 +- libyul/Scope.cpp | 18 +- libyul/Scope.h | 26 +- libyul/ScopeFiller.cpp | 13 +- libyul/ScopeFiller.h | 4 +- libyul/YulName.cpp | 57 +++-- libyul/YulName.h | 14 +- libyul/YulStack.cpp | 63 ++--- libyul/YulStack.h | 17 +- libyul/backends/evm/AsmCodeGen.cpp | 2 + libyul/backends/evm/AsmCodeGen.h | 1 + libyul/backends/evm/ConstantOptimiser.cpp | 55 +++-- libyul/backends/evm/ConstantOptimiser.h | 28 ++- .../backends/evm/ControlFlowGraphBuilder.cpp | 35 ++- libyul/backends/evm/ControlFlowGraphBuilder.h | 10 +- libyul/backends/evm/EVMCodeTransform.cpp | 45 ++-- libyul/backends/evm/EVMCodeTransform.h | 12 +- libyul/backends/evm/EVMDialect.cpp | 220 +++++++++-------- libyul/backends/evm/EVMDialect.h | 41 ++-- libyul/backends/evm/EVMMetrics.cpp | 16 +- libyul/backends/evm/EVMMetrics.h | 10 +- libyul/backends/evm/EVMObjectCompiler.cpp | 10 +- libyul/backends/evm/EVMObjectCompiler.h | 7 +- .../evm/OptimizedEVMCodeTransform.cpp | 41 ++-- .../backends/evm/OptimizedEVMCodeTransform.h | 6 +- libyul/backends/evm/StackHelpers.h | 12 +- libyul/backends/evm/StackLayoutGenerator.cpp | 12 +- libyul/backends/evm/StackLayoutGenerator.h | 6 +- .../backends/evm/VariableReferenceCounter.cpp | 2 +- .../backends/evm/VariableReferenceCounter.h | 2 +- libyul/optimiser/ASTCopier.cpp | 4 +- libyul/optimiser/ASTCopier.h | 10 +- libyul/optimiser/BlockHasher.cpp | 8 +- libyul/optimiser/BlockHasher.h | 4 +- libyul/optimiser/CallGraphGenerator.cpp | 14 +- libyul/optimiser/CallGraphGenerator.h | 8 +- libyul/optimiser/CircularReferencesPruner.cpp | 12 +- libyul/optimiser/CircularReferencesPruner.h | 6 +- .../CommonSubexpressionEliminator.cpp | 18 +- .../optimiser/CommonSubexpressionEliminator.h | 10 +- libyul/optimiser/ConditionalSimplifier.cpp | 12 +- libyul/optimiser/ConditionalSimplifier.h | 10 +- libyul/optimiser/ConditionalUnsimplifier.cpp | 10 +- libyul/optimiser/ConditionalUnsimplifier.h | 10 +- libyul/optimiser/ControlFlowSimplifier.cpp | 26 +- libyul/optimiser/ControlFlowSimplifier.h | 6 +- libyul/optimiser/DataFlowAnalyzer.cpp | 86 ++++--- libyul/optimiser/DataFlowAnalyzer.h | 60 ++--- libyul/optimiser/DeadCodeEliminator.cpp | 6 +- libyul/optimiser/DeadCodeEliminator.h | 10 +- libyul/optimiser/Disambiguator.cpp | 6 +- libyul/optimiser/Disambiguator.h | 19 +- libyul/optimiser/EqualStoreEliminator.cpp | 8 +- libyul/optimiser/EqualStoreEliminator.h | 6 +- libyul/optimiser/EquivalentFunctionCombiner.h | 4 +- libyul/optimiser/EquivalentFunctionDetector.h | 4 +- libyul/optimiser/ExpressionInliner.cpp | 10 +- libyul/optimiser/ExpressionInliner.h | 14 +- libyul/optimiser/ExpressionJoiner.h | 2 +- libyul/optimiser/ExpressionSimplifier.cpp | 10 +- libyul/optimiser/ExpressionSimplifier.h | 4 +- libyul/optimiser/ExpressionSplitter.cpp | 13 +- libyul/optimiser/ExpressionSplitter.h | 10 +- libyul/optimiser/ForLoopConditionIntoBody.cpp | 8 +- libyul/optimiser/ForLoopConditionIntoBody.h | 4 +- .../optimiser/ForLoopConditionOutOfBody.cpp | 8 +- libyul/optimiser/ForLoopConditionOutOfBody.h | 6 +- libyul/optimiser/FullInliner.cpp | 48 ++-- libyul/optimiser/FullInliner.h | 49 ++-- libyul/optimiser/FunctionCallFinder.cpp | 4 +- libyul/optimiser/FunctionCallFinder.h | 6 +- libyul/optimiser/FunctionHoister.h | 2 +- libyul/optimiser/FunctionSpecializer.cpp | 23 +- libyul/optimiser/FunctionSpecializer.h | 18 +- .../InlinableExpressionFunctionFinder.cpp | 4 +- .../InlinableExpressionFunctionFinder.h | 8 +- libyul/optimiser/KnowledgeBase.cpp | 39 +-- libyul/optimiser/KnowledgeBase.h | 41 ++-- libyul/optimiser/LoadResolver.cpp | 17 +- libyul/optimiser/LoadResolver.h | 6 +- libyul/optimiser/LoopInvariantCodeMotion.cpp | 18 +- libyul/optimiser/LoopInvariantCodeMotion.h | 16 +- libyul/optimiser/Metrics.cpp | 12 +- libyul/optimiser/Metrics.h | 10 +- libyul/optimiser/NameCollector.cpp | 22 +- libyul/optimiser/NameCollector.h | 30 +-- libyul/optimiser/NameDispenser.cpp | 69 ------ libyul/optimiser/NameDispenser.h | 70 ------ libyul/optimiser/NameDisplacer.cpp | 8 +- libyul/optimiser/NameDisplacer.h | 27 +-- libyul/optimiser/NameSimplifier.cpp | 122 ---------- libyul/optimiser/NameSimplifier.h | 72 ------ libyul/optimiser/OptimiserStep.h | 5 +- libyul/optimiser/OptimizerUtilities.cpp | 15 +- libyul/optimiser/OptimizerUtilities.h | 2 +- libyul/optimiser/Rematerialiser.cpp | 16 +- libyul/optimiser/Rematerialiser.h | 20 +- libyul/optimiser/SSATransform.cpp | 79 +++---- libyul/optimiser/SSATransform.h | 2 - libyul/optimiser/SSAValueTracker.cpp | 6 +- libyul/optimiser/SSAValueTracker.h | 10 +- libyul/optimiser/Semantics.cpp | 66 +++--- libyul/optimiser/Semantics.h | 58 ++--- libyul/optimiser/SimplificationRules.cpp | 38 +-- libyul/optimiser/SimplificationRules.h | 14 +- libyul/optimiser/StackCompressor.cpp | 88 ++++--- libyul/optimiser/StackCompressor.h | 2 +- libyul/optimiser/StackLimitEvader.cpp | 39 ++- libyul/optimiser/StackLimitEvader.h | 4 +- libyul/optimiser/StackToMemoryMover.cpp | 44 ++-- libyul/optimiser/StackToMemoryMover.h | 24 +- libyul/optimiser/Substitution.cpp | 2 +- libyul/optimiser/Substitution.h | 4 +- libyul/optimiser/Suite.cpp | 32 +-- libyul/optimiser/Suite.h | 6 +- libyul/optimiser/SyntacticalEquality.h | 6 +- libyul/optimiser/TypeInfo.cpp | 18 +- libyul/optimiser/TypeInfo.h | 20 +- libyul/optimiser/UnusedAssignEliminator.cpp | 14 +- libyul/optimiser/UnusedAssignEliminator.h | 12 +- .../UnusedFunctionParameterPruner.cpp | 17 +- libyul/optimiser/UnusedFunctionsCommon.cpp | 8 +- libyul/optimiser/UnusedFunctionsCommon.h | 7 +- libyul/optimiser/UnusedPruner.cpp | 54 ++--- libyul/optimiser/UnusedPruner.h | 40 ++-- libyul/optimiser/UnusedStoreBase.h | 6 +- libyul/optimiser/UnusedStoreEliminator.cpp | 59 +++-- libyul/optimiser/UnusedStoreEliminator.h | 25 +- libyul/optimiser/VarDeclInitializer.cpp | 4 +- libyul/optimiser/VarDeclInitializer.h | 6 +- libyul/optimiser/VarNameCleaner.cpp | 3 +- libyul/optimiser/VarNameCleaner.h | 3 +- test/cmdlineTests/ast_ir/output | 14 +- .../constant_optimizer_yul/output | 10 +- .../output | 10 +- .../output | 10 +- .../output | 10 +- .../debug_info_in_yul_snippet_escaping/output | 30 +-- .../output | 64 ++--- .../output | 20 +- .../ir_compiler_subobjects/output | 36 +-- .../output | 10 +- .../keccak_optimization_low_runs/output | 10 +- .../output | 10 +- .../output | 10 +- test/cmdlineTests/name_simplifier/output | 10 +- .../cmdlineTests/optimizer_array_sload/output | 28 +-- .../output.json | 10 +- .../output.json | 10 +- .../output.json | 10 +- .../output.json | 140 +++++------ .../output.json | 18 +- .../output.json | 84 +++---- .../strict_asm_debug_info_print_all/output | 4 +- .../output | 4 +- .../strict_asm_debug_info_print_none/output | 4 +- test/cmdlineTests/viair_subobjects/output | 36 +-- .../yul_function_name_clashes/output | 4 +- .../output | 4 +- .../output | 18 +- .../output | 84 +++---- test/cmdlineTests/~assembler_modes/test.sh | 6 +- .../~name_dependent_cse_bug/test.sh | 2 +- test/libsolidity/MemoryGuardTest.cpp | 5 +- ...on_external_storage_to_storage_dynamic.sol | 2 +- test/libyul/Common.cpp | 27 +-- test/libyul/Common.h | 8 +- test/libyul/CompilabilityChecker.cpp | 27 ++- test/libyul/ControlFlowGraphTest.cpp | 39 +-- test/libyul/ControlFlowGraphTest.h | 2 + test/libyul/ControlFlowSideEffectsTest.cpp | 8 +- test/libyul/EVMCodeTransformTest.cpp | 3 +- test/libyul/FunctionSideEffects.cpp | 13 +- test/libyul/Inliner.cpp | 11 +- test/libyul/KnowledgeBaseTest.cpp | 45 ++-- test/libyul/Metrics.cpp | 2 +- test/libyul/ObjectParser.cpp | 3 +- test/libyul/Parser.cpp | 223 ++++++++++-------- test/libyul/StackLayoutGeneratorTest.cpp | 48 ++-- test/libyul/StackLayoutGeneratorTest.h | 4 +- test/libyul/StackShufflingTest.cpp | 29 ++- test/libyul/StackShufflingTest.h | 5 +- test/libyul/SyntaxTest.cpp | 6 +- test/libyul/SyntaxTest.h | 2 +- test/libyul/YulInterpreterTest.cpp | 3 +- test/libyul/YulInterpreterTest.h | 2 + test/libyul/YulOptimizerTest.cpp | 7 +- test/libyul/YulOptimizerTest.h | 2 + test/libyul/YulOptimizerTestCommon.cpp | 102 +++++--- test/libyul/YulOptimizerTestCommon.h | 12 +- .../movable_functions.yul | 4 +- .../disambiguator/for_statement.yul | 2 +- .../disambiguator/funtion_call.yul | 4 +- .../disambiguator/if_statement.yul | 2 +- .../disambiguator/switch_statement.yul | 4 +- .../variables_inside_functions.yul | 6 +- .../simple_different_vars.yul | 4 +- .../argument_duplication_heuristic.yul | 4 +- .../combine_add_and_mod_constant.yul | 6 +- .../combine_mul_and_mod_constant.yul | 6 +- .../combine_shift_and_and_2.yul | 26 +- .../combine_shift_and_and_3.yul | 4 +- .../expressionSimplifier/create_and_mask.yul | 6 +- .../exp_simplifications.yul | 4 +- .../mcopy_non_zero_size.sol | 4 +- .../expressionSimplifier/mod_and_1.yul | 4 +- .../expressionSimplifier/mod_and_2.yul | 4 +- ...lied_function_call_different_arguments.yul | 6 +- .../remove_redundant_shift_masking.yul | 12 +- .../replace_too_large_shift.yul | 8 +- .../unassigend_vars_multi.yul | 2 +- .../fakeStackLimitEvader/connected.yul | 34 +-- ...lti_variable_declaration_without_value.yul | 4 +- .../fakeStackLimitEvader/return_leave.yul | 12 +- .../return_one_with_args.yul | 4 +- .../fakeStackLimitEvader/stub.yul | 56 ++--- .../call_arguments_with_side_effects.yul | 12 +- .../call_arguments_without_side_effects.yul | 34 +-- .../fullInliner/double_inline.yul | 26 +- .../fullInliner/inside_condition.yul | 12 +- .../fullInliner/large_function_multi_use.yul | 42 ++-- .../fullInliner/large_function_single_use.yul | 18 +- .../fullInliner/long_names.yul | 8 +- .../move_up_rightwards_argument.yul | 24 +- .../fullInliner/multi_fun.yul | 32 +-- .../fullInliner/multi_fun_callback.yul | 8 +- .../fullInliner/multi_return.yul | 14 +- .../fullInliner/multi_return_typed.yul | 12 +- .../no_inline_into_big_function.yul | 82 +++---- .../no_inline_into_big_global_context.yul | 80 +++---- .../fullInliner/no_inline_leave.yul | 4 +- .../fullInliner/no_return.yul | 4 +- .../fullInliner/not_inside_for.yul | 30 +-- .../fullInliner/pop_result.yul | 10 +- .../yulOptimizerTests/fullInliner/simple.yul | 12 +- .../call_arguments_without_side_effects.yul | 10 +- .../fullInlinerWithoutSplitter/simple.sol | 6 +- .../fullSimplify/constant_propagation.yul | 4 +- .../fullSimplify/invariant.yul | 4 +- .../fullSimplify/mod_and_1.yul | 4 +- .../fullSimplify/mod_and_2.yul | 4 +- ...lied_function_call_different_arguments.yul | 6 +- .../scoped_var_ref_in_function_call.yul | 10 +- .../yulOptimizerTests/fullSuite/abi2.yul | 66 +++--- .../fullSuite/abi_example1.yul | 88 +++---- .../yulOptimizerTests/fullSuite/aztec.yul | 72 +++--- .../fullSuite/loopInvariantCodeMotion.yul | 10 +- .../fullSuite/name_cleaner_reserved.yul | 10 +- .../name_dependent_cse_bug_part_2.yul | 4 +- ..._dependent_cse_bug_part_2_pre_shanghai.yul | 4 +- .../fullSuite/reserved_identifiers.yul | 15 +- .../fullSuite/ssaReverse.yul | 26 +- .../fullSuite/stack_compressor_msize.yul | 4 +- .../unusedFunctionParameterPruner.yul | 6 +- ...nusedFunctionParameterPruner_recursion.yul | 6 +- .../unusedFunctionParameterPruner_return.yul | 4 +- .../functionSpecializer/multiple.yul | 12 +- .../functionSpecializer/partial.yul | 10 +- .../functionSpecializer/simple.yul | 10 +- .../loadResolver/keccak_reuse_expr_mstore.yul | 4 +- .../keccak_reuse_in_expression.yul | 4 +- .../keccak_reuse_reassigned_branch.yul | 10 +- .../keccak_reuse_reassigned_value.yul | 10 +- .../loadResolver/keccak_short.yul | 8 +- ...y_with_different_kinds_of_invalidation.yul | 22 +- .../loadResolver/memory_with_msize.yul | 6 +- .../loadResolver/merge_known_write.yul | 16 +- .../merge_known_write_with_distance.yul | 12 +- .../merge_mload_with_known_distance.yul | 10 +- .../loadResolver/merge_unknown_write.yul | 16 +- .../loadResolver/mload_in_function.yul | 6 +- .../mstore_in_function_loop_body.yul | 4 +- .../mstore_in_function_loop_init.yul | 4 +- .../loadResolver/multi_sload_loop.yul | 2 +- .../reassign_value_expression.yul | 12 +- .../loadResolver/second_mstore_with_delta.yul | 10 +- .../loadResolver/second_store.yul | 8 +- .../loadResolver/second_store_same_value.yul | 10 +- .../loadResolver/second_store_with_delta.yul | 10 +- .../side_effects_of_user_functions.yul | 8 +- .../yulOptimizerTests/loadResolver/simple.yul | 6 +- .../loadResolver/simple_memory.yul | 6 +- .../loadResolver/verbatim_sload.yul | 8 +- .../no_move_memory.yul | 8 +- .../no_move_memory_msize.yul | 6 +- .../loopInvariantCodeMotion/no_move_state.yul | 20 +- .../no_move_storage.yul | 18 +- .../nameDisplacer/funtion_call.yul | 10 +- .../nameDisplacer/variables.yul | 4 +- .../variables_inside_functions.yul | 6 +- .../yulOptimizerTests/ssaAndBack/for_loop.yul | 4 +- .../ssaAndBack/multi_assign.yul | 4 +- .../ssaAndBack/multi_assign_multi_var_if.yul | 6 +- .../multi_assign_multi_var_switch.yul | 12 +- .../yulOptimizerTests/ssaAndBack/simple.yul | 4 +- .../yulOptimizerTests/ssaAndBack/two_vars.yul | 14 +- .../ssaPlusCleanup/control_structures.yul | 26 +- .../ssaTransform/for_def_in_init.yul | 14 +- .../ssaTransform/function.yul | 18 +- .../ssaTransform/multi_assign.yul | 18 +- .../ssaTransform/multi_decl.yul | 14 +- .../yulOptimizerTests/ssaTransform/nested.yul | 22 +- .../yulOptimizerTests/ssaTransform/typed.yul | 34 +-- .../stackLimitEvader/cycle_before_2.yul | 6 +- .../stackLimitEvader/tree.yul | 196 +++++++-------- .../verbatim_many_arguments_and_returns.yul | 42 ++-- .../verbatim_many_returns.yul | 66 +++--- .../unusedAssignEliminator/leave.yul | 8 +- .../LiteralRematerialiser.yul | 4 +- .../multiple_param.yul | 4 +- .../multiple_return.yul | 4 +- .../nested_function.yul | 10 +- .../nested_function_name_collision.yul | 18 +- .../no_return.yul | 4 +- .../recursion.yul | 4 +- .../unusedFunctionParameterPruner/simple.yul | 4 +- .../too_many_arguments.yul | 4 +- .../covering_calldatacopy.yul | 22 +- .../covering_calldatacopy_fixed.yul | 8 +- .../unusedStoreEliminator/function_end.yul | 2 +- .../if_overwrite_all_branches.yul | 4 +- .../unusedStoreEliminator/leave.yul | 4 +- .../unusedStoreEliminator/memoryguard.yul | 6 +- .../no_storage_inside_function.yul | 4 +- .../remove_before_revert.yul | 4 +- .../unusedStoreEliminator/tstore.yul | 2 +- .../unusedStoreEliminator/unknown_length2.yul | 16 +- .../unrelated_relative.yul | 10 +- .../varNameCleaner/builtins.yul | 2 +- .../varNameCleaner/function_names.yul | 2 +- .../varNameCleaner/function_parameters.yul | 10 +- .../varNameCleaner/function_scopes.yul | 4 +- .../varNameCleaner/instructions.yul | 2 +- .../varNameCleaner/name_stripping.yul | 8 +- .../varNameCleaner/reshuffling-inverse.yul | 6 +- .../varNameCleaner/reshuffling.yul | 6 +- .../tools/ossfuzz/StackReuseCodegenFuzzer.cpp | 7 +- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 4 +- test/tools/ossfuzz/yulFuzzerCommon.cpp | 4 +- test/tools/ossfuzz/yulFuzzerCommon.h | 2 +- test/tools/ossfuzz/yulProtoFuzzer.cpp | 2 +- .../EVMInstructionInterpreter.cpp | 2 +- test/tools/yulInterpreter/Inspector.cpp | 25 +- test/tools/yulInterpreter/Inspector.h | 32 +-- test/tools/yulInterpreter/Interpreter.cpp | 46 ++-- test/tools/yulInterpreter/Interpreter.h | 32 +-- test/tools/yulopti.cpp | 25 +- test/tools/yulrun.cpp | 5 +- test/yulPhaser/Program.cpp | 9 +- tools/yulPhaser/Program.cpp | 57 +++-- tools/yulPhaser/Program.h | 23 +- 399 files changed, 3665 insertions(+), 3737 deletions(-) delete mode 100644 libyul/optimiser/NameDispenser.cpp delete mode 100644 libyul/optimiser/NameDispenser.h delete mode 100644 libyul/optimiser/NameSimplifier.cpp delete mode 100644 libyul/optimiser/NameSimplifier.h diff --git a/Changelog.md b/Changelog.md index 7bffd07e1e29..cf9a8c1342d6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ Compiler Features: Bugfixes: + * AsmParser: Parsing rules for source location comments have been relaxed: Whitespace between the indices as well as single-quoted code snippets are now allowed. * SMTChecker: Fix error that reports invalid number of verified checks for BMC and CHC engines. * SMTChecker: Fix formatting of unary minus expressions in invariants. * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index c20968a14d79..c280dcafb949 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -582,13 +582,13 @@ void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall) solAssert(m_currentNode && m_inlineAssembly, ""); yul::ASTWalker::operator()(_functionCall); - if (auto const *builtinFunction = m_inlineAssembly->dialect().builtin(_functionCall.functionName.name)) + if (auto const *builtinFunction = m_inlineAssembly->nameRepository().builtin(_functionCall.functionName.name)) { - if (builtinFunction->controlFlowSideEffects.canTerminate) + if (builtinFunction->data->controlFlowSideEffects.canTerminate) connect(m_currentNode, m_transactionReturnNode); - if (builtinFunction->controlFlowSideEffects.canRevert) + if (builtinFunction->data->controlFlowSideEffects.canRevert) connect(m_currentNode, m_revertNode); - if (!builtinFunction->controlFlowSideEffects.canContinue) + if (!builtinFunction->data->controlFlowSideEffects.canContinue) m_currentNode = newLabel(); } } diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index 9731ef3cc624..d832f77479b9 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -462,7 +462,8 @@ struct ReservedErrorSelector: public PostTypeChecker::Checker class YulLValueChecker : public solidity::yul::ASTWalker { public: - YulLValueChecker(ASTString const& _identifierName): m_identifierName(_identifierName) {} + YulLValueChecker(ASTString const& _identifierName, yul::YulNameRepository const& _yulNameRepository): + m_identifierName(_identifierName), m_yulNameRepository(_yulNameRepository) {} bool willBeWrittenTo() const { return m_willBeWrittenTo; } using solidity::yul::ASTWalker::operator(); void operator()(solidity::yul::Assignment const& _assignment) override @@ -472,12 +473,13 @@ class YulLValueChecker : public solidity::yul::ASTWalker if (ranges::any_of( _assignment.variableNames, - [&](auto const& yulIdentifier) { return yulIdentifier.name.str() == m_identifierName; } + [&](auto const& yulIdentifier) { return m_yulNameRepository.labelOf(yulIdentifier.name) == m_identifierName; } )) m_willBeWrittenTo = true; } private: ASTString const& m_identifierName; + yul::YulNameRepository const& m_yulNameRepository; bool m_willBeWrittenTo = false; }; @@ -505,7 +507,7 @@ class LValueChecker: public ASTConstVisitor if (m_willBeWrittenTo) return; - YulLValueChecker yulChecker{m_declaration->name()}; + YulLValueChecker yulChecker{m_declaration->name(), _inlineAssembly.nameRepository()}; yulChecker(_inlineAssembly.operations()); m_willBeWrittenTo = yulChecker.willBeWrittenTo(); } diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index fd7def71459a..184acfdf2772 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -236,7 +236,9 @@ bool ReferencesResolver::visit(UsingForDirective const& _usingFor) bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) { m_yulAnnotation = &_inlineAssembly.annotation(); + m_yulNameRepository = &_inlineAssembly.nameRepository(); (*this)(_inlineAssembly.operations()); + m_yulNameRepository = nullptr; m_yulAnnotation = nullptr; return false; @@ -270,12 +272,13 @@ bool ReferencesResolver::visit(BinaryOperation const& _binaryOperation) void ReferencesResolver::operator()(yul::FunctionDefinition const& _function) { + solAssert(m_yulNameRepository != nullptr); solAssert(nativeLocationOf(_function) == originLocationOf(_function), ""); - validateYulIdentifierName(_function.name, nativeLocationOf(_function)); + validateYulIdentifierName(m_yulNameRepository->labelOf(_function.name), nativeLocationOf(_function)); for (yul::TypedName const& varName: _function.parameters + _function.returnVariables) { solAssert(nativeLocationOf(varName) == originLocationOf(varName), ""); - validateYulIdentifierName(varName.name, nativeLocationOf(varName)); + validateYulIdentifierName(m_yulNameRepository->labelOf(varName.name), nativeLocationOf(varName)); } bool wasInsideFunction = m_yulInsideFunction; @@ -286,12 +289,13 @@ void ReferencesResolver::operator()(yul::FunctionDefinition const& _function) void ReferencesResolver::operator()(yul::Identifier const& _identifier) { + solAssert(m_yulNameRepository != nullptr); solAssert(nativeLocationOf(_identifier) == originLocationOf(_identifier), ""); - + auto const identifierLabel = m_yulNameRepository->labelOf(_identifier.name); if (m_resolver.experimentalSolidity()) { std::vector splitName; - boost::split(splitName, _identifier.name.str(), boost::is_any_of(".")); + boost::split(splitName, identifierLabel, boost::is_any_of(".")); solAssert(!splitName.empty()); if (splitName.size() > 2) { @@ -332,22 +336,22 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier) static std::set suffixes{"slot", "offset", "length", "address", "selector"}; std::string suffix; for (std::string const& s: suffixes) - if (boost::algorithm::ends_with(_identifier.name.str(), "." + s)) + if (boost::algorithm::ends_with(identifierLabel, "." + s)) suffix = s; // Could also use `pathFromCurrentScope`, split by '.'. // If we do that, suffix should only be set for when it has a special // meaning, not for normal identifierPaths. - auto declarations = m_resolver.nameFromCurrentScope(_identifier.name.str()); + auto declarations = m_resolver.nameFromCurrentScope(std::string(identifierLabel)); if (!suffix.empty()) { // special mode to access storage variables if (!declarations.empty()) // the special identifier exists itself, we should not allow that. return; - std::string realName = _identifier.name.str().substr(0, _identifier.name.str().size() - suffix.size() - 1); + auto const realName = identifierLabel.substr(0, identifierLabel.size() - suffix.size() - 1); solAssert(!realName.empty(), "Empty name."); - declarations = m_resolver.nameFromCurrentScope(realName); + declarations = m_resolver.nameFromCurrentScope(std::string(realName)); if (!declarations.empty()) // To support proper path resolution, we have to use pathFromCurrentScope. solAssert(!util::contains(realName, '.'), ""); @@ -364,8 +368,8 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier) else if (declarations.size() == 0) { if ( - boost::algorithm::ends_with(_identifier.name.str(), "_slot") || - boost::algorithm::ends_with(_identifier.name.str(), "_offset") + boost::algorithm::ends_with(identifierLabel, "_slot") || + boost::algorithm::ends_with(identifierLabel, "_offset") ) m_errorReporter.declarationError( 9467_error, @@ -391,13 +395,14 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier) void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl) { + solAssert(m_yulNameRepository != nullptr); for (auto const& identifier: _varDecl.variables) { solAssert(nativeLocationOf(identifier) == originLocationOf(identifier), ""); - validateYulIdentifierName(identifier.name, nativeLocationOf(identifier)); + validateYulIdentifierName(m_yulNameRepository->labelOf(identifier.name), nativeLocationOf(identifier)); if ( - auto declarations = m_resolver.nameFromCurrentScope(identifier.name.str()); + auto declarations = m_resolver.nameFromCurrentScope(std::string(m_yulNameRepository->labelOf(identifier.name))); !declarations.empty() ) { @@ -488,19 +493,19 @@ void ReferencesResolver::resolveInheritDoc(StructuredDocumentation const& _docum } } -void ReferencesResolver::validateYulIdentifierName(yul::YulString _name, SourceLocation const& _location) +void ReferencesResolver::validateYulIdentifierName(std::string_view const _name, SourceLocation const& _location) { - if (util::contains(_name.str(), '.')) + if (util::contains(_name, '.')) m_errorReporter.declarationError( 3927_error, _location, "User-defined identifiers in inline assembly cannot contain '.'." ); - if (std::set{"this", "super", "_"}.count(_name.str())) + if (std::set>{"this", "super", "_"}.count(_name)) m_errorReporter.declarationError( 4113_error, _location, - "The identifier name \"" + _name.str() + "\" is reserved." + fmt::format("The identifier name \"{}\" is reserved.", _name) ); } diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 13752e9c9345..e7c9d47c3af4 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -94,7 +94,7 @@ class ReferencesResolver: private ASTConstVisitor, private yul::ASTWalker void resolveInheritDoc(StructuredDocumentation const& _documentation, StructurallyDocumentedAnnotation& _annotation); /// Checks if the name contains a '.'. - void validateYulIdentifierName(yul::YulString _name, langutil::SourceLocation const& _location); + void validateYulIdentifierName(std::string_view _name, langutil::SourceLocation const& _location); langutil::ErrorReporter& m_errorReporter; NameAndTypeResolver& m_resolver; @@ -104,6 +104,7 @@ class ReferencesResolver: private ASTConstVisitor, private yul::ASTWalker bool const m_resolveInsideCode; InlineAssemblyAnnotation* m_yulAnnotation = nullptr; + yul::YulNameRepository const* m_yulNameRepository = nullptr; bool m_yulInsideFunction = false; bool m_typeContext = false; }; diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index b083690cced6..21966bae0def 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -354,7 +354,7 @@ bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly) if (!m_useYulOptimizer) return false; - if (yul::MSizeFinder::containsMSize(_inlineAssembly.dialect(), _inlineAssembly.operations())) + if (yul::MSizeFinder::containsMSize(_inlineAssembly.nameRepository(), _inlineAssembly.operations())) m_errorReporter.syntaxError( 6553_error, _inlineAssembly.location(), diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index dfd334295a2a..89605b9ba61f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -944,7 +944,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) yul::AsmAnalyzer analyzer( *_inlineAssembly.annotation().analysisInfo, m_errorReporter, - _inlineAssembly.dialect(), + _inlineAssembly.nameRepository(), identifierAccess ); if (!analyzer.analyze(_inlineAssembly.operations())) diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 3f6b954e75da..8bb00b4962e1 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -38,10 +38,10 @@ class AssemblyViewPureChecker { public: explicit AssemblyViewPureChecker( - yul::Dialect const& _dialect, + yul::YulNameRepository const& _yulNameRepository, std::function _reportMutability ): - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_reportMutability(std::move(_reportMutability)) {} void operator()(yul::Literal const&) {} @@ -65,10 +65,10 @@ class AssemblyViewPureChecker } void operator()(yul::FunctionCall const& _funCall) { - if (yul::EVMDialect const* dialect = dynamic_cast(&m_dialect)) - if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name)) - if (fun->instruction) - checkInstruction(nativeLocationOf(_funCall), *fun->instruction); + if (yul::EVMDialect const* dialect = dynamic_cast(&m_yulNameRepository.dialect())) + if (auto const* fun = m_yulNameRepository.builtin(_funCall.functionName.name)) + if (auto const* evmFun = dynamic_cast(fun->data); evmFun->instruction) + checkInstruction(nativeLocationOf(_funCall), *evmFun->instruction); for (auto const& arg: _funCall.arguments) std::visit(*this, arg); @@ -119,7 +119,7 @@ class AssemblyViewPureChecker m_reportMutability(StateMutability::View, _location); } - yul::Dialect const& m_dialect; + yul::YulNameRepository const& m_yulNameRepository; std::function m_reportMutability; }; @@ -224,7 +224,7 @@ void ViewPureChecker::endVisit(Identifier const& _identifier) void ViewPureChecker::endVisit(InlineAssembly const& _inlineAssembly) { AssemblyViewPureChecker{ - _inlineAssembly.dialect(), + _inlineAssembly.nameRepository(), [&](StateMutability _mutability, SourceLocation const& _location) { reportMutability(_mutability, _location); } }(_inlineAssembly.operations()); } diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index a3aab07fba29..0e5533e431c8 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,7 @@ #include #include +#include using namespace solidity; using namespace solidity::frontend; @@ -1060,6 +1062,24 @@ TryCatchClause const* TryStatement::fallbackClause() const { return findClause(m_clauses); } +InlineAssembly::InlineAssembly( + int64_t _id, + SourceLocation const& _location, + ASTPointer const& _docString, + std::unique_ptr _yulNameRepository, + ASTPointer>> _flags, + std::shared_ptr _operations +): + Statement(_id, _location, _docString), + m_yulNameRepository(std::move(_yulNameRepository)), + m_flags(std::move(_flags)), + m_operations(std::move(_operations)) +{ + solAssert(m_yulNameRepository != nullptr); +} + +InlineAssembly::~InlineAssembly() = default; + /// Experimental Solidity nodes /// @{ TypeClassDefinitionAnnotation& TypeClassDefinition::annotation() const diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 3494ab94b9b4..83c101f004c0 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -49,7 +49,7 @@ namespace solidity::yul { // Forward-declaration to struct Block; -struct Dialect; +class YulNameRepository; } namespace solidity::frontend @@ -1567,26 +1567,22 @@ class InlineAssembly: public Statement int64_t _id, SourceLocation const& _location, ASTPointer const& _docString, - yul::Dialect const& _dialect, + std::unique_ptr _yulNameRepository, ASTPointer>> _flags, std::shared_ptr _operations - ): - Statement(_id, _location, _docString), - m_dialect(_dialect), - m_flags(std::move(_flags)), - m_operations(std::move(_operations)) - {} + ); + ~InlineAssembly() override; void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; - yul::Dialect const& dialect() const { return m_dialect; } + yul::YulNameRepository& nameRepository() const { return *m_yulNameRepository; } yul::Block const& operations() const { return *m_operations; } ASTPointer>> const& flags() const { return m_flags; } InlineAssemblyAnnotation& annotation() const override; private: - yul::Dialect const& m_dialect; + std::unique_ptr mutable m_yulNameRepository; ASTPointer>> m_flags; std::shared_ptr m_operations; }; diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 69f51618e3d4..509d82200890 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -654,7 +654,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) for (auto const& it: _node.annotation().externalReferences) if (it.first) externalReferences.emplace_back(std::make_pair( - it.first->name.str(), + _node.nameRepository().labelOf(it.first->name), inlineAssemblyIdentifierToJson(it) )); @@ -665,9 +665,9 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) externalReferencesJson.emplace_back(std::move(it)); std::vector> attributes = { - std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))), + std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()), _node.nameRepository())(_node.operations()))), std::make_pair("externalReferences", std::move(externalReferencesJson)), - std::make_pair("evmVersion", dynamic_cast(_node.dialect()).evmVersion().name()) + std::make_pair("evmVersion", dynamic_cast(_node.nameRepository().dialect()).evmVersion().name()) }; if (_node.flags()) diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 728d77c0de8b..0df3f0fd2f26 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -733,11 +733,12 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json const& _no flags->emplace_back(std::make_shared(flag.get())); } } - std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST"))); + auto repository = std::make_unique(dialect); + std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames, *repository).createBlock(member(_node, "AST"))); return createASTNode( _node, nullOrASTString(_node, "documentation"), - dialect, + std::move(repository), std::move(flags), operations ); diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index d9264c6ac5f1..3a0d19e9a563 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -387,12 +387,14 @@ void CompilerContext::appendInlineAssembly( ) { unsigned startStackHeight = stackHeight(); + yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); + yul::YulNameRepository nameRepository (dialect); - std::set externallyUsedIdentifiers; + std::set externallyUsedIdentifiers; for (auto const& fun: _externallyUsedFunctions) - externallyUsedIdentifiers.insert(yul::YulString(fun)); + externallyUsedIdentifiers.insert(nameRepository.defineName(fun)); for (auto const& var: _localVariables) - externallyUsedIdentifiers.insert(yul::YulString(var)); + externallyUsedIdentifiers.insert(nameRepository.defineName(var)); yul::ExternalIdentifierAccess identifierAccess; identifierAccess.resolve = [&]( @@ -403,7 +405,7 @@ void CompilerContext::appendInlineAssembly( { if (_insideFunction) return false; - return util::contains(_localVariables, _identifier.name.str()); + return util::contains(_localVariables, nameRepository.labelOf(_identifier.name)); }; identifierAccess.generateCode = [&]( yul::Identifier const& _identifier, @@ -412,7 +414,7 @@ void CompilerContext::appendInlineAssembly( ) { solAssert(_context == yul::IdentifierContext::RValue || _context == yul::IdentifierContext::LValue, ""); - auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str()); + auto it = std::find(_localVariables.begin(), _localVariables.end(), nameRepository.labelOf(_identifier.name)); solAssert(it != _localVariables.end(), ""); auto stackDepth = static_cast(distance(it, _localVariables.end())); size_t stackDiff = static_cast(_assembly.stackHeight()) - startStackHeight + stackDepth; @@ -436,12 +438,11 @@ void CompilerContext::appendInlineAssembly( ErrorList errors; ErrorReporter errorReporter(errors); langutil::CharStream charStream(_assembly, _sourceName); - yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); std::optional locationOverride; if (!_system) locationOverride = m_asm->currentSourceLocation(); std::shared_ptr parserResult = - yul::Parser(errorReporter, dialect, std::move(locationOverride)) + yul::Parser(errorReporter, nameRepository, std::move(locationOverride)) .parse(charStream); #ifdef SOL_OUTPUT_ASM cout << yul::AsmPrinter(&dialect)(*parserResult) << endl; @@ -470,7 +471,7 @@ void CompilerContext::appendInlineAssembly( analyzerResult = yul::AsmAnalyzer( analysisInfo, errorReporter, - dialect, + nameRepository, identifierAccess.resolve ).analyze(*parserResult); if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) @@ -485,17 +486,17 @@ void CompilerContext::appendInlineAssembly( obj.analysisInfo = std::make_shared(analysisInfo); solAssert(!dialect.providesObjectAccess()); - optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers); + optimizeYul(obj, dialect, nameRepository, _optimiserSettings, externallyUsedIdentifiers); if (_system) { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - m_generatedYulUtilityCode = yul::AsmPrinter(dialect)(*obj.code); - std::string code = yul::AsmPrinter{dialect}(*obj.code); + m_generatedYulUtilityCode = yul::AsmPrinter(nameRepository)(*obj.code); + std::string code = yul::AsmPrinter(nameRepository)(*obj.code); langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); - obj.code = yul::Parser(errorReporter, dialect).parse(charStream); - *obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(dialect, obj); + obj.code = yul::Parser(errorReporter, nameRepository).parse(charStream); + *obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(nameRepository, obj); } analysisInfo = std::move(*obj.analysisInfo); @@ -522,6 +523,7 @@ void CompilerContext::appendInlineAssembly( analysisInfo, *m_asm, m_evmVersion, + nameRepository, identifierAccess.generateCode, _system, _optimiserSettings.optimizeStackAllocation @@ -532,16 +534,16 @@ void CompilerContext::appendInlineAssembly( } -void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) +void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, yul::YulNameRepository& _yulNameRepository, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) { #ifdef SOL_OUTPUT_ASM - cout << yul::AsmPrinter(*dialect)(*_object.code) << endl; + cout << yul::AsmPrinter(_yulNameRepository)(*_object.code) << endl; #endif bool const isCreation = runtimeContext() != nullptr; - yul::GasMeter meter(_dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); + yul::GasMeter meter(_yulNameRepository, _dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); yul::OptimiserSuite::run( - _dialect, + _yulNameRepository, &meter, _object, _optimiserSettings.optimizeStackAllocation, @@ -553,7 +555,7 @@ void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _ #ifdef SOL_OUTPUT_ASM cout << "After optimizer:" << endl; - cout << yul::AsmPrinter(*dialect)(*object.code) << endl; + cout << yul::AsmPrinter(_yulNameRepository)(*object.code) << endl; #endif } diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 8eba084eba7b..bd8dab318fc0 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -277,7 +277,7 @@ class CompilerContext /// Otherwise returns "revert(0, 0)". std::string revertReasonIfDebug(std::string const& _message = ""); - void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); + void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, yul::YulNameRepository& _yulNameRepository, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); /// Appends arbitrary data to the end of the bytecode. void appendToAuxiliaryData(bytes const& _data) { m_asm->appendToAuxiliaryData(_data); } diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 2326d3336364..c4707d29f460 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -940,14 +940,14 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) _inlineAssembly.annotation().externalReferences.empty() ) { - yul::EVMDialect const* dialect = dynamic_cast(&_inlineAssembly.dialect()); + yul::EVMDialect const* dialect = dynamic_cast(&_inlineAssembly.nameRepository().dialect()); solAssert(dialect, ""); // Create a modifiable copy of the code and analysis object.code = std::make_shared(yul::ASTCopier().translate(*code)); - object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(*dialect, object)); + object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(_inlineAssembly.nameRepository(), object)); - m_context.optimizeYul(object, *dialect, m_optimiserSettings); + m_context.optimizeYul(object, *dialect, _inlineAssembly.nameRepository(), m_optimiserSettings); code = object.code.get(); analysisInfo = object.analysisInfo.get(); @@ -958,6 +958,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) *analysisInfo, *m_context.assemblyPtr(), m_context.evmVersion(), + _inlineAssembly.nameRepository(), identifierAccessCodeGen, false, m_optimiserSettings.optimizeStackAllocation diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 1c212cd828c3..85d3c2004553 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -63,8 +63,8 @@ struct CopyTranslate: public yul::ASTCopier { using ExternalRefsMap = std::map; - CopyTranslate(yul::Dialect const& _dialect, IRGenerationContext& _context, ExternalRefsMap const& _references): - m_dialect(_dialect), m_context(_context), m_references(_references) {} + CopyTranslate(yul::YulNameRepository& _yulNameRepository, IRGenerationContext& _context, ExternalRefsMap const& _references): + m_yulNameRepository(_yulNameRepository), m_context(_context), m_references(_references) {} using ASTCopier::operator(); @@ -78,16 +78,16 @@ struct CopyTranslate: public yul::ASTCopier return ASTCopier::operator()(_identifier); } - yul::YulString translateIdentifier(yul::YulString _name) override + yul::YulName translateIdentifier(yul::YulName _name) override { // Strictly, the dialect used by inline assembly (m_dialect) could be different // from the Yul dialect we are compiling to. So we are assuming here that the builtin // functions are identical. This should not be a problem for now since everything // is EVM anyway. - if (m_dialect.builtin(_name)) + if (m_yulNameRepository.isBuiltinName(_name)) return _name; else - return yul::YulString{"usr$" + _name.str()}; + return m_yulNameRepository.defineName("usr$" + std::string(m_yulNameRepository.labelOf(_name))); } yul::Identifier translate(yul::Identifier const& _identifier) override @@ -206,11 +206,11 @@ struct CopyTranslate: public yul::ASTCopier if (isDigit(value.front())) return yul::Literal{_identifier.debugData, yul::LiteralKind::Number, yul::valueOfNumberLiteral(value), {}}; else - return yul::Identifier{_identifier.debugData, yul::YulString{value}}; + return yul::Identifier{_identifier.debugData, m_yulNameRepository.defineName(value)}; } - yul::Dialect const& m_dialect; + yul::YulNameRepository& m_yulNameRepository; IRGenerationContext& m_context; ExternalRefsMap const& m_references; }; @@ -2250,14 +2250,14 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) setLocation(_inlineAsm); if (*_inlineAsm.annotation().hasMemoryEffects && !_inlineAsm.annotation().markedMemorySafe) m_context.setMemoryUnsafeInlineAssemblySeen(); - CopyTranslate bodyCopier{_inlineAsm.dialect(), m_context, _inlineAsm.annotation().externalReferences}; + CopyTranslate bodyCopier{_inlineAsm.nameRepository(), m_context, _inlineAsm.annotation().externalReferences}; yul::Statement modified = bodyCopier(_inlineAsm.operations()); solAssert(std::holds_alternative(modified)); // Do not provide dialect so that we get the full type information. - appendCode() << yul::AsmPrinter()(std::get(modified)) << "\n"; + appendCode() << yul::AsmPrinter(_inlineAsm.nameRepository())(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/experimental/analysis/TypeInference.cpp b/libsolidity/experimental/analysis/TypeInference.cpp index 6913dc0bf7cd..0b7c525a1843 100644 --- a/libsolidity/experimental/analysis/TypeInference.cpp +++ b/libsolidity/experimental/analysis/TypeInference.cpp @@ -299,7 +299,7 @@ bool TypeInference::visit(InlineAssembly const& _inlineAssembly) yul::AsmAnalyzer analyzer( *_inlineAssembly.annotation().analysisInfo, m_errorReporter, - _inlineAssembly.dialect(), + _inlineAssembly.nameRepository(), identifierAccess ); if (!analyzer.analyze(_inlineAssembly.operations())) diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index cb4705f0d189..863d04b13306 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -54,9 +54,9 @@ struct CopyTranslate: public yul::ASTCopier { CopyTranslate( IRGenerationContext const& _context, - yul::Dialect const& _dialect, + yul::YulNameRepository& _yulNameRepository, std::map _references - ): m_context(_context), m_dialect(_dialect), m_references(std::move(_references)) {} + ): m_context(_context), m_yulNameRepository(_yulNameRepository), m_references(std::move(_references)) {} using ASTCopier::operator(); @@ -70,12 +70,12 @@ struct CopyTranslate: public yul::ASTCopier return ASTCopier::operator()(_identifier); } - yul::YulString translateIdentifier(yul::YulString _name) override + yul::YulName translateIdentifier(yul::YulName _name) override { - if (m_dialect.builtin(_name)) + if (m_yulNameRepository.isBuiltinName(_name)) return _name; else - return yul::YulString{"usr$" + _name.str()}; + return m_yulNameRepository.defineName("usr$" + std::string(m_yulNameRepository.labelOf(_name))); } yul::Identifier translate(yul::Identifier const& _identifier) override @@ -102,11 +102,11 @@ struct CopyTranslate: public yul::ASTCopier solAssert(type); solAssert(m_context.env->typeEquals(*type, m_context.analysis.typeSystem().type(PrimitiveType::Word, {}))); std::string value = IRNames::localVariable(*varDecl); - return yul::Identifier{_identifier.debugData, yul::YulString{value}}; + return yul::Identifier{_identifier.debugData, m_yulNameRepository.defineName(value)}; } IRGenerationContext const& m_context; - yul::Dialect const& m_dialect; + yul::YulNameRepository& m_yulNameRepository; std::map m_references; }; @@ -129,10 +129,10 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tupleExpression) bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly) { - CopyTranslate bodyCopier{m_context, _assembly.dialect(), _assembly.annotation().externalReferences}; + CopyTranslate bodyCopier{m_context, _assembly.nameRepository(), _assembly.annotation().externalReferences}; yul::Statement modified = bodyCopier(_assembly.operations()); solAssert(std::holds_alternative(modified)); - m_code << yul::AsmPrinter()(std::get(modified)) << "\n"; + m_code << yul::AsmPrinter(_assembly.nameRepository())(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 44282289d1e2..f016785d7b38 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -330,7 +330,7 @@ bool SMTEncoder::visit(InlineAssembly const& _inlineAsm) } }; - yul::SideEffectsCollector sideEffectsCollector(_inlineAsm.dialect(), _inlineAsm.operations()); + yul::SideEffectsCollector sideEffectsCollector(_inlineAsm.nameRepository(), _inlineAsm.operations()); if (sideEffectsCollector.invalidatesMemory()) resetMemoryVariables(); if (sideEffectsCollector.invalidatesStorage()) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 8ee55d87f5a5..603fef445181 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -837,9 +837,10 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run ErrorReporter errorReporter(errors); CharStream charStream(source, sourceName); yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); - std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); + YulNameRepository yulNameRepository(dialect); + std::shared_ptr parserResult = yul::Parser{errorReporter, yulNameRepository}.parse(charStream); solAssert(parserResult, ""); - sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex}(*parserResult); + sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex, yulNameRepository}(*parserResult); sources[0]["name"] = sourceName; sources[0]["id"] = sourceIndex; sources[0]["language"] = "Yul"; diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 672067d81cc7..8fcb2cd095b2 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -69,6 +69,11 @@ class AssemblyItem; using AssemblyItems = std::vector; } +namespace solidity::yul +{ +class YulNameRepository; +} + namespace solidity::frontend { diff --git a/libsolidity/lsp/RenameSymbol.cpp b/libsolidity/lsp/RenameSymbol.cpp index 497ee50fb451..2a4a29f61870 100644 --- a/libsolidity/lsp/RenameSymbol.cpp +++ b/libsolidity/lsp/RenameSymbol.cpp @@ -283,7 +283,7 @@ void RenameSymbol::extractNameAndDeclaration(InlineAssembly const& _inlineAssemb if (location.containsOffset(_cursorBytePosition)) { m_declarationToRename = externalReference.declaration; - m_symbolName = identifier->name.str(); + m_symbolName = _inlineAssembly.nameRepository().labelOf(identifier->name); if (!externalReference.suffix.empty()) m_symbolName = m_symbolName.substr(0, m_symbolName.length() - externalReference.suffix.size() - 1); @@ -296,7 +296,7 @@ void RenameSymbol::Visitor::endVisit(InlineAssembly const& _node) { for (auto&& [identifier, externalReference]: _node.annotation().externalReferences) { - std::string identifierName = identifier->name.str(); + auto identifierName = _node.nameRepository().labelOf(identifier->name); if (!externalReference.suffix.empty()) identifierName = identifierName.substr(0, identifierName.length() - externalReference.suffix.size() - 1); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index b51eb9c44099..0e40c4fc9067 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1472,13 +1472,14 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con expectToken(Token::RParen); } - yul::Parser asmParser(m_errorReporter, dialect); + auto nameRepository = std::make_unique(dialect); + yul::Parser asmParser(m_errorReporter, *nameRepository); std::shared_ptr block = asmParser.parseInline(m_scanner); if (block == nullptr) BOOST_THROW_EXCEPTION(FatalError()); location.end = nativeLocationOf(*block).end; - return std::make_shared(nextID(), location, _docString, dialect, std::move(flags), block); + return std::make_shared(nextID(), location, _docString, std::move(nameRepository), std::move(flags), block); } ASTPointer Parser::parseIfStatement(ASTPointer const& _docString) diff --git a/libsolutil/StringUtils.h b/libsolutil/StringUtils.h index 77ffe6735401..59c989d1acfe 100644 --- a/libsolutil/StringUtils.h +++ b/libsolutil/StringUtils.h @@ -71,7 +71,7 @@ std::string joinHumanReadable for (auto it = begin(_list); it != itEnd; ) { - std::string element = *it; + std::string element {*it}; bool first = (it == begin(_list)); ++it; if (!first) diff --git a/libyul/AST.h b/libyul/AST.h index ad60e468592a..ad28cfa59937 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -24,6 +24,7 @@ #pragma once #include +#include #include #include @@ -36,9 +37,9 @@ namespace solidity::yul { -using Type = YulString; +using Type = YulName; -struct TypedName { langutil::DebugData::ConstPtr debugData; YulString name; Type type; }; +struct TypedName { langutil::DebugData::ConstPtr debugData; YulName name {}; Type type {}; }; using TypedNameList = std::vector; /// Literal number or string (up to 32 bytes) @@ -68,9 +69,9 @@ class LiteralValue { std::optional m_numericValue; std::shared_ptr m_stringValue; }; -struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; LiteralValue value; Type type; }; +struct Literal { langutil::DebugData::ConstPtr debugData; LiteralKind kind; LiteralValue value; Type type {}; }; /// External / internal identifier or label reference -struct Identifier { langutil::DebugData::ConstPtr debugData; YulString name; }; +struct Identifier { langutil::DebugData::ConstPtr debugData; YulName name {}; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. /// @@ -86,7 +87,7 @@ struct VariableDeclaration { langutil::DebugData::ConstPtr debugData; TypedNameL /// Block that creates a scope (frees declared stack variables) struct Block { langutil::DebugData::ConstPtr debugData; std::vector statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") -struct FunctionDefinition { langutil::DebugData::ConstPtr debugData; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; +struct FunctionDefinition { langutil::DebugData::ConstPtr debugData; YulName name{}; TypedNameList parameters; TypedNameList returnVariables; Block body; }; /// Conditional execution without "else" part. struct If { langutil::DebugData::ConstPtr debugData; std::unique_ptr condition; Block body; }; /// Switch case or default case diff --git a/libyul/ASTForward.h b/libyul/ASTForward.h index 12992edf8872..129dffe9c105 100644 --- a/libyul/ASTForward.h +++ b/libyul/ASTForward.h @@ -46,6 +46,7 @@ struct Continue; struct Leave; struct ExpressionStatement; struct Block; +struct Dialect; struct TypedName; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index ac97f988d47d..a27260d93ae9 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -68,7 +68,7 @@ bool AsmAnalyzer::analyze(Block const& _block) auto watcher = m_errorReporter.errorWatcher(); try { - if (!(ScopeFiller(m_info, m_errorReporter))(_block)) + if (!(ScopeFiller(m_info, m_errorReporter, m_yulNameRepository))(_block)) return false; (*this)(_block); @@ -84,7 +84,7 @@ bool AsmAnalyzer::analyze(Block const& _block) return watcher.ok(); } -AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object) +AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(YulNameRepository const& _yulNameRepository, Object const& _object) { ErrorList errorList; langutil::ErrorReporter errors(errorList); @@ -92,7 +92,7 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, bool success = yul::AsmAnalyzer( analysisInfo, errors, - _dialect, + _yulNameRepository, {}, _object.qualifiedDataNames() ).analyze(*_object.code); @@ -100,7 +100,7 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, return analysisInfo; } -std::vector AsmAnalyzer::operator()(Literal const& _literal) +std::vector AsmAnalyzer::operator()(Literal const& _literal) { expectValidType(_literal.type, nativeLocationOf(_literal)); bool erroneousLiteralValue = false; @@ -119,12 +119,16 @@ std::vector AsmAnalyzer::operator()(Literal const& _literal) m_errorReporter.typeError(6708_error, nativeLocationOf(_literal), "Number literal too large (> 256 bits)"); } - if (!m_dialect.validTypeForLiteral(_literal.kind, _literal.value, _literal.type)) + if (!m_yulNameRepository.dialect().validTypeForLiteral(_literal.kind, _literal.value, _literal.type, m_yulNameRepository)) { m_errorReporter.typeError( 5170_error, nativeLocationOf(_literal), - "Invalid type \"" + _literal.type.str() + "\" for literal \"" + formatLiteral(_literal) + "\"." + fmt::format( + R"(Invalid type "{}" for literal "{}".)", + m_yulNameRepository.labelOf(_literal.type), + formatLiteral(_literal, false) + ) ); } @@ -132,11 +136,11 @@ std::vector AsmAnalyzer::operator()(Literal const& _literal) return {_literal.type}; } -std::vector AsmAnalyzer::operator()(Identifier const& _identifier) +std::vector AsmAnalyzer::operator()(Identifier const& _identifier) { - yulAssert(!_identifier.name.empty(), ""); + yulAssert(_identifier.name != YulNameRepository::emptyName()); auto watcher = m_errorReporter.errorWatcher(); - YulString type = m_dialect.defaultType; + auto type = m_yulNameRepository.predefined().defaultType; if (m_currentScope->lookup(_identifier.name, GenericVisitor{ [&](Scope::Variable const& _var) @@ -145,7 +149,10 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) m_errorReporter.declarationError( 4990_error, nativeLocationOf(_identifier), - "Variable " + _identifier.name.str() + " used before it was declared." + fmt::format( + "Variable {} used before it was declared.", + m_yulNameRepository.labelOf(_identifier.name) + ) ); type = _var.type; }, @@ -154,7 +161,7 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) m_errorReporter.typeError( 6041_error, nativeLocationOf(_identifier), - "Function " + _identifier.name.str() + " used without being called." + fmt::format("Function {} used without being called.", m_yulNameRepository.labelOf(_identifier.name)) ); } })) @@ -179,7 +186,7 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) m_errorReporter.declarationError( 8198_error, nativeLocationOf(_identifier), - "Identifier \"" + _identifier.name.str() + "\" not found." + fmt::format("Identifier \"{}\" not found.", m_yulNameRepository.labelOf(_identifier.name)) ); } @@ -190,7 +197,7 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) void AsmAnalyzer::operator()(ExpressionStatement const& _statement) { auto watcher = m_errorReporter.errorWatcher(); - std::vector types = std::visit(*this, _statement.expression); + std::vector types = std::visit(*this, _statement.expression); if (watcher.ok() && !types.empty()) m_errorReporter.typeError( 3083_error, @@ -209,30 +216,30 @@ void AsmAnalyzer::operator()(Assignment const& _assignment) size_t const numVariables = _assignment.variableNames.size(); yulAssert(numVariables >= 1, ""); - std::set variables; + std::set variables; for (auto const& _variableName: _assignment.variableNames) if (!variables.insert(_variableName.name).second) m_errorReporter.declarationError( 9005_error, nativeLocationOf(_assignment), - "Variable " + - _variableName.name.str() + - " occurs multiple times on the left-hand side of the assignment." + fmt::format( + "Variable {} occurs multiple times on the left-hand side of the assignment.", + m_yulNameRepository.labelOf(_variableName.name) + ) ); - std::vector types = std::visit(*this, *_assignment.value); + std::vector types = std::visit(*this, *_assignment.value); if (types.size() != numVariables) m_errorReporter.declarationError( 8678_error, nativeLocationOf(_assignment), - "Variable count for assignment to \"" + - joinHumanReadable(applyMap(_assignment.variableNames, [](auto const& _identifier){ return _identifier.name.str(); })) + - "\" does not match number of values (" + - std::to_string(numVariables) + - " vs. " + - std::to_string(types.size()) + - ")" + fmt::format( + "Variable count for assignment to \"{}\" does not match number of values ({} vs. {})", + joinHumanReadable(applyMap(_assignment.variableNames, [this](auto const& _identifier){ return m_yulNameRepository.labelOf(_identifier.name); })), + numVariables, + types.size() + ) ); for (size_t i = 0; i < numVariables; ++i) @@ -259,23 +266,22 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) if (_varDecl.value) { - std::vector types = std::visit(*this, *_varDecl.value); + std::vector types = std::visit(*this, *_varDecl.value); if (types.size() != numVariables) m_errorReporter.declarationError( 3812_error, nativeLocationOf(_varDecl), - "Variable count mismatch for declaration of \"" + - joinHumanReadable(applyMap(_varDecl.variables, [](auto const& _identifier){ return _identifier.name.str(); })) + - + "\": " + - std::to_string(numVariables) + - " variables and " + - std::to_string(types.size()) + - " values." + fmt::format( + "Variable count mismatch for declaration of \"{}\": {} variables and {} values.", + joinHumanReadable(applyMap(_varDecl.variables, [this](auto const& _identifier){ return m_yulNameRepository.labelOf(_identifier.name); })), + numVariables, + types.size() + ) ); for (size_t i = 0; i < _varDecl.variables.size(); ++i) { - YulString givenType = m_dialect.defaultType; + auto givenType = m_yulNameRepository.predefined().defaultType; if (i < types.size()) givenType = types[i]; TypedName const& variable = _varDecl.variables[i]; @@ -283,7 +289,11 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) m_errorReporter.typeError( 3947_error, nativeLocationOf(variable), - "Assigning value of type \"" + givenType.str() + "\" to variable of type \"" + variable.type.str() + "\"." + fmt::format( + R"(Assigning value of type "{}" to variable of type "{}".)", + m_yulNameRepository.labelOf(givenType), + m_yulNameRepository.labelOf(variable.type) + ) ); } } @@ -296,11 +306,11 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) void AsmAnalyzer::operator()(FunctionDefinition const& _funDef) { - yulAssert(!_funDef.name.empty(), ""); + yulAssert(_funDef.name != YulNameRepository::emptyName()); expectValidIdentifier(_funDef.name, nativeLocationOf(_funDef)); Block const* virtualBlock = m_info.virtualBlocks.at(&_funDef).get(); yulAssert(virtualBlock, ""); - Scope& varScope = scope(virtualBlock); + Scope const& varScope = scope(virtualBlock); for (auto const& var: _funDef.parameters + _funDef.returnVariables) { expectValidIdentifier(var.name, nativeLocationOf(var)); @@ -311,17 +321,17 @@ void AsmAnalyzer::operator()(FunctionDefinition const& _funDef) (*this)(_funDef.body); } -std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) +std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) { - yulAssert(!_funCall.functionName.name.empty(), ""); + yulAssert(_funCall.functionName.name != YulNameRepository::emptyName()); auto watcher = m_errorReporter.errorWatcher(); - std::vector const* parameterTypes = nullptr; - std::vector const* returnTypes = nullptr; + std::vector const* parameterTypes = nullptr; + std::vector const* returnTypes = nullptr; std::vector> const* literalArguments = nullptr; - if (BuiltinFunction const* f = m_dialect.builtin(_funCall.functionName.name)) + if (auto const* f = m_yulNameRepository.builtin(_funCall.functionName.name)) { - if (_funCall.functionName.name == "selfdestruct"_yulstring) + if (_funCall.functionName.name == m_yulNameRepository.predefined().selfdestruct) m_errorReporter.warning( 1699_error, nativeLocationOf(_funCall.functionName), @@ -334,7 +344,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) ); else if ( m_evmVersion.supportsTransientStorage() && - _funCall.functionName.name == "tstore"_yulstring && + _funCall.functionName.name == m_yulNameRepository.predefined().tstore && !m_errorReporter.hasError({2394}) ) m_errorReporter.warning( @@ -349,11 +359,11 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) parameterTypes = &f->parameters; returnTypes = &f->returns; - if (!f->literalArguments.empty()) - literalArguments = &f->literalArguments; + if (!f->data->literalArguments.empty()) + literalArguments = &f->data->literalArguments; validateInstructions(_funCall); - m_sideEffects += f->sideEffects; + m_sideEffects += f->data->sideEffects; } else if (m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{ [&](Scope::Variable const&) @@ -385,7 +395,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.declarationError( 4619_error, nativeLocationOf(_funCall.functionName), - "Function \"" + _funCall.functionName.name.str() + "\" not found." + fmt::format("Function \"{}\" not found.", m_yulNameRepository.labelOf(_funCall.functionName.name)) ); yulAssert(!watcher.ok(), "Expected a reported error."); } @@ -394,13 +404,15 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.typeError( 7000_error, nativeLocationOf(_funCall.functionName), - "Function \"" + _funCall.functionName.name.str() + "\" expects " + - std::to_string(parameterTypes->size()) + - " arguments but got " + - std::to_string(_funCall.arguments.size()) + "." + fmt::format( + "Function \"{}\" expects {} arguments but got {}.", + m_yulNameRepository.labelOf(_funCall.functionName.name), + parameterTypes->size(), + _funCall.arguments.size() + ) ); - std::vector argTypes; + std::vector argTypes; for (size_t i = _funCall.arguments.size(); i > 0; i--) { Expression const& arg = _funCall.arguments[i - 1]; @@ -424,8 +436,8 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) ); else if (*literalArgumentKind == LiteralKind::String) { - std::string functionName = _funCall.functionName.name.str(); - if (functionName == "datasize" || functionName == "dataoffset") + auto const functionName = _funCall.functionName.name; + if (functionName == m_yulNameRepository.predefined().datasize || functionName == m_yulNameRepository.predefined().dataoffset) { auto const& argumentAsLiteral = std::get(arg); if (!m_dataNames.count(YulString(formatLiteral(argumentAsLiteral)))) @@ -435,7 +447,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) "Unknown data object \"" + formatLiteral(argumentAsLiteral) + "\"." ); } - else if (functionName.substr(0, "verbatim_"s.size()) == "verbatim_") + else if (m_yulNameRepository.isVerbatimFunction(functionName)) { auto const& literalValue = std::get(arg).value; yulAssert(literalValue.unlimited()); // verbatim literals are always unlimited @@ -465,7 +477,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) return *returnTypes; } else if (returnTypes) - return std::vector(returnTypes->size(), m_dialect.defaultType); + return std::vector(returnTypes->size(), m_yulNameRepository.predefined().defaultType); else return {}; } @@ -488,7 +500,7 @@ void AsmAnalyzer::operator()(Switch const& _switch) "\"switch\" statement with only a default case." ); - YulString valueType = expectExpression(*_switch.expression); + auto valueType = expectExpression(*_switch.expression); std::set cases; for (auto const& _case: _switch.cases) @@ -553,9 +565,9 @@ void AsmAnalyzer::operator()(Block const& _block) m_currentScope = previousScope; } -YulString AsmAnalyzer::expectExpression(Expression const& _expr) +Type AsmAnalyzer::expectExpression(Expression const& _expr) { - std::vector types = std::visit(*this, _expr); + std::vector types = std::visit(*this, _expr); if (types.size() != 1) m_errorReporter.typeError( 3950_error, @@ -564,38 +576,38 @@ YulString AsmAnalyzer::expectExpression(Expression const& _expr) std::to_string(types.size()) + " values instead." ); - return types.empty() ? m_dialect.defaultType : types.front(); + return types.empty() ? m_yulNameRepository.predefined().defaultType : types.front(); } -YulString AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) +Type AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal) const { yulAssert(_literal.kind == LiteralKind::String); - yulAssert(m_dialect.validTypeForLiteral(LiteralKind::String, _literal.value, _literal.type)); + yulAssert(m_yulNameRepository.dialect().validTypeForLiteral(LiteralKind::String, _literal.value, _literal.type, m_yulNameRepository)); yulAssert(_literal.value.unlimited()); - return {_literal.type}; + return _literal.type; } void AsmAnalyzer::expectBoolExpression(Expression const& _expr) { - YulString type = expectExpression(_expr); - if (type != m_dialect.boolType) + auto const type = expectExpression(_expr); + if (type != m_yulNameRepository.predefined().boolType) m_errorReporter.typeError( 1733_error, nativeLocationOf(_expr), - "Expected a value of boolean type \"" + - m_dialect.boolType.str() + - "\" but got \"" + - type.str() + - "\"" + fmt::format( + R"(Expected a value of boolean type "{}" but got "{}")", + m_yulNameRepository.labelOf(m_yulNameRepository.predefined().boolType), + m_yulNameRepository.labelOf(type) + ) ); } -void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueType) +void AsmAnalyzer::checkAssignment(Identifier const& _variable, Type _valueType) { - yulAssert(!_variable.name.empty(), ""); + yulAssert(_variable.name != YulNameRepository::emptyName()); auto watcher = m_errorReporter.errorWatcher(); - YulString const* variableType = nullptr; + Type const* variableType = nullptr; bool found = false; if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name)) { @@ -613,7 +625,7 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT m_errorReporter.declarationError( 1133_error, nativeLocationOf(_variable), - "Variable " + _variable.name.str() + " used before it was declared." + fmt::format("Variable {} used before it was declared.", m_yulNameRepository.labelOf(_variable.name)) ); else variableType = &std::get(*var).type; @@ -625,7 +637,7 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT if (m_resolver(_variable, yul::IdentifierContext::LValue, insideFunction)) { found = true; - variableType = &m_dialect.defaultType; + variableType = &m_yulNameRepository.predefined().defaultType; } } @@ -636,11 +648,11 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT m_errorReporter.typeError( 9547_error, nativeLocationOf(_variable), - "Assigning a value of type \"" + - _valueType.str() + - "\" to a variable of type \"" + - variableType->str() + - "\"." + fmt::format( + R"(Assigning a value of type "{}" to a variable of type "{}".)", + m_yulNameRepository.labelOf(_valueType), + m_yulNameRepository.labelOf(*variableType) + ) ); yulAssert(!watcher.ok() || variableType, ""); @@ -654,59 +666,67 @@ Scope& AsmAnalyzer::scope(Block const* _block) return *scopePtr; } -void AsmAnalyzer::expectValidIdentifier(YulString _identifier, SourceLocation const& _location) +void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation const& _location) { + auto const label = m_yulNameRepository.labelOf(_identifier); // NOTE: the leading dot case is handled by the parser not allowing it. - if (boost::ends_with(_identifier.str(), ".")) + if (boost::ends_with(label, ".")) m_errorReporter.syntaxError( 3384_error, _location, - "\"" + _identifier.str() + "\" is not a valid identifier (ends with a dot)." + fmt::format("\"{}\" is not a valid identifier (ends with a dot).", label) ); - if (_identifier.str().find("..") != std::string::npos) + if (label.find("..") != std::string::npos) m_errorReporter.syntaxError( 7771_error, _location, - "\"" + _identifier.str() + "\" is not a valid identifier (contains consecutive dots)." + fmt::format("\"{}\" is not a valid identifier (contains consecutive dots).", label) ); - if (m_dialect.reservedIdentifier(_identifier)) + if (m_yulNameRepository.dialect().reservedIdentifier(label)) m_errorReporter.declarationError( 5017_error, _location, - "The identifier \"" + _identifier.str() + "\" is reserved and can not be used." + fmt::format("The identifier \"{}\" is reserved and can not be used.", label) ); } -void AsmAnalyzer::expectValidType(YulString _type, SourceLocation const& _location) +void AsmAnalyzer::expectValidType(Type _type, SourceLocation const& _location) { - if (!m_dialect.types.count(_type)) + if (!m_yulNameRepository.isType(_type)) m_errorReporter.typeError( 5473_error, _location, - fmt::format("\"{}\" is not a valid type (user defined types are not yet supported).", _type) + fmt::format("\"{}\" is not a valid type (user defined types are not yet supported).", m_yulNameRepository.labelOf(_type)) ); } -void AsmAnalyzer::expectType(YulString _expectedType, YulString _givenType, SourceLocation const& _location) +void AsmAnalyzer::expectType(Type _expectedType, Type _givenType, SourceLocation const& _location) { if (_expectedType != _givenType) m_errorReporter.typeError( 3781_error, _location, - fmt::format("Expected a value of type \"{}\" but got \"{}\".", _expectedType, _givenType) + fmt::format( + R"(Expected a value of type "{}" but got "{}".)", + m_yulNameRepository.labelOf(_expectedType), + m_yulNameRepository.labelOf(_givenType) + ) ); } -bool AsmAnalyzer::validateInstructions(std::string const& _instructionIdentifier, langutil::SourceLocation const& _location) +bool AsmAnalyzer::validateInstructions(std::string_view const _instructionIdentifier, langutil::SourceLocation const& _location) { // NOTE: This function uses the default EVM version instead of the currently selected one. - auto const builtin = EVMDialect::strictAssemblyForEVM(EVMVersion{}).builtin(YulString(_instructionIdentifier)); - if (builtin && builtin->instruction.has_value()) - return validateInstructions(builtin->instruction.value(), _location); - else - return false; + auto const& defaultDialect = EVMDialect::strictAssemblyForEVM(EVMVersion{}); + { + auto const builtin = defaultDialect.builtin(_instructionIdentifier); + if (builtin && builtin->instruction.has_value()) + return validateInstructions(builtin->instruction.value(), _location); + else + return false; + } } bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocation const& _location) @@ -729,7 +749,7 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio _errorId, _location, fmt::format( - "The \"{instruction}\" instruction is {kind} VMs (you are currently compiling for \"{version}\").", + R"(The "{instruction}" instruction is {kind} VMs (you are currently compiling for "{version}").)", fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name)), fmt::arg("kind", vmKindMessage), fmt::arg("version", m_evmVersion.name()) @@ -786,5 +806,5 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall) { - return validateInstructions(_functionCall.functionName.name.str(), nativeLocationOf(_functionCall.functionName)); + return validateInstructions(m_yulNameRepository.labelOf(_functionCall.functionName.name), nativeLocationOf(_functionCall.functionName)); } diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index c49e6855914d..00c5fc8e4446 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -59,17 +59,17 @@ class AsmAnalyzer explicit AsmAnalyzer( AsmAnalysisInfo& _analysisInfo, langutil::ErrorReporter& _errorReporter, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, ExternalIdentifierAccess::Resolver _resolver = ExternalIdentifierAccess::Resolver(), std::set _dataNames = {} ): m_resolver(std::move(_resolver)), m_info(_analysisInfo), m_errorReporter(_errorReporter), - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_dataNames(std::move(_dataNames)) { - if (EVMDialect const* evmDialect = dynamic_cast(&m_dialect)) + if (EVMDialect const* evmDialect = dynamic_cast(&m_yulNameRepository.dialect())) m_evmVersion = evmDialect->evmVersion(); } @@ -77,15 +77,15 @@ class AsmAnalyzer /// Performs analysis on the outermost code of the given object and returns the analysis info. /// Asserts on failure. - static AsmAnalysisInfo analyzeStrictAssertCorrect(Dialect const& _dialect, Object const& _object); + static AsmAnalysisInfo analyzeStrictAssertCorrect(YulNameRepository const& _yulNameRepository, Object const& _object); - std::vector operator()(Literal const& _literal); - std::vector operator()(Identifier const&); + std::vector operator()(Literal const& _literal); + std::vector operator()(Identifier const&); void operator()(ExpressionStatement const&); void operator()(Assignment const& _assignment); void operator()(VariableDeclaration const& _variableDeclaration); void operator()(FunctionDefinition const& _functionDefinition); - std::vector operator()(FunctionCall const& _functionCall); + std::vector operator()(FunctionCall const& _functionCall); void operator()(If const& _if); void operator()(Switch const& _switch); void operator()(ForLoop const& _forLoop); @@ -99,23 +99,23 @@ class AsmAnalyzer private: /// Visits the expression, expects that it evaluates to exactly one value and /// returns the type. Reports errors on errors and returns the default type. - YulString expectExpression(Expression const& _expr); - YulString expectUnlimitedStringLiteral(Literal const& _literal); + Type expectExpression(Expression const& _expr); + Type expectUnlimitedStringLiteral(Literal const& _literal) const; /// Visits the expression and expects it to return a single boolean value. /// Reports an error otherwise. void expectBoolExpression(Expression const& _expr); /// Verifies that a variable to be assigned to exists, can be assigned to /// and has the same type as the value. - void checkAssignment(Identifier const& _variable, YulString _valueType); + void checkAssignment(Identifier const& _variable, Type _valueType); Scope& scope(Block const* _block); - void expectValidIdentifier(YulString _identifier, langutil::SourceLocation const& _location); - void expectValidType(YulString _type, langutil::SourceLocation const& _location); - void expectType(YulString _expectedType, YulString _givenType, langutil::SourceLocation const& _location); + void expectValidIdentifier(YulName _identifier, langutil::SourceLocation const& _location); + void expectValidType(Type _type, langutil::SourceLocation const& _location); + void expectType(Type _expectedType, Type _givenType, langutil::SourceLocation const& _location); bool validateInstructions(evmasm::Instruction _instr, langutil::SourceLocation const& _location); - bool validateInstructions(std::string const& _instrIdentifier, langutil::SourceLocation const& _location); + bool validateInstructions(std::string_view _instrIdentifier, langutil::SourceLocation const& _location); bool validateInstructions(FunctionCall const& _functionCall); yul::ExternalIdentifierAccess::Resolver m_resolver; @@ -126,7 +126,7 @@ class AsmAnalyzer AsmAnalysisInfo& m_info; langutil::ErrorReporter& m_errorReporter; langutil::EVMVersion m_evmVersion; - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; /// Names of data objects to be referenced by builtin functions with literal arguments. std::set m_dataNames; ForLoop const* m_currentForLoop = nullptr; diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index 60475497542a..69b6803920d5 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -24,12 +24,16 @@ #include #include #include +#include #include #include namespace solidity::yul { +AsmJsonConverter::AsmJsonConverter(std::optional _sourceIndex, YulNameRepository const& _yulNameRepository): + m_sourceIndex(_sourceIndex), m_yulNameRepository(_yulNameRepository) {} + Json AsmJsonConverter::operator()(Block const& _node) const { Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulBlock"); @@ -39,10 +43,10 @@ Json AsmJsonConverter::operator()(Block const& _node) const Json AsmJsonConverter::operator()(TypedName const& _node) const { - yulAssert(!_node.name.empty(), "Invalid variable name."); + yulAssert(YulNameRepository::emptyName() != _node.name, "Invalid variable name."); Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulTypedName"); - ret["name"] = _node.name.str(); - ret["type"] = _node.type.str(); + ret["name"] = m_yulNameRepository.labelOf(_node.name); + ret["type"] = m_yulNameRepository.labelOf(_node.type); return ret; } @@ -63,7 +67,7 @@ Json AsmJsonConverter::operator()(Literal const& _node) const ret["hexValue"] = util::toHex(util::asBytes(formatLiteral(_node))); break; } - ret["type"] = _node.type.str(); + ret["type"] = m_yulNameRepository.labelOf(_node.type); { auto const formattedLiteral = formatLiteral(_node); if (util::validateUTF8(formattedLiteral)) @@ -74,9 +78,9 @@ Json AsmJsonConverter::operator()(Literal const& _node) const Json AsmJsonConverter::operator()(Identifier const& _node) const { - yulAssert(!_node.name.empty(), "Invalid identifier"); + yulAssert(YulNameRepository::emptyName() != _node.name, "Invalid identifier"); Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIdentifier"); - ret["name"] = _node.name.str(); + ret["name"] = m_yulNameRepository.labelOf(_node.name); return ret; } @@ -116,9 +120,9 @@ Json AsmJsonConverter::operator()(VariableDeclaration const& _node) const Json AsmJsonConverter::operator()(FunctionDefinition const& _node) const { - yulAssert(!_node.name.empty(), "Invalid function name."); + yulAssert(YulNameRepository::emptyName() != _node.name, "Invalid function name."); Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionDefinition"); - ret["name"] = _node.name.str(); + ret["name"] = m_yulNameRepository.labelOf(_node.name); for (auto const& var: _node.parameters) ret["parameters"].emplace_back((*this)(var)); for (auto const& var: _node.returnVariables) diff --git a/libyul/AsmJsonConverter.h b/libyul/AsmJsonConverter.h index 9c4b5d5e8ebc..f5a9b47949b7 100644 --- a/libyul/AsmJsonConverter.h +++ b/libyul/AsmJsonConverter.h @@ -41,7 +41,7 @@ class AsmJsonConverter: public boost::static_visitor public: /// Create a converter to JSON for any block of inline assembly /// @a _sourceIndex to be used to abbreviate source name in the source locations - explicit AsmJsonConverter(std::optional _sourceIndex): m_sourceIndex(_sourceIndex) {} + explicit AsmJsonConverter(std::optional _sourceIndex, YulNameRepository const& _yulNameRepository); Json operator()(Block const& _node) const; Json operator()(TypedName const& _node) const; @@ -67,6 +67,7 @@ class AsmJsonConverter: public boost::static_visitor Json vectorOfVariantsToJson(std::vector const& vec) const; std::optional const m_sourceIndex; + YulNameRepository const& m_yulNameRepository; }; } diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index 63b1d65d26ec..e973406ee974 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -72,8 +73,8 @@ Json AsmJsonImporter::member(Json const& _node, std::string const& _name) TypedName AsmJsonImporter::createTypedName(Json const& _node) { auto typedName = createAsmNode(_node); - typedName.type = YulString{member(_node, "type").get()}; - typedName.name = YulString{member(_node, "name").get()}; + typedName.type = m_yulNameRepository.nameOfType(member(_node, "type").get()); + typedName.name = m_yulNameRepository.defineName(member(_node, "name").get()); return typedName; } @@ -171,7 +172,7 @@ Literal AsmJsonImporter::createLiteral(Json const& _node) value = util::asString(util::fromHex(member(_node, "hexValue").get())); else value = member(_node, "value").get(); - lit.type = YulString{member(_node, "type").get()}; + lit.type = m_yulNameRepository.nameOfType(member(_node, "type").get()); if (kind == "number") { langutil::CharStream charStream(value, ""); @@ -219,7 +220,7 @@ Leave AsmJsonImporter::createLeave(Json const& _node) Identifier AsmJsonImporter::createIdentifier(Json const& _node) { auto identifier = createAsmNode(_node); - identifier.name = YulString(member(_node, "name").get()); + identifier.name = m_yulNameRepository.defineName(member(_node, "name").get()); return identifier; } @@ -269,7 +270,7 @@ VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json const& _node FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json const& _node) { auto funcDef = createAsmNode(_node); - funcDef.name = YulString{member(_node, "name").get()}; + funcDef.name = m_yulNameRepository.defineName(member(_node, "name").get()); if (_node.contains("parameters")) for (auto const& var: member(_node, "parameters")) diff --git a/libyul/AsmJsonImporter.h b/libyul/AsmJsonImporter.h index 87933761a654..d7bad0a0c2c2 100644 --- a/libyul/AsmJsonImporter.h +++ b/libyul/AsmJsonImporter.h @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -38,8 +39,8 @@ namespace solidity::yul class AsmJsonImporter { public: - explicit AsmJsonImporter(std::vector> const& _sourceNames): - m_sourceNames(_sourceNames) + explicit AsmJsonImporter(std::vector> const& _sourceNames, YulNameRepository& _yulNameRepository): + m_yulNameRepository(_yulNameRepository), m_dialect(_yulNameRepository.dialect()), m_sourceNames(_sourceNames) {} yul::Block createBlock(Json const& _node); @@ -72,6 +73,8 @@ class AsmJsonImporter yul::Break createBreak(Json const& _node); yul::Continue createContinue(Json const& _node); + YulNameRepository& m_yulNameRepository; + Dialect const& m_dialect; std::vector> const& m_sourceNames; }; diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 2ae4dd805bc1..b92ce7b9d942 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -432,8 +432,14 @@ Statement Parser::parseStatement() auto const& identifier = std::get(elementary); - if (m_dialect.builtin(identifier.name)) - fatalParserError(6272_error, "Cannot assign to builtin function \"" + identifier.name.str() + "\"."); + if (m_yulNameRepository.isBuiltinName(identifier.name)) + fatalParserError( + 6272_error, + fmt::format( + "Cannot assign to builtin function \"{}\".", + m_yulNameRepository.labelOf(identifier.name) + ) + ); assignment.variableNames.emplace_back(identifier); @@ -515,11 +521,11 @@ Expression Parser::parseExpression(bool _unlimitedLiteralArgument) { if (currentToken() == Token::LParen) return parseCall(std::move(operation)); - if (m_dialect.builtin(_identifier.name)) + if (m_yulNameRepository.isBuiltinName(_identifier.name)) fatalParserError( 7104_error, nativeLocationOf(_identifier), - "Builtin function \"" + _identifier.name.str() + "\" must be called." + fmt::format("Builtin function \"{}\" must be called.", m_yulNameRepository.labelOf(_identifier.name)) ); return std::move(_identifier); }, @@ -537,7 +543,7 @@ std::variant Parser::parseLiteralOrIdentifier(bool _unlimit { case Token::Identifier: { - Identifier identifier{createDebugData(), YulString{currentLiteral()}}; + Identifier identifier{createDebugData(), m_yulNameRepository.defineName(currentLiteral())}; advance(); return identifier; } @@ -571,7 +577,7 @@ std::variant Parser::parseLiteralOrIdentifier(bool _unlimit createDebugData(), kind, valueOfLiteral(currentLiteral(), kind, _unlimitedLiteralArgument && kind == LiteralKind::String), - kind == LiteralKind::Boolean ? m_dialect.boolType : m_dialect.defaultType + kind == LiteralKind::Boolean ? m_yulNameRepository.predefined().boolType : m_yulNameRepository.predefined().defaultType }; advance(); if (currentToken() == Token::Colon) @@ -674,9 +680,9 @@ FunctionCall Parser::parseCall(std::variant&& _initialOp) FunctionCall ret; ret.functionName = std::move(std::get(_initialOp)); ret.debugData = ret.functionName.debugData; - auto const isUnlimitedLiteralArgument = [f=m_dialect.builtin(ret.functionName.name)](size_t const index) { - if (f && index < f->literalArguments.size()) - return f->literalArgument(index).has_value(); + auto const isUnlimitedLiteralArgument = [f=m_yulNameRepository.builtin(ret.functionName.name)](size_t const index) { + if (f && index < f->data->literalArguments.size()) + return f->data->literalArgument(index).has_value(); return false; }; size_t argumentIndex {0}; @@ -707,16 +713,22 @@ TypedName Parser::parseTypedName() typedName.type = expectAsmIdentifier(); } else - typedName.type = m_dialect.defaultType; + typedName.type = m_yulNameRepository.predefined().defaultType; return typedName; } -YulString Parser::expectAsmIdentifier() +Type Parser::expectAsmIdentifier() { - YulString name{currentLiteral()}; - if (currentToken() == Token::Identifier && m_dialect.builtin(name)) - fatalParserError(5568_error, "Cannot use builtin function name \"" + name.str() + "\" as identifier name."); + auto const name = m_yulNameRepository.defineName(currentLiteral()); + if (currentToken() == Token::Identifier && m_yulNameRepository.dialect().builtin(currentLiteral())) + fatalParserError( + 5568_error, + fmt::format( + "Cannot use builtin function name \"{}\" as identifier name.", + currentLiteral() + ) + ); // NOTE: We keep the expectation here to ensure the correct source location for the error above. expectToken(Token::Identifier); return name; diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 3348904091f2..5eca4041d1b9 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -55,11 +55,11 @@ class Parser: public langutil::ParserBase explicit Parser( langutil::ErrorReporter& _errorReporter, - Dialect const& _dialect, + YulNameRepository& _yulNameRepository, std::optional _locationOverride = {} ): ParserBase(_errorReporter), - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_locationOverride{_locationOverride ? *_locationOverride : langutil::SourceLocation{}}, m_useSourceLocationFrom{ _locationOverride ? @@ -72,11 +72,11 @@ class Parser: public langutil::ParserBase /// from the comments (via @src and other tags). explicit Parser( langutil::ErrorReporter& _errorReporter, - Dialect const& _dialect, + YulNameRepository& _yulNameRepository, std::optional>> _sourceNames ): ParserBase(_errorReporter), - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_sourceNames{std::move(_sourceNames)}, m_useSourceLocationFrom{ m_sourceNames.has_value() ? @@ -146,7 +146,7 @@ class Parser: public langutil::ParserBase FunctionDefinition parseFunctionDefinition(); FunctionCall parseCall(std::variant&& _initialOp); TypedName parseTypedName(); - YulString expectAsmIdentifier(); + Type expectAsmIdentifier(); /// Reports an error if we are currently not inside the body part of a for loop. void checkBreakContinuePosition(std::string const& _which); @@ -154,7 +154,7 @@ class Parser: public langutil::ParserBase static bool isValidNumberLiteral(std::string const& _literal); private: - Dialect const& m_dialect; + YulNameRepository& m_yulNameRepository; std::optional>> m_sourceNames; langutil::SourceLocation m_locationOverride; diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 191fc5d2d6a1..a7f335080c60 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -65,8 +65,8 @@ std::string AsmPrinter::operator()(Literal const& _literal) std::string AsmPrinter::operator()(Identifier const& _identifier) { - yulAssert(!_identifier.name.empty(), "Invalid identifier."); - return formatDebugData(_identifier) + _identifier.name.str(); + yulAssert(_identifier.name != YulNameRepository::emptyName(), "Invalid identifier."); + return formatDebugData(_identifier) + std::string(m_nameRepository.labelOf(_identifier.name)); } std::string AsmPrinter::operator()(ExpressionStatement const& _statement) @@ -109,10 +109,10 @@ std::string AsmPrinter::operator()(VariableDeclaration const& _variableDeclarati std::string AsmPrinter::operator()(FunctionDefinition const& _functionDefinition) { - yulAssert(!_functionDefinition.name.empty(), "Invalid function name."); + yulAssert(_functionDefinition.name != YulNameRepository::emptyName(), "Invalid function name."); std::string out = formatDebugData(_functionDefinition); - out += "function " + _functionDefinition.name.str() + "("; + out += "function " + std::string(m_nameRepository.labelOf(_functionDefinition.name)) + "("; out += boost::algorithm::join( _functionDefinition.parameters | ranges::views::transform( [this](TypedName argument) { return formatTypedName(argument); } @@ -237,26 +237,26 @@ std::string AsmPrinter::operator()(Block const& _block) } } -std::string AsmPrinter::formatTypedName(TypedName _variable) +std::string AsmPrinter::formatTypedName(TypedName const& _variable) { - yulAssert(!_variable.name.empty(), "Invalid variable name."); - return formatDebugData(_variable) + _variable.name.str() + appendTypeName(_variable.type); + yulAssert(_variable.name != YulNameRepository::emptyName(), "Invalid variable name."); + return formatDebugData(_variable) + std::string(m_nameRepository.labelOf(_variable.name)) + appendTypeName(_variable.type); } -std::string AsmPrinter::appendTypeName(YulString _type, bool _isBoolLiteral) const +std::string AsmPrinter::appendTypeName(Type _type, bool const _isBoolLiteral) const { - if (m_dialect && !_type.empty()) + if (m_printingMode == Mode::OmitDefaultType && _type != YulNameRepository::emptyName()) { - if (!_isBoolLiteral && _type == m_dialect->defaultType) + if (!_isBoolLiteral && _type == m_nameRepository.predefined().defaultType) _type = {}; - else if (_isBoolLiteral && _type == m_dialect->boolType && !m_dialect->defaultType.empty()) + else if (_isBoolLiteral && _type == m_nameRepository.predefined().boolType && m_nameRepository.predefined().defaultType != YulNameRepository::emptyName()) // Special case: If we have a bool type but empty default type, do not remove the type. _type = {}; } - if (_type.empty()) + if (_type == YulNameRepository::emptyName()) return {}; else - return ":" + _type.str(); + return fmt::format(":{}", m_nameRepository.labelOf(_type)); } std::string AsmPrinter::formatSourceLocation( diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index d3f80b9a09d5..bd6a54a361c2 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -25,6 +25,7 @@ #include #include +#include #include @@ -33,6 +34,7 @@ #include #include +#include namespace solidity::yul { @@ -46,13 +48,21 @@ struct Dialect; class AsmPrinter { public: + enum class Mode + { + OmitDefaultType, + FullTypeInfo + }; + explicit AsmPrinter( - Dialect const* _dialect = nullptr, + YulNameRepository const& _nameRepository, + Mode const _printingMode = Mode::FullTypeInfo, std::optional>> _sourceIndexToName = {}, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr ): - m_dialect(_dialect), + m_nameRepository(_nameRepository), + m_printingMode(_printingMode), m_debugInfoSelection(_debugInfoSelection), m_soliditySourceProvider(_soliditySourceProvider) { @@ -61,13 +71,6 @@ class AsmPrinter m_nameToSourceIndex[*name] = index; } - explicit AsmPrinter( - Dialect const& _dialect, - std::optional>> _sourceIndexToName = {}, - langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), - langutil::CharStreamProvider const* _soliditySourceProvider = nullptr - ): AsmPrinter(&_dialect, _sourceIndexToName, _debugInfoSelection, _soliditySourceProvider) {} - std::string operator()(Literal const& _literal); std::string operator()(Identifier const& _identifier); std::string operator()(ExpressionStatement const& _expr); @@ -91,8 +94,8 @@ class AsmPrinter ); private: - std::string formatTypedName(TypedName _variable); - std::string appendTypeName(YulString _type, bool _isBoolLiteral = false) const; + std::string formatTypedName(TypedName const& _variable); + std::string appendTypeName(Type _type, bool _isBoolLiteral = false) const; std::string formatDebugData(langutil::DebugData::ConstPtr const& _debugData, bool _statement); template std::string formatDebugData(T const& _node) @@ -101,7 +104,8 @@ class AsmPrinter return formatDebugData(_node.debugData, !isExpression); } - Dialect const* const m_dialect = nullptr; + YulNameRepository const& m_nameRepository; + Mode const m_printingMode; std::map m_nameToSourceIndex; langutil::SourceLocation m_lastLocation = {}; langutil::DebugInfoSelection m_debugInfoSelection = {}; diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index b074fc4853a8..b45be894d98e 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -37,6 +37,8 @@ add_library(yul ScopeFiller.h Utilities.cpp Utilities.h + YulName.cpp + YulName.h YulString.h YulName.cpp YulName.h @@ -135,12 +137,8 @@ add_library(yul optimiser/Metrics.h optimiser/NameCollector.cpp optimiser/NameCollector.h - optimiser/NameDispenser.cpp - optimiser/NameDispenser.h optimiser/NameDisplacer.cpp optimiser/NameDisplacer.h - optimiser/NameSimplifier.cpp - optimiser/NameSimplifier.h optimiser/OptimiserStep.h optimiser/OptimizerUtilities.cpp optimiser/OptimizerUtilities.h diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 9e18f48d824c..49a96f15b427 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -31,17 +31,17 @@ using namespace solidity::yul; using namespace solidity::util; CompilabilityChecker::CompilabilityChecker( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Object const& _object, bool _optimizeStackAllocation ) { - if (auto const* evmDialect = dynamic_cast(&_dialect)) + if (auto const* evmDialect = dynamic_cast(&_yulNameRepository.dialect())) { NoOutputEVMDialect noOutputDialect(*evmDialect); yul::AsmAnalysisInfo analysisInfo = - yul::AsmAnalyzer::analyzeStrictAssertCorrect(noOutputDialect, _object); + yul::AsmAnalyzer::analyzeStrictAssertCorrect(_yulNameRepository, _object); BuiltinContext builtinContext; builtinContext.currentObject = &_object; @@ -54,6 +54,7 @@ CompilabilityChecker::CompilabilityChecker( assembly, analysisInfo, *_object.code, + _yulNameRepository, noOutputDialect, builtinContext, _optimizeStackAllocation diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index c046df94ffb9..782021dd4303 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -44,9 +44,9 @@ namespace solidity::yul */ struct CompilabilityChecker { - CompilabilityChecker(Dialect const& _dialect, Object const& _object, bool _optimizeStackAllocation); - std::map> unreachableVariables; - std::map stackDeficit; + CompilabilityChecker(YulNameRepository const& _yulNameRepository, Object const& _object, bool _optimizeStackAllocation); + std::map> unreachableVariables; + std::map stackDeficit; }; } diff --git a/libyul/ControlFlowSideEffectsCollector.cpp b/libyul/ControlFlowSideEffectsCollector.cpp index c657fa17cba2..445d8ed657db 100644 --- a/libyul/ControlFlowSideEffectsCollector.cpp +++ b/libyul/ControlFlowSideEffectsCollector.cpp @@ -167,10 +167,10 @@ ControlFlowNode* ControlFlowBuilder::newNode() ControlFlowSideEffectsCollector::ControlFlowSideEffectsCollector( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block const& _ast ): - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_cfgBuilder(_ast), m_functionReferences(FunctionReferenceResolver{_ast}.references()) { @@ -229,9 +229,9 @@ ControlFlowSideEffectsCollector::ControlFlowSideEffectsCollector( } } -std::map ControlFlowSideEffectsCollector::functionSideEffectsNamed() const +std::map ControlFlowSideEffectsCollector::functionSideEffectsNamed() const { - std::map result; + std::map result; for (auto&& [function, sideEffects]: m_functionSideEffects) yulAssert(result.insert({function->name, sideEffects}).second); return result; @@ -271,8 +271,8 @@ ControlFlowNode const* ControlFlowSideEffectsCollector::nextProcessableNode(Func ControlFlowSideEffects const& ControlFlowSideEffectsCollector::sideEffects(FunctionCall const& _call) const { - if (auto const* builtin = m_dialect.builtin(_call.functionName.name)) - return builtin->controlFlowSideEffects; + if (auto const* builtin = m_yulNameRepository.builtin(_call.functionName.name)) + return builtin->data->controlFlowSideEffects; else return m_functionSideEffects.at(m_functionReferences.at(&_call)); } diff --git a/libyul/ControlFlowSideEffectsCollector.h b/libyul/ControlFlowSideEffectsCollector.h index a4ab2bfae770..8f53dd9e14cc 100644 --- a/libyul/ControlFlowSideEffectsCollector.h +++ b/libyul/ControlFlowSideEffectsCollector.h @@ -92,7 +92,7 @@ class ControlFlowSideEffectsCollector { public: explicit ControlFlowSideEffectsCollector( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block const& _ast ); @@ -101,7 +101,7 @@ class ControlFlowSideEffectsCollector return m_functionSideEffects; } /// Returns the side effects by function name, requires unique function names. - std::map functionSideEffectsNamed() const; + std::map functionSideEffectsNamed() const; private: /// @returns false if nothing could be processed. @@ -121,7 +121,7 @@ class ControlFlowSideEffectsCollector /// `*_node->functionCall`. void recordReachabilityAndQueue(FunctionDefinition const& _function, ControlFlowNode const* _node); - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; ControlFlowBuilder m_cfgBuilder; /// Function references, but only for calls to user-defined functions. std::map m_functionReferences; diff --git a/libyul/Dialect.cpp b/libyul/Dialect.cpp index 69ca1e9dc68d..054c999c7a96 100644 --- a/libyul/Dialect.cpp +++ b/libyul/Dialect.cpp @@ -19,32 +19,32 @@ * Yul dialect. */ -#include #include +#include +#include using namespace solidity::yul; using namespace solidity::langutil; -Literal Dialect::zeroLiteralForType(solidity::yul::YulString _type) const +Literal Dialect::zeroLiteralForType(YulName const _type, YulNameRepository const& _nameRepository) const { - if (_type == boolType && _type != defaultType) + if (_type == _nameRepository.predefined().boolType && _type != _nameRepository.predefined().defaultType) return {DebugData::create(), LiteralKind::Boolean, LiteralValue(false), _type}; return {DebugData::create(), LiteralKind::Number, LiteralValue(0, std::nullopt), _type}; } - -Literal Dialect::trueLiteral() const +bool Dialect::validTypeForLiteral(LiteralKind _kind, LiteralValue const&, std::string_view _type) const { - if (boolType != defaultType) - return {DebugData::create(), LiteralKind::Boolean, LiteralValue(true), boolType}; + if (_kind == LiteralKind::Boolean) + return _type == boolType; else - return {DebugData::create(), LiteralKind::Number, LiteralValue(1), defaultType}; + return true; } -bool Dialect::validTypeForLiteral(LiteralKind _kind, LiteralValue const&, YulString _type) const +bool Dialect::validTypeForLiteral(LiteralKind _kind, LiteralValue const&, Type _type, YulNameRepository const& _nameRepository) const { if (_kind == LiteralKind::Boolean) - return _type == boolType; + return _type == _nameRepository.predefined().boolType; else return true; } @@ -58,22 +58,22 @@ Dialect const& Dialect::yulDeprecated() { // TODO will probably change, especially the list of types. dialect = std::make_unique(); - dialect->defaultType = "u256"_yulstring; - dialect->boolType = "bool"_yulstring; + dialect->defaultType = "u256"; + dialect->boolType = "bool"; dialect->types = { - "bool"_yulstring, - "u8"_yulstring, - "s8"_yulstring, - "u32"_yulstring, - "s32"_yulstring, - "u64"_yulstring, - "s64"_yulstring, - "u128"_yulstring, - "s128"_yulstring, - "u256"_yulstring, - "s256"_yulstring + "bool", + "u8", + "s8", + "u32", + "s32", + "u64", + "s64", + "u128", + "s128", + "u256", + "s256" }; - }; + } return *dialect; } diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 9f3cd22d1f24..c6f873db7de3 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -21,9 +21,9 @@ #pragma once -#include #include #include +#include #include #include @@ -33,16 +33,17 @@ namespace solidity::yul { class YulString; -using Type = YulString; enum class LiteralKind; class LiteralValue; struct Literal; struct BuiltinFunction { - YulString name; - std::vector parameters; - std::vector returns; + virtual ~BuiltinFunction() = default; + + std::string name; + std::vector parameters; + std::vector returns; SideEffects sideEffects; ControlFlowSideEffects controlFlowSideEffects; /// If true, this is the msize instruction or might contain it. @@ -58,42 +59,41 @@ struct BuiltinFunction struct Dialect { - /// Noncopiable. + /// Noncopyable. Dialect(Dialect const&) = delete; Dialect& operator=(Dialect const&) = delete; /// Default type, can be omitted. - YulString defaultType; + std::string defaultType; /// Type used for the literals "true" and "false". - YulString boolType; - std::set types = {{}}; + std::string boolType; + std::set types = {{}}; /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. - virtual BuiltinFunction const* builtin(YulString /*_name*/) const { return nullptr; } + virtual BuiltinFunction const* builtin(std::string_view /*_name*/) const { return nullptr; } /// @returns true if the identifier is reserved. This includes the builtins too. - virtual bool reservedIdentifier(YulString _name) const { return builtin(_name) != nullptr; } + virtual bool reservedIdentifier(std::string_view _name) const { return builtin(_name) != nullptr; } - virtual BuiltinFunction const* discardFunction(YulString /* _type */) const { return nullptr; } - virtual BuiltinFunction const* equalityFunction(YulString /* _type */) const { return nullptr; } + virtual BuiltinFunction const* discardFunction(std::string_view /* _type */) const { return nullptr; } + virtual BuiltinFunction const* equalityFunction(std::string_view /* _type */) const { return nullptr; } virtual BuiltinFunction const* booleanNegationFunction() const { return nullptr; } - virtual BuiltinFunction const* memoryStoreFunction(YulString /* _type */) const { return nullptr; } - virtual BuiltinFunction const* memoryLoadFunction(YulString /* _type */) const { return nullptr; } - virtual BuiltinFunction const* storageStoreFunction(YulString /* _type */) const { return nullptr; } - virtual BuiltinFunction const* storageLoadFunction(YulString /* _type */) const { return nullptr; } - virtual YulString hashFunction(YulString /* _type */ ) const { return YulString{}; } - - /// Check whether the given type is legal for the given literal value. - /// Should only be called if the type exists in the dialect at all. - virtual bool validTypeForLiteral(LiteralKind _kind, LiteralValue const& _value, YulString _type) const; + virtual BuiltinFunction const* memoryStoreFunction(std::string_view /* _type */) const { return nullptr; } + virtual BuiltinFunction const* memoryLoadFunction(std::string_view /* _type */) const { return nullptr; } + virtual BuiltinFunction const* storageStoreFunction(std::string_view /* _type */) const { return nullptr; } + virtual BuiltinFunction const* storageLoadFunction(std::string_view /* _type */) const { return nullptr; } - virtual Literal zeroLiteralForType(YulString _type) const; - virtual Literal trueLiteral() const; + virtual std::string_view hashFunction(std::string_view /* _type */ ) const { return {}; } virtual std::set builtinNames() const { return {}; } - virtual std::set fixedFunctionNames() const { return {}; } + /// Check whether the given type is legal for the given literal value. + /// Should only be called if the type exists in the dialect at all. + virtual bool validTypeForLiteral(LiteralKind _kind, LiteralValue const& _value, std::string_view _type) const; + virtual bool validTypeForLiteral(LiteralKind _kind, LiteralValue const& _value, Type _type, YulNameRepository const& _nameRepository) const; + + virtual Literal zeroLiteralForType(YulName _type, YulNameRepository const& _nameRepository) const; Dialect() = default; virtual ~Dialect() = default; diff --git a/libyul/Exceptions.h b/libyul/Exceptions.h index 45c681a5d6e5..4f7569b73812 100644 --- a/libyul/Exceptions.h +++ b/libyul/Exceptions.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -40,18 +41,18 @@ struct YulAssertion: virtual YulException {}; struct StackTooDeepError: virtual YulException { - StackTooDeepError(YulString _variable, int _depth, std::string const& _message): + StackTooDeepError(YulName _variable, int _depth, std::string const& _message): variable(_variable), depth(_depth) { *this << util::errinfo_comment(_message); } - StackTooDeepError(YulString _functionName, YulString _variable, int _depth, std::string const& _message): + StackTooDeepError(YulName _functionName, YulName _variable, int _depth, std::string const& _message): functionName(_functionName), variable(_variable), depth(_depth) { *this << util::errinfo_comment(_message); } - YulString functionName; - YulString variable; + YulName functionName {YulNameRepository::emptyName()}; + YulName variable; int depth; }; diff --git a/libyul/FunctionReferenceResolver.h b/libyul/FunctionReferenceResolver.h index 8c1385adb6c7..dcc5f50e5b76 100644 --- a/libyul/FunctionReferenceResolver.h +++ b/libyul/FunctionReferenceResolver.h @@ -41,7 +41,7 @@ class FunctionReferenceResolver: private ASTWalker void operator()(Block const& _block) override; std::map m_functionReferences; - std::vector> m_scopes; + std::vector> m_scopes; }; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 260cb733011f..59ace66da38c 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -38,13 +38,14 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; -std::string Data::toString(Dialect const*, DebugInfoSelection const&, CharStreamProvider const*) const +std::string Data::toString(YulNameRepository const&, AsmPrinter::Mode, DebugInfoSelection const&, CharStreamProvider const*) const { return "data \"" + name.str() + "\" hex\"" + util::toHex(data) + "\""; } std::string Object::toString( - Dialect const* _dialect, + YulNameRepository const& _yulNameRepository, + AsmPrinter::Mode const _printingMode, DebugInfoSelection const& _debugInfoSelection, CharStreamProvider const* _soliditySourceProvider ) const @@ -63,19 +64,20 @@ std::string Object::toString( "\n"; std::string inner = "code " + AsmPrinter( - _dialect, + _yulNameRepository, + _printingMode, debugData->sourceNames, _debugInfoSelection, _soliditySourceProvider )(*code); for (auto const& obj: subObjects) - inner += "\n" + obj->toString(_dialect, _debugInfoSelection, _soliditySourceProvider); + inner += "\n" + obj->toString(_yulNameRepository, _printingMode, _debugInfoSelection, _soliditySourceProvider); return useSrcComment + "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; } -Json Data::toJson() const +Json Data::toJson(YulNameRepository const&) const { Json ret; ret["nodeType"] = "YulData"; @@ -83,21 +85,21 @@ Json Data::toJson() const return ret; } -Json Object::toJson() const +Json Object::toJson(YulNameRepository const& _yulNameRepository) const { yulAssert(code, "No code"); Json codeJson; - codeJson["nodeType"] = "YulCode"; - codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */)(*code); + codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */, _yulNameRepository)(*code); Json subObjectsJson = Json::array(); for (std::shared_ptr const& subObject: subObjects) - subObjectsJson.emplace_back(subObject->toJson()); + subObjectsJson.emplace_back(subObject->toJson(_yulNameRepository)); Json ret; ret["nodeType"] = "YulObject"; ret["name"] = name.str(); + codeJson["nodeType"] = "YulCode"; ret["code"] = codeJson; ret["subObjects"] = subObjectsJson; return ret; diff --git a/libyul/Object.h b/libyul/Object.h index 54a8080d08c0..711b1e628126 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -22,7 +22,9 @@ #pragma once #include +#include #include +#include #include #include @@ -54,11 +56,12 @@ struct ObjectNode /// Can be empty since .yul files can also just contain code, without explicitly placing it in an object. YulString name; virtual std::string toString( - Dialect const* _dialect, + YulNameRepository const& _yulNameRepository, + AsmPrinter::Mode printingMode, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const = 0; - virtual Json toJson() const = 0; + virtual Json toJson(YulNameRepository const& _yulNameRepository) const = 0; }; /** @@ -71,11 +74,12 @@ struct Data: public ObjectNode bytes data; std::string toString( - Dialect const* _dialect, + YulNameRepository const& _yulNameRepository, + AsmPrinter::Mode printingMode, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider ) const override; - Json toJson() const override; + Json toJson(YulNameRepository const& _yulNameRepository) const override; }; @@ -93,12 +97,13 @@ struct Object: public ObjectNode public: /// @returns a (parseable) string representation. std::string toString( - Dialect const* _dialect, + YulNameRepository const& _yulNameRepository, + AsmPrinter::Mode printingMode = AsmPrinter::Mode::FullTypeInfo, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr - ) const; + ) const override; /// @returns a compact JSON representation of the AST. - Json toJson() const; + Json toJson(YulNameRepository const& _yulNameRepository) const override; /// @returns the set of names of data objects accessible from within the code of /// this object, including the name of object itself /// Handles all names containing dots as reserved identifiers, not accessible as data. diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index a02b9660b978..dcc71194e2c1 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -171,7 +171,7 @@ std::optional ObjectParser::tryParseSourceNameMapping() const std::shared_ptr ObjectParser::parseBlock(std::optional _sourceNames) { - Parser parser(m_errorReporter, m_dialect, std::move(_sourceNames)); + Parser parser(m_errorReporter, m_yulNameRepository, std::move(_sourceNames)); std::shared_ptr block = parser.parseInline(m_scanner); yulAssert(block || m_errorReporter.hasErrors(), "Invalid block but no error!"); return block; diff --git a/libyul/ObjectParser.h b/libyul/ObjectParser.h index 716a191ea878..836cb0cb8d90 100644 --- a/libyul/ObjectParser.h +++ b/libyul/ObjectParser.h @@ -46,8 +46,8 @@ namespace solidity::yul class ObjectParser: public langutil::ParserBase { public: - explicit ObjectParser(langutil::ErrorReporter& _errorReporter, Dialect const& _dialect): - ParserBase(_errorReporter), m_dialect(_dialect) {} + explicit ObjectParser(langutil::ErrorReporter& _errorReporter, YulNameRepository& _yulNameRepository): + ParserBase(_errorReporter), m_yulNameRepository(_yulNameRepository) {} /// Parses a Yul object. /// Falls back to code-only parsing if the source starts with `{`. @@ -66,7 +66,7 @@ class ObjectParser: public langutil::ParserBase YulString parseUniqueName(Object const* _containingObject); void addNamedSubObject(Object& _container, YulString _name, std::shared_ptr _subObject); - Dialect const& m_dialect; + YulNameRepository& m_yulNameRepository; }; } diff --git a/libyul/Scope.cpp b/libyul/Scope.cpp index 4471aa53130d..a84ce7d42d35 100644 --- a/libyul/Scope.cpp +++ b/libyul/Scope.cpp @@ -25,26 +25,28 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; -bool Scope::registerVariable(YulString _name, YulType const& _type) +bool Scope::registerVariable(YulName const _name, YulType const& _type, YulNameRepository const& _nameRepository) { - if (exists(_name)) + if (exists(_name, _nameRepository)) return false; Variable variable; variable.type = _type; variable.name = _name; identifiers[_name] = variable; + identifierLabels.emplace(_name); return true; } -bool Scope::registerFunction(YulString _name, std::vector _arguments, std::vector _returns) +bool Scope::registerFunction(YulName const _name, std::vector _arguments, std::vector _returns, YulNameRepository const& _nameRepository) { - if (exists(_name)) + if (exists(_name, _nameRepository)) return false; identifiers[_name] = Function{std::move(_arguments), std::move(_returns), _name}; + identifierLabels.emplace(_name); return true; } -Scope::Identifier* Scope::lookup(YulString _name) +Scope::Identifier* Scope::lookup(YulName _name) { bool crossedFunctionBoundary = false; for (Scope* s = this; s; s = s->superScope) @@ -64,12 +66,12 @@ Scope::Identifier* Scope::lookup(YulString _name) return nullptr; } -bool Scope::exists(YulString _name) const +bool Scope::exists(YulName const _name, YulNameRepository const& _nameRepository) const { - if (identifiers.count(_name)) + if (identifierLabels.count(_name)) return true; else if (superScope) - return superScope->exists(_name); + return superScope->exists(_name, _nameRepository); else return false; } diff --git a/libyul/Scope.h b/libyul/Scope.h index f9ac3830a295..ff0e8254be9e 100644 --- a/libyul/Scope.h +++ b/libyul/Scope.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -35,27 +35,28 @@ namespace solidity::yul struct Scope { - using YulType = YulString; + using YulType = YulName; struct Variable { - YulType type; - YulString name; + YulType type {}; + YulName name {}; }; struct Function { std::vector arguments; std::vector returns; - YulString name; + YulName name {}; }; using Identifier = std::variant; - bool registerVariable(YulString _name, YulType const& _type); + bool registerVariable(YulName _name, YulType const& _type, YulNameRepository const& _nameRepository); bool registerFunction( - YulString _name, + YulName _name, std::vector _arguments, - std::vector _returns + std::vector _returns, + YulNameRepository const& _nameRepository ); /// Looks up the identifier in this or super scopes and returns a valid pointer if found @@ -63,12 +64,12 @@ struct Scope /// will any lookups across assembly boundaries. /// The pointer will be invalidated if the scope is modified. /// @param _crossedFunction if true, we already crossed a function boundary during recursive lookup - Identifier* lookup(YulString _name); + Identifier* lookup(YulName _name); /// Looks up the identifier in this and super scopes (will not find variables across function /// boundaries and generally stops at assembly boundaries) and calls the visitor, returns /// false if not found. template - bool lookup(YulString _name, V const& _visitor) + bool lookup(YulName _name, V const& _visitor) { if (Identifier* id = lookup(_name)) { @@ -80,7 +81,7 @@ struct Scope } /// @returns true if the name exists in this scope or in super scopes (also searches /// across function and assembly boundaries). - bool exists(YulString _name) const; + bool exists(YulName _name, YulNameRepository const& _nameRepository) const; /// @returns the number of variables directly registered inside the scope. size_t numberOfVariables() const; @@ -91,7 +92,8 @@ struct Scope /// If true, variables from the super scope are not visible here (other identifiers are), /// but they are still taken into account to prevent shadowing. bool functionScope = false; - std::map identifiers; + std::map identifiers; + std::set identifierLabels; }; } diff --git a/libyul/ScopeFiller.cpp b/libyul/ScopeFiller.cpp index 22c0d17e3289..4d530094da3b 100644 --- a/libyul/ScopeFiller.cpp +++ b/libyul/ScopeFiller.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -38,8 +39,8 @@ using namespace solidity::yul; using namespace solidity::util; using namespace solidity::langutil; -ScopeFiller::ScopeFiller(AsmAnalysisInfo& _info, ErrorReporter& _errorReporter): - m_info(_info), m_errorReporter(_errorReporter) +ScopeFiller::ScopeFiller(AsmAnalysisInfo& _info, ErrorReporter& _errorReporter, YulNameRepository const& _yulNameRegistry): + m_yulNameRegistry(_yulNameRegistry), m_info(_info), m_errorReporter(_errorReporter) { m_currentScope = &scope(nullptr); } @@ -135,13 +136,13 @@ bool ScopeFiller::operator()(Block const& _block) bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const& _location, Scope& _scope) { - if (!_scope.registerVariable(_name.name, _name.type)) + if (!_scope.registerVariable(_name.name, _name.type, m_yulNameRegistry)) { //@TODO secondary location m_errorReporter.declarationError( 1395_error, _location, - "Variable name " + _name.name.str() + " already taken in this scope." + fmt::format("Variable name {} already taken in this scope.", m_yulNameRegistry.labelOf(_name.name)) ); return false; } @@ -156,13 +157,13 @@ bool ScopeFiller::registerFunction(FunctionDefinition const& _funDef) std::vector returns; for (auto const& returnVariable: _funDef.returnVariables) returns.emplace_back(returnVariable.type); - if (!m_currentScope->registerFunction(_funDef.name, std::move(parameters), std::move(returns))) + if (!m_currentScope->registerFunction(_funDef.name, std::move(parameters), std::move(returns), m_yulNameRegistry)) { //@TODO secondary location m_errorReporter.declarationError( 6052_error, nativeLocationOf(_funDef), - "Function name " + _funDef.name.str() + " already taken in this scope." + fmt::format("Function name {} already taken in this scope.", m_yulNameRegistry.labelOf(_funDef.name)) ); return false; } diff --git a/libyul/ScopeFiller.h b/libyul/ScopeFiller.h index b43910874337..12663c0610c2 100644 --- a/libyul/ScopeFiller.h +++ b/libyul/ScopeFiller.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include #include @@ -46,7 +47,7 @@ struct AsmAnalysisInfo; class ScopeFiller { public: - ScopeFiller(AsmAnalysisInfo& _info, langutil::ErrorReporter& _errorReporter); + ScopeFiller(AsmAnalysisInfo& _info, langutil::ErrorReporter& _errorReporter, YulNameRepository const& _yulNameRegistry); bool operator()(Literal const&) { return true; } bool operator()(Identifier const&) { return true; } @@ -64,6 +65,7 @@ class ScopeFiller bool operator()(Block const& _block); private: + YulNameRepository const& m_yulNameRegistry; bool registerVariable( TypedName const& _name, langutil::SourceLocation const& _location, diff --git a/libyul/YulName.cpp b/libyul/YulName.cpp index faec03b2bb79..32bf777e3ddb 100644 --- a/libyul/YulName.cpp +++ b/libyul/YulName.cpp @@ -41,12 +41,12 @@ YulNameRepository::YulNameRepository(solidity::yul::Dialect const& _dialect): if (type.empty()) { m_indexBoundaries.beginTypes = 0; - m_dialectTypes.emplace_back(emptyName(), type.str()); + m_dialectTypes.emplace_back(emptyName(), type); } else { m_indexBoundaries.beginTypes = 1; - m_dialectTypes.emplace_back(defineName(type.str()), type.str()); + m_dialectTypes.emplace_back(defineName(type), type); } m_indexBoundaries.endTypes = m_index; m_indexBoundaries.beginBuiltins = m_index; @@ -57,13 +57,13 @@ YulNameRepository::YulNameRepository(solidity::yul::Dialect const& _dialect): if (!label.empty()) { auto const name = defineName(label); - if (auto const* function = m_dialect.get().builtin(YulString(label))) + if (auto const* function = m_dialect.get().builtin(label)) m_builtinFunctions[name] = convertBuiltinFunction(name, *function); } m_indexBoundaries.endBuiltins = m_index; - m_predefined.boolType = nameOfType(_dialect.boolType.str()); - m_predefined.defaultType = nameOfType(_dialect.defaultType.str()); + m_predefined.boolType = nameOfType(_dialect.boolType); + m_predefined.defaultType = nameOfType(_dialect.defaultType); auto const predefinedName = [&](std::string const& label) { @@ -88,42 +88,42 @@ YulNameRepository::YulNameRepository(solidity::yul::Dialect const& _dialect): for (auto const& [typeName, typeLabel]: types) { - if (auto const* discardFunction = m_dialect.get().discardFunction(YulString(typeLabel))) - m_predefinedBuiltinFunctions.discardFunctions.emplace_back(nameOfBuiltin(discardFunction->name.str())); + if (auto const* discardFunction = m_dialect.get().discardFunction(typeLabel)) + m_predefinedBuiltinFunctions.discardFunctions.emplace_back(nameOfBuiltin(discardFunction->name)); else m_predefinedBuiltinFunctions.discardFunctions.emplace_back(std::nullopt); - if (auto const* equalityFunction = m_dialect.get().equalityFunction(YulString(typeLabel))) - m_predefinedBuiltinFunctions.equalityFunctions.emplace_back(nameOfBuiltin(equalityFunction->name.str())); + if (auto const* equalityFunction = m_dialect.get().equalityFunction(typeLabel)) + m_predefinedBuiltinFunctions.equalityFunctions.emplace_back(nameOfBuiltin(equalityFunction->name)); else m_predefinedBuiltinFunctions.equalityFunctions.emplace_back(std::nullopt); if (auto const* booleanNegationFunction = m_dialect.get().booleanNegationFunction()) - m_predefinedBuiltinFunctions.booleanNegationFunction = nameOfBuiltin(booleanNegationFunction->name.str()); + m_predefinedBuiltinFunctions.booleanNegationFunction = nameOfBuiltin(booleanNegationFunction->name); else m_predefinedBuiltinFunctions.booleanNegationFunction = std::nullopt; - if (auto const* memStoreFunction = m_dialect.get().memoryStoreFunction(YulString(typeLabel))) - m_predefinedBuiltinFunctions.memoryStoreFunctions.emplace_back(nameOfBuiltin(memStoreFunction->name.str())); + if (auto const* memStoreFunction = m_dialect.get().memoryStoreFunction(typeLabel)) + m_predefinedBuiltinFunctions.memoryStoreFunctions.emplace_back(nameOfBuiltin(memStoreFunction->name)); else m_predefinedBuiltinFunctions.memoryStoreFunctions.emplace_back(std::nullopt); - if (auto const* memLoadFunction = m_dialect.get().memoryLoadFunction(YulString(typeLabel))) - m_predefinedBuiltinFunctions.memoryLoadFunctions.emplace_back(nameOfBuiltin(memLoadFunction->name.str())); + if (auto const* memLoadFunction = m_dialect.get().memoryLoadFunction(typeLabel)) + m_predefinedBuiltinFunctions.memoryLoadFunctions.emplace_back(nameOfBuiltin(memLoadFunction->name)); else m_predefinedBuiltinFunctions.memoryLoadFunctions.emplace_back(std::nullopt); - if (auto const* storageStoreFunction = m_dialect.get().storageStoreFunction(YulString(typeLabel))) - m_predefinedBuiltinFunctions.storageStoreFunctions.emplace_back(nameOfBuiltin(storageStoreFunction->name.str())); + if (auto const* storageStoreFunction = m_dialect.get().storageStoreFunction(typeLabel)) + m_predefinedBuiltinFunctions.storageStoreFunctions.emplace_back(nameOfBuiltin(storageStoreFunction->name)); else m_predefinedBuiltinFunctions.storageStoreFunctions.emplace_back(std::nullopt); - if (auto const* storageLoadFunction = m_dialect.get().storageLoadFunction(YulString(typeLabel))) - m_predefinedBuiltinFunctions.storageLoadFunctions.emplace_back(nameOfBuiltin(storageLoadFunction->name.str())); + if (auto const* storageLoadFunction = m_dialect.get().storageLoadFunction(typeLabel)) + m_predefinedBuiltinFunctions.storageLoadFunctions.emplace_back(nameOfBuiltin(storageLoadFunction->name)); else m_predefinedBuiltinFunctions.storageLoadFunctions.emplace_back(std::nullopt); - m_predefinedBuiltinFunctions.hashFunctions.emplace_back(nameOfBuiltin(m_dialect.get().hashFunction(YulString(typeLabel)).str())); + m_predefinedBuiltinFunctions.hashFunctions.emplace_back(nameOfBuiltin(m_dialect.get().hashFunction(typeLabel))); } } @@ -158,7 +158,7 @@ std::optional YulNameRepository::labelOf(YulName const _name) { auto const* builtinFun = builtin(_name); yulAssert(builtinFun); - return builtinFun->data->name.str(); + return builtinFun->data->name; } return std::nullopt; } @@ -245,9 +245,9 @@ YulNameRepository::BuiltinFunction YulNameRepository::convertBuiltinFunction(Yul BuiltinFunction result; result.name = _name; for (auto const& type: _builtin.parameters) - result.parameters.push_back(nameOfType(type.str())); + result.parameters.push_back(nameOfType(type)); for (auto const& type: _builtin.returns) - result.returns.push_back(nameOfType(type.str())); + result.returns.push_back(nameOfType(type)); result.data = &_builtin; return result; } @@ -312,9 +312,9 @@ bool YulNameRepository::isVerbatimFunction(YulName const _name) const YulName YulNameRepository::defineName(std::string_view const _label) { - if (auto const* builtin = m_dialect.get().builtin(YulString(std::string(_label)))) + if (auto const* builtin = m_dialect.get().builtin(_label)) { - if (builtin->name.str().substr(0, std::string_view("verbatim").size()) == "verbatim") + if (builtin->name.substr(0, std::string_view("verbatim").size()) == "verbatim") { auto const key = std::make_tuple(builtin->parameters.size(), builtin->returns.size()); auto [it, emplaced] = m_verbatimNames.try_emplace(key); @@ -423,10 +423,9 @@ void YulNameRepository::generateLabels(std::set const& _usedNames, std: } } -// commented out for the time being until the AST is refactored to use YulName over YulString -// void YulNameRepository::generateLabels(Block const& _ast, std::set const& _illegal) -// { -// generateLabels(NameCollector(_ast).names(), _illegal); -// } +void YulNameRepository::generateLabels(Block const& _ast, std::set const& _illegal) +{ + generateLabels(NameCollector(_ast).names(), _illegal); +} } diff --git a/libyul/YulName.h b/libyul/YulName.h index 7d8a6c0ff9f9..d83123d5506a 100644 --- a/libyul/YulName.h +++ b/libyul/YulName.h @@ -154,10 +154,19 @@ class YulNameRepository /// This will change the state of all derived names in _usedNames to "not derived" with a label associated to them. void generateLabels(std::set const& _usedNames, std::set const& _illegal = {}); - // commented out for the time being, as it requires AST refactoring to be YulName-based - // void generateLabels(Block const& _ast, std::set const& _illegal = {}); + void generateLabels(Block const& _ast, std::set const& _illegal = {}); private: + bool nameWithinBounds(YulName const _name) const { return _name < m_index; } + + size_t indexOfType(YulName _type) const; + BuiltinFunction convertBuiltinFunction(YulName _name, yul::BuiltinFunction const& _builtin) const; + BuiltinFunction const* fetchTypedPredefinedFunction(YulName _type, std::vector> const& _functions) const; + + Dialect const& m_dialect; + std::vector> m_dialectTypes; + std::map m_builtinFunctions; + struct PredefinedBuiltinFunctions { std::vector> discardFunctions; @@ -198,5 +207,6 @@ class YulNameRepository IndexBoundaries m_indexBoundaries; }; using YulName = YulNameRepository::YulName; +using Type = YulName; } diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 94e9ad7a8d55..4536619ace03 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -47,7 +47,7 @@ using namespace solidity::langutil; namespace { -Dialect const& languageToDialect(YulStack::Language _language, EVMVersion _version) +EVMDialect const& languageToDialect(YulStack::Language _language, EVMVersion _version) { switch (_language) { @@ -58,11 +58,24 @@ Dialect const& languageToDialect(YulStack::Language _language, EVMVersion _versi return EVMDialectTyped::instance(_version); } yulAssert(false, ""); - return Dialect::yulDeprecated(); } } +YulStack::YulStack( + langutil::EVMVersion _evmVersion, + std::optional _eofVersion, + solidity::yul::YulStack::Language _language, + solidity::frontend::OptimiserSettings _optimiserSettings, + langutil::DebugInfoSelection const& _debugInfoSelection +): + m_yulNameRepository(std::make_shared(languageToDialect(_language, _evmVersion))), + m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), + m_optimiserSettings(std::move(_optimiserSettings)), + m_debugInfoSelection(_debugInfoSelection), + m_errorReporter(m_errors) +{} CharStream const& YulStack::charStream(std::string const& _sourceName) const { @@ -78,7 +91,7 @@ bool YulStack::parse(std::string const& _sourceName, std::string const& _source) { m_charStream = std::make_unique(_source, _sourceName); std::shared_ptr scanner = std::make_shared(*m_charStream); - m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion)).parse(scanner, false); + m_parserResult = ObjectParser(m_errorReporter, *yulNameRepository()).parse(scanner, false); } catch (UnimplementedFeatureError const& _error) { @@ -115,7 +128,7 @@ void YulStack::optimize() { if ( !m_optimiserSettings.runYulOptimiser && - yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult) + yul::MSizeFinder::containsMSize(*yulNameRepository(), *m_parserResult) ) return; @@ -145,7 +158,7 @@ bool YulStack::analyzeParsed(Object& _object) AsmAnalyzer analyzer( *_object.analysisInfo, m_errorReporter, - languageToDialect(m_language, m_evmVersion), + *yulNameRepository(), {}, _object.qualifiedDataNames() ); @@ -171,30 +184,19 @@ bool YulStack::analyzeParsed(Object& _object) return success; } -void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) const +void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) { - EVMDialect const* dialect = nullptr; - switch (m_language) - { - case Language::Assembly: - case Language::StrictAssembly: - dialect = &EVMDialect::strictAssemblyForEVMObjects(m_evmVersion); - break; - case Language::Yul: - dialect = &EVMDialectTyped::instance(m_evmVersion); - break; - default: - yulAssert(false, "Invalid language."); - break; - } - - EVMObjectCompiler::compile(*m_parserResult, _assembly, *dialect, _optimize, m_eofVersion); + auto const* evmDialect = dynamic_cast(&yulNameRepository()->dialect()); + yulAssert(evmDialect); + EVMObjectCompiler::compile(*m_parserResult, _assembly, *yulNameRepository(), *evmDialect, _optimize, m_eofVersion); } void YulStack::optimize(Object& _object, bool _isCreation) { yulAssert(_object.code, ""); yulAssert(_object.analysisInfo, ""); + auto const* evmDialect = dynamic_cast(&yulNameRepository()->dialect()); + yulAssert(evmDialect); for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) { @@ -202,10 +204,8 @@ void YulStack::optimize(Object& _object, bool _isCreation) optimize(*subObject, isCreation); } - Dialect const& dialect = languageToDialect(m_language, m_evmVersion); std::unique_ptr meter; - if (EVMDialect const* evmDialect = dynamic_cast(&dialect)) - meter = std::make_unique(*evmDialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment); + meter = std::make_unique(*yulNameRepository(), *evmDialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment); auto [optimizeStackAllocation, yulOptimiserSteps, yulOptimiserCleanupSteps] = [&]() -> std::tuple { @@ -233,7 +233,7 @@ void YulStack::optimize(Object& _object, bool _isCreation) }(); OptimiserSuite::run( - dialect, + *yulNameRepository(), meter.get(), _object, // Defaults are the minimum necessary to avoid running into "Stack too deep" constantly. @@ -318,7 +318,7 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) // it with the minimal steps required to avoid "stack too deep". bool optimize = m_optimiserSettings.optimizeStackAllocation || ( !m_optimiserSettings.runYulOptimiser && - !yul::MSizeFinder::containsMSize(languageToDialect(m_language, m_evmVersion), *m_parserResult) + !yul::MSizeFinder::containsMSize(*yulNameRepository(), *m_parserResult) ); try { @@ -365,7 +365,7 @@ std::string YulStack::print( yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); - return m_parserResult->toString(&languageToDialect(m_language, m_evmVersion), m_debugInfoSelection, _soliditySourceProvider) + "\n"; + return m_parserResult->toString(*yulNameRepository(), AsmPrinter::Mode::FullTypeInfo, m_debugInfoSelection, _soliditySourceProvider) + "\n"; } Json YulStack::astJson() const @@ -373,7 +373,7 @@ Json YulStack::astJson() const yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); - return m_parserResult->toJson(); + return m_parserResult->toJson(*yulNameRepository()); } std::shared_ptr YulStack::parserResult() const @@ -389,3 +389,8 @@ void YulStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& solAssert(_error.comment(), "Unimplemented feature errors must include a message for the user"); m_errorReporter.unimplementedFeatureError(1920_error, _error.sourceLocation(), *_error.comment()); } + +std::shared_ptr const YulStack::yulNameRepository() const +{ + return m_yulNameRepository; +} diff --git a/libyul/YulStack.h b/libyul/YulStack.h index d75ff200f5ce..cc8b34e617c8 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -50,6 +50,7 @@ class Scanner; namespace solidity::yul { class AbstractAssembly; +struct EVMDialect; struct MachineAssemblyObject @@ -89,14 +90,7 @@ class YulStack: public langutil::CharStreamProvider Language _language, solidity::frontend::OptimiserSettings _optimiserSettings, langutil::DebugInfoSelection const& _debugInfoSelection - ): - m_language(_language), - m_evmVersion(_evmVersion), - m_eofVersion(_eofVersion), - m_optimiserSettings(std::move(_optimiserSettings)), - m_debugInfoSelection(_debugInfoSelection), - m_errorReporter(m_errors) - {} + ); /// @returns the char stream used during parsing langutil::CharStream const& charStream(std::string const& _sourceName) const override; @@ -140,18 +134,21 @@ class YulStack: public langutil::CharStreamProvider /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; + std::shared_ptr const yulNameRepository() const; + private: bool parse(std::string const& _sourceName, std::string const& _source); bool analyzeParsed(); bool analyzeParsed(yul::Object& _object); - void compileEVM(yul::AbstractAssembly& _assembly, bool _optimize) const; + void compileEVM(yul::AbstractAssembly& _assembly, bool _optimize); void optimize(yul::Object& _object, bool _isCreation); void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); - Language m_language = Language::Assembly; + std::shared_ptr m_yulNameRepository; + langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; solidity::frontend::OptimiserSettings m_optimiserSettings; diff --git a/libyul/backends/evm/AsmCodeGen.cpp b/libyul/backends/evm/AsmCodeGen.cpp index 645d1fd87bc1..1a1edb711282 100644 --- a/libyul/backends/evm/AsmCodeGen.cpp +++ b/libyul/backends/evm/AsmCodeGen.cpp @@ -38,6 +38,7 @@ void CodeGenerator::assemble( AsmAnalysisInfo& _analysisInfo, evmasm::Assembly& _assembly, langutil::EVMVersion _evmVersion, + YulNameRepository const& _yulNameRepository, ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, bool _useNamedLabelsForFunctions, bool _optimizeStackAllocation @@ -49,6 +50,7 @@ void CodeGenerator::assemble( assemblyAdapter, _analysisInfo, _parsedData, + _yulNameRepository, EVMDialect::strictAssemblyForEVM(_evmVersion), builtinContext, _optimizeStackAllocation, diff --git a/libyul/backends/evm/AsmCodeGen.h b/libyul/backends/evm/AsmCodeGen.h index b79338074957..13cfe48c8315 100644 --- a/libyul/backends/evm/AsmCodeGen.h +++ b/libyul/backends/evm/AsmCodeGen.h @@ -44,6 +44,7 @@ class CodeGenerator AsmAnalysisInfo& _analysisInfo, evmasm::Assembly& _assembly, langutil::EVMVersion _evmVersion, + YulNameRepository const& _yulNameRepository, ExternalIdentifierAccess::CodeGenerator _identifierAccess = {}, bool _useNamedLabelsForFunctions = false, bool _optimizeStackAllocation = false diff --git a/libyul/backends/evm/ConstantOptimiser.cpp b/libyul/backends/evm/ConstantOptimiser.cpp index 7b17f7d89012..6a9377270c9b 100644 --- a/libyul/backends/evm/ConstantOptimiser.cpp +++ b/libyul/backends/evm/ConstantOptimiser.cpp @@ -40,7 +40,7 @@ namespace { struct MiniEVMInterpreter { - explicit MiniEVMInterpreter(EVMDialect const& _dialect): m_dialect(_dialect) {} + explicit MiniEVMInterpreter(YulNameRepository const& _yulNameRepository): m_yulNameRepository(_yulNameRepository) {} u256 eval(Expression const& _expr) { @@ -74,10 +74,11 @@ struct MiniEVMInterpreter u256 operator()(FunctionCall const& _funCall) { - BuiltinFunctionForEVM const* fun = m_dialect.builtin(_funCall.functionName.name); + auto const* fun = m_yulNameRepository.builtin(_funCall.functionName.name); yulAssert(fun, "Expected builtin function."); - yulAssert(fun->instruction, "Expected EVM instruction."); - return eval(*fun->instruction, _funCall.arguments); + auto const* evmFun = dynamic_cast(fun->data); + yulAssert(evmFun->instruction, "Expected EVM instruction."); + return eval(*evmFun->instruction, _funCall.arguments); } u256 operator()(Literal const& _literal) { @@ -85,7 +86,7 @@ struct MiniEVMInterpreter } u256 operator()(Identifier const&) { yulAssert(false, ""); } - EVMDialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; }; } @@ -99,7 +100,7 @@ void ConstantOptimiser::visit(Expression& _e) if ( Expression const* repr = - RepresentationFinder(m_dialect, m_meter, debugDataOf(_e), m_cache) + RepresentationFinder(m_yulNameRepository, m_evmDialect, m_meter, debugDataOf(_e), m_cache) .tryFindRepresentation(literal.value.value()) ) _e = ASTCopier{}.translate(*repr); @@ -108,6 +109,22 @@ void ConstantOptimiser::visit(Expression& _e) ASTModifier::visit(_e); } +RepresentationFinder::RepresentationFinder(YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, GasMeter const& _meter, langutil::DebugData::ConstPtr _debugData, std::map& _cache): + m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), + m_meter(_meter), + m_debugData(std::move(_debugData)), + m_cache(_cache) +{ + yulAssert(dynamic_cast(&_yulNameRepository.dialect())); + m_instr_not = m_yulNameRepository.nameOfBuiltin("not"); + m_instr_shl = m_yulNameRepository.nameOfBuiltin("shl"); + m_instr_exp = m_yulNameRepository.nameOfBuiltin("exp"); + m_instr_mul = m_yulNameRepository.nameOfBuiltin("mul"); + m_instr_add = m_yulNameRepository.nameOfBuiltin("add"); + m_instr_sub = m_yulNameRepository.nameOfBuiltin("sub"); +} + Expression const* RepresentationFinder::tryFindRepresentation(u256 const& _value) { if (_value < 0x10000) @@ -129,7 +146,7 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu if (numberEncodingSize(~_value) < numberEncodingSize(_value)) // Negated is shorter to represent - routine = min(std::move(routine), represent("not"_yulstring, findRepresentation(~_value))); + routine = min(std::move(routine), represent(m_instr_not, findRepresentation(~_value))); // Decompose value into a * 2**k + b where abs(b) << 2**k for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits) @@ -152,27 +169,27 @@ Representation const& RepresentationFinder::findRepresentation(u256 const& _valu continue; Representation newRoutine; if (m_dialect.evmVersion().hasBitwiseShifting()) - newRoutine = represent("shl"_yulstring, represent(bits), findRepresentation(upperPart)); + newRoutine = represent(m_instr_shl, represent(bits), findRepresentation(upperPart)); else { - newRoutine = represent("exp"_yulstring, represent(2), represent(bits)); + newRoutine = represent(m_instr_exp, represent(2), represent(bits)); if (upperPart != 1) - newRoutine = represent("mul"_yulstring, findRepresentation(upperPart), newRoutine); + newRoutine = represent(m_instr_mul, findRepresentation(upperPart), newRoutine); } if (newRoutine.cost >= routine.cost) continue; if (lowerPart > 0) - newRoutine = represent("add"_yulstring, newRoutine, findRepresentation(u256(abs(lowerPart)))); + newRoutine = represent(m_instr_add, newRoutine, findRepresentation(u256(abs(lowerPart)))); else if (lowerPart < 0) - newRoutine = represent("sub"_yulstring, newRoutine, findRepresentation(u256(abs(lowerPart)))); + newRoutine = represent(m_instr_sub, newRoutine, findRepresentation(u256(abs(lowerPart)))); if (m_maxSteps > 0) m_maxSteps--; routine = min(std::move(routine), std::move(newRoutine)); } - yulAssert(MiniEVMInterpreter{m_dialect}.eval(*routine.expression) == _value, "Invalid expression generated."); + yulAssert(MiniEVMInterpreter{m_yulNameRepository}.eval(*routine.expression) == _value, "Invalid expression generated."); return m_cache[_value] = std::move(routine); } @@ -185,7 +202,7 @@ Representation RepresentationFinder::represent(u256 const& _value) const } Representation RepresentationFinder::represent( - YulString _instruction, + YulName const _instruction, Representation const& _argument ) const { @@ -195,12 +212,14 @@ Representation RepresentationFinder::represent( Identifier{m_debugData, _instruction}, {ASTCopier{}.translate(*_argument.expression)} }); - repr.cost = _argument.cost + m_meter.instructionCosts(*m_dialect.builtin(_instruction)->instruction); + auto const* builtin = dynamic_cast(m_yulNameRepository.builtin(_instruction)->data); + yulAssert(builtin); + repr.cost = _argument.cost + m_meter.instructionCosts(*builtin->instruction); return repr; } Representation RepresentationFinder::represent( - YulString _instruction, + YulName const _instruction, Representation const& _arg1, Representation const& _arg2 ) const @@ -211,7 +230,9 @@ Representation RepresentationFinder::represent( Identifier{m_debugData, _instruction}, {ASTCopier{}.translate(*_arg1.expression), ASTCopier{}.translate(*_arg2.expression)} }); - repr.cost = m_meter.instructionCosts(*m_dialect.builtin(_instruction)->instruction) + _arg1.cost + _arg2.cost; + auto const* builtin = dynamic_cast(m_yulNameRepository.builtin(_instruction)->data); + yulAssert(builtin); + repr.cost = m_meter.instructionCosts(*builtin->instruction) + _arg1.cost + _arg2.cost; return repr; } diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index 280f50bf9b97..0fe03b021569 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -48,8 +48,9 @@ class GasMeter; class ConstantOptimiser: public ASTModifier { public: - ConstantOptimiser(EVMDialect const& _dialect, GasMeter const& _meter): - m_dialect(_dialect), + ConstantOptimiser(YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, GasMeter const& _meter): + m_yulNameRepository(_yulNameRepository), + m_evmDialect(_dialect), m_meter(_meter) {} @@ -62,7 +63,8 @@ class ConstantOptimiser: public ASTModifier }; private: - EVMDialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; + EVMDialect const& m_evmDialect; GasMeter const& m_meter; std::map m_cache; }; @@ -72,16 +74,12 @@ class RepresentationFinder public: using Representation = ConstantOptimiser::Representation; RepresentationFinder( + YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, GasMeter const& _meter, langutil::DebugData::ConstPtr _debugData, std::map& _cache - ): - m_dialect(_dialect), - m_meter(_meter), - m_debugData(std::move(_debugData)), - m_cache(_cache) - {} + ); /// @returns a cheaper representation for the number than its representation /// as a literal or nullptr otherwise. @@ -93,17 +91,25 @@ class RepresentationFinder Representation const& findRepresentation(u256 const& _value); Representation represent(u256 const& _value) const; - Representation represent(YulString _instruction, Representation const& _arg) const; - Representation represent(YulString _instruction, Representation const& _arg1, Representation const& _arg2) const; + Representation represent(YulName _instruction, Representation const& _arg) const; + Representation represent(YulName _instruction, Representation const& _arg1, Representation const& _arg2) const; Representation min(Representation _a, Representation _b); EVMDialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; GasMeter const& m_meter; langutil::DebugData::ConstPtr m_debugData; /// Counter for the complexity of optimization, will stop when it reaches zero. size_t m_maxSteps = 10000; std::map& m_cache; + + YulName m_instr_not; + YulName m_instr_shl; + YulName m_instr_exp; + YulName m_instr_mul; + YulName m_instr_add; + YulName m_instr_sub; }; } diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index a5e9613b5887..087c0e84dbd2 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -207,15 +207,15 @@ void markNeedsCleanStack(CFG& _cfg) std::unique_ptr ControlFlowGraphBuilder::build( AsmAnalysisInfo const& _analysisInfo, - Dialect const& _dialect, + YulNameRepository& _yulNameRepository, Block const& _block ) { auto result = std::make_unique(); result->entry = &result->makeBlock(debugDataOf(_block)); - ControlFlowSideEffectsCollector sideEffects(_dialect, _block); - ControlFlowGraphBuilder builder(*result, _analysisInfo, sideEffects.functionSideEffects(), _dialect); + ControlFlowSideEffectsCollector sideEffects(_yulNameRepository, _block); + ControlFlowGraphBuilder builder(*result, _analysisInfo, sideEffects.functionSideEffects(), _yulNameRepository); builder.m_currentBlock = result->entry; builder(_block); @@ -234,12 +234,12 @@ ControlFlowGraphBuilder::ControlFlowGraphBuilder( CFG& _graph, AsmAnalysisInfo const& _analysisInfo, std::map const& _functionSideEffects, - Dialect const& _dialect + YulNameRepository& _yulNameRepository ): m_graph(_graph), m_info(_analysisInfo), m_functionSideEffects(_functionSideEffects), - m_dialect(_dialect) + m_yulNameRepository(_yulNameRepository) { } @@ -335,9 +335,8 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) yulAssert(m_currentBlock, ""); langutil::DebugData::ConstPtr preSwitchDebugData = debugDataOf(_switch); - auto ghostVariableId = m_graph.ghostVariables.size(); - YulString ghostVariableName("GHOST[" + std::to_string(ghostVariableId) + "]"); - auto& ghostVar = m_graph.ghostVariables.emplace_back(Scope::Variable{""_yulstring, ghostVariableName}); + auto const ghostVariableName = m_yulNameRepository.addGhost(); + auto& ghostVar = m_graph.ghostVariables.emplace_back(Scope::Variable{YulNameRepository::emptyName(), ghostVariableName}); // Artificially generate: // let := @@ -349,7 +348,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) CFG::Assignment{_switch.debugData, {ghostVarSlot}} }); - BuiltinFunction const* equalityBuiltin = m_dialect.equalityFunction({}); + auto const* equalityBuiltin = m_yulNameRepository.equalityFunction({}); yulAssert(equalityBuiltin, ""); // Artificially generate: @@ -357,13 +356,13 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) auto makeValueCompare = [&](Case const& _case) { yul::FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(yul::FunctionCall{ debugDataOf(_case), - yul::Identifier{{}, "eq"_yulstring}, + yul::Identifier{{}, m_yulNameRepository.predefined().eq}, {*_case.value, Identifier{{}, ghostVariableName}} }); CFG::Operation& operation = m_currentBlock->operations.emplace_back(CFG::Operation{ Stack{ghostVarSlot, LiteralSlot{_case.value->value.value(), debugDataOf(*_case.value)}}, Stack{TemporarySlot{ghostCall, 0}}, - CFG::BuiltinCall{debugDataOf(_case), *equalityBuiltin, ghostCall, 2}, + CFG::BuiltinCall{debugDataOf(_case), *(equalityBuiltin->data), ghostCall, 2}, }); return operation.output.front(); }; @@ -468,7 +467,7 @@ void ControlFlowGraphBuilder::operator()(FunctionDefinition const& _function) CFG::FunctionInfo& functionInfo = m_graph.functionInfo.at(&function); - ControlFlowGraphBuilder builder{m_graph, m_info, m_functionSideEffects, m_dialect}; + ControlFlowGraphBuilder builder{m_graph, m_info, m_functionSideEffects, m_yulNameRepository}; builder.m_currentFunction = &functionInfo; builder.m_currentBlock = functionInfo.entry; builder(_function.body); @@ -516,13 +515,13 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal Stack const* output = nullptr; bool canContinue = true; - if (BuiltinFunction const* builtin = m_dialect.builtin(_call.functionName.name)) + if (auto const* builtin = m_yulNameRepository.builtin(_call.functionName.name)) { Stack inputs; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) - if (!builtin->literalArgument(idx).has_value()) + if (!builtin->data->literalArgument(idx).has_value()) inputs.emplace_back(std::visit(*this, arg)); - CFG::BuiltinCall builtinCall{_call.debugData, *builtin, _call, inputs.size()}; + CFG::BuiltinCall builtinCall{_call.debugData, *builtin->data, _call, inputs.size()}; output = &m_currentBlock->operations.emplace_back(CFG::Operation{ // input std::move(inputs), @@ -533,7 +532,7 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal // operation std::move(builtinCall) }).output; - canContinue = builtin->controlFlowSideEffects.canContinue; + canContinue = builtin->data->controlFlowSideEffects.canContinue; } else { @@ -578,7 +577,7 @@ Stack ControlFlowGraphBuilder::visitAssignmentRightHandSide(Expression const& _e }, _expression); } -Scope::Function const& ControlFlowGraphBuilder::lookupFunction(YulString _name) const +Scope::Function const& ControlFlowGraphBuilder::lookupFunction(YulName _name) const { Scope::Function const* function = nullptr; yulAssert(m_scope->lookup(_name, util::GenericVisitor{ @@ -589,7 +588,7 @@ Scope::Function const& ControlFlowGraphBuilder::lookupFunction(YulString _name) return *function; } -Scope::Variable const& ControlFlowGraphBuilder::lookupVariable(YulString _name) const +Scope::Variable const& ControlFlowGraphBuilder::lookupVariable(YulName _name) const { yulAssert(m_scope, ""); Scope::Variable const* var = nullptr; diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index 5007d361089b..dba1aa3423cb 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -31,7 +31,7 @@ class ControlFlowGraphBuilder public: ControlFlowGraphBuilder(ControlFlowGraphBuilder const&) = delete; ControlFlowGraphBuilder& operator=(ControlFlowGraphBuilder const&) = delete; - static std::unique_ptr build(AsmAnalysisInfo const& _analysisInfo, Dialect const& _dialect, Block const& _block); + static std::unique_ptr build(AsmAnalysisInfo const& _analysisInfo, YulNameRepository& _yulNameRepository, Block const& _block); StackSlot operator()(Expression const& _literal); StackSlot operator()(Literal const& _literal); @@ -57,14 +57,14 @@ class ControlFlowGraphBuilder CFG& _graph, AsmAnalysisInfo const& _analysisInfo, std::map const& _functionSideEffects, - Dialect const& _dialect + YulNameRepository& _yulNameRepository ); void registerFunction(FunctionDefinition const& _function); Stack const& visitFunctionCall(FunctionCall const&); Stack visitAssignmentRightHandSide(Expression const& _expression, size_t _expectedSlotCount); - Scope::Function const& lookupFunction(YulString _name) const; - Scope::Variable const& lookupVariable(YulString _name) const; + Scope::Function const& lookupFunction(YulName _name) const; + Scope::Variable const& lookupVariable(YulName _name) const; /// Resets m_currentBlock to enforce a subsequent explicit reassignment. void makeConditionalJump( langutil::DebugData::ConstPtr _debugData, @@ -80,7 +80,7 @@ class ControlFlowGraphBuilder CFG& m_graph; AsmAnalysisInfo const& m_info; std::map const& m_functionSideEffects; - Dialect const& m_dialect; + YulNameRepository& m_yulNameRepository; CFG::BasicBlock* m_currentBlock = nullptr; Scope* m_scope = nullptr; struct ForLoopInfo diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index bdce395ef89f..8d2b2915af15 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -51,6 +51,7 @@ CodeTransform::CodeTransform( AsmAnalysisInfo& _analysisInfo, Block const& _block, bool _allowStackOpt, + YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, BuiltinContext& _builtinContext, ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, @@ -61,6 +62,7 @@ CodeTransform::CodeTransform( ): m_assembly(_assembly), m_info(_analysisInfo), + m_yulNameRepository(_yulNameRepository), m_dialect(_dialect), m_builtinContext(_builtinContext), m_allowStackOpt(_allowStackOpt), @@ -79,7 +81,7 @@ CodeTransform::CodeTransform( } } -void CodeTransform::decreaseReference(YulString, Scope::Variable const& _var) +void CodeTransform::decreaseReference(YulName /*_name*/, Scope::Variable const& _var) { if (!m_allowStackOpt) return; @@ -158,7 +160,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl) for (size_t varIndex = 0; varIndex < numVariables; ++varIndex) { size_t varIndexReverse = numVariables - 1 - varIndex; - YulString varName = _varDecl.variables[varIndexReverse].name; + YulName varName = _varDecl.variables[varIndexReverse].name; auto& var = std::get(m_scope->identifiers.at(varName)); m_context->variableStackHeights[&var] = heightAtStart + varIndexReverse; if (!m_allowStackOpt) @@ -230,13 +232,14 @@ void CodeTransform::operator()(FunctionCall const& _call) yulAssert(m_scope, ""); m_assembly.setSourceLocation(originLocationOf(_call)); - if (BuiltinFunctionForEVM const* builtin = m_dialect.builtin(_call.functionName.name)) + if (auto const* builtin = m_yulNameRepository.builtin(_call.functionName.name)) { + auto const* evmBuiltin = dynamic_cast(builtin->data); for (auto&& [i, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) - if (!builtin->literalArgument(i)) + if (!evmBuiltin->literalArgument(i)) visitExpression(arg); m_assembly.setSourceLocation(originLocationOf(_call)); - builtin->generateCode(_call, m_assembly, m_builtinContext); + evmBuiltin->generateCode(_call, m_assembly, m_builtinContext); } else { @@ -385,6 +388,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) m_info, _function.body, m_allowStackOpt, + m_yulNameRepository, m_dialect, m_builtinContext, m_identifierAccessCodeGen, @@ -419,7 +423,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) m_assembly.markAsInvalid(); for (StackTooDeepError& stackError: subTransform.m_stackErrors) { - if (stackError.functionName.empty()) + if (stackError.functionName == YulNameRepository::emptyName()) stackError.functionName = _function.name; m_stackErrors.emplace_back(std::move(stackError)); } @@ -457,13 +461,12 @@ void CodeTransform::operator()(FunctionDefinition const& _function) { StackTooDeepError error( _function.name, - YulString{}, + YulNameRepository::emptyName(), static_cast(stackLayout.size()) - 17, - "The function " + - _function.name.str() + - " has " + - std::to_string(stackLayout.size() - 17) + - " parameters or return variables too many to fit the stack size." + fmt::format( + "The function {} has {} parameters or return variables too many to fit the stack size.", + m_yulNameRepository.labelOf(_function.name), stackLayout.size() - 17 + ) ); stackError(std::move(error), m_assembly.stackHeight() - static_cast(_function.parameters.size())); } @@ -602,7 +605,7 @@ void CodeTransform::createFunctionEntryID(FunctionDefinition const& _function) !nameAlreadySeen ) ? m_assembly.namedLabel( - _function.name.str(), + std::string(m_yulNameRepository.labelOf(_function.name)), _function.parameters.size(), _function.returnVariables.size(), astID @@ -667,7 +670,7 @@ bool statementNeedsReturnVariableSetup(Statement const& _statement, std::vector< std::holds_alternative(_statement) ) { - std::map references = VariableReferencesCounter::countReferences(_statement); + std::map references = VariableReferencesCounter::countReferences(_statement); auto isReferenced = [&references](TypedName const& _returnVariable) { return references.count(_returnVariable.name); }; @@ -771,7 +774,7 @@ void CodeTransform::generateAssignment(Identifier const& _variableName) } } -size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString _varName, bool _forSwap) +size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulName _varName, bool _forSwap) { yulAssert(m_context->variableStackHeights.count(&_var), ""); size_t heightDiff = static_cast(m_assembly.stackHeight()) - m_context->variableStackHeights[&_var]; @@ -782,12 +785,10 @@ size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString m_stackErrors.emplace_back( _varName, heightDiff - limit, - "Variable " + - _varName.str() + - " is " + - std::to_string(heightDiff - limit) + - " slot(s) too deep inside the stack. " + - stackTooDeepString + fmt::format( + "Variable {} is {} slot(s) too deep inside the stack. {}", + m_yulNameRepository.labelOf(_varName), heightDiff - limit, stackTooDeepString + ) ); m_assembly.markAsInvalid(); return _forSwap ? 2 : 1; @@ -795,7 +796,7 @@ size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString return heightDiff; } -int CodeTransform::variableStackHeight(YulString _name) const +int CodeTransform::variableStackHeight(YulName _name) const { Scope::Variable const* var = std::get_if(m_scope->lookup(_name)); yulAssert(var, ""); diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index bad9a357ff29..fcdedb05c5cd 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -78,6 +78,7 @@ class CodeTransform AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, Block const& _block, + YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, BuiltinContext& _builtinContext, bool _allowStackOpt = false, @@ -88,6 +89,7 @@ class CodeTransform _analysisInfo, _block, _allowStackOpt, + _yulNameRepository, _dialect, _builtinContext, _identifierAccessCodeGen, @@ -109,6 +111,7 @@ class CodeTransform AsmAnalysisInfo& _analysisInfo, Block const& _block, bool _allowStackOpt, + YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, BuiltinContext& _builtinContext, ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, @@ -118,7 +121,7 @@ class CodeTransform std::optional _functionExitLabel ); - void decreaseReference(YulString _name, Scope::Variable const& _var); + void decreaseReference(YulName _name, Scope::Variable const& _var); bool unreferenced(Scope::Variable const& _var) const; /// Marks slots of variables that are not used anymore /// and were defined in the current scope for reuse. @@ -165,10 +168,10 @@ class CodeTransform /// the (positive) stack height difference otherwise. /// @param _forSwap if true, produces stack error if the difference is invalid for a swap /// opcode, otherwise checks for validity for a dup opcode. - size_t variableHeightDiff(Scope::Variable const& _var, YulString _name, bool _forSwap); + size_t variableHeightDiff(Scope::Variable const& _var, YulName _name, bool _forSwap); /// Determines the stack height of the given variable. Throws if the variable is not in scope. - int variableStackHeight(YulString _name) const; + int variableStackHeight(YulName _name) const; void expectDeposit(int _deposit, int _oldHeight) const; @@ -194,11 +197,12 @@ class CodeTransform AbstractAssembly& m_assembly; AsmAnalysisInfo& m_info; Scope* m_scope = nullptr; + YulNameRepository const& m_yulNameRepository; EVMDialect const& m_dialect; BuiltinContext& m_builtinContext; bool const m_allowStackOpt = true; UseNamedLabels const m_useNamedLabelsForFunctions = UseNamedLabels::Never; - std::set m_assignedNamedLabels; + std::set m_assignedNamedLabels; ExternalIdentifierAccess::CodeGenerator m_identifierAccessCodeGen; std::shared_ptr m_context; diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 463bd458837f..a7e80632da46 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -48,7 +48,7 @@ using namespace solidity::util; namespace { -std::pair createEVMFunction( +std::pair createEVMFunction( langutil::EVMVersion _evmVersion, std::string const& _name, evmasm::Instruction _instruction @@ -56,7 +56,7 @@ std::pair createEVMFunction( { evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion); BuiltinFunctionForEVM f; - f.name = YulString{_name}; + f.name = _name; f.parameters.resize(static_cast(info.args)); f.returns.resize(static_cast(info.ret)); f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction); @@ -85,12 +85,12 @@ std::pair createEVMFunction( _assembly.appendInstruction(_instruction); }; - YulString name = f.name; + auto const name = f.name; return {name, std::move(f)}; } -std::pair createFunction( - std::string _name, +std::pair createFunction( + std::string const& _name, size_t _params, size_t _returns, SideEffects _sideEffects, @@ -100,9 +100,8 @@ std::pair createFunction( { yulAssert(_literalArguments.size() == _params || _literalArguments.empty(), ""); - YulString name{std::move(_name)}; BuiltinFunctionForEVM f; - f.name = name; + f.name = _name; f.parameters.resize(_params); f.returns.resize(_returns); f.sideEffects = std::move(_sideEffects); @@ -110,10 +109,10 @@ std::pair createFunction( f.isMSize = false; f.instruction = {}; f.generateCode = std::move(_generateCode); - return {name, f}; + return {f.name, f}; } -std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) +EVMDialect::ReservedIdentifiers createReservedIdentifiers(langutil::EVMVersion _evmVersion) { // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name // basefee for VMs before london. @@ -159,7 +158,7 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) (_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD); }; - std::set reserved; + EVMDialect::ReservedIdentifiers reserved; for (auto const& instr: evmasm::c_instructions) { std::string name = toLower(instr.first); @@ -173,18 +172,18 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion) ) reserved.emplace(name); } - reserved += std::vector{ - "linkersymbol"_yulstring, - "datasize"_yulstring, - "dataoffset"_yulstring, - "datacopy"_yulstring, - "setimmutable"_yulstring, - "loadimmutable"_yulstring, + reserved += std::vector{ + "linkersymbol", + "datasize", + "dataoffset", + "datacopy", + "setimmutable", + "loadimmutable" }; return reserved; } -std::map createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess) +EVMDialect::BuiltinsMap createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess) { // Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris. @@ -193,7 +192,7 @@ std::map createBuiltins(langutil::EVMVersion _ return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris()); }; - std::map builtins; + EVMDialect::BuiltinsMap builtins; for (auto const& instr: evmasm::c_instructions) { std::string name = toLower(instr.first); @@ -306,8 +305,7 @@ std::map createBuiltins(langutil::EVMVersion _ BuiltinContext& ) { _assembly.appendInstruction(evmasm::Instruction::CODECOPY); - } - )); + })); builtins.emplace(createFunction( "setimmutable", 3, @@ -330,10 +328,9 @@ std::map createBuiltins(langutil::EVMVersion _ BuiltinContext& ) { yulAssert(_call.arguments.size() == 3, ""); - auto const identifier = (formatLiteral(std::get(_call.arguments[1]))); + auto const identifier = formatLiteral(std::get(_call.arguments[1])); _assembly.appendImmutableAssignment(identifier); - } - )); + })); builtins.emplace(createFunction( "loadimmutable", 1, @@ -367,28 +364,37 @@ EVMDialect::EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess): m_evmVersion(_evmVersion), m_functions(createBuiltins(_evmVersion, _objectAccess)), m_reserved(createReservedIdentifiers(_evmVersion)) -{ -} +{} -BuiltinFunctionForEVM const* EVMDialect::builtin(YulString _name) const +BuiltinFunctionForEVM const* EVMDialect::builtin(std::string_view const _name) const { if (m_objectAccess) { std::smatch match; - if (regex_match(_name.str(), match, verbatimPattern())) + auto const input = std::string(_name); + if (std::regex_match(input, match, verbatimPattern())) return verbatimFunction(stoul(match[1]), stoul(match[2])); } - auto it = m_functions.find(_name); + auto const it = m_functions.find(_name); if (it != m_functions.end()) return &it->second; else return nullptr; } -bool EVMDialect::reservedIdentifier(YulString _name) const +BuiltinFunctionForEVM const* EVMDialect::builtinNoVerbatim(std::string_view const _name) const +{ + auto const it = m_functions.find(_name); + if (it != m_functions.end()) + return &it->second; + else + return nullptr; +} + +bool EVMDialect::reservedIdentifier(std::string_view const _name) const { if (m_objectAccess) - if (_name.str().substr(0, "verbatim"s.size()) == "verbatim") + if (_name.substr(0, "verbatim"s.size()) == "verbatim") return true; return m_reserved.count(_name) != 0; } @@ -434,11 +440,12 @@ SideEffects EVMDialect::sideEffectsOfInstruction(evmasm::Instruction _instructio BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, size_t _returnVariables) const { std::pair key{_arguments, _returnVariables}; - std::shared_ptr& function = m_verbatimFunctions[key]; - if (!function) + auto [it, emplaced] = m_verbatimFunctions.try_emplace(std::make_pair(_arguments, _returnVariables)); + if (emplaced) { + auto const name = "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o"; BuiltinFunctionForEVM builtinFunction = createFunction( - "verbatim_" + std::to_string(_arguments) + "i_" + std::to_string(_returnVariables) + "o", + name, 1 + _arguments, _returnVariables, SideEffects::worst(), @@ -459,9 +466,16 @@ BuiltinFunctionForEVM const* EVMDialect::verbatimFunction(size_t _arguments, siz } ).second; builtinFunction.isMSize = true; - function = std::make_shared(std::move(builtinFunction)); + std::fill(builtinFunction.parameters.begin(), builtinFunction.parameters.end(), defaultType); + std::fill(builtinFunction.returns.begin(), builtinFunction.returns.end(), defaultType); + it->second = std::make_shared(std::move(builtinFunction)); } - return function.get(); + return it->second.get(); +} +std::set EVMDialect::builtinNames() const { + static constexpr std::array verbatim {"verbatim"}; + auto const keys = ranges::views::concat(ranges::views::keys(m_functions), verbatim); + return { keys.begin(), keys.end() }; } std::set EVMDialect::builtinNames() const { @@ -474,9 +488,11 @@ std::set EVMDialect::builtinNames() const { EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess): EVMDialect(_evmVersion, _objectAccess) { - defaultType = "u256"_yulstring; - boolType = "bool"_yulstring; + defaultType = "u256"; + boolType = "bool"; types = {defaultType, boolType}; + not_ = "not"; + popbool_ = "popbool"; // Set all types to ``defaultType`` for (auto& fun: m_functions) @@ -487,81 +503,91 @@ EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectA r = defaultType; } - m_functions["lt"_yulstring].returns = {"bool"_yulstring}; - m_functions["gt"_yulstring].returns = {"bool"_yulstring}; - m_functions["slt"_yulstring].returns = {"bool"_yulstring}; - m_functions["sgt"_yulstring].returns = {"bool"_yulstring}; - m_functions["eq"_yulstring].returns = {"bool"_yulstring}; + m_functions["lt"].returns = {boolType}; + m_functions["gt"].returns = {boolType}; + m_functions["slt"].returns = {boolType}; + m_functions["sgt"].returns = {boolType}; + m_functions["eq"].returns = {boolType}; // "not" and "bitnot" replace "iszero" and "not" - m_functions["bitnot"_yulstring] = m_functions["not"_yulstring]; - m_functions["bitnot"_yulstring].name = "bitnot"_yulstring; - m_functions["not"_yulstring] = m_functions["iszero"_yulstring]; - m_functions["not"_yulstring].name = "not"_yulstring; - m_functions["not"_yulstring].returns = {"bool"_yulstring}; - m_functions["not"_yulstring].parameters = {"bool"_yulstring}; - m_functions.erase("iszero"_yulstring); - - m_functions["bitand"_yulstring] = m_functions["and"_yulstring]; - m_functions["bitand"_yulstring].name = "bitand"_yulstring; - m_functions["bitor"_yulstring] = m_functions["or"_yulstring]; - m_functions["bitor"_yulstring].name = "bitor"_yulstring; - m_functions["bitxor"_yulstring] = m_functions["xor"_yulstring]; - m_functions["bitxor"_yulstring].name = "bitxor"_yulstring; - m_functions["and"_yulstring].parameters = {"bool"_yulstring, "bool"_yulstring}; - m_functions["and"_yulstring].returns = {"bool"_yulstring}; - m_functions["or"_yulstring].parameters = {"bool"_yulstring, "bool"_yulstring}; - m_functions["or"_yulstring].returns = {"bool"_yulstring}; - m_functions["xor"_yulstring].parameters = {"bool"_yulstring, "bool"_yulstring}; - m_functions["xor"_yulstring].returns = {"bool"_yulstring}; - m_functions["popbool"_yulstring] = m_functions["pop"_yulstring]; - m_functions["popbool"_yulstring].name = "popbool"_yulstring; - m_functions["popbool"_yulstring].parameters = {"bool"_yulstring}; - m_functions.insert(createFunction("bool_to_u256", 1, 1, {}, {}, []( - FunctionCall const&, - AbstractAssembly&, - BuiltinContext& - ) {})); - m_functions["bool_to_u256"_yulstring].parameters = {"bool"_yulstring}; - m_functions["bool_to_u256"_yulstring].returns = {"u256"_yulstring}; - m_functions.insert(createFunction("u256_to_bool", 1, 1, {}, {}, []( - FunctionCall const&, - AbstractAssembly& _assembly, - BuiltinContext& - ) { - // TODO this should use a Panic. - // A value larger than 1 causes an invalid instruction. - _assembly.appendConstant(2); - _assembly.appendInstruction(evmasm::Instruction::DUP2); - _assembly.appendInstruction(evmasm::Instruction::LT); - AbstractAssembly::LabelID inRange = _assembly.newLabelId(); - _assembly.appendJumpToIf(inRange); - _assembly.appendInstruction(evmasm::Instruction::INVALID); - _assembly.appendLabel(inRange); - })); - m_functions["u256_to_bool"_yulstring].parameters = {"u256"_yulstring}; - m_functions["u256_to_bool"_yulstring].returns = {"bool"_yulstring}; + m_functions["bitnot"] = m_functions[not_]; + m_functions["bitnot"].name = "bitnot"; + m_functions[not_] = m_functions["iszero"]; + m_functions[not_].name = not_; + m_functions[not_].returns = {boolType}; + m_functions[not_].parameters = {boolType}; + m_functions.erase("iszero"); + + m_functions["bitand"] = m_functions["and"]; + m_functions["bitand"].name = "bitand"; + m_functions["bitor"] = m_functions["or"]; + m_functions["bitor"].name = "bitor"; + m_functions["bitxor"] = m_functions["xor"]; + m_functions["bitxor"].name = "bitxor"; + m_functions["and"].parameters = {boolType, boolType}; + m_functions["and"].returns = {boolType}; + m_functions["or"].parameters = {boolType, boolType}; + m_functions["or"].returns = {boolType}; + m_functions["xor"].parameters = {boolType, boolType}; + m_functions["xor"].returns = {boolType}; + m_functions["popbool"] = m_functions["pop"]; + m_functions["popbool"].name = "popbool"; + m_functions["popbool"].parameters = {boolType}; + { + auto const [it, _] = m_functions.insert(createFunction( + "bool_to_u256", + 1, + 1, + {}, + {}, + [](FunctionCall const&, AbstractAssembly&, BuiltinContext&) {}) + ); + m_functions[it->first].parameters = {boolType}; + m_functions[it->first].returns = {defaultType}; + } + { + auto const [it, _] = m_functions.insert(createFunction( + "u256_to_bool", + 1, + 1, + {}, + {}, + [](FunctionCall const&, AbstractAssembly& _assembly, BuiltinContext&) + { + // TODO this should use a Panic. + // A value larger than 1 causes an invalid instruction. + _assembly.appendConstant(2); + _assembly.appendInstruction(evmasm::Instruction::DUP2); + _assembly.appendInstruction(evmasm::Instruction::LT); + AbstractAssembly::LabelID inRange = _assembly.newLabelId(); + _assembly.appendJumpToIf(inRange); + _assembly.appendInstruction(evmasm::Instruction::INVALID); + _assembly.appendLabel(inRange); + })); + m_functions[it->first].parameters = {defaultType}; + m_functions[it->first].returns = {boolType}; + } } -BuiltinFunctionForEVM const* EVMDialectTyped::discardFunction(YulString _type) const +BuiltinFunctionForEVM const* EVMDialectTyped::discardFunction(std::string_view const _type) const { - if (_type == "bool"_yulstring) - return builtin("popbool"_yulstring); + if (_type == boolType) + return builtinNoVerbatim(popbool_); else { yulAssert(_type == defaultType, ""); - return builtin("pop"_yulstring); + return builtinNoVerbatim("pop"); } } -BuiltinFunctionForEVM const* EVMDialectTyped::equalityFunction(YulString _type) const +BuiltinFunctionForEVM const* EVMDialectTyped::equalityFunction(std::string_view _type) const { - if (_type == "bool"_yulstring) + if (_type == boolType) return nullptr; else { yulAssert(_type == defaultType, ""); - return builtin("eq"_yulstring); + return builtinNoVerbatim("eq"); } } diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 3ae23b7a1674..1546e0281694 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -34,7 +34,6 @@ namespace solidity::yul { class YulString; -using Type = YulString; struct FunctionCall; struct Object; @@ -66,23 +65,30 @@ struct BuiltinFunctionForEVM: public BuiltinFunction */ struct EVMDialect: public Dialect { + using BuiltinsMap = std::map>; + using ReservedIdentifiers = std::set>; + /// Constructor, should only be used internally. Use the factory functions below. EVMDialect(langutil::EVMVersion _evmVersion, bool _objectAccess); /// @returns the builtin function of the given name or a nullptr if it is not a builtin function. - BuiltinFunctionForEVM const* builtin(YulString _name) const override; + BuiltinFunctionForEVM const* builtin(std::string_view _name) const override; + BuiltinFunctionForEVM const* builtinNoVerbatim(std::string_view _name) const; /// @returns true if the identifier is reserved. This includes the builtins too. - bool reservedIdentifier(YulString _name) const override; + bool reservedIdentifier(std::string_view _name) const override; + + BuiltinFunctionForEVM const* discardFunction(std::string_view /*_type*/) const override { return builtinNoVerbatim("pop"); } + BuiltinFunctionForEVM const* equalityFunction(std::string_view /*_type*/) const override { return builtinNoVerbatim("eq"); } + BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtinNoVerbatim("iszero"); } + BuiltinFunctionForEVM const* memoryStoreFunction(std::string_view /*_type*/) const override { return builtinNoVerbatim("mstore"); } + BuiltinFunctionForEVM const* memoryLoadFunction(std::string_view /*_type*/) const override { return builtinNoVerbatim("mload"); } + BuiltinFunctionForEVM const* storageStoreFunction(std::string_view /*_type*/) const override { return builtinNoVerbatim("sstore"); } + BuiltinFunctionForEVM const* storageLoadFunction(std::string_view /*_type*/) const override { return builtinNoVerbatim("sload"); } + - BuiltinFunctionForEVM const* discardFunction(YulString /*_type*/) const override { return builtin("pop"_yulstring); } - BuiltinFunctionForEVM const* equalityFunction(YulString /*_type*/) const override { return builtin("eq"_yulstring); } - BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("iszero"_yulstring); } - BuiltinFunctionForEVM const* memoryStoreFunction(YulString /*_type*/) const override { return builtin("mstore"_yulstring); } - BuiltinFunctionForEVM const* memoryLoadFunction(YulString /*_type*/) const override { return builtin("mload"_yulstring); } - BuiltinFunctionForEVM const* storageStoreFunction(YulString /*_type*/) const override { return builtin("sstore"_yulstring); } - BuiltinFunctionForEVM const* storageLoadFunction(YulString /*_type*/) const override { return builtin("sload"_yulstring); } - YulString hashFunction(YulString /*_type*/) const override { return "keccak256"_yulstring; } + + std::string_view hashFunction(std::string_view /*_type*/) const override { return "keccak256"; } static EVMDialect const& strictAssemblyForEVM(langutil::EVMVersion _version); static EVMDialect const& strictAssemblyForEVMObjects(langutil::EVMVersion _version); @@ -100,9 +106,9 @@ struct EVMDialect: public Dialect bool const m_objectAccess; langutil::EVMVersion const m_evmVersion; - std::map m_functions; + BuiltinsMap m_functions; std::map, std::shared_ptr> mutable m_verbatimFunctions; - std::set m_reserved; + ReservedIdentifiers m_reserved; }; /** @@ -120,11 +126,14 @@ struct EVMDialectTyped: public EVMDialect /// Constructor, should only be used internally. Use the factory function below. EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess); - BuiltinFunctionForEVM const* discardFunction(YulString _type) const override; - BuiltinFunctionForEVM const* equalityFunction(YulString _type) const override; - BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtin("not"_yulstring); } + BuiltinFunctionForEVM const* discardFunction(std::string_view _type) const override; + BuiltinFunctionForEVM const* equalityFunction(std::string_view _type) const override; + BuiltinFunctionForEVM const* booleanNegationFunction() const override { return builtinNoVerbatim(not_); } static EVMDialectTyped const& instance(langutil::EVMVersion _version); + + std::string not_; + std::string popbool_; }; } diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index 84ebdab1d2be..73edbf2fe5fe 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -37,12 +37,12 @@ using namespace solidity::util; bigint GasMeter::costs(Expression const& _expression) const { - return combineCosts(GasMeterVisitor::costs(_expression, m_dialect, m_isCreation)); + return combineCosts(GasMeterVisitor::costs(_expression, m_yulNameRepository, m_dialect, m_isCreation)); } bigint GasMeter::instructionCosts(evmasm::Instruction _instruction) const { - return combineCosts(GasMeterVisitor::instructionCosts(_instruction, m_dialect, m_isCreation)); + return combineCosts(GasMeterVisitor::instructionCosts(_instruction, m_yulNameRepository, m_dialect, m_isCreation)); } bigint GasMeter::combineCosts(std::pair _costs) const @@ -53,22 +53,24 @@ bigint GasMeter::combineCosts(std::pair _costs) const std::pair GasMeterVisitor::costs( Expression const& _expression, + YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, bool _isCreation ) { - GasMeterVisitor gmv(_dialect, _isCreation); + GasMeterVisitor gmv(_yulNameRepository, _dialect, _isCreation); gmv.visit(_expression); return {gmv.m_runGas, gmv.m_dataGas}; } std::pair GasMeterVisitor::instructionCosts( evmasm::Instruction _instruction, + YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, bool _isCreation ) { - GasMeterVisitor gmv(_dialect, _isCreation); + GasMeterVisitor gmv(_yulNameRepository, _dialect, _isCreation); gmv.instructionCostsInternal(_instruction); return {gmv.m_runGas, gmv.m_dataGas}; } @@ -76,10 +78,10 @@ std::pair GasMeterVisitor::instructionCosts( void GasMeterVisitor::operator()(FunctionCall const& _funCall) { ASTWalker::operator()(_funCall); - if (BuiltinFunctionForEVM const* f = m_dialect.builtin(_funCall.functionName.name)) - if (f->instruction) + if (auto const* f = m_yulNameRepository.builtin(_funCall.functionName.name)) + if (auto const* evmFun = dynamic_cast(f->data); evmFun && evmFun->instruction) { - instructionCostsInternal(*f->instruction); + instructionCostsInternal(*evmFun->instruction); return; } yulAssert(false, "Functions not implemented."); diff --git a/libyul/backends/evm/EVMMetrics.h b/libyul/backends/evm/EVMMetrics.h index b67cb77cdd50..578bc7d07e0b 100644 --- a/libyul/backends/evm/EVMMetrics.h +++ b/libyul/backends/evm/EVMMetrics.h @@ -43,7 +43,8 @@ struct EVMDialect; class GasMeter { public: - GasMeter(EVMDialect const& _dialect, bool _isCreation, bigint _runs): + GasMeter(YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, bool _isCreation, bigint _runs): + m_yulNameRepository(_yulNameRepository), m_dialect(_dialect), m_isCreation{_isCreation}, m_runs(_isCreation? 1 : _runs) @@ -58,6 +59,7 @@ class GasMeter private: bigint combineCosts(std::pair _costs) const; + YulNameRepository const& m_yulNameRepository; EVMDialect const& m_dialect; bool m_isCreation = false; bigint m_runs; @@ -68,18 +70,21 @@ class GasMeterVisitor: public ASTWalker public: static std::pair costs( Expression const& _expression, + YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, bool _isCreation ); static std::pair instructionCosts( evmasm::Instruction _instruction, + YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, bool _isCreation = false ); public: - GasMeterVisitor(EVMDialect const& _dialect, bool _isCreation): + GasMeterVisitor(YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, bool _isCreation): + m_yulNameRepository(_yulNameRepository), m_dialect(_dialect), m_isCreation{_isCreation} {} @@ -95,6 +100,7 @@ class GasMeterVisitor: public ASTWalker /// Does not work particularly exact for anything apart from arithmetic. void instructionCostsInternal(evmasm::Instruction _instruction); + YulNameRepository const& m_yulNameRepository; EVMDialect const& m_dialect; bool m_isCreation = false; bigint m_runGas = 0; diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 28b72c0871ee..f3bf8a9b078a 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -37,12 +37,13 @@ using namespace solidity::yul; void EVMObjectCompiler::compile( Object& _object, AbstractAssembly& _assembly, + YulNameRepository& _yulNameRepository, EVMDialect const& _dialect, bool _optimize, std::optional _eofVersion ) { - EVMObjectCompiler compiler(_assembly, _dialect, _eofVersion); + EVMObjectCompiler compiler(_assembly, _yulNameRepository, _dialect, _eofVersion); compiler.run(_object, _optimize); } @@ -59,7 +60,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name.str()); context.subIDs[subObject->name] = subAssemblyAndID.second; subObject->subId = subAssemblyAndID.second; - compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize, m_eofVersion); + compile(*subObject, *subAssemblyAndID.first, m_yulNameRepository, m_dialect, _optimize, m_eofVersion); } else { @@ -84,7 +85,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) m_assembly, *_object.analysisInfo, *_object.code, - m_dialect, + m_yulNameRepository, context, OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName ); @@ -92,7 +93,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) { std::vector memoryGuardCalls = FunctionCallFinder::run( *_object.code, - "memoryguard"_yulstring + m_yulNameRepository.predefined().memoryguard ); auto stackError = stackErrors.front(); std::string msg = stackError.comment() ? *stackError.comment() : ""; @@ -114,6 +115,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) m_assembly, *_object.analysisInfo, *_object.code, + m_yulNameRepository, m_dialect, context, _optimize, diff --git a/libyul/backends/evm/EVMObjectCompiler.h b/libyul/backends/evm/EVMObjectCompiler.h index df8d71c2cef5..3c9fabbbfa79 100644 --- a/libyul/backends/evm/EVMObjectCompiler.h +++ b/libyul/backends/evm/EVMObjectCompiler.h @@ -29,6 +29,7 @@ namespace solidity::yul struct Object; class AbstractAssembly; struct EVMDialect; +class YulNameRepository; class EVMObjectCompiler { @@ -36,18 +37,20 @@ class EVMObjectCompiler static void compile( Object& _object, AbstractAssembly& _assembly, + YulNameRepository& _yulNameRepository, EVMDialect const& _dialect, bool _optimize, std::optional _eofVersion ); private: - EVMObjectCompiler(AbstractAssembly& _assembly, EVMDialect const& _dialect, std::optional _eofVersion): - m_assembly(_assembly), m_dialect(_dialect), m_eofVersion(_eofVersion) + EVMObjectCompiler(AbstractAssembly& _assembly, YulNameRepository& _yulNameRepository, EVMDialect const& _dialect, std::optional _eofVersion): + m_assembly(_assembly), m_yulNameRepository(_yulNameRepository), m_dialect(_dialect), m_eofVersion(_eofVersion) {} void run(Object& _object, bool _optimize); AbstractAssembly& m_assembly; + YulNameRepository& m_yulNameRepository; EVMDialect const& m_dialect; std::optional m_eofVersion; }; diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 047014e3dc43..a9726ffbf1e8 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -43,19 +43,20 @@ std::vector OptimizedEVMCodeTransform::run( AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, Block const& _block, - EVMDialect const& _dialect, + YulNameRepository& _yulNameRepository, BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions ) { - std::unique_ptr dfg = ControlFlowGraphBuilder::build(_analysisInfo, _dialect, _block); + std::unique_ptr dfg = ControlFlowGraphBuilder::build(_analysisInfo, _yulNameRepository, _block); StackLayout stackLayout = StackLayoutGenerator::run(*dfg); OptimizedEVMCodeTransform optimizedCodeTransform( _assembly, _builtinContext, _useNamedLabelsForFunctions, *dfg, - stackLayout + stackLayout, + _yulNameRepository ); // Create initial entry layout. optimizedCodeTransform.createStackLayout(debugDataOf(*dfg->entry), stackLayout.blockInfos.at(dfg->entry).entryLayout); @@ -177,7 +178,8 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions, CFG const& _dfg, - StackLayout const& _stackLayout + StackLayout const& _stackLayout, + YulNameRepository const& _yulNameRepository ): m_assembly(_assembly), m_builtinContext(_builtinContext), @@ -185,7 +187,7 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( m_stackLayout(_stackLayout), m_functionLabels([&](){ std::map functionLabels; - std::set assignedFunctionNames; + std::set assignedFunctionNames; for (Scope::Function const* function: m_dfg.functions) { CFG::FunctionInfo const& functionInfo = m_dfg.functionInfo.at(function); @@ -195,7 +197,7 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( bool useNamedLabel = _useNamedLabelsForFunctions != UseNamedLabels::Never && !nameAlreadySeen; functionLabels[&functionInfo] = useNamedLabel ? m_assembly.namedLabel( - function->name.str(), + std::string(_yulNameRepository.labelOf(function->name)), function->arguments.size(), function->returns.size(), functionInfo.debugData ? functionInfo.debugData->astID : std::nullopt @@ -203,7 +205,8 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( m_assembly.newLabelId(); } return functionLabels; - }()) + }()), + m_yulNameRepository(_yulNameRepository) { } @@ -242,7 +245,7 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr static constexpr auto slotVariableName = [](StackSlot const& _slot) { return std::visit(util::GenericVisitor{ [](VariableSlot const& _var) { return _var.variable.get().name; }, - [](auto const&) { return YulString{}; } + [](auto const&) { return YulNameRepository::emptyName(); } }, _slot); }; @@ -264,15 +267,15 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr { int deficit = static_cast(_i) - 16; StackSlot const& deepSlot = m_stack.at(m_stack.size() - _i - 1); - YulString varNameDeep = slotVariableName(deepSlot); - YulString varNameTop = slotVariableName(m_stack.back()); + YulName varNameDeep = slotVariableName(deepSlot); + YulName varNameTop = slotVariableName(m_stack.back()); std::string msg = - "Cannot swap " + (varNameDeep.empty() ? "Slot " + stackSlotToString(deepSlot) : "Variable " + varNameDeep.str()) + - " with " + (varNameTop.empty() ? "Slot " + stackSlotToString(m_stack.back()) : "Variable " + varNameTop.str()) + - ": too deep in the stack by " + std::to_string(deficit) + " slots in " + stackToString(m_stack); + "Cannot swap " + (varNameDeep == YulNameRepository::emptyName() ? "Slot " + stackSlotToString(deepSlot, m_yulNameRepository) : "Variable " + std::string(m_yulNameRepository.labelOf(varNameDeep))) + + " with " + (varNameTop == YulNameRepository::emptyName() ? "Slot " + stackSlotToString(m_stack.back(), m_yulNameRepository) : "Variable " + std::string(m_yulNameRepository.labelOf(varNameTop))) + + ": too deep in the stack by " + std::to_string(deficit) + " slots in " + stackToString(m_stack, m_yulNameRepository); m_stackErrors.emplace_back(StackTooDeepError( - m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulString{}, - varNameDeep.empty() ? varNameTop : varNameDeep, + m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulNameRepository::emptyName(), + varNameDeep == YulNameRepository::emptyName() ? varNameTop : varNameDeep, deficit, msg )); @@ -295,12 +298,12 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr else if (!canBeFreelyGenerated(_slot)) { int deficit = static_cast(*depth - 15); - YulString varName = slotVariableName(_slot); + YulName varName = slotVariableName(_slot); std::string msg = - (varName.empty() ? "Slot " + stackSlotToString(_slot) : "Variable " + varName.str()) - + " is " + std::to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack); + (varName == YulNameRepository::emptyName() ? "Slot " + stackSlotToString(_slot, m_yulNameRepository) : "Variable " + std::string(m_yulNameRepository.labelOf(varName))) + + " is " + std::to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack, m_yulNameRepository); m_stackErrors.emplace_back(StackTooDeepError( - m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulString{}, + m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulNameRepository::emptyName(), varName, deficit, msg diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.h b/libyul/backends/evm/OptimizedEVMCodeTransform.h index 7e648ca964bb..d3632af3abec 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.h +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.h @@ -51,7 +51,7 @@ class OptimizedEVMCodeTransform AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, Block const& _block, - EVMDialect const& _dialect, + YulNameRepository& _yulNameRepository, BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions ); @@ -68,7 +68,8 @@ class OptimizedEVMCodeTransform BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions, CFG const& _dfg, - StackLayout const& _stackLayout + StackLayout const& _stackLayout, + YulNameRepository const& _yulNameRepository ); /// Assert that it is valid to transition from @a _currentStack to @a _desiredStack. @@ -110,6 +111,7 @@ class OptimizedEVMCodeTransform std::set m_generated; CFG::FunctionInfo const* m_currentFunctionInfo = nullptr; std::vector m_stackErrors; + YulNameRepository const& m_yulNameRepository; }; } diff --git a/libyul/backends/evm/StackHelpers.h b/libyul/backends/evm/StackHelpers.h index dae4352a02c4..4644511c9488 100644 --- a/libyul/backends/evm/StackHelpers.h +++ b/libyul/backends/evm/StackHelpers.h @@ -33,23 +33,23 @@ namespace solidity::yul { -inline std::string stackSlotToString(StackSlot const& _slot) +inline std::string stackSlotToString(StackSlot const& _slot, YulNameRepository const& _yulNameRepository) { return std::visit(util::GenericVisitor{ - [](FunctionCallReturnLabelSlot const& _ret) -> std::string { return "RET[" + _ret.call.get().functionName.name.str() + "]"; }, + [&_yulNameRepository](FunctionCallReturnLabelSlot const& _ret) -> std::string { return fmt::format("RET[{}]", _yulNameRepository.labelOf(_ret.call.get().functionName.name)); }, [](FunctionReturnLabelSlot const&) -> std::string { return "RET"; }, - [](VariableSlot const& _var) { return _var.variable.get().name.str(); }, + [&_yulNameRepository](VariableSlot const& _var) { return std::string(_yulNameRepository.labelOf(_var.variable.get().name)); }, [](LiteralSlot const& _lit) { return toCompactHexWithPrefix(_lit.value); }, - [](TemporarySlot const& _tmp) -> std::string { return "TMP[" + _tmp.call.get().functionName.name.str() + ", " + std::to_string(_tmp.index) + "]"; }, + [&_yulNameRepository](TemporarySlot const& _tmp) -> std::string { return fmt::format("TMP[{}, {}]", _yulNameRepository.labelOf(_tmp.call.get().functionName.name), _tmp.index); }, [](JunkSlot const&) -> std::string { return "JUNK"; } }, _slot); } -inline std::string stackToString(Stack const& _stack) +inline std::string stackToString(Stack const& _stack, YulNameRepository const& _yulNameRepository) { std::string result("[ "); for (auto const& slot: _stack) - result += stackSlotToString(slot) + ' '; + result += stackSlotToString(slot, _yulNameRepository) + ' '; result += ']'; return result; } diff --git a/libyul/backends/evm/StackLayoutGenerator.cpp b/libyul/backends/evm/StackLayoutGenerator.cpp index 954c9f2af7af..576a1fbce57d 100644 --- a/libyul/backends/evm/StackLayoutGenerator.cpp +++ b/libyul/backends/evm/StackLayoutGenerator.cpp @@ -58,21 +58,21 @@ StackLayout StackLayoutGenerator::run(CFG const& _cfg) return stackLayout; } -std::map> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg) +std::map> StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg) { - std::map> stackTooDeepErrors; - stackTooDeepErrors[YulString{}] = reportStackTooDeep(_cfg, YulString{}); + std::map> stackTooDeepErrors; + stackTooDeepErrors[YulNameRepository::emptyName()] = reportStackTooDeep(_cfg, YulNameRepository::emptyName()); for (auto const& function: _cfg.functions) if (auto errors = reportStackTooDeep(_cfg, function->name); !errors.empty()) stackTooDeepErrors[function->name] = std::move(errors); return stackTooDeepErrors; } -std::vector StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulString _functionName) +std::vector StackLayoutGenerator::reportStackTooDeep(CFG const& _cfg, YulName _functionName) { StackLayout stackLayout; CFG::FunctionInfo const* functionInfo = nullptr; - if (!_functionName.empty()) + if (_functionName != YulNameRepository::emptyName()) { functionInfo = &ranges::find( _cfg.functionInfo, @@ -102,7 +102,7 @@ std::vector findStackTooDeep(Stack const& _s Stack currentStack = _source; std::vector stackTooDeepErrors; auto getVariableChoices = [](auto&& _range) { - std::vector result; + std::vector result; for (auto const& slot: _range) if (auto const* variableSlot = std::get_if(&slot)) if (!util::contains(result, variableSlot->variable.get().name)) diff --git a/libyul/backends/evm/StackLayoutGenerator.h b/libyul/backends/evm/StackLayoutGenerator.h index d04b80bdc02a..fc846a9deced 100644 --- a/libyul/backends/evm/StackLayoutGenerator.h +++ b/libyul/backends/evm/StackLayoutGenerator.h @@ -52,18 +52,18 @@ class StackLayoutGenerator /// Number of slots that need to be saved. size_t deficit = 0; /// Set of variables, eliminating which would decrease the stack deficit. - std::vector variableChoices; + std::vector variableChoices; }; static StackLayout run(CFG const& _cfg); /// @returns a map from function names to the stack too deep errors occurring in that function. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// The empty string is mapped to the stack too deep errors of the main entry point. - static std::map> reportStackTooDeep(CFG const& _cfg); + static std::map> reportStackTooDeep(CFG const& _cfg); /// @returns all stack too deep errors in the function named @a _functionName. /// Requires @a _cfg to be a control flow graph generated from disambiguated Yul. /// If @a _functionName is empty, the stack too deep errors of the main entry point are reported instead. - static std::vector reportStackTooDeep(CFG const& _cfg, YulString _functionName); + static std::vector reportStackTooDeep(CFG const& _cfg, YulName _functionName); private: StackLayoutGenerator(StackLayout& _context, CFG::FunctionInfo const* _functionInfo); diff --git a/libyul/backends/evm/VariableReferenceCounter.cpp b/libyul/backends/evm/VariableReferenceCounter.cpp index c2afb399d28f..9f4857887754 100644 --- a/libyul/backends/evm/VariableReferenceCounter.cpp +++ b/libyul/backends/evm/VariableReferenceCounter.cpp @@ -71,7 +71,7 @@ void VariableReferenceCounter::operator()(Block const& _block) m_scope = originalScope; } -void VariableReferenceCounter::increaseRefIfFound(YulString _variableName) +void VariableReferenceCounter::increaseRefIfFound(YulName _variableName) { m_scope->lookup(_variableName, util::GenericVisitor{ [&](Scope::Variable const& _var) diff --git a/libyul/backends/evm/VariableReferenceCounter.h b/libyul/backends/evm/VariableReferenceCounter.h index ba6404b17180..75552279359b 100644 --- a/libyul/backends/evm/VariableReferenceCounter.h +++ b/libyul/backends/evm/VariableReferenceCounter.h @@ -58,7 +58,7 @@ struct VariableReferenceCounter: public yul::ASTWalker ): m_info(_assemblyInfo) {} - void increaseRefIfFound(YulString _variableName); + void increaseRefIfFound(YulName _variableName); AsmAnalysisInfo const& m_info; Scope* m_scope = nullptr; diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index 9f41079418b2..28e4e3044114 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -83,7 +83,7 @@ Statement ASTCopier::operator()(Switch const& _switch) Statement ASTCopier::operator()(FunctionDefinition const& _function) { - YulString translatedName = translateIdentifier(_function.name); + auto const translatedName = translateIdentifier(_function.name); enterFunction(_function); ScopeGuard g([&]() { this->leaveFunction(_function); }); @@ -168,7 +168,7 @@ TypedName ASTCopier::translate(TypedName const& _typedName) return TypedName{_typedName.debugData, translateIdentifier(_typedName.name), _typedName.type}; } -YulString FunctionCopier::translateIdentifier(YulString _name) +YulName FunctionCopier::translateIdentifier(YulName _name) { if (m_translations.count(_name)) return m_translations.at(_name); diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index db9d72af35ec..88d2a34510ad 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -106,7 +106,7 @@ class ASTCopier: public ExpressionCopier, public StatementCopier virtual void leaveScope(Block const&) { } virtual void enterFunction(FunctionDefinition const&) { } virtual void leaveFunction(FunctionDefinition const&) { } - virtual YulString translateIdentifier(YulString _name) { return _name; } + virtual YulName translateIdentifier(YulName _name) { return _name; } }; template @@ -124,16 +124,16 @@ class FunctionCopier: public ASTCopier { public: FunctionCopier( - std::map const& _translations + std::map const& _translations ): m_translations(_translations) {} using ASTCopier::operator(); - YulString translateIdentifier(YulString _name) override; + YulName translateIdentifier(YulName _name) override; private: /// A mapping between old and new names. We replace the names of variable declarations contained /// in the mapping with their new names. - std::map const& m_translations; + std::map const& m_translations; }; } diff --git a/libyul/optimiser/BlockHasher.cpp b/libyul/optimiser/BlockHasher.cpp index 9d6db206675f..6e7dc6634d23 100644 --- a/libyul/optimiser/BlockHasher.cpp +++ b/libyul/optimiser/BlockHasher.cpp @@ -48,7 +48,7 @@ void ASTHasherBase::hashLiteral(solidity::yul::Literal const& _literal) hash64(std::hash{}(_literal.value.value())); else hash64(std::hash{}(_literal.value.builtinStringLiteralValue())); - hash64(_literal.type.hash()); + hash64(_literal.type); hash8(_literal.value.unlimited()); } @@ -87,7 +87,7 @@ void BlockHasher::operator()(Identifier const& _identifier) void BlockHasher::operator()(FunctionCall const& _funCall) { hash64(compileTimeLiteralHash("FunctionCall")); - hash64(_funCall.functionName.name.hash()); + hash64(_funCall.functionName.name); hash64(_funCall.arguments.size()); ASTWalker::operator()(_funCall); } @@ -214,13 +214,13 @@ void ExpressionHasher::operator()(Literal const& _literal) void ExpressionHasher::operator()(Identifier const& _identifier) { hash64(compileTimeLiteralHash("Identifier")); - hash64(_identifier.name.hash()); + hash64(_identifier.name); } void ExpressionHasher::operator()(FunctionCall const& _funCall) { hash64(compileTimeLiteralHash("FunctionCall")); - hash64(_funCall.functionName.name.hash()); + hash64(_funCall.functionName.name); hash64(_funCall.arguments.size()); ASTWalker::operator()(_funCall); } diff --git a/libyul/optimiser/BlockHasher.h b/libyul/optimiser/BlockHasher.h index 2b9a71f101ac..82ca7cf22bbb 100644 --- a/libyul/optimiser/BlockHasher.h +++ b/libyul/optimiser/BlockHasher.h @@ -112,8 +112,8 @@ class BlockHasher: public ASTWalker, public ASTHasherBase size_t id = 0; bool isExternal = false; }; - std::map m_variableReferences; - std::vector m_externalReferences; + std::map m_variableReferences; + std::vector m_externalReferences; size_t m_externalIdentifierCount = 0; size_t m_internalIdentifierCount = 0; }; diff --git a/libyul/optimiser/CallGraphGenerator.cpp b/libyul/optimiser/CallGraphGenerator.cpp index 87035e68a0e7..526ecdb451c4 100644 --- a/libyul/optimiser/CallGraphGenerator.cpp +++ b/libyul/optimiser/CallGraphGenerator.cpp @@ -35,11 +35,11 @@ namespace struct CallGraphCycleFinder { CallGraph const& callGraph; - std::set containedInCycle{}; - std::set visited{}; - std::vector currentPath{}; + std::set containedInCycle{}; + std::set visited{}; + std::vector currentPath{}; - void visit(YulString _function) + void visit(YulName _function) { if (visited.count(_function)) return; @@ -61,7 +61,7 @@ struct CallGraphCycleFinder }; } -std::set CallGraph::recursiveFunctions() const +std::set CallGraph::recursiveFunctions() const { CallGraphCycleFinder cycleFinder{*this}; // Visiting the root only is not enough, since there may be disconnected recursive functions. @@ -93,7 +93,7 @@ void CallGraphGenerator::operator()(ForLoop const& _forLoop) void CallGraphGenerator::operator()(FunctionDefinition const& _functionDefinition) { - YulString previousFunction = m_currentFunction; + auto previousFunction = m_currentFunction; m_currentFunction = _functionDefinition.name; yulAssert(m_callGraph.functionCalls.count(m_currentFunction) == 0, ""); m_callGraph.functionCalls[m_currentFunction] = {}; @@ -103,6 +103,6 @@ void CallGraphGenerator::operator()(FunctionDefinition const& _functionDefinitio CallGraphGenerator::CallGraphGenerator() { - m_callGraph.functionCalls[YulString{}] = {}; + m_callGraph.functionCalls[YulNameRepository::emptyName()] = {}; } diff --git a/libyul/optimiser/CallGraphGenerator.h b/libyul/optimiser/CallGraphGenerator.h index ad19878b6892..192f7c32d4c3 100644 --- a/libyul/optimiser/CallGraphGenerator.h +++ b/libyul/optimiser/CallGraphGenerator.h @@ -32,12 +32,12 @@ namespace solidity::yul struct CallGraph { - std::map> functionCalls; - std::set functionsWithLoops; + std::map> functionCalls; + std::set functionsWithLoops; /// @returns the set of functions contained in cycles in the call graph, i.e. /// functions that are part of a (mutual) recursion. /// Note that this does not include functions that merely call recursive functions. - std::set recursiveFunctions() const; + std::set recursiveFunctions() const; }; /** @@ -62,7 +62,7 @@ class CallGraphGenerator: public ASTWalker CallGraph m_callGraph; /// The name of the function we are currently visiting during traversal. - YulString m_currentFunction; + YulName m_currentFunction {}; }; } diff --git a/libyul/optimiser/CircularReferencesPruner.cpp b/libyul/optimiser/CircularReferencesPruner.cpp index 824d2be39fb0..b6bd509cef2d 100644 --- a/libyul/optimiser/CircularReferencesPruner.cpp +++ b/libyul/optimiser/CircularReferencesPruner.cpp @@ -34,7 +34,7 @@ void CircularReferencesPruner::run(OptimiserStepContext& _context, Block& _ast) void CircularReferencesPruner::operator()(Block& _block) { - std::set functionsToKeep = + std::set functionsToKeep = functionsCalledFromOutermostContext(CallGraphGenerator::callGraph(_block)); for (auto&& statement: _block.statements) @@ -48,13 +48,13 @@ void CircularReferencesPruner::operator()(Block& _block) removeEmptyBlocks(_block); } -std::set CircularReferencesPruner::functionsCalledFromOutermostContext(CallGraph const& _callGraph) +std::set CircularReferencesPruner::functionsCalledFromOutermostContext(CallGraph const& _callGraph) { - std::set verticesToTraverse = m_reservedIdentifiers; - verticesToTraverse.insert(YulString("")); + std::set verticesToTraverse = m_reservedIdentifiers; + verticesToTraverse.insert(YulNameRepository::emptyName()); - return util::BreadthFirstSearch{{verticesToTraverse.begin(), verticesToTraverse.end()}}.run( - [&_callGraph](YulString _function, auto&& _addChild) { + return util::BreadthFirstSearch{{verticesToTraverse.begin(), verticesToTraverse.end()}}.run( + [&_callGraph](YulName _function, auto&& _addChild) { if (_callGraph.functionCalls.count(_function)) for (auto const& callee: _callGraph.functionCalls.at(_function)) if (_callGraph.functionCalls.count(callee)) diff --git a/libyul/optimiser/CircularReferencesPruner.h b/libyul/optimiser/CircularReferencesPruner.h index 0602445af4ab..db7ef7b8310e 100644 --- a/libyul/optimiser/CircularReferencesPruner.h +++ b/libyul/optimiser/CircularReferencesPruner.h @@ -44,16 +44,16 @@ class CircularReferencesPruner: public ASTModifier using ASTModifier::operator(); void operator()(Block& _block) override; private: - CircularReferencesPruner(std::set const& _reservedIdentifiers): + CircularReferencesPruner(std::set const& _reservedIdentifiers): m_reservedIdentifiers(_reservedIdentifiers) {} /// Run a breadth-first search starting from the outermost context and /// externally referenced functions to find all the functions that are /// called from there either directly or indirectly. - std::set functionsCalledFromOutermostContext(CallGraph const& _callGraph); + std::set functionsCalledFromOutermostContext(CallGraph const& _callGraph); - std::set const& m_reservedIdentifiers; + std::set const& m_reservedIdentifiers; }; } diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index 1c7879056d61..287885f2cca3 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -38,17 +38,17 @@ using namespace solidity::util; void CommonSubexpressionEliminator::run(OptimiserStepContext& _context, Block& _ast) { CommonSubexpressionEliminator cse{ - _context.dialect, - SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)) + _context.yulNameRepository, + SideEffectsPropagator::sideEffects(_context.yulNameRepository, CallGraphGenerator::callGraph(_ast)) }; cse(_ast); } CommonSubexpressionEliminator::CommonSubexpressionEliminator( - Dialect const& _dialect, - std::map _functionSideEffects + YulNameRepository const& _yulNameRepository, + std::map _functionSideEffects ): - DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore, std::move(_functionSideEffects)) + DataFlowAnalyzer(_yulNameRepository, MemoryAndStorage::Ignore, std::move(_functionSideEffects)) { } @@ -72,13 +72,13 @@ void CommonSubexpressionEliminator::visit(Expression& _e) { FunctionCall& funCall = std::get(_e); - if (BuiltinFunction const* builtin = m_dialect.builtin(funCall.functionName.name)) + if (auto const* builtin = m_yulNameRepository.builtin(funCall.functionName.name)) { for (size_t i = funCall.arguments.size(); i > 0; i--) // We should not modify function arguments that have to be literals // Note that replacing the function call entirely is fine, // if the function call is movable. - if (!builtin->literalArgument(i - 1)) + if (!builtin->data->literalArgument(i - 1)) visit(funCall.arguments[i - 1]); descend = false; @@ -95,7 +95,7 @@ void CommonSubexpressionEliminator::visit(Expression& _e) if (Identifier const* identifier = std::get_if(&_e)) { - YulString identifierName = identifier->name; + YulName identifierName = identifier->name; if (AssignedValue const* assignedValue = variableValue(identifierName)) { assertThrow(assignedValue->value, OptimizerException, ""); @@ -126,7 +126,7 @@ void CommonSubexpressionEliminator::visit(Expression& _e) } } -void CommonSubexpressionEliminator::assignValue(YulString _variable, Expression const* _value) +void CommonSubexpressionEliminator::assignValue(YulName _variable, Expression const* _value) { if (_value) m_replacementCandidates[*_value].insert(_variable); diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index 163c9df994e4..14f7652edee9 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -52,20 +52,20 @@ class CommonSubexpressionEliminator: public DataFlowAnalyzer private: CommonSubexpressionEliminator( - Dialect const& _dialect, - std::map _functionSideEffects + YulNameRepository const& _yulNameRepository, + std::map _functionSideEffects ); protected: using ASTModifier::visit; void visit(Expression& _e) override; - void assignValue(YulString _variable, Expression const* _value) override; + void assignValue(YulName _variable, Expression const* _value) override; private: - std::set m_returnVariables; + std::set m_returnVariables; std::unordered_map< std::reference_wrapper, - std::set, + std::set, ExpressionHash, SyntacticallyEqualExpression > m_replacementCandidates; diff --git a/libyul/optimiser/ConditionalSimplifier.cpp b/libyul/optimiser/ConditionalSimplifier.cpp index 7119091257d3..ba79e4d5c9c9 100644 --- a/libyul/optimiser/ConditionalSimplifier.cpp +++ b/libyul/optimiser/ConditionalSimplifier.cpp @@ -29,8 +29,8 @@ using namespace solidity::util; void ConditionalSimplifier::run(OptimiserStepContext& _context, Block& _ast) { ConditionalSimplifier{ - _context.dialect, - ControlFlowSideEffectsCollector{_context.dialect, _ast}.functionSideEffectsNamed() + _context.yulNameRepository, + ControlFlowSideEffectsCollector{_context.yulNameRepository, _ast}.functionSideEffectsNamed() }(_ast); } @@ -42,7 +42,7 @@ void ConditionalSimplifier::operator()(Switch& _switch) ASTModifier::operator()(_switch); return; } - YulString expr = std::get(*_switch.expression).name; + auto expr = std::get(*_switch.expression).name; for (auto& _case: _switch.cases) { if (_case.value) @@ -73,18 +73,18 @@ void ConditionalSimplifier::operator()(Block& _block) if ( std::holds_alternative(*_if.condition) && !_if.body.statements.empty() && - TerminationFinder(m_dialect, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) != + TerminationFinder(m_yulNameRepository, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) != TerminationFinder::ControlFlow::FlowOut ) { - YulString condition = std::get(*_if.condition).name; + auto condition = std::get(*_if.condition).name; langutil::DebugData::ConstPtr debugData = _if.debugData; return make_vector( std::move(_s), Assignment{ debugData, {Identifier{debugData, condition}}, - std::make_unique(m_dialect.zeroLiteralForType(m_dialect.boolType)) + std::make_unique(m_yulNameRepository.dialect().zeroLiteralForType(m_yulNameRepository.predefined().boolType, m_yulNameRepository)) } ); } diff --git a/libyul/optimiser/ConditionalSimplifier.h b/libyul/optimiser/ConditionalSimplifier.h index e558a1c6cf5c..ac3d901f414a 100644 --- a/libyul/optimiser/ConditionalSimplifier.h +++ b/libyul/optimiser/ConditionalSimplifier.h @@ -61,13 +61,13 @@ class ConditionalSimplifier: public ASTModifier private: explicit ConditionalSimplifier( - Dialect const& _dialect, - std::map _sideEffects + YulNameRepository const& _yulNameRepository, + std::map _sideEffects ): - m_dialect(_dialect), m_functionSideEffects(std::move(_sideEffects)) + m_yulNameRepository(_yulNameRepository), m_functionSideEffects(std::move(_sideEffects)) {} - Dialect const& m_dialect; - std::map m_functionSideEffects; + YulNameRepository const& m_yulNameRepository; + std::map m_functionSideEffects; }; } diff --git a/libyul/optimiser/ConditionalUnsimplifier.cpp b/libyul/optimiser/ConditionalUnsimplifier.cpp index 104ec1e4f095..7f26dcf43765 100644 --- a/libyul/optimiser/ConditionalUnsimplifier.cpp +++ b/libyul/optimiser/ConditionalUnsimplifier.cpp @@ -30,8 +30,8 @@ using namespace solidity::util; void ConditionalUnsimplifier::run(OptimiserStepContext& _context, Block& _ast) { ConditionalUnsimplifier{ - _context.dialect, - ControlFlowSideEffectsCollector{_context.dialect, _ast}.functionSideEffectsNamed() + _context.yulNameRepository, + ControlFlowSideEffectsCollector{_context.yulNameRepository, _ast}.functionSideEffectsNamed() }(_ast); } @@ -43,7 +43,7 @@ void ConditionalUnsimplifier::operator()(Switch& _switch) ASTModifier::operator()(_switch); return; } - YulString expr = std::get(*_switch.expression).name; + auto expr = std::get(*_switch.expression).name; for (auto& _case: _switch.cases) { if (_case.value) @@ -83,10 +83,10 @@ void ConditionalUnsimplifier::operator()(Block& _block) !_if.body.statements.empty() ) { - YulString condition = std::get(*_if.condition).name; + auto condition = std::get(*_if.condition).name; if ( std::holds_alternative(_stmt2) && - TerminationFinder(m_dialect, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) != + TerminationFinder(m_yulNameRepository, &m_functionSideEffects).controlFlowKind(_if.body.statements.back()) != TerminationFinder::ControlFlow::FlowOut ) { diff --git a/libyul/optimiser/ConditionalUnsimplifier.h b/libyul/optimiser/ConditionalUnsimplifier.h index 8025b661b96b..76e371fa8a91 100644 --- a/libyul/optimiser/ConditionalUnsimplifier.h +++ b/libyul/optimiser/ConditionalUnsimplifier.h @@ -41,13 +41,13 @@ class ConditionalUnsimplifier: public ASTModifier private: explicit ConditionalUnsimplifier( - Dialect const& _dialect, - std::map const& _sideEffects + YulNameRepository const& _yulNameRepository, + std::map const& _sideEffects ): - m_dialect(_dialect), m_functionSideEffects(_sideEffects) + m_yulNameRepository(_yulNameRepository), m_functionSideEffects(_sideEffects) {} - Dialect const& m_dialect; - std::map const& m_functionSideEffects; + YulNameRepository const& m_yulNameRepository; + std::map const& m_functionSideEffects; }; } diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index 10f479a421b4..f077afd56a1d 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -38,7 +38,7 @@ namespace ExpressionStatement makeDiscardCall( langutil::DebugData::ConstPtr const& _debugData, - BuiltinFunction const& _discardFunction, + YulNameRepository::BuiltinFunction const& _discardFunction, Expression&& _expression ) { @@ -72,8 +72,8 @@ void removeEmptyCasesFromSwitch(Switch& _switchStmt) void ControlFlowSimplifier::run(OptimiserStepContext& _context, Block& _ast) { - TypeInfo typeInfo(_context.dialect, _ast); - ControlFlowSimplifier{_context.dialect, typeInfo}(_ast); + TypeInfo typeInfo(_context.yulNameRepository, _ast); + ControlFlowSimplifier{_context.yulNameRepository, typeInfo}(_ast); } void ControlFlowSimplifier::operator()(Block& _block) @@ -105,7 +105,7 @@ void ControlFlowSimplifier::visit(Statement& _st) if (!forLoop.body.statements.empty()) { bool isTerminating = false; - TerminationFinder::ControlFlow controlFlow = TerminationFinder{m_dialect}.controlFlowKind(forLoop.body.statements.back()); + TerminationFinder::ControlFlow controlFlow = TerminationFinder{m_yulNameRepository}.controlFlowKind(forLoop.body.statements.back()); if (controlFlow == TerminationFinder::ControlFlow::Break) { isTerminating = true; @@ -138,12 +138,12 @@ void ControlFlowSimplifier::simplify(std::vector& _statements) GenericVisitor visitor{ VisitorFallback{}, [&](If& _ifStmt) -> OptionalStatements { - if (_ifStmt.body.statements.empty() && m_dialect.discardFunction(m_dialect.boolType)) + if (_ifStmt.body.statements.empty() && m_yulNameRepository.discardFunction(m_yulNameRepository.predefined().boolType)) { OptionalStatements s = std::vector{}; s->emplace_back(makeDiscardCall( _ifStmt.debugData, - *m_dialect.discardFunction(m_dialect.boolType), + *m_yulNameRepository.discardFunction(m_yulNameRepository.predefined().boolType), std::move(*_ifStmt.condition) )); return s; @@ -179,8 +179,8 @@ void ControlFlowSimplifier::simplify(std::vector& _statements) OptionalStatements ControlFlowSimplifier::reduceNoCaseSwitch(Switch& _switchStmt) const { yulAssert(_switchStmt.cases.empty(), "Expected no case!"); - BuiltinFunction const* discardFunction = - m_dialect.discardFunction(m_typeInfo.typeOf(*_switchStmt.expression)); + auto const* discardFunction = + m_yulNameRepository.discardFunction(m_typeInfo.typeOf(*_switchStmt.expression)); if (!discardFunction) return {}; @@ -197,16 +197,16 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch auto& switchCase = _switchStmt.cases.front(); langutil::DebugData::ConstPtr debugData = debugDataOf(*_switchStmt.expression); - YulString type = m_typeInfo.typeOf(*_switchStmt.expression); + YulName type = m_typeInfo.typeOf(*_switchStmt.expression); if (switchCase.value) { - if (!m_dialect.equalityFunction(type)) + if (!m_yulNameRepository.equalityFunction(type)) return {}; return make_vector(If{ std::move(_switchStmt.debugData), std::make_unique(FunctionCall{ debugData, - Identifier{debugData, m_dialect.equalityFunction(type)->name}, + Identifier{debugData, m_yulNameRepository.equalityFunction(type)->name}, {std::move(*switchCase.value), std::move(*_switchStmt.expression)} }), std::move(switchCase.body) @@ -214,13 +214,13 @@ OptionalStatements ControlFlowSimplifier::reduceSingleCaseSwitch(Switch& _switch } else { - if (!m_dialect.discardFunction(type)) + if (!m_yulNameRepository.discardFunction(type)) return {}; return make_vector( makeDiscardCall( debugData, - *m_dialect.discardFunction(type), + *m_yulNameRepository.discardFunction(type), std::move(*_switchStmt.expression) ), std::move(switchCase.body) diff --git a/libyul/optimiser/ControlFlowSimplifier.h b/libyul/optimiser/ControlFlowSimplifier.h index 3ebbe7c9aeee..70d44348a3f6 100644 --- a/libyul/optimiser/ControlFlowSimplifier.h +++ b/libyul/optimiser/ControlFlowSimplifier.h @@ -63,8 +63,8 @@ class ControlFlowSimplifier: public ASTModifier void visit(Statement& _st) override; private: - ControlFlowSimplifier(Dialect const& _dialect, TypeInfo const& _typeInfo): - m_dialect(_dialect), + ControlFlowSimplifier(YulNameRepository const& _yulNameRepository, TypeInfo const& _typeInfo): + m_yulNameRepository(_yulNameRepository), m_typeInfo(_typeInfo) {} @@ -73,7 +73,7 @@ class ControlFlowSimplifier: public ASTModifier std::optional> reduceNoCaseSwitch(Switch& _switchStmt) const; std::optional> reduceSingleCaseSwitch(Switch& _switchStmt) const; - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; TypeInfo const& m_typeInfo; size_t m_numBreakStatements = 0; size_t m_numContinueStatements = 0; diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 5ec3cf248df9..0d7d88f772e5 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -43,25 +43,33 @@ using namespace solidity::util; using namespace solidity::yul; DataFlowAnalyzer::DataFlowAnalyzer( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, MemoryAndStorage _analyzeStores, - std::map _functionSideEffects + std::map _functionSideEffects ): - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_functionSideEffects(std::move(_functionSideEffects)), - m_knowledgeBase([this](YulString _var) { return variableValue(_var); }), + m_knowledgeBase([this](YulName _var) { return variableValue(_var); }, _yulNameRepository), m_analyzeStores(_analyzeStores == MemoryAndStorage::Analyze) { if (m_analyzeStores) { - if (auto const* builtin = _dialect.memoryStoreFunction(YulString{})) + if (auto const* builtin = _yulNameRepository.memoryStoreFunction(YulNameRepository::emptyName())) m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.memoryLoadFunction(YulString{})) + else + m_storeFunctionName[static_cast(StoreLoadLocation::Memory)] = std::nullopt; + if (auto const* builtin = _yulNameRepository.memoryLoadFunction(YulNameRepository::emptyName())) m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = builtin->name; - if (auto const* builtin = _dialect.storageStoreFunction(YulString{})) + else + m_loadFunctionName[static_cast(StoreLoadLocation::Memory)] = std::nullopt; + if (auto const* builtin = _yulNameRepository.storageStoreFunction(YulNameRepository::emptyName())) m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; - if (auto const* builtin = _dialect.storageLoadFunction(YulString{})) + else + m_storeFunctionName[static_cast(StoreLoadLocation::Storage)] = std::nullopt; + if (auto const* builtin = _yulNameRepository.storageLoadFunction(YulNameRepository::emptyName())) m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = builtin->name; + else + m_loadFunctionName[static_cast(StoreLoadLocation::Storage)] = std::nullopt; } } @@ -98,7 +106,7 @@ void DataFlowAnalyzer::operator()(ExpressionStatement& _statement) void DataFlowAnalyzer::operator()(Assignment& _assignment) { - std::set names; + std::set names; for (auto const& var: _assignment.variableNames) names.emplace(var.name); assertThrow(_assignment.value, OptimizerException, ""); @@ -109,7 +117,7 @@ void DataFlowAnalyzer::operator()(Assignment& _assignment) void DataFlowAnalyzer::operator()(VariableDeclaration& _varDecl) { - std::set names; + std::set names; for (auto const& var: _varDecl.variables) names.emplace(var.name); m_variableScopes.back().variables += names; @@ -138,14 +146,14 @@ void DataFlowAnalyzer::operator()(Switch& _switch) { clearKnowledgeIfInvalidated(*_switch.expression); visit(*_switch.expression); - std::set assignedVariables; + std::set assignedVariables; for (auto& _case: _switch.cases) { Environment preEnvironment = m_state.environment; (*this)(_case.body); joinKnowledge(preEnvironment); - std::set variables = assignedVariableNames(_case.body); + std::set variables = assignedVariableNames(_case.body); assignedVariables += variables; // This is a little too destructive, we could retain the old values. clearValues(variables); @@ -191,7 +199,7 @@ void DataFlowAnalyzer::operator()(ForLoop& _for) AssignmentsSinceContinue assignmentsSinceCont; assignmentsSinceCont(_for.body); - std::set assignedVariables = + std::set assignedVariables = assignedVariableNames(_for.body) + assignedVariableNames(_for.post); clearValues(assignedVariables); @@ -222,36 +230,36 @@ void DataFlowAnalyzer::operator()(Block& _block) assertThrow(numScopes == m_variableScopes.size(), OptimizerException, ""); } -std::optional DataFlowAnalyzer::storageValue(YulString _key) const +std::optional DataFlowAnalyzer::storageValue(YulName _key) const { - if (YulString const* value = valueOrNullptr(m_state.environment.storage, _key)) + if (YulName const* value = valueOrNullptr(m_state.environment.storage, _key)) return *value; else return std::nullopt; } -std::optional DataFlowAnalyzer::memoryValue(YulString _key) const +std::optional DataFlowAnalyzer::memoryValue(YulName _key) const { - if (YulString const* value = valueOrNullptr(m_state.environment.memory, _key)) + if (YulName const* value = valueOrNullptr(m_state.environment.memory, _key)) return *value; else return std::nullopt; } -std::optional DataFlowAnalyzer::keccakValue(YulString _start, YulString _length) const +std::optional DataFlowAnalyzer::keccakValue(YulName _start, YulName _length) const { - if (YulString const* value = valueOrNullptr(m_state.environment.keccak, std::make_pair(_start, _length))) + if (YulName const* value = valueOrNullptr(m_state.environment.keccak, std::make_pair(_start, _length))) return *value; else return std::nullopt; } -void DataFlowAnalyzer::handleAssignment(std::set const& _variables, Expression* _value, bool _isDeclaration) +void DataFlowAnalyzer::handleAssignment(std::set const& _variables, Expression* _value, bool _isDeclaration) { if (!_isDeclaration) clearValues(_variables); - MovableChecker movableChecker{m_dialect, &m_functionSideEffects}; + MovableChecker movableChecker{m_yulNameRepository, &m_functionSideEffects}; if (_value) movableChecker.visit(*_value); else @@ -260,7 +268,7 @@ void DataFlowAnalyzer::handleAssignment(std::set const& _variables, E if (_value && _variables.size() == 1) { - YulString name = *_variables.begin(); + YulName name = *_variables.begin(); // Expression has to be movable and cannot contain a reference // to the variable that will be assigned to. if (movableChecker.movable() && !movableChecker.referencedVariables().count(name)) @@ -289,7 +297,7 @@ void DataFlowAnalyzer::handleAssignment(std::set const& _variables, E if (_value && _variables.size() == 1) { - YulString variable = *_variables.begin(); + YulName variable = *_variables.begin(); if (!movableChecker.referencedVariables().count(variable)) { // This might erase additional knowledge about the slot. @@ -320,7 +328,7 @@ void DataFlowAnalyzer::popScope() m_variableScopes.pop_back(); } -void DataFlowAnalyzer::clearValues(std::set _variables) +void DataFlowAnalyzer::clearValues(std::set _variables) { // All variables that reference variables to be cleared also have to be // cleared, but not recursively, since only the value of the original @@ -351,7 +359,7 @@ void DataFlowAnalyzer::clearValues(std::set _variables) }); // Also clear variables that reference variables to be cleared. - std::set referencingVariables; + std::set referencingVariables; for (auto const& variableToClear: _variables) for (auto const& [ref, names]: m_state.references) if (names.count(variableToClear)) @@ -365,7 +373,7 @@ void DataFlowAnalyzer::clearValues(std::set _variables) } } -void DataFlowAnalyzer::assignValue(YulString _variable, Expression const* _value) +void DataFlowAnalyzer::assignValue(YulName _variable, Expression const* _value) { m_state.value[_variable] = {_value, m_loopDepth}; } @@ -374,7 +382,7 @@ void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Block const& _block) { if (!m_analyzeStores) return; - SideEffectsCollector sideEffects(m_dialect, _block, &m_functionSideEffects); + SideEffectsCollector sideEffects(m_yulNameRepository, _block, &m_functionSideEffects); if (sideEffects.invalidatesStorage()) m_state.environment.storage.clear(); if (sideEffects.invalidatesMemory()) @@ -388,7 +396,7 @@ void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Expression const& _expr) { if (!m_analyzeStores) return; - SideEffectsCollector sideEffects(m_dialect, _expr, &m_functionSideEffects); + SideEffectsCollector sideEffects(m_yulNameRepository, _expr, &m_functionSideEffects); if (sideEffects.invalidatesStorage()) m_state.environment.storage.clear(); if (sideEffects.invalidatesMemory()) @@ -398,7 +406,7 @@ void DataFlowAnalyzer::clearKnowledgeIfInvalidated(Expression const& _expr) } } -bool DataFlowAnalyzer::inScope(YulString _variableName) const +bool DataFlowAnalyzer::inScope(YulName _variableName) const { for (auto const& scope: m_variableScopes | ranges::views::reverse) { @@ -410,7 +418,7 @@ bool DataFlowAnalyzer::inScope(YulString _variableName) const return false; } -std::optional DataFlowAnalyzer::valueOfIdentifier(YulString const& _name) const +std::optional DataFlowAnalyzer::valueOfIdentifier(YulName const& _name) const { if (AssignedValue const* value = variableValue(_name)) if (Literal const* literal = std::get_if(value->value)) @@ -418,7 +426,7 @@ std::optional DataFlowAnalyzer::valueOfIdentifier(YulString const& _name) return std::nullopt; } -std::optional> DataFlowAnalyzer::isSimpleStore( +std::optional> DataFlowAnalyzer::isSimpleStore( StoreLoadLocation _location, ExpressionStatement const& _statement ) const @@ -431,7 +439,7 @@ std::optional> DataFlowAnalyzer::isSimpleStore( return {}; } -std::optional DataFlowAnalyzer::isSimpleLoad( +std::optional DataFlowAnalyzer::isSimpleLoad( StoreLoadLocation _location, Expression const& _expression ) const @@ -440,13 +448,13 @@ std::optional DataFlowAnalyzer::isSimpleLoad( if (funCall->functionName.name == m_loadFunctionName[static_cast(_location)]) if (Identifier const* key = std::get_if(&funCall->arguments.front())) return key->name; - return {}; + return std::nullopt; } -std::optional> DataFlowAnalyzer::isKeccak(Expression const& _expression) const +std::optional> DataFlowAnalyzer::isKeccak(Expression const& _expression) const { if (FunctionCall const* funCall = std::get_if(&_expression)) - if (funCall->functionName.name == m_dialect.hashFunction({})) + if (funCall->functionName.name == m_yulNameRepository.hashFunction(m_yulNameRepository.predefined().defaultType)) if (Identifier const* start = std::get_if(&funCall->arguments.at(0))) if (Identifier const* length = std::get_if(&funCall->arguments.at(1))) return std::make_pair(start->name, length->name); @@ -460,14 +468,14 @@ void DataFlowAnalyzer::joinKnowledge(Environment const& _olderEnvironment) joinKnowledgeHelper(m_state.environment.storage, _olderEnvironment.storage); joinKnowledgeHelper(m_state.environment.memory, _olderEnvironment.memory); cxx20::erase_if(m_state.environment.keccak, mapTuple([&_olderEnvironment](auto&& key, auto&& currentValue) { - YulString const* oldValue = valueOrNullptr(_olderEnvironment.keccak, key); + YulName const* oldValue = valueOrNullptr(_olderEnvironment.keccak, key); return !oldValue || *oldValue != currentValue; })); } void DataFlowAnalyzer::joinKnowledgeHelper( - std::unordered_map& _this, - std::unordered_map const& _older + std::unordered_map& _this, + std::unordered_map const& _older ) { // We clear if the key does not exist in the older map or if the value is different. @@ -475,7 +483,7 @@ void DataFlowAnalyzer::joinKnowledgeHelper( // of m_state.environment.memory and thus any overlapping write would have cleared the keys // that are not known to be different inside m_state.environment.memory already. cxx20::erase_if(_this, mapTuple([&_older](auto&& key, auto&& currentValue){ - YulString const* oldValue = valueOrNullptr(_older, key); + YulName const* oldValue = valueOrNullptr(_older, key); return !oldValue || *oldValue != currentValue; })); } diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index e41620b15f27..5deec31c0cfd 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -87,9 +87,9 @@ class DataFlowAnalyzer: public ASTModifier /// if this is not provided or the function is not found. /// The parameter is mostly used to determine movability of expressions. explicit DataFlowAnalyzer( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, MemoryAndStorage _analyzeStores, - std::map _functionSideEffects = {} + std::map _functionSideEffects = {} ); using ASTModifier::operator(); @@ -103,16 +103,16 @@ class DataFlowAnalyzer: public ASTModifier void operator()(Block& _block) override; /// @returns the current value of the given variable, if known - always movable. - AssignedValue const* variableValue(YulString _variable) const { return util::valueOrNullptr(m_state.value, _variable); } - std::set const* references(YulString _variable) const { return util::valueOrNullptr(m_state.references, _variable); } - std::map const& allValues() const { return m_state.value; } - std::optional storageValue(YulString _key) const; - std::optional memoryValue(YulString _key) const; - std::optional keccakValue(YulString _start, YulString _length) const; + AssignedValue const* variableValue(YulName _variable) const { return util::valueOrNullptr(m_state.value, _variable); } + std::set const* references(YulName _variable) const { return util::valueOrNullptr(m_state.references, _variable); } + std::map const& allValues() const { return m_state.value; } + std::optional storageValue(YulName _key) const; + std::optional memoryValue(YulName _key) const; + std::optional keccakValue(YulName _start, YulName _length) const; protected: /// Registers the assignment. - void handleAssignment(std::set const& _names, Expression* _value, bool _isDeclaration); + void handleAssignment(std::set const& _names, Expression* _value, bool _isDeclaration); /// Creates a new inner scope. void pushScope(bool _functionScope); @@ -122,9 +122,9 @@ class DataFlowAnalyzer: public ASTModifier /// Clears information about the values assigned to the given variables, /// for example at points where control flow is merged. - void clearValues(std::set _names); + void clearValues(std::set _names); - virtual void assignValue(YulString _variable, Expression const* _value); + virtual void assignValue(YulName _variable, Expression const* _value); /// Clears knowledge about storage or memory if they may be modified inside the block. void clearKnowledgeIfInvalidated(Block const& _block); @@ -133,10 +133,10 @@ class DataFlowAnalyzer: public ASTModifier void clearKnowledgeIfInvalidated(Expression const& _expression); /// Returns true iff the variable is in scope. - bool inScope(YulString _variableName) const; + bool inScope(YulName _variableName) const; /// Returns the literal value of the identifier, if it exists. - std::optional valueOfIdentifier(YulString const& _name) const; + std::optional valueOfIdentifier(YulName const& _name) const; enum class StoreLoadLocation { Memory = 0, @@ -146,41 +146,41 @@ class DataFlowAnalyzer: public ASTModifier /// Checks if the statement is sstore(a, b) / mstore(a, b) /// where a and b are variables and returns these variables in that case. - std::optional> isSimpleStore( + std::optional> isSimpleStore( StoreLoadLocation _location, ExpressionStatement const& _statement ) const; /// Checks if the expression is sload(a) / mload(a) /// where a is a variable and returns the variable in that case. - std::optional isSimpleLoad( + std::optional isSimpleLoad( StoreLoadLocation _location, Expression const& _expression ) const; /// Checks if the expression is keccak256(s, l) /// where s and l are variables and returns these variables in that case. - std::optional> isKeccak(Expression const& _expression) const; + std::optional> isKeccak(Expression const& _expression) const; - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; /// Side-effects of user-defined functions. Worst-case side-effects are assumed /// if this is not provided or the function is not found. - std::map m_functionSideEffects; + std::map m_functionSideEffects; private: struct Environment { - std::unordered_map storage; - std::unordered_map memory; + std::unordered_map storage; + std::unordered_map memory; /// If keccak[s, l] = y then y := keccak256(s, l) occurs in the code. - std::map, YulString> keccak; + std::map, YulName> keccak; }; struct State { /// Current values of variables, always movable. - std::map value; + std::map value; /// m_references[a].contains(b) <=> the current expression assigned to a references b - std::unordered_map> references; + std::unordered_map> references; Environment environment; }; @@ -192,8 +192,8 @@ class DataFlowAnalyzer: public ASTModifier void joinKnowledge(Environment const& _olderEnvironment); static void joinKnowledgeHelper( - std::unordered_map& _thisData, - std::unordered_map const& _olderData + std::unordered_map& _thisData, + std::unordered_map const& _olderData ); State m_state; @@ -203,8 +203,8 @@ class DataFlowAnalyzer: public ASTModifier /// If true, analyzes memory and storage content via mload/mstore and sload/sstore. bool m_analyzeStores = true; - YulString m_storeFunctionName[static_cast(StoreLoadLocation::Last) + 1]; - YulString m_loadFunctionName[static_cast(StoreLoadLocation::Last) + 1]; + std::optional m_storeFunctionName[static_cast(StoreLoadLocation::Last) + 1]; + std::optional m_loadFunctionName[static_cast(StoreLoadLocation::Last) + 1]; /// Current nesting depth of loops. size_t m_loopDepth{0}; @@ -212,12 +212,12 @@ class DataFlowAnalyzer: public ASTModifier struct Scope { explicit Scope(bool _isFunction): isFunction(_isFunction) {} - std::set variables; + std::set variables; bool isFunction; }; /// Special expression whose address will be used in m_value. - /// YulString does not need to be reset because DataFlowAnalyzer is short-lived. - Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue{0, "0"}, {}}}; + /// YulName does not need to be reset because DataFlowAnalyzer is short-lived. + Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue(0, std::nullopt), {}}}; /// List of scopes. std::vector m_variableScopes; }; diff --git a/libyul/optimiser/DeadCodeEliminator.cpp b/libyul/optimiser/DeadCodeEliminator.cpp index 71682584a25e..324d2df3394f 100644 --- a/libyul/optimiser/DeadCodeEliminator.cpp +++ b/libyul/optimiser/DeadCodeEliminator.cpp @@ -36,9 +36,9 @@ using namespace solidity::yul; void DeadCodeEliminator::run(OptimiserStepContext& _context, Block& _ast) { - ControlFlowSideEffectsCollector sideEffects(_context.dialect, _ast); + ControlFlowSideEffectsCollector sideEffects(_context.yulNameRepository, _ast); DeadCodeEliminator{ - _context.dialect, + _context.yulNameRepository, sideEffects.functionSideEffectsNamed() }(_ast); } @@ -53,7 +53,7 @@ void DeadCodeEliminator::operator()(Block& _block) { TerminationFinder::ControlFlow controlFlowChange; size_t index; - std::tie(controlFlowChange, index) = TerminationFinder{m_dialect, &m_functionSideEffects}.firstUnconditionalControlFlowChange(_block.statements); + std::tie(controlFlowChange, index) = TerminationFinder{m_yulNameRepository, &m_functionSideEffects}.firstUnconditionalControlFlowChange(_block.statements); // Erase everything after the terminating statement that is not a function definition. if (controlFlowChange != TerminationFinder::ControlFlow::FlowOut && index != std::numeric_limits::max()) diff --git a/libyul/optimiser/DeadCodeEliminator.h b/libyul/optimiser/DeadCodeEliminator.h index ae8c1b2a6a4a..e7268455fb41 100644 --- a/libyul/optimiser/DeadCodeEliminator.h +++ b/libyul/optimiser/DeadCodeEliminator.h @@ -61,12 +61,12 @@ class DeadCodeEliminator: public ASTModifier private: DeadCodeEliminator( - Dialect const& _dialect, - std::map _sideEffects - ): m_dialect(_dialect), m_functionSideEffects(std::move(_sideEffects)) {} + YulNameRepository const& _yulNameRepository, + std::map _sideEffects + ): m_yulNameRepository(_yulNameRepository), m_functionSideEffects(std::move(_sideEffects)) {} - Dialect const& m_dialect; - std::map m_functionSideEffects; + YulNameRepository const& m_yulNameRepository; + std::map m_functionSideEffects; }; } diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index 34e6bc7e6a9b..0c552e5b2b17 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -30,16 +30,16 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; -YulString Disambiguator::translateIdentifier(YulString _originalName) +YulName Disambiguator::translateIdentifier(YulName _originalName) { - if (m_dialect.builtin(_originalName) || m_externallyUsedIdentifiers.count(_originalName)) + if (m_yulNameRepository.isBuiltinName(_originalName) || m_externallyUsedIdentifiers.count(_originalName)) return _originalName; assertThrow(!m_scopes.empty() && m_scopes.back(), OptimizerException, ""); Scope::Identifier const* id = m_scopes.back()->lookup(_originalName); assertThrow(id, OptimizerException, ""); if (!m_translations.count(id)) - m_translations[id] = m_nameDispenser.newName(_originalName); + m_translations[id] = m_yulNameRepository.deriveName(_originalName); return m_translations.at(id); } diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index 062173882761..c2981a42dfd1 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -40,14 +39,13 @@ class Disambiguator: public ASTCopier { public: explicit Disambiguator( - Dialect const& _dialect, + YulNameRepository& _yulNameRepository, AsmAnalysisInfo const& _analysisInfo, - std::set const& _externallyUsedIdentifiers = {} + std::set const& _externallyUsedIdentifiers = {} ): m_info(_analysisInfo), - m_dialect(_dialect), - m_externallyUsedIdentifiers(_externallyUsedIdentifiers), - m_nameDispenser(_dialect, m_externallyUsedIdentifiers) + m_yulNameRepository(_yulNameRepository), + m_externallyUsedIdentifiers(_externallyUsedIdentifiers) { } @@ -56,18 +54,17 @@ class Disambiguator: public ASTCopier void leaveScope(Block const& _block) override; void enterFunction(FunctionDefinition const& _function) override; void leaveFunction(FunctionDefinition const& _function) override; - YulString translateIdentifier(YulString _name) override; + YulName translateIdentifier(YulName _name) override; void enterScopeInternal(Scope& _scope); void leaveScopeInternal(Scope& _scope); AsmAnalysisInfo const& m_info; - Dialect const& m_dialect; - std::set const& m_externallyUsedIdentifiers; + YulNameRepository& m_yulNameRepository; + std::set const& m_externallyUsedIdentifiers; std::vector m_scopes; - std::map m_translations; - NameDispenser m_nameDispenser; + std::map m_translations; }; } diff --git a/libyul/optimiser/EqualStoreEliminator.cpp b/libyul/optimiser/EqualStoreEliminator.cpp index 1e894608e9f9..c3f7ce47aee2 100644 --- a/libyul/optimiser/EqualStoreEliminator.cpp +++ b/libyul/optimiser/EqualStoreEliminator.cpp @@ -36,8 +36,8 @@ using namespace solidity::yul; void EqualStoreEliminator::run(OptimiserStepContext const& _context, Block& _ast) { EqualStoreEliminator eliminator{ - _context.dialect, - SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)) + _context.yulNameRepository, + SideEffectsPropagator::sideEffects(_context.yulNameRepository, CallGraphGenerator::callGraph(_ast)) }; eliminator(_ast); @@ -53,13 +53,13 @@ void EqualStoreEliminator::visit(Statement& _statement) { if (auto vars = isSimpleStore(StoreLoadLocation::Storage, *expression)) { - if (std::optional currentValue = storageValue(vars->first)) + if (std::optional currentValue = storageValue(vars->first)) if (*currentValue == vars->second) m_pendingRemovals.insert(&_statement); } else if (auto vars = isSimpleStore(StoreLoadLocation::Memory, *expression)) { - if (std::optional currentValue = memoryValue(vars->first)) + if (std::optional currentValue = memoryValue(vars->first)) if (*currentValue == vars->second) m_pendingRemovals.insert(&_statement); } diff --git a/libyul/optimiser/EqualStoreEliminator.h b/libyul/optimiser/EqualStoreEliminator.h index b8572f4667fd..f65cc5ed6168 100644 --- a/libyul/optimiser/EqualStoreEliminator.h +++ b/libyul/optimiser/EqualStoreEliminator.h @@ -44,10 +44,10 @@ class EqualStoreEliminator: public DataFlowAnalyzer private: EqualStoreEliminator( - Dialect const& _dialect, - std::map _functionSideEffects + YulNameRepository const& _yulNameRepository, + std::map _functionSideEffects ): - DataFlowAnalyzer(_dialect, MemoryAndStorage::Analyze, std::move(_functionSideEffects)) + DataFlowAnalyzer(_yulNameRepository, MemoryAndStorage::Analyze, std::move(_functionSideEffects)) {} protected: diff --git a/libyul/optimiser/EquivalentFunctionCombiner.h b/libyul/optimiser/EquivalentFunctionCombiner.h index 5337f76842d6..627dcb3ff4fd 100644 --- a/libyul/optimiser/EquivalentFunctionCombiner.h +++ b/libyul/optimiser/EquivalentFunctionCombiner.h @@ -46,8 +46,8 @@ class EquivalentFunctionCombiner: public ASTModifier void operator()(FunctionCall& _funCall) override; private: - EquivalentFunctionCombiner(std::map _duplicates): m_duplicates(std::move(_duplicates)) {} - std::map m_duplicates; + EquivalentFunctionCombiner(std::map _duplicates): m_duplicates(std::move(_duplicates)) {} + std::map m_duplicates; }; diff --git a/libyul/optimiser/EquivalentFunctionDetector.h b/libyul/optimiser/EquivalentFunctionDetector.h index d3ddc25f7bdb..7cd161af1a45 100644 --- a/libyul/optimiser/EquivalentFunctionDetector.h +++ b/libyul/optimiser/EquivalentFunctionDetector.h @@ -35,7 +35,7 @@ namespace solidity::yul class EquivalentFunctionDetector: public ASTWalker { public: - static std::map run(Block& _block) + static std::map run(Block& _block) { EquivalentFunctionDetector detector{BlockHasher::run(_block)}; detector(_block); @@ -50,7 +50,7 @@ class EquivalentFunctionDetector: public ASTWalker std::map m_blockHashes; std::map> m_candidates; - std::map m_duplicates; + std::map m_duplicates; }; diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index cacf5843d6b3..b2f7fba962a2 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -37,7 +37,7 @@ void ExpressionInliner::run(OptimiserStepContext& _context, Block& _ast) { InlinableExpressionFunctionFinder funFinder; funFinder(_ast); - ExpressionInliner inliner{_context.dialect, funFinder.inlinableFunctions()}; + ExpressionInliner inliner{_context.yulNameRepository, funFinder.inlinableFunctions()}; inliner(_ast); } @@ -56,17 +56,17 @@ void ExpressionInliner::visit(Expression& _expression) return; FunctionDefinition const& fun = *m_inlinableFunctions.at(funCall.functionName.name); - std::map substitutions; + std::map substitutions; for (size_t i = 0; i < funCall.arguments.size(); i++) { Expression const& arg = funCall.arguments[i]; - YulString paraName = fun.parameters[i].name; + auto paraName = fun.parameters[i].name; - if (!SideEffectsCollector(m_dialect, arg).movable()) + if (!SideEffectsCollector(m_yulNameRepository, arg).movable()) return; size_t refs = ReferencesCounter::countReferences(fun.body)[paraName]; - size_t cost = CodeCost::codeCost(m_dialect, arg); + size_t cost = CodeCost::codeCost(m_yulNameRepository, arg); if (refs > 1 && cost > 1) return; diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index ff7da67b8832..d341354d7528 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -58,17 +58,17 @@ class ExpressionInliner: public ASTModifier private: ExpressionInliner( - Dialect const& _dialect, - std::map const& _inlinableFunctions - ): m_dialect(_dialect), m_inlinableFunctions(_inlinableFunctions) + YulNameRepository const& _yulNameRepository, + std::map const& _inlinableFunctions + ): m_yulNameRepository(_yulNameRepository), m_inlinableFunctions(_inlinableFunctions) {} - Dialect const& m_dialect; - std::map const& m_inlinableFunctions; + YulNameRepository const& m_yulNameRepository; + std::map const& m_inlinableFunctions; - std::map m_varReplacements; + std::map m_varReplacements; /// Set of functions we are currently visiting inside. - std::set m_currentFunctions; + std::set m_currentFunctions; }; } diff --git a/libyul/optimiser/ExpressionJoiner.h b/libyul/optimiser/ExpressionJoiner.h index 3a1fdf743579..07f86ddce73a 100644 --- a/libyul/optimiser/ExpressionJoiner.h +++ b/libyul/optimiser/ExpressionJoiner.h @@ -93,7 +93,7 @@ class ExpressionJoiner: public ASTModifier private: Block* m_currentBlock = nullptr; ///< Pointer to current block holding the statement being visited. size_t m_latestStatementInBlock = 0; ///< Offset to m_currentBlock's statements of the last visited statement. - std::map m_references; ///< Holds reference counts to all variable declarations in current block. + std::map m_references; ///< Holds reference counts to all variable declarations in current block. }; } diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index 6d0a8c9d7409..1a52ab34e766 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -34,7 +34,7 @@ using namespace solidity::yul; void ExpressionSimplifier::run(OptimiserStepContext& _context, Block& _ast) { - ExpressionSimplifier{_context.dialect}(_ast); + ExpressionSimplifier{_context.yulNameRepository}(_ast); } void ExpressionSimplifier::visit(Expression& _expression) @@ -43,13 +43,13 @@ void ExpressionSimplifier::visit(Expression& _expression) while (auto const* match = SimplificationRules::findFirstMatch( _expression, - m_dialect, - [this](YulString _var) { return variableValue(_var); } + m_yulNameRepository, + [this](YulName _var) { return variableValue(_var); } )) - _expression = match->action().toExpression(debugDataOf(_expression), evmVersionFromDialect(m_dialect)); + _expression = match->action().toExpression(debugDataOf(_expression), evmVersionFromDialect(m_yulNameRepository.dialect()), m_yulNameRepository); if (auto* functionCall = std::get_if(&_expression)) - if (std::optional instruction = toEVMInstruction(m_dialect, functionCall->functionName.name)) + if (std::optional instruction = toEVMInstruction(m_yulNameRepository, functionCall->functionName.name)) for (auto op: evmasm::SemanticInformation::readWriteOperations(*instruction)) if (op.startParameter && op.lengthParameter) { diff --git a/libyul/optimiser/ExpressionSimplifier.h b/libyul/optimiser/ExpressionSimplifier.h index 662c8c389936..a574eedf467d 100644 --- a/libyul/optimiser/ExpressionSimplifier.h +++ b/libyul/optimiser/ExpressionSimplifier.h @@ -51,8 +51,8 @@ class ExpressionSimplifier: public DataFlowAnalyzer void visit(Expression& _expression) override; private: - explicit ExpressionSimplifier(Dialect const& _dialect): - DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore) + explicit ExpressionSimplifier(YulNameRepository const& _yulNameRepository): + DataFlowAnalyzer(_yulNameRepository, MemoryAndStorage::Ignore) {} bool knownToBeZero(Expression const& _expression) const; }; diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 6f0834d7760e..012fb8541cbd 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -37,16 +37,16 @@ using namespace solidity::langutil; void ExpressionSplitter::run(OptimiserStepContext& _context, Block& _ast) { - TypeInfo typeInfo(_context.dialect, _ast); - ExpressionSplitter{_context.dialect, _context.dispenser, typeInfo}(_ast); + TypeInfo typeInfo(_context.yulNameRepository, _ast); + ExpressionSplitter{_context.yulNameRepository, typeInfo}(_ast); } void ExpressionSplitter::operator()(FunctionCall& _funCall) { - BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name); + auto const* builtin = m_yulNameRepository.builtin(_funCall.functionName.name); for (size_t i = _funCall.arguments.size(); i > 0; i--) - if (!builtin || !builtin->literalArgument(i - 1)) + if (!builtin || !builtin->data->literalArgument(i - 1)) outlineExpression(_funCall.arguments[i - 1]); } @@ -99,8 +99,8 @@ void ExpressionSplitter::outlineExpression(Expression& _expr) visit(_expr); langutil::DebugData::ConstPtr debugData = debugDataOf(_expr); - YulString var = m_nameDispenser.newName({}); - YulString type = m_typeInfo.typeOf(_expr); + YulName var = m_yulNameRepository.deriveName(YulNameRepository::emptyName()); + YulName type = m_typeInfo.typeOf(_expr); m_statementsToPrefix.emplace_back(VariableDeclaration{ debugData, {{TypedName{debugData, var, type}}}, @@ -109,4 +109,3 @@ void ExpressionSplitter::outlineExpression(Expression& _expr) _expr = Identifier{debugData, var}; m_typeInfo.setVariableType(var, type); } - diff --git a/libyul/optimiser/ExpressionSplitter.h b/libyul/optimiser/ExpressionSplitter.h index bbde8d6a2df0..7f83e56af655 100644 --- a/libyul/optimiser/ExpressionSplitter.h +++ b/libyul/optimiser/ExpressionSplitter.h @@ -24,7 +24,6 @@ #include #include -#include #include @@ -70,12 +69,10 @@ class ExpressionSplitter: public ASTModifier private: explicit ExpressionSplitter( - Dialect const& _dialect, - NameDispenser& _nameDispenser, + YulNameRepository& _yulNameRepository, TypeInfo& _typeInfo ): - m_dialect(_dialect), - m_nameDispenser(_nameDispenser), + m_yulNameRepository(_yulNameRepository), m_typeInfo(_typeInfo) { } @@ -87,8 +84,7 @@ class ExpressionSplitter: public ASTModifier /// List of statements that should go in front of the currently visited AST element, /// at the statement level. std::vector m_statementsToPrefix; - Dialect const& m_dialect; - NameDispenser& m_nameDispenser; + YulNameRepository& m_yulNameRepository; TypeInfo& m_typeInfo; }; diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index df9847376af7..6bb282f1caeb 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -27,13 +27,13 @@ using namespace solidity::yul; void ForLoopConditionIntoBody::run(OptimiserStepContext& _context, Block& _ast) { - ForLoopConditionIntoBody{_context.dialect}(_ast); + ForLoopConditionIntoBody{_context.yulNameRepository}(_ast); } void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) { if ( - m_dialect.booleanNegationFunction() && + m_yulNameRepository.booleanNegationFunction() && !std::holds_alternative(*_forLoop.condition) && !std::holds_alternative(*_forLoop.condition) ) @@ -47,7 +47,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) std::make_unique( FunctionCall { debugData, - {debugData, m_dialect.booleanNegationFunction()->name}, + {debugData, m_yulNameRepository.booleanNegationFunction()->name}, util::make_vector(std::move(*_forLoop.condition)) } ), @@ -59,7 +59,7 @@ void ForLoopConditionIntoBody::operator()(ForLoop& _forLoop) debugData, LiteralKind::Boolean, LiteralValue{true}, - m_dialect.boolType + m_yulNameRepository.predefined().boolType } ); } diff --git a/libyul/optimiser/ForLoopConditionIntoBody.h b/libyul/optimiser/ForLoopConditionIntoBody.h index 2a9c92c23783..da55a9eabc75 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.h +++ b/libyul/optimiser/ForLoopConditionIntoBody.h @@ -50,9 +50,9 @@ class ForLoopConditionIntoBody: public ASTModifier void operator()(ForLoop& _forLoop) override; private: - ForLoopConditionIntoBody(Dialect const& _dialect): m_dialect(_dialect) {} + explicit ForLoopConditionIntoBody(YulNameRepository const& _yulNameRepository): m_yulNameRepository(_yulNameRepository) {} - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; }; } diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index 83b1e20a8e33..8b0de94de100 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -28,7 +28,7 @@ using namespace solidity::yul; void ForLoopConditionOutOfBody::run(OptimiserStepContext& _context, Block& _ast) { - ForLoopConditionOutOfBody{_context.dialect}(_ast); + ForLoopConditionOutOfBody{_context.yulNameRepository}(_ast); } void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) @@ -36,7 +36,7 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) ASTModifier::operator()(_forLoop); if ( - !m_dialect.booleanNegationFunction() || + !m_yulNameRepository.booleanNegationFunction() || !std::holds_alternative(*_forLoop.condition) || std::get(*_forLoop.condition).value.value() == 0 || _forLoop.body.statements.empty() || @@ -50,10 +50,10 @@ void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop) !std::holds_alternative(firstStatement.body.statements.front()) ) return; - if (!SideEffectsCollector(m_dialect, *firstStatement.condition).movable()) + if (!SideEffectsCollector(m_yulNameRepository, *firstStatement.condition).movable()) return; - YulString iszero = m_dialect.booleanNegationFunction()->name; + YulName const iszero = m_yulNameRepository.booleanNegationFunction()->name; langutil::DebugData::ConstPtr debugData = debugDataOf(*firstStatement.condition); if ( diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.h b/libyul/optimiser/ForLoopConditionOutOfBody.h index ba3b7eb18309..e2d510d628f3 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.h +++ b/libyul/optimiser/ForLoopConditionOutOfBody.h @@ -65,11 +65,11 @@ class ForLoopConditionOutOfBody: public ASTModifier void operator()(ForLoop& _forLoop) override; private: - ForLoopConditionOutOfBody(Dialect const& _dialect): - m_dialect(_dialect) + ForLoopConditionOutOfBody(YulNameRepository const& _yulNameRepository): + m_yulNameRepository(_yulNameRepository) {} - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; }; } diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index 6e4d8497199f..171b7fc5af57 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -46,15 +46,15 @@ using namespace solidity::yul; void FullInliner::run(OptimiserStepContext& _context, Block& _ast) { - FullInliner inliner{_ast, _context.dispenser, _context.dialect}; + FullInliner inliner{_ast, _context.yulNameRepository, _context.dialect}; inliner.run(Pass::InlineTiny); inliner.run(Pass::InlineRest); } -FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& _dialect): +FullInliner::FullInliner(Block& _ast, YulNameRepository& _yulNameRepository, Dialect const& _dialect): m_ast(_ast), m_recursiveFunctions(CallGraphGenerator::callGraph(_ast).recursiveFunctions()), - m_nameDispenser(_dispenser), + m_yulNameRepository(_yulNameRepository), m_dialect(_dialect) { @@ -66,8 +66,8 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& m_constants.emplace(ssaValue.first); // Store size of global statements. - m_functionSizes[YulString{}] = CodeSize::codeSize(_ast); - std::map references = ReferencesCounter::countReferences(m_ast); + m_functionSizes[YulNameRepository::emptyName()] = CodeSize::codeSize(_ast); + std::map references = ReferencesCounter::countReferences(m_ast); for (auto& statement: m_ast.statements) { if (!std::holds_alternative(statement)) @@ -85,7 +85,7 @@ FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& // Check for memory guard. std::vector memoryGuardCalls = FunctionCallFinder::run( _ast, - "memoryguard"_yulstring + m_yulNameRepository.predefined().memoryguard ); // We will perform less aggressive inlining, if no ``memoryguard`` call is found. if (!memoryGuardCalls.empty()) @@ -104,7 +104,7 @@ void FullInliner::run(Pass _pass) // function name) order. // We use stable_sort below to keep the inlining order of two functions // with the same depth. - std::map depths = callDepths(); + std::map depths = callDepths(); std::vector functions; for (auto& statement: m_ast.statements) if (std::holds_alternative(statement)) @@ -126,25 +126,25 @@ void FullInliner::run(Pass _pass) handleBlock({}, std::get(statement)); } -std::map FullInliner::callDepths() const +std::map FullInliner::callDepths() const { CallGraph cg = CallGraphGenerator::callGraph(m_ast); - cg.functionCalls.erase(""_yulstring); + cg.functionCalls.erase(YulNameRepository::emptyName()); // Remove calls to builtin functions. for (auto& call: cg.functionCalls) for (auto it = call.second.begin(); it != call.second.end();) - if (m_dialect.builtin(*it)) + if (m_yulNameRepository.isBuiltinName(*it)) it = call.second.erase(it); else ++it; - std::map depths; + std::map depths; size_t currentDepth = 0; while (true) { - std::vector removed; + std::vector removed; for (auto it = cg.functionCalls.begin(); it != cg.functionCalls.end();) { auto const& [fun, callees] = *it; @@ -159,7 +159,7 @@ std::map FullInliner::callDepths() const } for (auto& call: cg.functionCalls) - for (YulString toBeRemoved: removed) + for (YulName toBeRemoved: removed) ranges::actions::remove(call.second, toBeRemoved); currentDepth++; @@ -175,7 +175,7 @@ std::map FullInliner::callDepths() const return depths; } -bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite) +bool FullInliner::shallInline(FunctionCall const& _funCall, YulName _callSite) { // No recursive inlining if (_funCall.functionName.name == _callSite) @@ -237,7 +237,7 @@ bool FullInliner::shallInline(FunctionCall const& _funCall, YulString _callSite) return (size < (aggressiveInlining ? 8u : 6u) || (constantArg && size < (aggressiveInlining ? 16u : 12u))); } -void FullInliner::tentativelyUpdateCodeSize(YulString _function, YulString _callSite) +void FullInliner::tentativelyUpdateCodeSize(YulName _function, YulName _callSite) { m_functionSizes.at(_callSite) += m_functionSizes.at(_function); } @@ -247,14 +247,14 @@ void FullInliner::updateCodeSize(FunctionDefinition const& _fun) m_functionSizes[_fun.name] = CodeSize::codeSize(_fun.body); } -void FullInliner::handleBlock(YulString _currentFunctionName, Block& _block) +void FullInliner::handleBlock(YulName _currentFunctionName, Block& _block) { - InlineModifier{*this, m_nameDispenser, _currentFunctionName, m_dialect}(_block); + InlineModifier{*this, _currentFunctionName, m_yulNameRepository, m_dialect}(_block); } bool FullInliner::recursive(FunctionDefinition const& _fun) const { - std::map references = ReferencesCounter::countReferences(_fun); + std::map references = ReferencesCounter::countReferences(_fun); return references[_fun.name] > 0; } @@ -292,7 +292,7 @@ std::optional> InlineModifier::tryInlineStatement(Stateme std::vector InlineModifier::performInline(Statement& _statement, FunctionCall& _funCall) { std::vector newStatements; - std::map variableReplacements; + std::map variableReplacements; FunctionDefinition* function = m_driver.function(_funCall.functionName.name); assertThrow(!!function, OptimizerException, "Attempt to inline invalid function."); @@ -302,13 +302,13 @@ std::vector InlineModifier::performInline(Statement& _statement, Func // helper function to create a new variable that is supposed to model // an existing variable. auto newVariable = [&](TypedName const& _existingVariable, Expression* _value) { - YulString newName = m_nameDispenser.newName(_existingVariable.name); + auto newName = m_yulNameRepository.deriveName(_existingVariable.name); variableReplacements[_existingVariable.name] = newName; VariableDeclaration varDecl{_funCall.debugData, {{_funCall.debugData, newName, _existingVariable.type}}, {}}; if (_value) varDecl.value = std::make_unique(std::move(*_value)); else - varDecl.value = std::make_unique(m_dialect.zeroLiteralForType(varDecl.variables.front().type)); + varDecl.value = std::make_unique(m_dialect.zeroLiteralForType(varDecl.variables.front().type, m_yulNameRepository)); newStatements.emplace_back(std::move(varDecl)); }; @@ -317,7 +317,7 @@ std::vector InlineModifier::performInline(Statement& _statement, Func for (auto const& var: function->returnVariables) newVariable(var, nullptr); - Statement newBody = BodyCopier(m_nameDispenser, variableReplacements)(function->body); + Statement newBody = BodyCopier(variableReplacements, m_yulNameRepository)(function->body); newStatements += std::move(std::get(newBody).statements); std::visit(util::GenericVisitor{ @@ -354,7 +354,7 @@ std::vector InlineModifier::performInline(Statement& _statement, Func Statement BodyCopier::operator()(VariableDeclaration const& _varDecl) { for (auto const& var: _varDecl.variables) - m_variableReplacements[var.name] = m_nameDispenser.newName(var.name); + m_variableReplacements[var.name] = m_yulNameRepository.deriveName(var.name); return ASTCopier::operator()(_varDecl); } @@ -364,7 +364,7 @@ Statement BodyCopier::operator()(FunctionDefinition const&) return {}; } -YulString BodyCopier::translateIdentifier(YulString _name) +YulName BodyCopier::translateIdentifier(YulName _name) { if (m_variableReplacements.count(_name)) return m_variableReplacements.at(_name); diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index 931315305c57..c3dc055cbd83 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -75,9 +74,9 @@ class FullInliner: public ASTModifier /// Inlining heuristic. /// @param _callSite the name of the function in which the function call is located. - bool shallInline(FunctionCall const& _funCall, YulString _callSite); + bool shallInline(FunctionCall const& _funCall, YulName _callSite); - FunctionDefinition* function(YulString _name) + FunctionDefinition* function(YulName _name) { auto it = m_functions.find(_name); if (it != m_functions.end()) @@ -88,39 +87,39 @@ class FullInliner: public ASTModifier /// Adds the size of _funCall to the size of _callSite. This is just /// a rough estimate that is done during inlining. The proper size /// should be determined after inlining is completed. - void tentativelyUpdateCodeSize(YulString _function, YulString _callSite); + void tentativelyUpdateCodeSize(YulName _function, YulName _callSite); private: enum Pass { InlineTiny, InlineRest }; - FullInliner(Block& _ast, NameDispenser& _dispenser, Dialect const& _dialect); + FullInliner(Block& _ast, YulNameRepository& _yulNameRepository, Dialect const& _dialect); void run(Pass _pass); /// @returns a map containing the maximum depths of a call chain starting at each /// function. For recursive functions, the value is one larger than for all others. - std::map callDepths() const; + std::map callDepths() const; void updateCodeSize(FunctionDefinition const& _fun); - void handleBlock(YulString _currentFunctionName, Block& _block); + void handleBlock(YulName _currentFunctionName, Block& _block); bool recursive(FunctionDefinition const& _fun) const; Pass m_pass; /// The AST to be modified. The root block itself will not be modified, because /// we store pointers to functions. Block& m_ast; - std::map m_functions; + std::map m_functions; /// Functions not to be inlined (because they contain the ``leave`` statement). - std::set m_noInlineFunctions; + std::set m_noInlineFunctions; /// True, if the code contains a ``memoryguard`` and we can expect to be able to move variables to memory later. bool m_hasMemoryGuard = false; /// Set of recursive functions. - std::set m_recursiveFunctions; + std::set m_recursiveFunctions; /// Names of functions to always inline. - std::set m_singleUse; + std::set m_singleUse; /// Variables that are constants (used for inlining heuristic) - std::set m_constants; - std::map m_functionSizes; - NameDispenser& m_nameDispenser; + std::set m_constants; + std::map m_functionSizes; + YulNameRepository& m_yulNameRepository; Dialect const& m_dialect; }; @@ -131,10 +130,10 @@ class FullInliner: public ASTModifier class InlineModifier: public ASTModifier { public: - InlineModifier(FullInliner& _driver, NameDispenser& _nameDispenser, YulString _functionName, Dialect const& _dialect): + InlineModifier(FullInliner& _driver, YulName _functionName, YulNameRepository& _yulNameRepository, Dialect const& _dialect): m_currentFunction(std::move(_functionName)), m_driver(_driver), - m_nameDispenser(_nameDispenser), + m_yulNameRepository(_yulNameRepository), m_dialect(_dialect) { } @@ -144,9 +143,9 @@ class InlineModifier: public ASTModifier std::optional> tryInlineStatement(Statement& _statement); std::vector performInline(Statement& _statement, FunctionCall& _funCall); - YulString m_currentFunction; + YulName m_currentFunction; FullInliner& m_driver; - NameDispenser& m_nameDispenser; + YulNameRepository& m_yulNameRepository; Dialect const& m_dialect; }; @@ -159,11 +158,11 @@ class BodyCopier: public ASTCopier { public: BodyCopier( - NameDispenser& _nameDispenser, - std::map _variableReplacements + std::map _variableReplacements, + YulNameRepository& _yulNameRepository ): - m_nameDispenser(_nameDispenser), - m_variableReplacements(std::move(_variableReplacements)) + m_variableReplacements(std::move(_variableReplacements)), + m_yulNameRepository(_yulNameRepository) {} using ASTCopier::operator (); @@ -171,10 +170,10 @@ class BodyCopier: public ASTCopier Statement operator()(VariableDeclaration const& _varDecl) override; Statement operator()(FunctionDefinition const& _funDef) override; - YulString translateIdentifier(YulString _name) override; + YulName translateIdentifier(YulName _name) override; - NameDispenser& m_nameDispenser; - std::map m_variableReplacements; + std::map m_variableReplacements; + YulNameRepository& m_yulNameRepository; }; diff --git a/libyul/optimiser/FunctionCallFinder.cpp b/libyul/optimiser/FunctionCallFinder.cpp index 9d94dc5f9ca1..45f23503629f 100644 --- a/libyul/optimiser/FunctionCallFinder.cpp +++ b/libyul/optimiser/FunctionCallFinder.cpp @@ -21,14 +21,14 @@ using namespace solidity; using namespace solidity::yul; -std::vector FunctionCallFinder::run(Block& _block, YulString _functionName) +std::vector FunctionCallFinder::run(Block& _block, YulName _functionName) { FunctionCallFinder functionCallFinder(_functionName); functionCallFinder(_block); return functionCallFinder.m_calls; } -FunctionCallFinder::FunctionCallFinder(YulString _functionName): m_functionName(_functionName) {} +FunctionCallFinder::FunctionCallFinder(YulName _functionName): m_functionName(_functionName) {} void FunctionCallFinder::operator()(FunctionCall& _functionCall) { diff --git a/libyul/optimiser/FunctionCallFinder.h b/libyul/optimiser/FunctionCallFinder.h index 365f86688b74..fd6367019a64 100644 --- a/libyul/optimiser/FunctionCallFinder.h +++ b/libyul/optimiser/FunctionCallFinder.h @@ -35,12 +35,12 @@ namespace solidity::yul class FunctionCallFinder: ASTModifier { public: - static std::vector run(Block& _block, YulString _functionName); + static std::vector run(Block& _block, YulName _functionName); private: - FunctionCallFinder(YulString _functionName); + FunctionCallFinder(YulName _functionName); using ASTModifier::operator(); void operator()(FunctionCall& _functionCall) override; - YulString m_functionName; + YulName m_functionName; std::vector m_calls; }; diff --git a/libyul/optimiser/FunctionHoister.h b/libyul/optimiser/FunctionHoister.h index 04d7f64e3d73..e537c82bffac 100644 --- a/libyul/optimiser/FunctionHoister.h +++ b/libyul/optimiser/FunctionHoister.h @@ -49,7 +49,7 @@ class FunctionHoister: public ASTModifier FunctionHoister() = default; bool m_isTopLevel = true; - std::vector m_functions; + std::vector m_functions {}; }; } diff --git a/libyul/optimiser/FunctionSpecializer.cpp b/libyul/optimiser/FunctionSpecializer.cpp index 7e6d486327ea..6c70c9d6899f 100644 --- a/libyul/optimiser/FunctionSpecializer.cpp +++ b/libyul/optimiser/FunctionSpecializer.cpp @@ -21,10 +21,8 @@ #include #include #include -#include #include -#include #include #include @@ -55,7 +53,7 @@ void FunctionSpecializer::operator()(FunctionCall& _f) // TODO When backtracking is implemented, the restriction of recursive functions can be lifted. if ( - m_dialect.builtin(_f.functionName.name) || + m_yulNameRepository.isBuiltinName(_f.functionName.name) || m_recursiveFunctions.count(_f.functionName.name) ) return; @@ -64,8 +62,8 @@ void FunctionSpecializer::operator()(FunctionCall& _f) if (ranges::any_of(arguments, [](auto& _a) { return _a.has_value(); })) { - YulString oldName = std::move(_f.functionName.name); - auto newName = m_nameDispenser.newName(oldName); + auto oldName = std::move(_f.functionName.name); + auto newName = m_yulNameRepository.deriveName(oldName); m_oldToNewMap[oldName].emplace_back(std::make_pair(newName, arguments)); @@ -79,19 +77,19 @@ void FunctionSpecializer::operator()(FunctionCall& _f) FunctionDefinition FunctionSpecializer::specialize( FunctionDefinition const& _f, - YulString _newName, + YulName _newName, FunctionSpecializer::LiteralArguments _arguments ) { yulAssert(_arguments.size() == _f.parameters.size(), ""); - std::map translatedNames = applyMap( + std::map translatedNames = applyMap( NameCollector{_f, NameCollector::OnlyVariables}.names(), - [&](auto& _name) -> std::pair + [&](auto& _name) -> std::pair { - return std::make_pair(_name, m_nameDispenser.newName(_name)); + return std::make_pair(_name, m_yulNameRepository.deriveName(_name)); }, - std::map{} + std::map{} ); FunctionDefinition newFunction = std::get(FunctionCopier{translatedNames}(_f)); @@ -119,7 +117,7 @@ FunctionDefinition FunctionSpecializer::specialize( applyMap(_arguments, [&](auto const& _v) { return !_v; }) ); - newFunction.name = std::move(_newName); + newFunction.name = _newName; return newFunction; } @@ -128,8 +126,7 @@ void FunctionSpecializer::run(OptimiserStepContext& _context, Block& _ast) { FunctionSpecializer f{ CallGraphGenerator::callGraph(_ast).recursiveFunctions(), - _context.dispenser, - _context.dialect + _context.yulNameRepository }; f(_ast); diff --git a/libyul/optimiser/FunctionSpecializer.h b/libyul/optimiser/FunctionSpecializer.h index b922ece8b09f..a69cb5a0b2f1 100644 --- a/libyul/optimiser/FunctionSpecializer.h +++ b/libyul/optimiser/FunctionSpecializer.h @@ -19,7 +19,6 @@ #pragma once #include -#include #include #include @@ -67,13 +66,11 @@ class FunctionSpecializer: public ASTModifier private: explicit FunctionSpecializer( - std::set _recursiveFunctions, - NameDispenser& _nameDispenser, - Dialect const& _dialect + std::set _recursiveFunctions, + YulNameRepository& _yulNameRepository ): m_recursiveFunctions(std::move(_recursiveFunctions)), - m_nameDispenser(_nameDispenser), - m_dialect(_dialect) + m_yulNameRepository(_yulNameRepository) {} /// Returns a vector of Expressions, where the index `i` is an expression if the function's /// `i`-th argument can be specialized, nullopt otherwise. @@ -96,18 +93,17 @@ class FunctionSpecializer: public ASTModifier /// FunctionDefinition specialize( FunctionDefinition const& _f, - YulString _newName, + YulName _newName, FunctionSpecializer::LiteralArguments _arguments ); /// A mapping between the old function name and a pair of new function name and its arguments. /// Note that at least one of the argument will have a literal value. - std::map>> m_oldToNewMap; + std::map>> m_oldToNewMap; /// We skip specializing recursive functions. Need backtracking to properly deal with them. - std::set const m_recursiveFunctions; + std::set const m_recursiveFunctions; - NameDispenser& m_nameDispenser; - Dialect const& m_dialect; + YulNameRepository& m_yulNameRepository; }; } diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp index 0bb4d368d841..d719302dcbc2 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp @@ -43,7 +43,7 @@ void InlinableExpressionFunctionFinder::operator()(FunctionDefinition const& _fu { if (_function.returnVariables.size() == 1 && _function.body.statements.size() == 1) { - YulString retVariable = _function.returnVariables.front().name; + YulName retVariable = _function.returnVariables.front().name; Statement const& bodyStatement = _function.body.statements.front(); if (std::holds_alternative(bodyStatement)) { @@ -56,7 +56,7 @@ void InlinableExpressionFunctionFinder::operator()(FunctionDefinition const& _fu // would not be valid here if we were searching inside a functionally inlinable // function body. assertThrow(m_disallowedIdentifiers.empty() && !m_foundDisallowedIdentifier, OptimizerException, ""); - m_disallowedIdentifiers = std::set{retVariable, _function.name}; + m_disallowedIdentifiers = std::set{retVariable, _function.name}; std::visit(*this, *assignment.value); if (!m_foundDisallowedIdentifier) m_inlinableFunctions[_function.name] = &_function; diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.h b/libyul/optimiser/InlinableExpressionFunctionFinder.h index 587bdca91172..e7210da69a0a 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.h +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.h @@ -42,7 +42,7 @@ class InlinableExpressionFunctionFinder: public ASTWalker { public: - std::map const& inlinableFunctions() const + std::map const& inlinableFunctions() const { return m_inlinableFunctions; } @@ -53,15 +53,15 @@ class InlinableExpressionFunctionFinder: public ASTWalker void operator()(FunctionDefinition const& _function) override; private: - void checkAllowed(YulString _name) + void checkAllowed(YulName _name) { if (m_disallowedIdentifiers.count(_name)) m_foundDisallowedIdentifier = true; } bool m_foundDisallowedIdentifier = false; - std::set m_disallowedIdentifiers; - std::map m_inlinableFunctions; + std::set m_disallowedIdentifiers; + std::map m_inlinableFunctions; }; } diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index 79eb2b317940..9932ed844ded 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -32,19 +32,20 @@ using namespace solidity; using namespace solidity::yul; -KnowledgeBase::KnowledgeBase(std::map const& _ssaValues): +KnowledgeBase::KnowledgeBase(std::map const& _ssaValues, YulNameRepository const& _yulNameRepository): m_valuesAreSSA(true), - m_variableValues([_ssaValues](YulString _var) { return util::valueOrNullptr(_ssaValues, _var); }) + m_variableValues([_ssaValues](YulName _var) { return util::valueOrNullptr(_ssaValues, _var); }), + m_yulNameRepository(_yulNameRepository) {} -bool KnowledgeBase::knownToBeDifferent(YulString _a, YulString _b) +bool KnowledgeBase::knownToBeDifferent(YulName _a, YulName _b) { if (std::optional difference = differenceIfKnownConstant(_a, _b)) return difference != 0; return false; } -std::optional KnowledgeBase::differenceIfKnownConstant(YulString _a, YulString _b) +std::optional KnowledgeBase::differenceIfKnownConstant(YulName _a, YulName _b) { VariableOffset offA = explore(_a); VariableOffset offB = explore(_b); @@ -55,7 +56,7 @@ std::optional KnowledgeBase::differenceIfKnownConstant(YulString _a, YulSt } -bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b) +bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulName _a, YulName _b) { if (std::optional difference = differenceIfKnownConstant(_a, _b)) return difference >= 32 && difference <= u256(0) - 32; @@ -63,12 +64,12 @@ bool KnowledgeBase::knownToBeDifferentByAtLeast32(YulString _a, YulString _b) return false; } -bool KnowledgeBase::knownToBeZero(YulString _a) +bool KnowledgeBase::knownToBeZero(YulName _a) { return valueIfKnownConstant(_a) == 0; } -std::optional KnowledgeBase::valueIfKnownConstant(YulString _a) +std::optional KnowledgeBase::valueIfKnownConstant(YulName _a) { return explore(_a).absoluteValue(); } @@ -83,7 +84,7 @@ std::optional KnowledgeBase::valueIfKnownConstant(Expression const& _expre return std::nullopt; } -KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) +KnowledgeBase::VariableOffset KnowledgeBase::explore(YulName _var) { Expression const* value = nullptr; if (m_valuesAreSSA) @@ -113,12 +114,12 @@ KnowledgeBase::VariableOffset KnowledgeBase::explore(YulString _var) std::optional KnowledgeBase::explore(Expression const& _value) { if (Literal const* literal = std::get_if(&_value)) - return VariableOffset{YulString{}, literal->value.value()}; + return VariableOffset{YulNameRepository::emptyName(), literal->value.value()}; else if (Identifier const* identifier = std::get_if(&_value)) return explore(identifier->name); else if (FunctionCall const* f = std::get_if(&_value)) { - if (f->functionName.name == "add"_yulstring) + if (f->functionName.name == m_yulNameRepository.predefined().add) { if (std::optional a = explore(f->arguments[0])) if (std::optional b = explore(f->arguments[1])) @@ -132,13 +133,13 @@ std::optional KnowledgeBase::explore(Expression c return VariableOffset{a->reference, offset}; } } - else if (f->functionName.name == "sub"_yulstring) + else if (f->functionName.name == m_yulNameRepository.predefined().sub) if (std::optional a = explore(f->arguments[0])) if (std::optional b = explore(f->arguments[1])) { u256 offset = a->offset - b->offset; if (a->reference == b->reference) - return VariableOffset{YulString{}, offset}; + return VariableOffset{YulNameRepository::emptyName(), offset}; else if (b->isAbsolute()) // b is constant return VariableOffset{a->reference, offset}; @@ -148,7 +149,7 @@ std::optional KnowledgeBase::explore(Expression c return std::nullopt; } -Expression const* KnowledgeBase::valueOf(YulString _var) +Expression const* KnowledgeBase::valueOf(YulName _var) { AssignedValue const* assignedValue = m_variableValues(_var); Expression const* currentValue = assignedValue ? assignedValue->value : nullptr; @@ -162,7 +163,7 @@ Expression const* KnowledgeBase::valueOf(YulString _var) return currentValue; } -void KnowledgeBase::reset(YulString _var) +void KnowledgeBase::reset(YulName _var) { yulAssert(!m_valuesAreSSA); @@ -174,16 +175,16 @@ void KnowledgeBase::reset(YulString _var) m_groupMembers[offset->reference].erase(_var); m_offsets.erase(_var); } - if (std::set* group = util::valueOrNullptr(m_groupMembers, _var)) + if (std::set* group = util::valueOrNullptr(m_groupMembers, _var)) { // _var was a representative, we might have to find a new one. if (!group->empty()) { - YulString newRepresentative = *group->begin(); + YulName newRepresentative = *group->begin(); yulAssert(newRepresentative != _var); u256 newOffset = m_offsets[newRepresentative].offset; // newOffset = newRepresentative - _var - for (YulString groupMember: *group) + for (YulName groupMember: *group) { yulAssert(m_offsets[groupMember].reference == _var); m_offsets[groupMember].reference = newRepresentative; @@ -200,12 +201,12 @@ void KnowledgeBase::reset(YulString _var) } } -KnowledgeBase::VariableOffset KnowledgeBase::setOffset(YulString _variable, VariableOffset _value) +KnowledgeBase::VariableOffset KnowledgeBase::setOffset(YulName _variable, VariableOffset _value) { m_offsets[_variable] = _value; // Constants are not tracked in m_groupMembers because // the "representative" can never be reset. - if (!_value.reference.empty()) + if (_value.reference != YulNameRepository::emptyName()) m_groupMembers[_value.reference].insert(_variable); return _value; } diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index f83c5ac66105..fa39a21c98a9 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include @@ -62,32 +62,32 @@ class KnowledgeBase public: /// Constructor for arbitrary value callback that allows for variable values /// to change in between calls to functions of this class. - explicit KnowledgeBase(std::function _variableValues): - m_variableValues(std::move(_variableValues)) + explicit KnowledgeBase(std::function _variableValues, YulNameRepository const& _yulNameRepository): + m_variableValues(std::move(_variableValues)), m_yulNameRepository(_yulNameRepository) {} /// Constructor to use if source code is in SSA form and values are constant. - explicit KnowledgeBase(std::map const& _ssaValues); + explicit KnowledgeBase(std::map const& _ssaValues, YulNameRepository const& _yulNameRepository); - bool knownToBeDifferent(YulString _a, YulString _b); - std::optional differenceIfKnownConstant(YulString _a, YulString _b); - bool knownToBeDifferentByAtLeast32(YulString _a, YulString _b); - bool knownToBeZero(YulString _a); - std::optional valueIfKnownConstant(YulString _a); + bool knownToBeDifferent(YulName _a, YulName _b); + std::optional differenceIfKnownConstant(YulName _a, YulName _b); + bool knownToBeDifferentByAtLeast32(YulName _a, YulName _b); + bool knownToBeZero(YulName _a); + std::optional valueIfKnownConstant(YulName _a); std::optional valueIfKnownConstant(Expression const& _expression); private: /** * Constant offset relative to a reference variable, or absolute constant if the - * reference variable is the empty YulString. + * reference variable is the empty YulName. */ struct VariableOffset { - YulString reference; + YulName reference; u256 offset; bool isAbsolute() const { - return reference.empty(); + return reference == YulNameRepository::emptyName(); } std::optional absoluteValue() const @@ -99,30 +99,31 @@ class KnowledgeBase } }; - VariableOffset explore(YulString _var); + VariableOffset explore(YulName _var); std::optional explore(Expression const& _value); /// Retrieves the current value of a variable and potentially resets the variable if it is not up to date. - Expression const* valueOf(YulString _var); + Expression const* valueOf(YulName _var); /// Resets all information about the variable and removes it from its group, /// potentially finding a new representative. - void reset(YulString _var); + void reset(YulName _var); - VariableOffset setOffset(YulString _variable, VariableOffset _value); + VariableOffset setOffset(YulName _variable, VariableOffset _value); /// If true, we can assume that variable values never change and skip some steps. bool m_valuesAreSSA = false; /// Callback to retrieve the current value of a variable. - std::function m_variableValues; + std::function m_variableValues; /// Offsets for each variable to one representative per group. /// The empty string is the representative of the constant value zero. - std::map m_offsets; + std::map m_offsets; /// Last known value of each variable we queried. - std::map m_lastKnownValue; + std::map m_lastKnownValue; /// For each representative, variables that use it to offset from. - std::map> m_groupMembers; + std::map> m_groupMembers; + YulNameRepository const& m_yulNameRepository; }; } diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index 170eefc902b5..fb6a4a0b638c 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -43,10 +43,10 @@ using namespace solidity::yul; void LoadResolver::run(OptimiserStepContext& _context, Block& _ast) { - bool containsMSize = MSizeFinder::containsMSize(_context.dialect, _ast); + bool containsMSize = MSizeFinder::containsMSize(_context.yulNameRepository, _ast); LoadResolver{ - _context.dialect, - SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)), + _context.yulNameRepository, + SideEffectsPropagator::sideEffects(_context.yulNameRepository, CallGraphGenerator::callGraph(_ast)), containsMSize, _context.expectedExecutionsPerDeployment }(_ast); @@ -62,7 +62,7 @@ void LoadResolver::visit(Expression& _e) tryResolve(_e, StoreLoadLocation::Memory, funCall->arguments); else if (funCall->functionName.name == m_loadFunctionName[static_cast(StoreLoadLocation::Storage)]) tryResolve(_e, StoreLoadLocation::Storage, funCall->arguments); - else if (!m_containsMSize && funCall->functionName.name == m_dialect.hashFunction({})) + else if (!m_containsMSize && funCall->functionName.name == m_yulNameRepository.hashFunction({})) { Identifier const* start = std::get_if(&funCall->arguments.at(0)); Identifier const* length = std::get_if(&funCall->arguments.at(1)); @@ -87,7 +87,7 @@ void LoadResolver::tryResolve( if (_arguments.empty() || !std::holds_alternative(_arguments.at(0))) return; - YulString key = std::get(_arguments.at(0)).name; + YulName key = std::get(_arguments.at(0)).name; if (_location == StoreLoadLocation::Storage) { if (auto value = storageValue(key)) @@ -114,7 +114,8 @@ void LoadResolver::tryEvaluateKeccak( // The costs are only correct for hashes of 32 bytes or 1 word (when rounded up). GasMeter gasMeter{ - dynamic_cast(m_dialect), + m_yulNameRepository, + dynamic_cast(m_yulNameRepository.dialect()), !m_expectedExecutionsPerDeployment, m_expectedExecutionsPerDeployment ? *m_expectedExecutionsPerDeployment : 1 }; @@ -137,7 +138,7 @@ void LoadResolver::tryEvaluateKeccak( if (costOfLiteral > costOfKeccak) return; - std::optional value = memoryValue(memoryKey->name); + std::optional value = memoryValue(memoryKey->name); if (value && inScope(*value)) { std::optional memoryContent = valueOfIdentifier(*value); @@ -151,7 +152,7 @@ void LoadResolver::tryEvaluateKeccak( debugDataOf(_e), LiteralKind::Number, LiteralValue{contentHash}, - m_dialect.defaultType + m_yulNameRepository.predefined().defaultType }; } } diff --git a/libyul/optimiser/LoadResolver.h b/libyul/optimiser/LoadResolver.h index e56bc6c4a206..bfe47fb70237 100644 --- a/libyul/optimiser/LoadResolver.h +++ b/libyul/optimiser/LoadResolver.h @@ -48,12 +48,12 @@ class LoadResolver: public DataFlowAnalyzer private: LoadResolver( - Dialect const& _dialect, - std::map _functionSideEffects, + YulNameRepository const& _yulNameRepository, + std::map _functionSideEffects, bool _containsMSize, std::optional _expectedExecutionsPerDeployment ): - DataFlowAnalyzer(_dialect, MemoryAndStorage::Analyze, std::move(_functionSideEffects)), + DataFlowAnalyzer(_yulNameRepository, MemoryAndStorage::Analyze, std::move(_functionSideEffects)), m_containsMSize(_containsMSize), m_expectedExecutionsPerDeployment(std::move(_expectedExecutionsPerDeployment)) {} diff --git a/libyul/optimiser/LoopInvariantCodeMotion.cpp b/libyul/optimiser/LoopInvariantCodeMotion.cpp index da3c5e3e0a5a..b166b5d87680 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.cpp +++ b/libyul/optimiser/LoopInvariantCodeMotion.cpp @@ -32,11 +32,11 @@ using namespace solidity::yul; void LoopInvariantCodeMotion::run(OptimiserStepContext& _context, Block& _ast) { - std::map functionSideEffects = - SideEffectsPropagator::sideEffects(_context.dialect, CallGraphGenerator::callGraph(_ast)); - bool containsMSize = MSizeFinder::containsMSize(_context.dialect, _ast); - std::set ssaVars = SSAValueTracker::ssaVariables(_ast); - LoopInvariantCodeMotion{_context.dialect, ssaVars, functionSideEffects, containsMSize}(_ast); + std::map functionSideEffects = + SideEffectsPropagator::sideEffects(_context.yulNameRepository, CallGraphGenerator::callGraph(_ast)); + bool containsMSize = MSizeFinder::containsMSize(_context.yulNameRepository, _ast); + std::set ssaVars = SSAValueTracker::ssaVariables(_ast); + LoopInvariantCodeMotion{_context.yulNameRepository, ssaVars, functionSideEffects, containsMSize}(_ast); } void LoopInvariantCodeMotion::operator()(Block& _block) @@ -56,7 +56,7 @@ void LoopInvariantCodeMotion::operator()(Block& _block) bool LoopInvariantCodeMotion::canBePromoted( VariableDeclaration const& _varDecl, - std::set const& _varsDefinedInCurrentScope, + std::set const& _varsDefinedInCurrentScope, SideEffects const& _forLoopSideEffects ) const { @@ -73,7 +73,7 @@ bool LoopInvariantCodeMotion::canBePromoted( for (auto const& ref: VariableReferencesCounter::countReferences(*_varDecl.value)) if (_varsDefinedInCurrentScope.count(ref.first) || !m_ssaVariables.count(ref.first)) return false; - SideEffectsCollector sideEffects{m_dialect, *_varDecl.value, &m_functionSideEffects}; + SideEffectsCollector sideEffects{m_yulNameRepository, *_varDecl.value, &m_functionSideEffects}; if (!sideEffects.movableRelativeTo(_forLoopSideEffects, m_containsMSize)) return false; } @@ -85,12 +85,12 @@ std::optional> LoopInvariantCodeMotion::rewriteLoop(ForLo assertThrow(_for.pre.statements.empty(), OptimizerException, ""); auto forLoopSideEffects = - SideEffectsCollector{m_dialect, _for, &m_functionSideEffects}.sideEffects(); + SideEffectsCollector{m_yulNameRepository, _for, &m_functionSideEffects}.sideEffects(); std::vector replacement; for (Block* block: {&_for.post, &_for.body}) { - std::set varsDefinedInScope; + std::set varsDefinedInScope; util::iterateReplacing( block->statements, [&](Statement& _s) -> std::optional> diff --git a/libyul/optimiser/LoopInvariantCodeMotion.h b/libyul/optimiser/LoopInvariantCodeMotion.h index 1b264792470c..2f597c9c770b 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.h +++ b/libyul/optimiser/LoopInvariantCodeMotion.h @@ -47,13 +47,13 @@ class LoopInvariantCodeMotion: public ASTModifier private: explicit LoopInvariantCodeMotion( - Dialect const& _dialect, - std::set const& _ssaVariables, - std::map const& _functionSideEffects, + YulNameRepository const& _yulNameRepository, + std::set const& _ssaVariables, + std::map const& _functionSideEffects, bool _containsMSize ): m_containsMSize(_containsMSize), - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_ssaVariables(_ssaVariables), m_functionSideEffects(_functionSideEffects) { } @@ -61,15 +61,15 @@ class LoopInvariantCodeMotion: public ASTModifier /// @returns true if the given variable declaration can be moved to in front of the loop. bool canBePromoted( VariableDeclaration const& _varDecl, - std::set const& _varsDefinedInCurrentScope, + std::set const& _varsDefinedInCurrentScope, SideEffects const& _forLoopSideEffects ) const; std::optional> rewriteLoop(ForLoop& _for); bool m_containsMSize = true; - Dialect const& m_dialect; - std::set const& m_ssaVariables; - std::map const& m_functionSideEffects; + YulNameRepository const& m_yulNameRepository; + std::set const& m_ssaVariables; + std::map const& m_functionSideEffects; }; } diff --git a/libyul/optimiser/Metrics.cpp b/libyul/optimiser/Metrics.cpp index 2f1dee93eabe..d9d3727c1240 100644 --- a/libyul/optimiser/Metrics.cpp +++ b/libyul/optimiser/Metrics.cpp @@ -125,9 +125,9 @@ void CodeSize::visit(Expression const& _expression) } -size_t CodeCost::codeCost(Dialect const& _dialect, Expression const& _expr) +size_t CodeCost::codeCost(YulNameRepository const& _yulNameRepository, Expression const& _expr) { - CodeCost cc(_dialect); + CodeCost cc(_yulNameRepository); cc.visit(_expr); return cc.m_cost; } @@ -137,7 +137,7 @@ void CodeCost::operator()(FunctionCall const& _funCall) { ASTWalker::operator()(_funCall); - if (auto instruction = toEVMInstruction(m_dialect, _funCall.functionName.name)) + if (auto instruction = toEVMInstruction(m_yulNameRepository, _funCall.functionName.name)) { addInstructionCost(*instruction); return; @@ -158,7 +158,7 @@ void CodeCost::operator()(Literal const& _literal) for (u256 n = _literal.value.value(); n >= 0x100; n >>= 8) cost++; if (_literal.value.value() == 0) - if (auto evmDialect = dynamic_cast(&m_dialect)) + if (auto evmDialect = dynamic_cast(&m_yulNameRepository.dialect())) if (evmDialect->evmVersion().hasPush0()) --m_cost; break; @@ -184,7 +184,7 @@ void CodeCost::visit(Expression const& _expression) void CodeCost::addInstructionCost(evmasm::Instruction _instruction) { - evmasm::Tier gasPriceTier = evmasm::instructionInfo(_instruction, evmVersionFromDialect(m_dialect)).gasPriceTier; + evmasm::Tier gasPriceTier = evmasm::instructionInfo(_instruction, evmVersionFromDialect(m_yulNameRepository.dialect())).gasPriceTier; if (gasPriceTier < evmasm::Tier::VeryLow) m_cost -= 1; else if (gasPriceTier < evmasm::Tier::High) @@ -199,7 +199,7 @@ void AssignmentCounter::operator()(Assignment const& _assignment) ++m_assignmentCounters[variable.name]; } -size_t AssignmentCounter::assignmentCount(YulString _name) const +size_t AssignmentCounter::assignmentCount(YulName const _name) const { auto it = m_assignmentCounters.find(_name); return (it == m_assignmentCounters.end()) ? 0 : it->second; diff --git a/libyul/optimiser/Metrics.h b/libyul/optimiser/Metrics.h index f86e3b28dfad..ee6743c6954b 100644 --- a/libyul/optimiser/Metrics.h +++ b/libyul/optimiser/Metrics.h @@ -113,10 +113,10 @@ class CodeSize: public ASTWalker class CodeCost: public ASTWalker { public: - static size_t codeCost(Dialect const& _dialect, Expression const& _expression); + static size_t codeCost(YulNameRepository const& _yulNameRepository, Expression const& _expression); private: - CodeCost(Dialect const& _dialect): m_dialect(_dialect) {} + CodeCost(YulNameRepository const& _yulNameRepository): m_yulNameRepository(_yulNameRepository) {} void operator()(FunctionCall const& _funCall) override; void operator()(Literal const& _literal) override; @@ -126,7 +126,7 @@ class CodeCost: public ASTWalker private: void addInstructionCost(evmasm::Instruction _instruction); - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; size_t m_cost = 0; }; @@ -139,9 +139,9 @@ class AssignmentCounter: public ASTWalker public: using ASTWalker::operator(); void operator()(Assignment const& _assignment) override; - std::size_t assignmentCount(YulString _name) const; + std::size_t assignmentCount(YulName _name) const; private: - std::map m_assignmentCounters; + std::map m_assignmentCounters; }; } diff --git a/libyul/optimiser/NameCollector.cpp b/libyul/optimiser/NameCollector.cpp index 7fb0c7ed28e9..d6db837f8485 100644 --- a/libyul/optimiser/NameCollector.cpp +++ b/libyul/optimiser/NameCollector.cpp @@ -59,21 +59,21 @@ void ReferencesCounter::operator()(FunctionCall const& _funCall) ASTWalker::operator()(_funCall); } -std::map ReferencesCounter::countReferences(Block const& _block) +std::map ReferencesCounter::countReferences(Block const& _block) { ReferencesCounter counter; counter(_block); return std::move(counter.m_references); } -std::map ReferencesCounter::countReferences(FunctionDefinition const& _function) +std::map ReferencesCounter::countReferences(FunctionDefinition const& _function) { ReferencesCounter counter; counter(_function); return std::move(counter.m_references); } -std::map ReferencesCounter::countReferences(Expression const& _expression) +std::map ReferencesCounter::countReferences(Expression const& _expression) { ReferencesCounter counter; counter.visit(_expression); @@ -85,28 +85,28 @@ void VariableReferencesCounter::operator()(Identifier const& _identifier) ++m_references[_identifier.name]; } -std::map VariableReferencesCounter::countReferences(Block const& _block) +std::map VariableReferencesCounter::countReferences(Block const& _block) { VariableReferencesCounter counter; counter(_block); return std::move(counter.m_references); } -std::map VariableReferencesCounter::countReferences(FunctionDefinition const& _function) +std::map VariableReferencesCounter::countReferences(FunctionDefinition const& _function) { VariableReferencesCounter counter; counter(_function); return std::move(counter.m_references); } -std::map VariableReferencesCounter::countReferences(Expression const& _expression) +std::map VariableReferencesCounter::countReferences(Expression const& _expression) { VariableReferencesCounter counter; counter.visit(_expression); return std::move(counter.m_references); } -std::map VariableReferencesCounter::countReferences(Statement const& _statement) +std::map VariableReferencesCounter::countReferences(Statement const& _statement) { VariableReferencesCounter counter; counter.visit(_statement); @@ -138,9 +138,9 @@ void AssignmentsSinceContinue::operator()(FunctionDefinition const&) yulAssert(false, ""); } -std::set solidity::yul::assignedVariableNames(Block const& _code) +std::set solidity::yul::assignedVariableNames(Block const& _code) { - std::set names; + std::set names; forEach(_code, [&](Assignment const& _assignment) { for (auto const& var: _assignment.variableNames) names.emplace(var.name); @@ -148,9 +148,9 @@ std::set solidity::yul::assignedVariableNames(Block const& _code) return names; } -std::map solidity::yul::allFunctionDefinitions(Block const& _block) +std::map solidity::yul::allFunctionDefinitions(Block const& _block) { - std::map result; + std::map result; forEach(_block, [&](FunctionDefinition const& _function) { result[_function.name] = &_function; }); diff --git a/libyul/optimiser/NameCollector.h b/libyul/optimiser/NameCollector.h index ad18e1e26bb3..38f45d92cbbf 100644 --- a/libyul/optimiser/NameCollector.h +++ b/libyul/optimiser/NameCollector.h @@ -59,9 +59,9 @@ class NameCollector: public ASTWalker void operator()(VariableDeclaration const& _varDecl) override; void operator()(FunctionDefinition const& _funDef) override; - std::set names() const { return m_names; } + std::set const& names() const { return m_names; } private: - std::set m_names; + std::set m_names; CollectWhat m_collectWhat = VariablesAndFunctions; }; @@ -75,12 +75,12 @@ class ReferencesCounter: public ASTWalker void operator()(Identifier const& _identifier) override; void operator()(FunctionCall const& _funCall) override; - static std::map countReferences(Block const& _block); - static std::map countReferences(FunctionDefinition const& _function); - static std::map countReferences(Expression const& _expression); + static std::map countReferences(Block const& _block); + static std::map countReferences(FunctionDefinition const& _function); + static std::map countReferences(Expression const& _expression); private: - std::map m_references; + std::map m_references; }; /** @@ -92,13 +92,13 @@ class VariableReferencesCounter: public ASTWalker using ASTWalker::operator (); void operator()(Identifier const& _identifier) override; - static std::map countReferences(Block const& _block); - static std::map countReferences(FunctionDefinition const& _function); - static std::map countReferences(Expression const& _expression); - static std::map countReferences(Statement const& _statement); + static std::map countReferences(Block const& _block); + static std::map countReferences(FunctionDefinition const& _function); + static std::map countReferences(Expression const& _expression); + static std::map countReferences(Statement const& _statement); private: - std::map m_references; + std::map m_references; }; /** @@ -117,21 +117,21 @@ class AssignmentsSinceContinue: public ASTWalker void operator()(Assignment const& _assignment) override; void operator()(FunctionDefinition const& _funDef) override; - std::set const& names() const { return m_names; } + std::set const& names() const { return m_names; } bool empty() const noexcept { return m_names.empty(); } private: size_t m_forLoopDepth = 0; bool m_continueFound = false; - std::set m_names; + std::set m_names; }; /// @returns the names of all variables that are assigned to inside @a _code. /// (ignores variable declarations) -std::set assignedVariableNames(Block const& _code); +std::set assignedVariableNames(Block const& _code); /// @returns all function definitions anywhere in the AST. /// Requires disambiguated source. -std::map allFunctionDefinitions(Block const& _block); +std::map allFunctionDefinitions(Block const& _block); } diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp deleted file mode 100644 index 3a8db5ee449e..000000000000 --- a/libyul/optimiser/NameDispenser.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - 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 -/** - * Optimiser component that can create new unique names. - */ - -#include - -#include -#include -#include -#include -#include - -#include - -using namespace solidity; -using namespace solidity::yul; -using namespace solidity::util; - -NameDispenser::NameDispenser(Dialect const& _dialect, Block const& _ast, std::set _reservedNames): - NameDispenser(_dialect, NameCollector(_ast).names() + _reservedNames) -{ - m_reservedNames = std::move(_reservedNames); -} - -NameDispenser::NameDispenser(Dialect const& _dialect, std::set _usedNames): - m_dialect(_dialect), - m_usedNames(std::move(_usedNames)) -{ -} - -YulString NameDispenser::newName(YulString _nameHint) -{ - YulString name = _nameHint; - while (illegalName(name)) - { - m_counter++; - name = YulString(_nameHint.str() + "_" + std::to_string(m_counter)); - } - m_usedNames.emplace(name); - return name; -} - -bool NameDispenser::illegalName(YulString _name) -{ - return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); -} - -void NameDispenser::reset(Block const& _ast) -{ - m_usedNames = NameCollector(_ast).names() + m_reservedNames; - m_counter = 0; -} diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h deleted file mode 100644 index 6e655e416b51..000000000000 --- a/libyul/optimiser/NameDispenser.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - 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 -/** - * Optimiser component that can create new unique names. - */ -#pragma once - -#include - -#include - -#include - -namespace solidity::yul -{ -struct Dialect; - -/** - * Optimizer component that can be used to generate new names that - * do not conflict with existing names. - * - * Tries to keep names short and appends decimals to disambiguate. - */ -class NameDispenser -{ -public: - /// Initialize the name dispenser with all the names used in the given AST. - explicit NameDispenser(Dialect const& _dialect, Block const& _ast, std::set _reservedNames = {}); - /// Initialize the name dispenser with the given used names. - explicit NameDispenser(Dialect const& _dialect, std::set _usedNames); - - /// @returns a currently unused name that should be similar to _nameHint. - YulString newName(YulString _nameHint); - - /// Mark @a _name as used, i.e. the dispenser's newName function will not - /// return it. - void markUsed(YulString _name) { m_usedNames.insert(_name); } - - std::set const& usedNames() { return m_usedNames; } - - /// Returns true if `_name` is either used or is a restricted identifier. - bool illegalName(YulString _name); - - /// Resets `m_usedNames` with *only* the names that are used in the AST. Also resets value of - /// `m_counter` to zero. - void reset(Block const& _ast); - -private: - Dialect const& m_dialect; - std::set m_usedNames; - std::set m_reservedNames; - size_t m_counter = 0; -}; - -} diff --git a/libyul/optimiser/NameDisplacer.cpp b/libyul/optimiser/NameDisplacer.cpp index 4d0d217d8619..efdc007eb28c 100644 --- a/libyul/optimiser/NameDisplacer.cpp +++ b/libyul/optimiser/NameDisplacer.cpp @@ -43,6 +43,7 @@ void NameDisplacer::operator()(FunctionDefinition& _function) { // Should have been done in the block already. yulAssert(!m_namesToFree.count(_function.name), ""); + // yulAssert(!m_namesToFree.count(m_yulNameRepository.baseNameOf(_function.name))); for (auto& param: _function.parameters) checkAndReplaceNew(param.name); @@ -69,16 +70,15 @@ void NameDisplacer::operator()(Block& _block) ASTModifier::operator()(_block); } -void NameDisplacer::checkAndReplaceNew(YulString& _name) +void NameDisplacer::checkAndReplaceNew(YulName& _name) { yulAssert(!m_translations.count(_name), ""); if (m_namesToFree.count(_name)) - _name = (m_translations[_name] = m_nameDispenser.newName(_name)); + _name = (m_translations[_name] = m_yulNameRepository.deriveName(_name)); } -void NameDisplacer::checkAndReplace(YulString& _name) const +void NameDisplacer::checkAndReplace(YulName& _name) const { if (m_translations.count(_name)) _name = m_translations.at(_name); } - diff --git a/libyul/optimiser/NameDisplacer.h b/libyul/optimiser/NameDisplacer.h index 336dd04e42de..db2fc8bee58d 100644 --- a/libyul/optimiser/NameDisplacer.h +++ b/libyul/optimiser/NameDisplacer.h @@ -22,7 +22,6 @@ #pragma once #include -#include #include #include @@ -43,15 +42,12 @@ class NameDisplacer: public ASTModifier { public: explicit NameDisplacer( - NameDispenser& _dispenser, - std::set const& _namesToFree + std::set const& _namesToFree, + YulNameRepository& _yulNameRepository ): - m_nameDispenser(_dispenser), - m_namesToFree(_namesToFree) - { - for (YulString n: _namesToFree) - m_nameDispenser.markUsed(n); - } + m_namesToFree(_namesToFree), + m_yulNameRepository(_yulNameRepository) + {} using ASTModifier::operator(); void operator()(Identifier& _identifier) override; @@ -60,17 +56,16 @@ class NameDisplacer: public ASTModifier void operator()(FunctionCall& _funCall) override; void operator()(Block& _block) override; - std::map const& translations() const { return m_translations; } + std::map const& translations() const { return m_translations; } protected: /// Check if the newly introduced identifier @a _name has to be replaced. - void checkAndReplaceNew(YulString& _name); + void checkAndReplaceNew(YulName& _name); /// Replace the identifier @a _name if it is in the translation map. - void checkAndReplace(YulString& _name) const; + void checkAndReplace(YulName& _name) const; - NameDispenser& m_nameDispenser; - std::set const& m_namesToFree; - std::map m_translations; + std::set const& m_namesToFree; + std::map m_translations; + YulNameRepository& m_yulNameRepository; }; - } diff --git a/libyul/optimiser/NameSimplifier.cpp b/libyul/optimiser/NameSimplifier.cpp deleted file mode 100644 index f7d732547773..000000000000 --- a/libyul/optimiser/NameSimplifier.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - 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 . -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -using namespace solidity::yul; - -NameSimplifier::NameSimplifier(OptimiserStepContext& _context, Block const& _ast): - m_context(_context) -{ - for (YulString name: _context.reservedIdentifiers) - m_translations[name] = name; - - for (YulString const& name: NameCollector(_ast).names()) - findSimplification(name); -} - -void NameSimplifier::operator()(FunctionDefinition& _funDef) -{ - translate(_funDef.name); - renameVariables(_funDef.parameters); - renameVariables(_funDef.returnVariables); - ASTModifier::operator()(_funDef); -} - -void NameSimplifier::operator()(VariableDeclaration& _varDecl) -{ - renameVariables(_varDecl.variables); - ASTModifier::operator()(_varDecl); -} - -void NameSimplifier::renameVariables(std::vector& _variables) -{ - for (TypedName& typedName: _variables) - translate(typedName.name); -} - -void NameSimplifier::operator()(Identifier& _identifier) -{ - translate(_identifier.name); -} - -void NameSimplifier::operator()(FunctionCall& _funCall) -{ - // The visitor on its own does not visit the function name. - if (!m_context.dialect.builtin(_funCall.functionName.name)) - (*this)(_funCall.functionName); - ASTModifier::operator()(_funCall); -} - -void NameSimplifier::findSimplification(YulString const& _name) -{ - if (m_translations.count(_name)) - return; - - std::string name = _name.str(); - - static auto replacements = std::vector>{ - {std::regex("_\\$|\\$_"), "_"}, // remove type mangling delimiters - {std::regex("_[0-9]+([^0-9a-fA-Fx])"), "$1"}, // removes AST IDs that are not hex. - {std::regex("_[0-9]+$"), ""}, // removes AST IDs that are not hex. - {std::regex("_t_"), "_"}, // remove type prefixes - {std::regex("__"), "_"}, - {std::regex("(abi_..code.*)_to_.*"), "$1"}, // removes _to... for abi functions - {std::regex("(stringliteral_?[0-9a-f][0-9a-f][0-9a-f][0-9a-f])[0-9a-f]*"), "$1"}, // shorten string literal - {std::regex("tuple_"), ""}, - {std::regex("_memory_ptr"), ""}, - {std::regex("_calldata_ptr"), "_calldata"}, - {std::regex("_fromStack"), ""}, - {std::regex("_storage_storage"), "_storage"}, - {std::regex("(storage.*)_?storage"), "$1"}, - {std::regex("_memory_memory"), "_memory"}, - {std::regex("_contract\\$_([^_]*)_?"), "$1_"}, - {std::regex("index_access_(t_)?array"), "index_access"}, - {std::regex("[0-9]*_$"), ""} - }; - - for (auto const& [pattern, substitute]: replacements) - { - std::string candidate = regex_replace(name, pattern, substitute); - if (!candidate.empty() && !m_context.dispenser.illegalName(YulString(candidate))) - name = candidate; - } - - if (name != _name.str()) - { - YulString newName{name}; - m_context.dispenser.markUsed(newName); - m_translations[_name] = std::move(newName); - } -} - -void NameSimplifier::translate(YulString& _name) -{ - auto it = m_translations.find(_name); - if (it != m_translations.end()) - _name = it->second; -} diff --git a/libyul/optimiser/NameSimplifier.h b/libyul/optimiser/NameSimplifier.h deleted file mode 100644 index 34cf6945115b..000000000000 --- a/libyul/optimiser/NameSimplifier.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - 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 -#include -#include -#include - -#include -#include -#include - -namespace solidity::yul -{ - -struct Dialect; - -/** - * Pass to "simplify" all identifier names. - * - * The purpose of this is to make generated code more readable, but also - * to remove AST identifiers that could lead to a different sorting order - * and thus influence e.g. the order of function inlining. - * - * Prerequisites: Disambiguator, FunctionHoister, FunctionGrouper - */ -class NameSimplifier: public ASTModifier -{ -public: - static constexpr char const* name{"NameSimplifier"}; - static void run(OptimiserStepContext& _context, Block& _ast) - { - NameSimplifier{_context, _ast}(_ast); - } - - using ASTModifier::operator(); - void operator()(VariableDeclaration& _varDecl) override; - void operator()(Identifier& _identifier) override; - void operator()(FunctionCall& _funCall) override; - void operator()(FunctionDefinition& _funDef) override; - -private: - NameSimplifier(OptimiserStepContext& _context, Block const& _ast); - - /// Tries to rename a list of variables. - void renameVariables(std::vector& _variables); - - void findSimplification(YulString const& _name); - void translate(YulString& _name); - - OptimiserStepContext& m_context; - std::map m_translations; -}; - -} diff --git a/libyul/optimiser/OptimiserStep.h b/libyul/optimiser/OptimiserStep.h index e3e5fe4c605d..91f34e52c086 100644 --- a/libyul/optimiser/OptimiserStep.h +++ b/libyul/optimiser/OptimiserStep.h @@ -30,13 +30,12 @@ namespace solidity::yul struct Dialect; struct Block; class YulString; -class NameDispenser; struct OptimiserStepContext { Dialect const& dialect; - NameDispenser& dispenser; - std::set const& reservedIdentifiers; + YulNameRepository& yulNameRepository; + std::set const& reservedIdentifiers; /// The value nullopt represents creation code std::optional expectedExecutionsPerDeployment; }; diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index bfa3d888f19b..ed5c48b2d9b7 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -39,7 +39,7 @@ using namespace solidity::yul; namespace { -bool hasLeadingOrTrailingDot(std::string_view const _s) +[[maybe_unused]] bool hasLeadingOrTrailingDot(std::string_view const _s) { yulAssert(!_s.empty()); return _s.front() == '.' || _s.back() == '.'; @@ -55,16 +55,17 @@ void yul::removeEmptyBlocks(Block& _block) ranges::actions::remove_if(_block.statements, isEmptyBlock); } -bool yul::isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifier) +bool yul::isRestrictedIdentifier(Dialect const& /*_dialect*/, YulString const& /*_identifier*/) { - return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier); + //return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier); + return false; //todo } -std::optional yul::toEVMInstruction(Dialect const& _dialect, YulString const& _name) +std::optional yul::toEVMInstruction(YulNameRepository const& _yulNameRepository, YulName const& _name) { - if (auto const* dialect = dynamic_cast(&_dialect)) - if (BuiltinFunctionForEVM const* builtin = dialect->builtin(_name)) - return builtin->instruction; + if (_yulNameRepository.isEvmDialect()) + if (auto const* builtin = _yulNameRepository.builtin(_name)) + return dynamic_cast(builtin->data)->instruction; return std::nullopt; } diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index cb07f7a53006..8c260cb560b6 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -48,7 +48,7 @@ void removeEmptyBlocks(Block& _block); bool isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifier); /// Helper function that returns the instruction, if the `_name` is a BuiltinFunction -std::optional toEVMInstruction(Dialect const& _dialect, YulString const& _name); +std::optional toEVMInstruction(YulNameRepository const& _yulNameRepository, YulName const& _name); /// Helper function that returns the EVM version from a dialect. /// It returns the default EVM version if dialect is not an EVMDialect. diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index db6920f2439b..d37192f3883b 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -31,18 +31,18 @@ using namespace solidity; using namespace solidity::yul; -void Rematerialiser::run(Dialect const& _dialect, Block& _ast, std::set _varsToAlwaysRematerialize, bool _onlySelectedVariables) +void Rematerialiser::run(YulNameRepository const& _yulNameRepository, Block& _ast, std::set _varsToAlwaysRematerialize, bool _onlySelectedVariables) { - Rematerialiser{_dialect, _ast, std::move(_varsToAlwaysRematerialize), _onlySelectedVariables}(_ast); + Rematerialiser{_yulNameRepository, _ast, std::move(_varsToAlwaysRematerialize), _onlySelectedVariables}(_ast); } Rematerialiser::Rematerialiser( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, - std::set _varsToAlwaysRematerialize, + std::set _varsToAlwaysRematerialize, bool _onlySelectedVariables ): - DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore), + DataFlowAnalyzer(_yulNameRepository, MemoryAndStorage::Ignore), m_referenceCounts(VariableReferencesCounter::countReferences(_ast)), m_varsToAlwaysRematerialize(std::move(_varsToAlwaysRematerialize)), m_onlySelectedVariables(_onlySelectedVariables) @@ -54,12 +54,12 @@ void Rematerialiser::visit(Expression& _e) if (std::holds_alternative(_e)) { Identifier& identifier = std::get(_e); - YulString name = identifier.name; + YulName name = identifier.name; if (AssignedValue const* value = variableValue(name)) { assertThrow(value->value, OptimizerException, ""); size_t refs = m_referenceCounts[name]; - size_t cost = CodeCost::codeCost(m_dialect, *value->value); + size_t cost = CodeCost::codeCost(m_yulNameRepository, *value->value); if ( ( !m_onlySelectedVariables && ( @@ -93,7 +93,7 @@ void LiteralRematerialiser::visit(Expression& _e) if (std::holds_alternative(_e)) { Identifier& identifier = std::get(_e); - YulString name = identifier.name; + YulName name = identifier.name; if (AssignedValue const* value = variableValue(name)) { assertThrow(value->value, OptimizerException, ""); diff --git a/libyul/optimiser/Rematerialiser.h b/libyul/optimiser/Rematerialiser.h index 9ee5209fdfeb..816a8089cf36 100644 --- a/libyul/optimiser/Rematerialiser.h +++ b/libyul/optimiser/Rematerialiser.h @@ -45,20 +45,20 @@ class Rematerialiser: public DataFlowAnalyzer static void run( OptimiserStepContext& _context, Block& _ast - ) { run(_context.dialect, _ast); } + ) { run(_context.yulNameRepository, _ast); } static void run( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, - std::set _varsToAlwaysRematerialize = {}, + std::set _varsToAlwaysRematerialize = {}, bool _onlySelectedVariables = false ); protected: Rematerialiser( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, - std::set _varsToAlwaysRematerialize = {}, + std::set _varsToAlwaysRematerialize = {}, bool _onlySelectedVariables = false ); @@ -67,8 +67,8 @@ class Rematerialiser: public DataFlowAnalyzer using ASTModifier::visit; void visit(Expression& _e) override; - std::map m_referenceCounts; - std::set m_varsToAlwaysRematerialize; + std::map m_referenceCounts; + std::set m_varsToAlwaysRematerialize; bool m_onlySelectedVariables = false; }; @@ -88,14 +88,14 @@ class LiteralRematerialiser: public DataFlowAnalyzer static void run( OptimiserStepContext& _context, Block& _ast - ) { LiteralRematerialiser{_context.dialect}(_ast); } + ) { LiteralRematerialiser{_context.yulNameRepository}(_ast); } using ASTModifier::visit; void visit(Expression& _e) override; private: - LiteralRematerialiser(Dialect const& _dialect): - DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore) + LiteralRematerialiser(YulNameRepository const& _yulNameRepository): + DataFlowAnalyzer(_yulNameRepository, MemoryAndStorage::Ignore) {} }; diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index dba2f6f04610..a4f491e2ec6e 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -45,21 +44,21 @@ class IntroduceSSA: public ASTModifier { public: explicit IntroduceSSA( - NameDispenser& _nameDispenser, - std::set const& _variablesToReplace, - TypeInfo& _typeInfo + std::set const& _variablesToReplace, + TypeInfo& _typeInfo, + YulNameRepository& _yulNameRepository ): - m_nameDispenser(_nameDispenser), m_variablesToReplace(_variablesToReplace), - m_typeInfo(_typeInfo) + m_typeInfo(_typeInfo), + m_yulNameRepository(_yulNameRepository) { } void operator()(Block& _block) override; private: - NameDispenser& m_nameDispenser; - std::set const& m_variablesToReplace; + std::set const& m_variablesToReplace; TypeInfo const& m_typeInfo; + YulNameRepository& m_yulNameRepository; }; @@ -90,8 +89,8 @@ void IntroduceSSA::operator()(Block& _block) TypedNameList newVariables; for (auto const& var: varDecl.variables) { - YulString oldName = var.name; - YulString newName = m_nameDispenser.newName(oldName); + auto oldName = var.name; + auto newName = m_yulNameRepository.deriveName(oldName); newVariables.emplace_back(TypedName{debugData, newName, var.type}); statements.emplace_back(VariableDeclaration{ debugData, @@ -117,8 +116,8 @@ void IntroduceSSA::operator()(Block& _block) TypedNameList newVariables; for (auto const& var: assignment.variableNames) { - YulString oldName = var.name; - YulString newName = m_nameDispenser.newName(oldName); + auto oldName = var.name; + auto newName = m_yulNameRepository.deriveName(oldName); newVariables.emplace_back(TypedName{debugData, newName, m_typeInfo.typeOfVariable(oldName) @@ -147,13 +146,13 @@ class IntroduceControlFlowSSA: public ASTModifier { public: explicit IntroduceControlFlowSSA( - NameDispenser& _nameDispenser, - std::set const& _variablesToReplace, - TypeInfo const& _typeInfo + std::set const& _variablesToReplace, + TypeInfo const& _typeInfo, + YulNameRepository& _yulNameRepository ): - m_nameDispenser(_nameDispenser), m_variablesToReplace(_variablesToReplace), - m_typeInfo(_typeInfo) + m_typeInfo(_typeInfo), + m_yulNameRepository(_yulNameRepository) { } void operator()(FunctionDefinition& _function) override; @@ -162,20 +161,20 @@ class IntroduceControlFlowSSA: public ASTModifier void operator()(Block& _block) override; private: - NameDispenser& m_nameDispenser; - std::set const& m_variablesToReplace; + std::set const& m_variablesToReplace; /// Variables (that are to be replaced) currently in scope. - std::set m_variablesInScope; + std::set m_variablesInScope; /// Variables that do not have a specific value. - util::UniqueVector m_variablesToReassign; + util::UniqueVector m_variablesToReassign; TypeInfo const& m_typeInfo; + YulNameRepository& m_yulNameRepository; }; void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function) { - std::set varsInScope; + std::set varsInScope; std::swap(varsInScope, m_variablesInScope); - util::UniqueVector toReassign; + util::UniqueVector toReassign; std::swap(toReassign, m_variablesToReassign); for (auto const& param: _function.parameters) @@ -207,7 +206,7 @@ void IntroduceControlFlowSSA::operator()(Switch& _switch) { yulAssert(m_variablesToReassign.empty(), ""); - util::UniqueVector toReassign; + util::UniqueVector toReassign; for (auto& c: _switch.cases) { (*this)(c.body); @@ -219,17 +218,17 @@ void IntroduceControlFlowSSA::operator()(Switch& _switch) void IntroduceControlFlowSSA::operator()(Block& _block) { - util::UniqueVector variablesDeclaredHere; - util::UniqueVector assignedVariables; + util::UniqueVector variablesDeclaredHere; + util::UniqueVector assignedVariables; util::iterateReplacing( _block.statements, [&](Statement& _s) -> std::optional> { std::vector toPrepend; - for (YulString toReassign: m_variablesToReassign) + for (YulName toReassign: m_variablesToReassign) { - YulString newName = m_nameDispenser.newName(toReassign); + YulName newName = m_yulNameRepository.deriveName(toReassign); toPrepend.emplace_back(VariableDeclaration{ debugDataOf(_s), {TypedName{debugDataOf(_s), newName, m_typeInfo.typeOfVariable(toReassign)}}, @@ -281,7 +280,7 @@ void IntroduceControlFlowSSA::operator()(Block& _block) class PropagateValues: public ASTModifier { public: - explicit PropagateValues(std::set const& _variablesToReplace): + explicit PropagateValues(std::set const& _variablesToReplace): m_variablesToReplace(_variablesToReplace) { } @@ -294,9 +293,9 @@ class PropagateValues: public ASTModifier private: /// This is a set of all variables that are assigned to anywhere in the code. /// Variables that are only declared but never re-assigned are not touched. - std::set const& m_variablesToReplace; - std::map m_currentVariableValues; - std::set m_clearAtEndOfBlock; + std::set const& m_variablesToReplace; + std::map m_currentVariableValues; + std::set m_clearAtEndOfBlock; }; void PropagateValues::operator()(Identifier& _identifier) @@ -312,7 +311,7 @@ void PropagateValues::operator()(VariableDeclaration& _varDecl) if (_varDecl.variables.size() != 1) return; - YulString variable = _varDecl.variables.front().name; + YulName variable = _varDecl.variables.front().name; if (m_variablesToReplace.count(variable)) { // `let a := a_1` - regular declaration of non-SSA variable @@ -323,7 +322,7 @@ void PropagateValues::operator()(VariableDeclaration& _varDecl) else if (_varDecl.value && std::holds_alternative(*_varDecl.value)) { // `let a_1 := a` - assignment to SSA variable after a branch. - YulString value = std::get(*_varDecl.value).name; + YulName value = std::get(*_varDecl.value).name; if (m_variablesToReplace.count(value)) { // This is safe because `a_1` is not a "variable to replace" and thus @@ -341,7 +340,7 @@ void PropagateValues::operator()(Assignment& _assignment) if (_assignment.variableNames.size() != 1) return; - YulString name = _assignment.variableNames.front().name; + YulName name = _assignment.variableNames.front().name; if (!m_variablesToReplace.count(name)) return; @@ -364,7 +363,7 @@ void PropagateValues::operator()(ForLoop& _for) void PropagateValues::operator()(Block& _block) { - std::set clearAtParentBlock = std::move(m_clearAtEndOfBlock); + std::set clearAtParentBlock = std::move(m_clearAtEndOfBlock); m_clearAtEndOfBlock.clear(); ASTModifier::operator()(_block); @@ -379,10 +378,10 @@ void PropagateValues::operator()(Block& _block) void SSATransform::run(OptimiserStepContext& _context, Block& _ast) { - TypeInfo typeInfo(_context.dialect, _ast); - std::set assignedVariables = assignedVariableNames(_ast); - IntroduceSSA{_context.dispenser, assignedVariables, typeInfo}(_ast); - IntroduceControlFlowSSA{_context.dispenser, assignedVariables, typeInfo}(_ast); + TypeInfo typeInfo(_context.yulNameRepository, _ast); + std::set assignedVariables = assignedVariableNames(_ast); + IntroduceSSA{assignedVariables, typeInfo, _context.yulNameRepository}(_ast); + IntroduceControlFlowSSA{assignedVariables, typeInfo, _context.yulNameRepository}(_ast); PropagateValues{assignedVariables}(_ast); } diff --git a/libyul/optimiser/SSATransform.h b/libyul/optimiser/SSATransform.h index 64181bf208d3..24b356debc8f 100644 --- a/libyul/optimiser/SSATransform.h +++ b/libyul/optimiser/SSATransform.h @@ -32,8 +32,6 @@ namespace solidity::yul { -class NameDispenser; - /** * Optimizer stage that tries to replace repeated assignments to * existing variables by declarations of new variables as much as diff --git a/libyul/optimiser/SSAValueTracker.cpp b/libyul/optimiser/SSAValueTracker.cpp index 1d25cb54b514..d39ce4b8d263 100644 --- a/libyul/optimiser/SSAValueTracker.cpp +++ b/libyul/optimiser/SSAValueTracker.cpp @@ -49,17 +49,17 @@ void SSAValueTracker::operator()(VariableDeclaration const& _varDecl) setValue(_varDecl.variables.front().name, _varDecl.value.get()); } -std::set SSAValueTracker::ssaVariables(Block const& _ast) +std::set SSAValueTracker::ssaVariables(Block const& _ast) { SSAValueTracker t; t(_ast); - std::set ssaVars; + std::set ssaVars; for (auto const& value: t.values()) ssaVars.insert(value.first); return ssaVars; } -void SSAValueTracker::setValue(YulString _name, Expression const* _value) +void SSAValueTracker::setValue(YulName _name, Expression const* _value) { assertThrow( m_values.count(_name) == 0, diff --git a/libyul/optimiser/SSAValueTracker.h b/libyul/optimiser/SSAValueTracker.h index 5a7eee5124b4..4d644b3f499c 100644 --- a/libyul/optimiser/SSAValueTracker.h +++ b/libyul/optimiser/SSAValueTracker.h @@ -47,18 +47,18 @@ class SSAValueTracker: public ASTWalker void operator()(VariableDeclaration const& _varDecl) override; void operator()(Assignment const& _assignment) override; - std::map const& values() const { return m_values; } - Expression const* value(YulString _name) const { return m_values.at(_name); } + std::map const& values() const { return m_values; } + Expression const* value(YulName _name) const { return m_values.at(_name); } - static std::set ssaVariables(Block const& _ast); + static std::set ssaVariables(Block const& _ast); private: - void setValue(YulString _name, Expression const* _value); + void setValue(YulName _name, Expression const* _value); /// Special expression whose address will be used in m_values. /// YulString does not need to be reset because SSAValueTracker is short-lived. Expression const m_zero{Literal{{}, LiteralKind::Number, LiteralValue(u256{0}), {}}}; - std::map m_values; + std::map m_values; }; } diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index 5d375b1454cb..f204d593a457 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -38,37 +38,37 @@ using namespace solidity::yul; SideEffectsCollector::SideEffectsCollector( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Expression const& _expression, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): - SideEffectsCollector(_dialect, _functionSideEffects) + SideEffectsCollector(_yulNameRepository, _functionSideEffects) { visit(_expression); } -SideEffectsCollector::SideEffectsCollector(Dialect const& _dialect, Statement const& _statement): - SideEffectsCollector(_dialect) +SideEffectsCollector::SideEffectsCollector(YulNameRepository const& _yulNameRepository, Statement const& _statement): + SideEffectsCollector(_yulNameRepository) { visit(_statement); } SideEffectsCollector::SideEffectsCollector( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block const& _ast, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): - SideEffectsCollector(_dialect, _functionSideEffects) + SideEffectsCollector(_yulNameRepository, _functionSideEffects) { operator()(_ast); } SideEffectsCollector::SideEffectsCollector( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, ForLoop const& _ast, - std::map const* _functionSideEffects + std::map const* _functionSideEffects ): - SideEffectsCollector(_dialect, _functionSideEffects) + SideEffectsCollector(_yulNameRepository, _functionSideEffects) { operator()(_ast); } @@ -77,30 +77,30 @@ void SideEffectsCollector::operator()(FunctionCall const& _functionCall) { ASTWalker::operator()(_functionCall); - YulString functionName = _functionCall.functionName.name; - if (BuiltinFunction const* f = m_dialect.builtin(functionName)) - m_sideEffects += f->sideEffects; + YulName functionName = _functionCall.functionName.name; + if (auto const* f = m_yulNameRepository.builtin(functionName)) + m_sideEffects += f->data->sideEffects; else if (m_functionSideEffects && m_functionSideEffects->count(functionName)) m_sideEffects += m_functionSideEffects->at(functionName); else m_sideEffects += SideEffects::worst(); } -bool MSizeFinder::containsMSize(Dialect const& _dialect, Block const& _ast) +bool MSizeFinder::containsMSize(YulNameRepository const& _yulNameRepository, Block const& _ast) { - MSizeFinder finder(_dialect); + MSizeFinder finder(_yulNameRepository); finder(_ast); return finder.m_msizeFound; } -bool MSizeFinder::containsMSize(Dialect const& _dialect, Object const& _object) +bool MSizeFinder::containsMSize(YulNameRepository const& _yulNameRepository, Object const& _object) { - if (containsMSize(_dialect, *_object.code)) + if (containsMSize(_yulNameRepository, *_object.code)) return true; for (std::shared_ptr const& node: _object.subObjects) if (auto const* object = dynamic_cast(node.get())) - if (containsMSize(_dialect, *object)) + if (containsMSize(_yulNameRepository, *object)) return true; return false; @@ -110,13 +110,13 @@ void MSizeFinder::operator()(FunctionCall const& _functionCall) { ASTWalker::operator()(_functionCall); - if (BuiltinFunction const* f = m_dialect.builtin(_functionCall.functionName.name)) - if (f->isMSize) + if (auto const* f = m_yulNameRepository.builtin(_functionCall.functionName.name)) + if (f->data->isMSize) m_msizeFound = true; } -std::map SideEffectsPropagator::sideEffects( - Dialect const& _dialect, +std::map SideEffectsPropagator::sideEffects( + YulNameRepository const& _yulNameRepository, CallGraph const& _directCallGraph ) { @@ -126,7 +126,7 @@ std::map SideEffectsPropagator::sideEffects( // In the future, we should refine that, because the property // is actually a bit different from "not movable". - std::map ret; + std::map ret; for (auto const& function: _directCallGraph.functionsWithLoops + _directCallGraph.recursiveFunctions()) { ret[function].movable = false; @@ -137,20 +137,20 @@ std::map SideEffectsPropagator::sideEffects( for (auto const& call: _directCallGraph.functionCalls) { - YulString funName = call.first; + YulName funName = call.first; SideEffects sideEffects; - auto _visit = [&, visited = std::set{}](YulString _function, auto&& _recurse) mutable { + auto _visit = [&, visited = std::set{}](YulName _function, auto&& _recurse) mutable { if (!visited.insert(_function).second) return; if (sideEffects == SideEffects::worst()) return; - if (BuiltinFunction const* f = _dialect.builtin(_function)) - sideEffects += f->sideEffects; + if (auto const* f = _yulNameRepository.builtin(_function)) + sideEffects += f->data->sideEffects; else { if (ret.count(_function)) sideEffects += ret[_function]; - for (YulString callee: _directCallGraph.functionCalls.at(_function)) + for (YulName callee: _directCallGraph.functionCalls.at(_function)) _recurse(callee, _recurse); } }; @@ -161,8 +161,8 @@ std::map SideEffectsPropagator::sideEffects( return ret; } -MovableChecker::MovableChecker(Dialect const& _dialect, Expression const& _expression): - MovableChecker(_dialect) +MovableChecker::MovableChecker(YulNameRepository const& _yulNameRepository, Expression const& _expression): + MovableChecker(_yulNameRepository) { visit(_expression); } @@ -227,8 +227,8 @@ bool TerminationFinder::containsNonContinuingFunctionCall(Expression const& _exp if (containsNonContinuingFunctionCall(arg)) return true; - if (auto builtin = m_dialect.builtin(functionCall->functionName.name)) - return !builtin->controlFlowSideEffects.canContinue; + if (auto builtin = m_yulNameRepository.builtin(functionCall->functionName.name)) + return !builtin->data->controlFlowSideEffects.canContinue; else if (m_functionSideEffects && m_functionSideEffects->count(functionCall->functionName.name)) return !m_functionSideEffects->at(functionCall->functionName.name).canContinue; } diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index df8ae17a58e1..a7e2649da9ff 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -41,24 +41,24 @@ class SideEffectsCollector: public ASTWalker { public: explicit SideEffectsCollector( - Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr - ): m_dialect(_dialect), m_functionSideEffects(_functionSideEffects) {} + YulNameRepository const& _yulNameRepository, + std::map const* _functionSideEffects = nullptr + ): m_yulNameRepository(_yulNameRepository), m_functionSideEffects(_functionSideEffects) {} SideEffectsCollector( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Expression const& _expression, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); - SideEffectsCollector(Dialect const& _dialect, Statement const& _statement); + SideEffectsCollector(YulNameRepository const& _yulNameRepository, Statement const& _statement); SideEffectsCollector( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block const& _ast, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); SideEffectsCollector( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, ForLoop const& _ast, - std::map const* _functionSideEffects = nullptr + std::map const* _functionSideEffects = nullptr ); using ASTWalker::operator(); @@ -116,8 +116,8 @@ class SideEffectsCollector: public ASTWalker SideEffects sideEffects() { return m_sideEffects; } private: - Dialect const& m_dialect; - std::map const* m_functionSideEffects = nullptr; + YulNameRepository const& m_yulNameRepository; + std::map const* m_functionSideEffects = nullptr; SideEffects m_sideEffects; }; @@ -130,8 +130,8 @@ class SideEffectsCollector: public ASTWalker class SideEffectsPropagator { public: - static std::map sideEffects( - Dialect const& _dialect, + static std::map sideEffects( + YulNameRepository const& _yulNameRepository, CallGraph const& _directCallGraph ); }; @@ -148,15 +148,15 @@ class SideEffectsPropagator class MSizeFinder: public ASTWalker { public: - static bool containsMSize(Dialect const& _dialect, Block const& _ast); - static bool containsMSize(Dialect const& _dialect, Object const& _object); + static bool containsMSize(YulNameRepository const& _yulNameRepository, Block const& _ast); + static bool containsMSize(YulNameRepository const& _yulNameRepository, Object const& _object); using ASTWalker::operator(); void operator()(FunctionCall const& _funCall) override; private: - MSizeFinder(Dialect const& _dialect): m_dialect(_dialect) {} - Dialect const& m_dialect; + MSizeFinder(YulNameRepository const& _yulNameRepository): m_yulNameRepository(_yulNameRepository) {} + YulNameRepository const& m_yulNameRepository; bool m_msizeFound = false; }; @@ -194,10 +194,10 @@ class MovableChecker: public SideEffectsCollector { public: explicit MovableChecker( - Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr - ): SideEffectsCollector(_dialect, _functionSideEffects) {} - MovableChecker(Dialect const& _dialect, Expression const& _expression); + YulNameRepository const& _yulNameRepository, + std::map const* _functionSideEffects = nullptr + ): SideEffectsCollector(_yulNameRepository, _functionSideEffects) {} + MovableChecker(YulNameRepository const& _yulNameRepository, Expression const& _expression); void operator()(Identifier const& _identifier) override; @@ -205,11 +205,11 @@ class MovableChecker: public SideEffectsCollector void visit(Statement const&) override; using ASTWalker::visit; - std::set const& referencedVariables() const { return m_variableReferences; } + std::set const& referencedVariables() const { return m_variableReferences; } private: /// Which variables the current expression references. - std::set m_variableReferences; + std::set m_variableReferences; }; struct ControlFlowSideEffects; @@ -230,9 +230,9 @@ class TerminationFinder enum class ControlFlow { FlowOut, Break, Continue, Terminate, Leave }; TerminationFinder( - Dialect const& _dialect, - std::map const* _functionSideEffects = nullptr - ): m_dialect(_dialect), m_functionSideEffects(_functionSideEffects) {} + YulNameRepository const& _yulNameRepository, + std::map const* _functionSideEffects = nullptr + ): m_yulNameRepository(_yulNameRepository), m_functionSideEffects(_functionSideEffects) {} /// @returns the index of the first statement in the provided sequence /// that is an unconditional ``break``, ``continue``, ``leave`` or a @@ -255,8 +255,8 @@ class TerminationFinder bool containsNonContinuingFunctionCall(Expression const& _expr); private: - Dialect const& m_dialect; - std::map const* m_functionSideEffects; + YulNameRepository const& m_yulNameRepository; + std::map const* m_functionSideEffects; }; } diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index e2d46832906e..a0054dab5f16 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -39,18 +39,18 @@ using namespace solidity::yul; SimplificationRules::Rule const* SimplificationRules::findFirstMatch( Expression const& _expr, - Dialect const& _dialect, - std::function const& _ssaValues + YulNameRepository const& _yulNameRepository, + std::function const& _ssaValues ) { - auto instruction = instructionAndArguments(_dialect, _expr); + auto instruction = instructionAndArguments(_yulNameRepository, _expr); if (!instruction) return nullptr; static std::map, std::unique_ptr> evmRules; std::optional version; - if (yul::EVMDialect const* evmDialect = dynamic_cast(&_dialect)) + if (yul::EVMDialect const* evmDialect = dynamic_cast(&_yulNameRepository.dialect())) version = evmDialect->evmVersion(); if (!evmRules[version]) @@ -62,7 +62,7 @@ SimplificationRules::Rule const* SimplificationRules::findFirstMatch( for (auto const& rule: rules.m_rules[uint8_t(instruction->first)]) { rules.resetMatchGroups(); - if (rule.pattern.matches(_expr, _dialect, _ssaValues)) + if (rule.pattern.matches(_expr, _yulNameRepository, _ssaValues)) if (!rule.feasible || rule.feasible()) return &rule; } @@ -75,13 +75,13 @@ bool SimplificationRules::isInitialized() const } std::optional const*>> - SimplificationRules::instructionAndArguments(Dialect const& _dialect, Expression const& _expr) + SimplificationRules::instructionAndArguments(YulNameRepository const& _yulNameRepository, Expression const& _expr) { if (std::holds_alternative(_expr)) - if (auto const* dialect = dynamic_cast(&_dialect)) - if (auto const* builtin = dialect->builtin(std::get(_expr).functionName.name)) - if (builtin->instruction) - return std::make_pair(*builtin->instruction, &std::get(_expr).arguments); + if (_yulNameRepository.isEvmDialect()) + if (auto const* builtin = _yulNameRepository.builtin(std::get(_expr).functionName.name)) + if (auto const* builtinEVM = dynamic_cast(builtin->data); builtinEVM->instruction) + return std::make_pair(*builtinEVM->instruction, &std::get(_expr).arguments); return {}; } @@ -136,8 +136,8 @@ void Pattern::setMatchGroup(unsigned _group, std::map const& _ssaValues + YulNameRepository const& _yulNameRepository, + std::function const& _ssaValues ) const { Expression const* expr = &_expr; @@ -146,7 +146,7 @@ bool Pattern::matches( // Do not do it for "Any" because we can check identity better for variables. if (m_kind != PatternKind::Any && std::holds_alternative(_expr)) { - YulString varName = std::get(_expr).name; + YulName varName = std::get(_expr).name; if (AssignedValue const* value = _ssaValues(varName)) if (Expression const* new_expr = value->value) expr = new_expr; @@ -166,7 +166,7 @@ bool Pattern::matches( } else if (m_kind == PatternKind::Operation) { - auto instrAndArgs = SimplificationRules::instructionAndArguments(_dialect, *expr); + auto instrAndArgs = SimplificationRules::instructionAndArguments(_yulNameRepository, *expr); if (!instrAndArgs || m_instruction != instrAndArgs->first) return false; assertThrow(m_arguments.size() == instrAndArgs->second->size(), OptimizerException, ""); @@ -178,7 +178,7 @@ bool Pattern::matches( // arbitrarily modifying the code. if ( std::holds_alternative(arg) || - !m_arguments[i].matches(arg, _dialect, _ssaValues) + !m_arguments[i].matches(arg, _yulNameRepository, _ssaValues) ) return false; } @@ -234,7 +234,7 @@ evmasm::Instruction Pattern::instruction() const return m_instruction; } -Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const +Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion, YulNameRepository const& _yulNameRepository) const { if (matchGroup()) return ASTCopier().translate(matchGroupValue()); @@ -247,12 +247,12 @@ Expression Pattern::toExpression(langutil::DebugData::ConstPtr const& _debugData { std::vector arguments; for (auto const& arg: m_arguments) - arguments.emplace_back(arg.toExpression(_debugData, _evmVersion)); + arguments.emplace_back(arg.toExpression(_debugData, _evmVersion, _yulNameRepository)); - std::string name = util::toLower(instructionInfo(m_instruction, _evmVersion).name); + auto const name = util::toLower(instructionInfo(m_instruction, _evmVersion).name); return FunctionCall{_debugData, - Identifier{_debugData, YulString{name}}, + Identifier{_debugData, _yulNameRepository.nameOfBuiltin(name)}, std::move(arguments) }; } diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index 5e498bd5c9a4..75bbcd8cfc29 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -63,8 +63,8 @@ class SimplificationRules /// @param _ssaValues values of variables that are assigned exactly once. static Rule const* findFirstMatch( Expression const& _expr, - Dialect const& _dialect, - std::function const& _ssaValues + YulNameRepository const& _yulNameRepository, + std::function const& _ssaValues ); /// Checks whether the rulelist is non-empty. This is usually enforced @@ -72,7 +72,7 @@ class SimplificationRules bool isInitialized() const; static std::optional const*>> - instructionAndArguments(Dialect const& _dialect, Expression const& _expr); + instructionAndArguments(YulNameRepository const& _yulNameRepository, Expression const& _expr); private: void addRules(std::vector const& _rules); @@ -120,8 +120,8 @@ class Pattern unsigned matchGroup() const { return m_matchGroup; } bool matches( Expression const& _expr, - Dialect const& _dialect, - std::function const& _ssaValues + YulNameRepository const& _yulNameRepository, + std::function const& _ssaValues ) const; std::vector arguments() const { return m_arguments; } @@ -133,7 +133,7 @@ class Pattern /// Turns this pattern into an actual expression. Should only be called /// for patterns resulting from an action, i.e. with match groups assigned. - Expression toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion) const; + Expression toExpression(langutil::DebugData::ConstPtr const& _debugData, langutil::EVMVersion _evmVersion, YulNameRepository const& _yulNameRepository) const; private: Expression const& matchGroupValue() const; diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 58552147a608..a38522672a0c 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -55,14 +55,14 @@ namespace class RematCandidateSelector: public DataFlowAnalyzer { public: - explicit RematCandidateSelector(Dialect const& _dialect): DataFlowAnalyzer(_dialect, MemoryAndStorage::Ignore) {} + explicit RematCandidateSelector(YulNameRepository const& _yulNameRepository): DataFlowAnalyzer(_yulNameRepository, MemoryAndStorage::Ignore) {} /// @returns a map from function name to rematerialisation costs to a vector of variables to rematerialise /// and variables that occur in their expression. /// While the map is sorted by cost, the contained vectors are sorted by the order of occurrence. - std::map>> candidates() + std::map>> candidates() { - std::map>> cand; + std::map>> cand; for (auto const& [functionName, candidate]: m_candidates) { if (size_t const* cost = util::valueOrNullptr(m_expressionCodeCost, candidate)) @@ -77,7 +77,7 @@ class RematCandidateSelector: public DataFlowAnalyzer using DataFlowAnalyzer::operator(); void operator()(FunctionDefinition& _function) override { - yulAssert(m_currentFunctionName.empty()); + yulAssert(m_currentFunctionName == YulNameRepository::emptyName()); m_currentFunctionName = _function.name; DataFlowAnalyzer::operator()(_function); m_currentFunctionName = {}; @@ -88,12 +88,12 @@ class RematCandidateSelector: public DataFlowAnalyzer DataFlowAnalyzer::operator()(_varDecl); if (_varDecl.variables.size() == 1) { - YulString varName = _varDecl.variables.front().name; + YulName varName = _varDecl.variables.front().name; if (AssignedValue const* value = variableValue(varName)) { yulAssert(!m_expressionCodeCost.count(varName), ""); m_candidates.emplace_back(m_currentFunctionName, varName); - m_expressionCodeCost[varName] = CodeCost::codeCost(m_dialect, *value->value); + m_expressionCodeCost[varName] = CodeCost::codeCost(m_yulNameRepository, *value->value); } } } @@ -111,7 +111,7 @@ class RematCandidateSelector: public DataFlowAnalyzer { if (std::holds_alternative(_e)) { - YulString name = std::get(_e).name; + YulName name = std::get(_e).name; if (m_expressionCodeCost.count(name)) { if (!variableValue(name)) @@ -124,29 +124,29 @@ class RematCandidateSelector: public DataFlowAnalyzer } /// Remove the variable from the candidate set. - void rematImpossible(YulString _variable) + void rematImpossible(YulName _variable) { m_numReferences.erase(_variable); m_expressionCodeCost.erase(_variable); } - YulString m_currentFunctionName = {}; + YulName m_currentFunctionName = {}; /// All candidate variables by function name, in order of occurrence. - std::vector> m_candidates; + std::vector> m_candidates; /// Candidate variables and the code cost of their value. - std::map m_expressionCodeCost; + std::map m_expressionCodeCost; /// Number of references to each candidate variable. - std::map m_numReferences; + std::map m_numReferences; }; /// Selects at most @a _numVariables among @a _candidates. -std::set chooseVarsToEliminate( - std::map> const& _candidates, +std::set chooseVarsToEliminate( + std::map> const& _candidates, size_t _numVariables ) { - std::set varsToEliminate; + std::set varsToEliminate; for (auto&& [cost, candidates]: _candidates) for (auto&& candidate: candidates) { @@ -158,55 +158,55 @@ std::set chooseVarsToEliminate( } void eliminateVariables( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, - std::map const& _numVariables, + std::map const& _numVariables, bool _allowMSizeOptimization ) { - RematCandidateSelector selector{_dialect}; + RematCandidateSelector selector{_yulNameRepository}; selector(_ast); - std::map>> candidates = selector.candidates(); + std::map>> candidates = selector.candidates(); - std::set varsToEliminate; + std::set varsToEliminate; for (auto const& [functionName, numVariables]: _numVariables) { yulAssert(numVariables > 0); varsToEliminate += chooseVarsToEliminate(candidates[functionName], static_cast(numVariables)); } - Rematerialiser::run(_dialect, _ast, std::move(varsToEliminate)); + Rematerialiser::run(_yulNameRepository, _ast, std::move(varsToEliminate)); // Do not remove functions. - std::set allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); - UnusedPruner::runUntilStabilised(_dialect, _ast, _allowMSizeOptimization, nullptr, allFunctions); + std::set allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); + UnusedPruner::runUntilStabilised(_yulNameRepository, _ast, _allowMSizeOptimization, nullptr, allFunctions); } void eliminateVariablesOptimizedCodegen( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, - std::map> const& _unreachables, + std::map> const& _unreachables, bool _allowMSizeOptimization ) { if (std::all_of(_unreachables.begin(), _unreachables.end(), [](auto const& _item) { return _item.second.empty(); })) return; - RematCandidateSelector selector{_dialect}; + RematCandidateSelector selector{_yulNameRepository}; selector(_ast); - std::map candidates; + std::map candidates; for (auto const& [functionName, candidatesInFunction]: selector.candidates()) for (auto [cost, candidatesWithCost]: candidatesInFunction) for (auto candidate: candidatesWithCost) candidates[candidate] = cost; - std::set varsToEliminate; + std::set varsToEliminate; // TODO: this currently ignores the fact that variables may reference other variables we want to eliminate. for (auto const& [functionName, unreachables]: _unreachables) for (auto const& unreachable: unreachables) { - std::map> suitableCandidates; + std::map> suitableCandidates; size_t neededSlots = unreachable.deficit; for (auto varName: unreachable.variableChoices) { @@ -227,16 +227,16 @@ void eliminateVariablesOptimizedCodegen( break; } } - Rematerialiser::run(_dialect, _ast, std::move(varsToEliminate), true); + Rematerialiser::run(_yulNameRepository, _ast, std::move(varsToEliminate), true); // Do not remove functions. - std::set allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); - UnusedPruner::runUntilStabilised(_dialect, _ast, _allowMSizeOptimization, nullptr, allFunctions); + std::set allFunctions = NameCollector{_ast, NameCollector::OnlyFunctions}.names(); + UnusedPruner::runUntilStabilised(_yulNameRepository, _ast, _allowMSizeOptimization, nullptr, allFunctions); } } bool StackCompressor::run( - Dialect const& _dialect, + YulNameRepository& _yulNameRepository, Object& _object, bool _optimizeStackAllocation, size_t _maxIterations @@ -248,36 +248,34 @@ bool StackCompressor::run( "Need to run the function grouper before the stack compressor." ); bool usesOptimizedCodeGenerator = false; - if (auto evmDialect = dynamic_cast(&_dialect)) + if (auto evmDialect = dynamic_cast(&_yulNameRepository.dialect())) usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, *_object.code); + bool allowMSizeOptimization = !MSizeFinder::containsMSize(_yulNameRepository, *_object.code); + _yulNameRepository.generateLabels(*_object.code); if (usesOptimizedCodeGenerator) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _dialect, *_object.code); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_yulNameRepository, _object); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _yulNameRepository, *_object.code); eliminateVariablesOptimizedCodegen( - _dialect, + _yulNameRepository, *_object.code, StackLayoutGenerator::reportStackTooDeep(*cfg), allowMSizeOptimization ); } else + { for (size_t iterations = 0; iterations < _maxIterations; iterations++) { - std::map stackSurplus = CompilabilityChecker(_dialect, _object, _optimizeStackAllocation).stackDeficit; + std::map stackSurplus = CompilabilityChecker(_yulNameRepository, _object, _optimizeStackAllocation).stackDeficit; if (stackSurplus.empty()) return true; - eliminateVariables( - _dialect, - *_object.code, - stackSurplus, - allowMSizeOptimization - ); + eliminateVariables(_yulNameRepository, *_object.code, stackSurplus, allowMSizeOptimization); } + } return false; } diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index d18618667f71..deb327bce6be 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -47,7 +47,7 @@ class StackCompressor /// Try to remove local variables until the AST is compilable. /// @returns true if it was successful. static bool run( - Dialect const& _dialect, + YulNameRepository& _yulNameRepository, Object& _object, bool _optimizeStackAllocation, size_t _maxIterations diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 904ee77e00f9..1b69d932821d 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -56,7 +55,7 @@ namespace */ struct MemoryOffsetAllocator { - uint64_t run(YulString _function = YulString{}) + uint64_t run(YulName _function = YulNameRepository::emptyName()) { if (slotsRequiredForFunction.count(_function)) return slotsRequiredForFunction[_function]; @@ -66,7 +65,7 @@ struct MemoryOffsetAllocator uint64_t requiredSlots = 0; if (callGraph.count(_function)) - for (YulString child: callGraph.at(_function)) + for (YulName child: callGraph.at(_function)) requiredSlots = std::max(run(child), requiredSlots); if (auto const* unreachables = util::valueOrNullptr(unreachableVariables, _function)) @@ -84,10 +83,10 @@ struct MemoryOffsetAllocator // Assign slots for all variables that become unreachable in the function body, if the above did not // assign a slot for them already. - for (YulString variable: *unreachables) + for (YulName variable: *unreachables) // The empty case is a function with too many arguments or return values, // which was already handled above. - if (!variable.empty() && !slotAllocations.count(variable)) + if (variable != YulNameRepository::emptyName() && !slotAllocations.count(variable)) slotAllocations[variable] = requiredSlots++; } @@ -96,16 +95,16 @@ struct MemoryOffsetAllocator /// Maps function names to the set of unreachable variables in that function. /// An empty variable name means that the function has too many arguments or return variables. - std::map> const& unreachableVariables; + std::map> const& unreachableVariables; /// The graph of immediate function calls of all functions. - std::map> const& callGraph; + std::map> const& callGraph; /// Maps the name of each user-defined function to its definition. - std::map const& functionDefinitions; + std::map const& functionDefinitions; /// Maps variable names to the memory slot the respective variable is assigned. - std::map slotAllocations{}; + std::map slotAllocations{}; /// Maps function names to the number of memory slots the respective function requires. - std::map slotsRequiredForFunction{}; + std::map slotsRequiredForFunction{}; }; u256 literalArgumentValue(FunctionCall const& _call) @@ -129,13 +128,13 @@ void StackLimitEvader::run( ); if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(*evmDialect, _object); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, *evmDialect, *_object.code); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_context.yulNameRepository, _object); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _context.yulNameRepository, *_object.code); run(_context, _object, StackLayoutGenerator::reportStackTooDeep(*cfg)); } else run(_context, _object, CompilabilityChecker{ - _context.dialect, + _context.yulNameRepository, _object, true }.unreachableVariables); @@ -145,10 +144,10 @@ void StackLimitEvader::run( void StackLimitEvader::run( OptimiserStepContext& _context, Object& _object, - std::map> const& _stackTooDeepErrors + std::map> const& _stackTooDeepErrors ) { - std::map> unreachableVariables; + std::map> unreachableVariables; for (auto&& [function, stackTooDeepErrors]: _stackTooDeepErrors) { auto& unreachables = unreachableVariables[function]; @@ -164,7 +163,7 @@ void StackLimitEvader::run( void StackLimitEvader::run( OptimiserStepContext& _context, Object& _object, - std::map> const& _unreachableVariables + std::map> const& _unreachableVariables ) { yulAssert(_object.code, ""); @@ -176,7 +175,7 @@ void StackLimitEvader::run( std::vector memoryGuardCalls = FunctionCallFinder::run( *_object.code, - "memoryguard"_yulstring + _context.yulNameRepository.predefined().memoryguard ); // Do not optimise, if no ``memoryguard`` call is found. if (memoryGuardCalls.empty()) @@ -193,11 +192,11 @@ void StackLimitEvader::run( CallGraph callGraph = CallGraphGenerator::callGraph(*_object.code); // We cannot move variables in recursive functions to fixed memory offsets. - for (YulString function: callGraph.recursiveFunctions()) + for (YulName function: callGraph.recursiveFunctions()) if (_unreachableVariables.count(function)) return; - std::map functionDefinitions = allFunctionDefinitions(*_object.code); + std::map functionDefinitions = allFunctionDefinitions(*_object.code); MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls, functionDefinitions}; uint64_t requiredSlots = memoryOffsetAllocator.run(); @@ -206,7 +205,7 @@ void StackLimitEvader::run( StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, *_object.code); reservedMemory += 32 * requiredSlots; - for (FunctionCall* memoryGuardCall: FunctionCallFinder::run(*_object.code, "memoryguard"_yulstring)) + for (FunctionCall* memoryGuardCall: FunctionCallFinder::run(*_object.code, _context.yulNameRepository.predefined().memoryguard)) { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); diff --git a/libyul/optimiser/StackLimitEvader.h b/libyul/optimiser/StackLimitEvader.h index 025553200f05..0411f05735bc 100644 --- a/libyul/optimiser/StackLimitEvader.h +++ b/libyul/optimiser/StackLimitEvader.h @@ -60,7 +60,7 @@ class StackLimitEvader static void run( OptimiserStepContext& _context, Object& _object, - std::map> const& _unreachableVariables + std::map> const& _unreachableVariables ); /// @a _stackTooDeepErrors can be determined by the StackLayoutGenerator. /// Can only be run on the EVM dialect with objects. @@ -70,7 +70,7 @@ class StackLimitEvader static void run( OptimiserStepContext& _context, Object& _object, - std::map> const& _stackTooDeepErrors + std::map> const& _stackTooDeepErrors ); /// Determines stack too deep errors using the appropriate code generation backend. /// Can only be run on the EVM dialect with objects. diff --git a/libyul/optimiser/StackToMemoryMover.cpp b/libyul/optimiser/StackToMemoryMover.cpp index dbf3183fb420..38eaf43342d4 100644 --- a/libyul/optimiser/StackToMemoryMover.cpp +++ b/libyul/optimiser/StackToMemoryMover.cpp @@ -16,7 +16,6 @@ */ #include #include -#include #include #include @@ -36,13 +35,13 @@ using namespace solidity::yul; namespace { std::vector generateMemoryStore( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, langutil::DebugData::ConstPtr const& _debugData, LiteralValue const& _mpos, Expression _value ) { - BuiltinFunction const* memoryStoreFunction = _dialect.memoryStoreFunction(_dialect.defaultType); + auto const* memoryStoreFunction = _yulNameRepository.memoryStoreFunction(_yulNameRepository.predefined().defaultType); yulAssert(memoryStoreFunction, ""); std::vector result; result.emplace_back(ExpressionStatement{_debugData, FunctionCall{ @@ -56,9 +55,9 @@ std::vector generateMemoryStore( return result; } -FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::ConstPtr const& _debugData, LiteralValue const& _mpos) +FunctionCall generateMemoryLoad(YulNameRepository const& _yulNameRepository, langutil::DebugData::ConstPtr const& _debugData, LiteralValue const& _mpos) { - BuiltinFunction const* memoryLoadFunction = _dialect.memoryLoadFunction(_dialect.defaultType); + auto const* memoryLoadFunction = _yulNameRepository.memoryLoadFunction(_yulNameRepository.predefined().defaultType); yulAssert(memoryLoadFunction, ""); return FunctionCall{ _debugData, @@ -77,7 +76,7 @@ FunctionCall generateMemoryLoad(Dialect const& _dialect, langutil::DebugData::Co void StackToMemoryMover::run( OptimiserStepContext& _context, u256 _reservedMemory, - std::map const& _memorySlots, + std::map const& _memorySlots, uint64_t _numRequiredSlots, Block& _block ) @@ -88,10 +87,10 @@ void StackToMemoryMover::run( memoryOffsetTracker, util::applyMap( allFunctionDefinitions(_block), - util::mapTuple([](YulString _name, FunctionDefinition const* _funDef) { + util::mapTuple([](YulName _name, FunctionDefinition const* _funDef) { return make_pair(_name, _funDef->returnVariables); }), - std::map{} + std::map{} ) ); stackToMemoryMover(_block); @@ -101,11 +100,10 @@ void StackToMemoryMover::run( StackToMemoryMover::StackToMemoryMover( OptimiserStepContext& _context, VariableMemoryOffsetTracker const& _memoryOffsetTracker, - std::map _functionReturnVariables + std::map _functionReturnVariables ): m_context(_context), m_memoryOffsetTracker(_memoryOffsetTracker), -m_nameDispenser(_context.dispenser), m_functionReturnVariables(std::move(_functionReturnVariables)) { auto const* evmDialect = dynamic_cast(&_context.dialect); @@ -127,7 +125,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) for (TypedName const& param: _functionDefinition.parameters) if (auto slot = m_memoryOffsetTracker(param.name)) memoryVariableInits += generateMemoryStore( - m_context.dialect, + m_context.yulNameRepository, param.debugData, *slot, Identifier{param.debugData, param.name} @@ -137,7 +135,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) for (TypedName const& returnVariable: _functionDefinition.returnVariables) if (auto slot = m_memoryOffsetTracker(returnVariable.name)) memoryVariableInits += generateMemoryStore( - m_context.dialect, + m_context.yulNameRepository, returnVariable.debugData, *slot, Literal{returnVariable.debugData, LiteralKind::Number, LiteralValue(u256{0}), {}} @@ -150,7 +148,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) std::not_fn(m_memoryOffsetTracker) ) | ranges::to; // Generate new function without return variable and with only the non-moved parameters. - YulString newFunctionName = m_context.dispenser.newName(_functionDefinition.name); + YulName newFunctionName = m_context.yulNameRepository.deriveName(_functionDefinition.name); m_newFunctionDefinitions.emplace_back(FunctionDefinition{ _functionDefinition.debugData, newFunctionName, @@ -159,9 +157,9 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) std::move(_functionDefinition.body) }); // Generate new names for the arguments to maintain disambiguation. - std::map newArgumentNames; + std::map newArgumentNames; for (TypedName const& _var: stackParameters) - newArgumentNames[_var.name] = m_context.dispenser.newName(_var.name); + newArgumentNames[_var.name] = m_context.yulNameRepository.deriveName(_var.name); for (auto& parameter: _functionDefinition.parameters) parameter.name = util::valueOrDefault(newArgumentNames, parameter.name, parameter.name); // Replace original function by a call to the new function and an assignment to the return variable from memory. @@ -180,7 +178,7 @@ void StackToMemoryMover::operator()(FunctionDefinition& _functionDefinition) _functionDefinition.debugData, {Identifier{_functionDefinition.debugData, _functionDefinition.returnVariables.front().name}}, std::make_unique(generateMemoryLoad( - m_context.dialect, + m_context.yulNameRepository, _functionDefinition.debugData, *m_memoryOffsetTracker(_functionDefinition.returnVariables.front().name) )) @@ -211,7 +209,7 @@ void StackToMemoryMover::operator()(Block& _block) { if (auto offset = m_memoryOffsetTracker(_lhsVars.front().name)) return generateMemoryStore( - m_context.dialect, + m_context.yulNameRepository, debugData, *offset, _stmt.value ? *std::move(_stmt.value) : Literal{debugData, LiteralKind::Number, LiteralValue(u256{0}), {}} @@ -224,7 +222,7 @@ void StackToMemoryMover::operator()(Block& _block) { FunctionCall const* functionCall = std::get_if(_stmt.value.get()); yulAssert(functionCall, ""); - if (m_context.dialect.builtin(functionCall->functionName.name)) + if (m_context.yulNameRepository.isBuiltinName(functionCall->functionName.name)) rhsMemorySlots = std::vector>(_lhsVars.size(), std::nullopt); else rhsMemorySlots = @@ -252,17 +250,17 @@ void StackToMemoryMover::operator()(Block& _block) { std::unique_ptr rhs; if (rhsSlot) - rhs = std::make_unique(generateMemoryLoad(m_context.dialect, debugData, *rhsSlot)); + rhs = std::make_unique(generateMemoryLoad(m_context.yulNameRepository, debugData, *rhsSlot)); else { - YulString tempVarName = m_nameDispenser.newName(lhsVar.name); + YulName tempVarName = m_context.yulNameRepository.deriveName(lhsVar.name); tempDecl.variables.emplace_back(TypedName{lhsVar.debugData, tempVarName, {}}); rhs = std::make_unique(Identifier{debugData, tempVarName}); } if (auto offset = m_memoryOffsetTracker(lhsVar.name)) memoryAssignments += generateMemoryStore( - m_context.dialect, + m_context.yulNameRepository, _stmt.debugData, *offset, std::move(*rhs) @@ -306,10 +304,10 @@ void StackToMemoryMover::visit(Expression& _expression) ASTModifier::visit(_expression); if (Identifier* identifier = std::get_if(&_expression)) if (auto offset = m_memoryOffsetTracker(identifier->name)) - _expression = generateMemoryLoad(m_context.dialect, identifier->debugData, *offset); + _expression = generateMemoryLoad(m_context.yulNameRepository, identifier->debugData, *offset); } -std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulString const& _variable) const +std::optional StackToMemoryMover::VariableMemoryOffsetTracker::operator()(YulName const& _variable) const { if (m_memorySlots.count(_variable)) { diff --git a/libyul/optimiser/StackToMemoryMover.h b/libyul/optimiser/StackToMemoryMover.h index 79c7276ede93..3369d07362a2 100644 --- a/libyul/optimiser/StackToMemoryMover.h +++ b/libyul/optimiser/StackToMemoryMover.h @@ -29,6 +29,7 @@ #include #include +#include namespace solidity::yul { @@ -142,7 +143,7 @@ class StackToMemoryMover: ASTModifier static void run( OptimiserStepContext& _context, u256 _reservedMemory, - std::map const& _memorySlots, + std::map const& _memorySlots, uint64_t _numRequiredSlots, Block& _block ); @@ -158,42 +159,41 @@ class StackToMemoryMover: ASTModifier public: VariableMemoryOffsetTracker( u256 _reservedMemory, - std::map const& _memorySlots, + std::map const& _memorySlots, uint64_t _numRequiredSlots - ): m_reservedMemory(_reservedMemory), m_memorySlots(_memorySlots), m_numRequiredSlots(_numRequiredSlots) + ): m_reservedMemory(std::move(_reservedMemory)), m_memorySlots(_memorySlots), m_numRequiredSlots(_numRequiredSlots) {} - /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal + /// @returns a YulName containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. - std::optional operator()(YulString const& _variable) const; - /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal + std::optional operator()(YulName const& _variable) const; + /// @returns a YulName containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. std::optional operator()(TypedName const& _variable) const; - /// @returns a YulString containing the memory offset to be assigned to @a _variable as number literal + /// @returns a YulName containing the memory offset to be assigned to @a _variable as number literal /// or std::nullopt if the variable should not be moved. std::optional operator()(Identifier const& _variable) const; private: u256 m_reservedMemory; - std::map const& m_memorySlots; + std::map const& m_memorySlots; uint64_t m_numRequiredSlots = 0; }; struct FunctionMoveInfo { - std::vector> returnVariableSlots; + std::vector> returnVariableSlots; }; StackToMemoryMover( OptimiserStepContext& _context, VariableMemoryOffsetTracker const& _memoryOffsetTracker, - std::map> _functionReturnVariables + std::map> _functionReturnVariables ); OptimiserStepContext& m_context; VariableMemoryOffsetTracker const& m_memoryOffsetTracker; - NameDispenser& m_nameDispenser; /// Map from function names to the return variables of the function with that name. - std::map> m_functionReturnVariables; + std::map> m_functionReturnVariables; /// List of functions generated while running this step that are to be appended to the code in the end. std::list m_newFunctionDefinitions; }; diff --git a/libyul/optimiser/Substitution.cpp b/libyul/optimiser/Substitution.cpp index b2d4d469e171..f72ff951a6a8 100644 --- a/libyul/optimiser/Substitution.cpp +++ b/libyul/optimiser/Substitution.cpp @@ -30,7 +30,7 @@ Expression Substitution::translate(Expression const& _expression) { if (std::holds_alternative(_expression)) { - YulString name = std::get(_expression).name; + auto name = std::get(_expression).name; if (m_substitutions.count(name)) // No recursive substitution return ASTCopier().translate(*m_substitutions.at(name)); diff --git a/libyul/optimiser/Substitution.h b/libyul/optimiser/Substitution.h index f76dcc72ea47..084edfcfb254 100644 --- a/libyul/optimiser/Substitution.h +++ b/libyul/optimiser/Substitution.h @@ -35,13 +35,13 @@ namespace solidity::yul class Substitution: public ASTCopier { public: - Substitution(std::map const& _substitutions): + Substitution(std::map const& _substitutions): m_substitutions(_substitutions) {} Expression translate(Expression const& _expression) override; private: - std::map const& m_substitutions; + std::map const& m_substitutions; }; } diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 83bc0370092b..629e8d149241 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include @@ -134,34 +133,32 @@ void outputPerformanceMetrics(map const& _metrics) void OptimiserSuite::run( - Dialect const& _dialect, + YulNameRepository& _yulNameRepository, GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, std::string_view _optimisationSequence, std::string_view _optimisationCleanupSequence, std::optional _expectedExecutionsPerDeployment, - std::set const& _externallyUsedIdentifiers + std::set const& _externallyUsedIdentifiers ) { - EVMDialect const* evmDialect = dynamic_cast(&_dialect); + EVMDialect const* evmDialect = dynamic_cast(&_yulNameRepository.dialect()); bool usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - std::set reservedIdentifiers = _externallyUsedIdentifiers; - reservedIdentifiers += _dialect.fixedFunctionNames(); + std::set reservedIdentifiers = _externallyUsedIdentifiers; *_object.code = std::get(Disambiguator( - _dialect, + _yulNameRepository, *_object.analysisInfo, reservedIdentifiers )(*_object.code)); Block& ast = *_object.code; - NameDispenser dispenser{_dialect, ast, reservedIdentifiers}; - OptimiserStepContext context{_dialect, dispenser, reservedIdentifiers, _expectedExecutionsPerDeployment}; + OptimiserStepContext context{_yulNameRepository.dialect(), _yulNameRepository, reservedIdentifiers, _expectedExecutionsPerDeployment}; OptimiserSuite suite(context, Debug::None); @@ -169,7 +166,6 @@ void OptimiserSuite::run( // ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely. suite.runSequence("hgfo", ast); - NameSimplifier::run(suite.m_context, ast); // Now the user-supplied part suite.runSequence(_optimisationSequence, ast); @@ -181,7 +177,7 @@ void OptimiserSuite::run( // message once we perform code generation. if (!usesOptimizedCodeGenerator) StackCompressor::run( - _dialect, + _yulNameRepository, _object, _optimizeStackAllocation, stackCompressorMaxIterations @@ -197,11 +193,11 @@ void OptimiserSuite::run( if (evmDialect) { yulAssert(_meter, ""); - ConstantOptimiser{*evmDialect, *_meter}(ast); + ConstantOptimiser{_yulNameRepository, *evmDialect, *_meter}(ast); if (usesOptimizedCodeGenerator) { StackCompressor::run( - _dialect, + _yulNameRepository, _object, _optimizeStackAllocation, stackCompressorMaxIterations @@ -213,15 +209,11 @@ void OptimiserSuite::run( StackLimitEvader::run(suite.m_context, _object); } - dispenser.reset(ast); - NameSimplifier::run(suite.m_context, ast); - VarNameCleaner::run(suite.m_context, ast); - #ifdef PROFILE_OPTIMIZER_STEPS outputPerformanceMetrics(suite.m_durationPerStepInMicroseconds); #endif - - *_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_dialect, _object); + _yulNameRepository.generateLabels(*_object.code); + *_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_yulNameRepository, _object); } namespace @@ -510,7 +502,7 @@ void OptimiserSuite::runSequence(std::vector const& _steps, Block& else { std::cout << "== Running " << step << " changed the AST." << std::endl; - std::cout << AsmPrinter{}(_ast) << std::endl; + std::cout << AsmPrinter{m_context.yulNameRepository}(_ast) << std::endl; copy = std::make_unique(std::get(ASTCopier{}(_ast))); } } diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 6e3886da3b2d..d9fbed92ddf3 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -24,8 +24,6 @@ #include #include #include -#include -#include #include #include @@ -63,14 +61,14 @@ class OptimiserSuite /// The value nullopt for `_expectedExecutionsPerDeployment` represents creation code. static void run( - Dialect const& _dialect, + YulNameRepository& _yulNameRepository, GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, std::string_view _optimisationSequence, std::string_view _optimisationCleanupSequence, std::optional _expectedExecutionsPerDeployment, - std::set const& _externallyUsedIdentifiers = {} + std::set const& _externallyUsedIdentifiers = {} ); /// Ensures that specified sequence of step abbreviations is well-formed and can be executed. diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index 5a8d2b49b267..0665a5efbe6e 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include @@ -84,8 +84,8 @@ class SyntacticallyEqual } std::size_t m_idsUsed = 0; - std::map m_identifiersLHS; - std::map m_identifiersRHS; + std::map m_identifiersLHS; + std::map m_identifiersRHS; }; /** diff --git a/libyul/optimiser/TypeInfo.cpp b/libyul/optimiser/TypeInfo.cpp index 16ce65496861..283b322a5dd2 100644 --- a/libyul/optimiser/TypeInfo.cpp +++ b/libyul/optimiser/TypeInfo.cpp @@ -62,26 +62,26 @@ class TypeInfo::TypeCollector: public ASTWalker } } - std::map variableTypes; - std::map functionTypes; + std::map variableTypes; + std::map functionTypes; }; -TypeInfo::TypeInfo(Dialect const& _dialect, Block const& _ast): - m_dialect(_dialect) +TypeInfo::TypeInfo(YulNameRepository const& _yulNameRepository, Block const& _ast): + m_yulNameRepository(_yulNameRepository) { TypeCollector types(_ast); m_functionTypes = std::move(types.functionTypes); m_variableTypes = std::move(types.variableTypes); } -YulString TypeInfo::typeOf(Expression const& _expression) const +YulName TypeInfo::typeOf(Expression const& _expression) const { return std::visit(GenericVisitor{ [&](FunctionCall const& _funCall) { - YulString name = _funCall.functionName.name; - std::vector const* retTypes = nullptr; - if (BuiltinFunction const* fun = m_dialect.builtin(name)) + auto name = _funCall.functionName.name; + std::vector const* retTypes; + if (auto const* fun = m_yulNameRepository.builtin(name)) retTypes = &fun->returns; else retTypes = &m_functionTypes.at(name).returns; @@ -97,7 +97,7 @@ YulString TypeInfo::typeOf(Expression const& _expression) const }, _expression); } -YulString TypeInfo::typeOfVariable(YulString _name) const +YulName TypeInfo::typeOfVariable(YulName _name) const { return m_variableTypes.at(_name); } diff --git a/libyul/optimiser/TypeInfo.h b/libyul/optimiser/TypeInfo.h index 5ed0a0d55c5f..6169755d398c 100644 --- a/libyul/optimiser/TypeInfo.h +++ b/libyul/optimiser/TypeInfo.h @@ -21,7 +21,7 @@ #pragma once #include -#include +#include #include #include @@ -38,28 +38,28 @@ struct Dialect; class TypeInfo { public: - TypeInfo(Dialect const& _dialect, Block const& _ast); + TypeInfo(YulNameRepository const& _yulNameRepository, Block const& _ast); - void setVariableType(YulString _name, YulString _type) { m_variableTypes[_name] = _type; } + void setVariableType(YulName _name, YulName _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; + YulName typeOf(Expression const& _expression) const; /// \returns the type of variable - YulString typeOfVariable(YulString _name) const; + YulName typeOfVariable(YulName _name) const; private: class TypeCollector; struct FunctionType { - std::vector parameters; - std::vector returns; + std::vector parameters; + std::vector returns; }; - Dialect const& m_dialect; - std::map m_variableTypes; - std::map m_functionTypes; + YulNameRepository const& m_yulNameRepository; + std::map m_variableTypes; + std::map m_functionTypes; }; } diff --git a/libyul/optimiser/UnusedAssignEliminator.cpp b/libyul/optimiser/UnusedAssignEliminator.cpp index f3d78288f3ca..ffe55a513d8b 100644 --- a/libyul/optimiser/UnusedAssignEliminator.cpp +++ b/libyul/optimiser/UnusedAssignEliminator.cpp @@ -40,8 +40,8 @@ using namespace solidity::yul; void UnusedAssignEliminator::run(OptimiserStepContext& _context, Block& _ast) { UnusedAssignEliminator uae{ - _context.dialect, - ControlFlowSideEffectsCollector{_context.dialect, _ast}.functionSideEffectsNamed() + _context.yulNameRepository, + ControlFlowSideEffectsCollector{_context.yulNameRepository, _ast}.functionSideEffectsNamed() }; uae(_ast); @@ -79,8 +79,8 @@ void UnusedAssignEliminator::operator()(FunctionCall const& _functionCall) UnusedStoreBase::operator()(_functionCall); ControlFlowSideEffects sideEffects; - if (auto builtin = m_dialect.builtin(_functionCall.functionName.name)) - sideEffects = builtin->controlFlowSideEffects; + if (auto const* builtin = m_yulNameRepository.builtin(_functionCall.functionName.name)) + sideEffects = builtin->data->controlFlowSideEffects; else sideEffects = m_controlFlowSideEffects.at(_functionCall.functionName.name); @@ -92,7 +92,7 @@ void UnusedAssignEliminator::operator()(FunctionCall const& _functionCall) void UnusedAssignEliminator::operator()(Leave const&) { - for (YulString name: m_returnVariables) + for (YulName name: m_returnVariables) markUsed(name); m_activeStores.clear(); } @@ -115,7 +115,7 @@ void UnusedAssignEliminator::visit(Statement const& _statement) { // We do not remove assignments whose values might have side-effects, // but clear the active stores to the assigned variables in any case. - if (SideEffectsCollector{m_dialect, *assignment->value}.movable()) + if (SideEffectsCollector{m_yulNameRepository, *assignment->value}.movable()) { m_allStores.insert(&_statement); for (auto const& var: assignment->variableNames) @@ -152,7 +152,7 @@ void UnusedAssignEliminator::finalizeFunctionDefinition(FunctionDefinition const markUsed(retParam.name); } -void UnusedAssignEliminator::markUsed(YulString _variable) +void UnusedAssignEliminator::markUsed(YulName const _variable) { for (auto& assignment: m_activeStores[_variable]) m_usedStores.insert(assignment); diff --git a/libyul/optimiser/UnusedAssignEliminator.h b/libyul/optimiser/UnusedAssignEliminator.h index 800d626eb840..3993f13295d7 100644 --- a/libyul/optimiser/UnusedAssignEliminator.h +++ b/libyul/optimiser/UnusedAssignEliminator.h @@ -120,10 +120,10 @@ class UnusedAssignEliminator: public UnusedStoreBase static void run(OptimiserStepContext&, Block& _ast); explicit UnusedAssignEliminator( - Dialect const& _dialect, - std::map _controlFlowSideEffects + YulNameRepository const& _yulNameRepository, + std::map _controlFlowSideEffects ): - UnusedStoreBase(_dialect), + UnusedStoreBase(_yulNameRepository), m_controlFlowSideEffects(_controlFlowSideEffects) {} @@ -141,10 +141,10 @@ class UnusedAssignEliminator: public UnusedStoreBase void shortcutNestedLoop(ActiveStores const& _beforeLoop) override; void finalizeFunctionDefinition(FunctionDefinition const& _functionDefinition) override; - void markUsed(YulString _variable); + void markUsed(YulName _variable); - std::set m_returnVariables; - std::map m_controlFlowSideEffects; + std::set m_returnVariables; + std::map m_controlFlowSideEffects; }; } diff --git a/libyul/optimiser/UnusedFunctionParameterPruner.cpp b/libyul/optimiser/UnusedFunctionParameterPruner.cpp index 40c2fe80c65d..a6d826b79ea0 100644 --- a/libyul/optimiser/UnusedFunctionParameterPruner.cpp +++ b/libyul/optimiser/UnusedFunctionParameterPruner.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -42,7 +41,7 @@ using namespace solidity::yul::unusedFunctionsCommon; void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ast) { - std::map references = VariableReferencesCounter::countReferences(_ast); + std::map references = VariableReferencesCounter::countReferences(_ast); auto used = [&](auto v) -> bool { return references.count(v.name); }; // Function name and a pair of boolean masks, the first corresponds to parameters and the second @@ -54,7 +53,7 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ // Similarly for the second vector in the pair, a value `false` at index `i` indicates that the // return parameter at index `i` in `FunctionDefinition::returnVariables` is unused inside // function body. - std::map, std::vector>> usedParametersAndReturnVariables; + std::map, std::vector>> usedParametersAndReturnVariables; // Step 1 of UnusedFunctionParameterPruner: Find functions whose parameters (both arguments and // return-parameters) are not used in its body. @@ -72,16 +71,16 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ }; } - std::set functionNamesToFree = util::keys(usedParametersAndReturnVariables); + std::set functionNamesToFree = util::keys(usedParametersAndReturnVariables); // Step 2 of UnusedFunctionParameterPruner: Renames the function and replaces all references to // the function, say `f`, by its new name, say `f_1`. - NameDisplacer replace{_context.dispenser, functionNamesToFree}; + NameDisplacer replace{functionNamesToFree, _context.yulNameRepository}; replace(_ast); // Inverse-Map of the above translations. In the above example, this will store an element with // key `f_1` and value `f`. - std::map newToOriginalNames = invertMap(replace.translations()); + std::map newToOriginalNames = invertMap(replace.translations()); // Step 3 of UnusedFunctionParameterPruner: introduce a new function in the block with body of // the old one. Replace the body of the old one with a function call to the new one with reduced @@ -98,8 +97,8 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ if (newToOriginalNames.count(originalFunction.name)) { - YulString linkingFunctionName = originalFunction.name; - YulString originalFunctionName = newToOriginalNames.at(linkingFunctionName); + YulName linkingFunctionName = originalFunction.name; + YulName originalFunctionName = newToOriginalNames.at(linkingFunctionName); std::pair, std::vector> used = usedParametersAndReturnVariables.at(originalFunctionName); @@ -108,7 +107,7 @@ void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ used, originalFunctionName, linkingFunctionName, - _context.dispenser + _context.yulNameRepository ); originalFunction.name = originalFunctionName; diff --git a/libyul/optimiser/UnusedFunctionsCommon.cpp b/libyul/optimiser/UnusedFunctionsCommon.cpp index ed9d0ba4c371..1de2d34d4c31 100644 --- a/libyul/optimiser/UnusedFunctionsCommon.cpp +++ b/libyul/optimiser/UnusedFunctionsCommon.cpp @@ -30,16 +30,16 @@ using namespace solidity::yul::unusedFunctionsCommon; FunctionDefinition unusedFunctionsCommon::createLinkingFunction( FunctionDefinition const& _original, std::pair, std::vector> const& _usedParametersAndReturns, - YulString const& _originalFunctionName, - YulString const& _linkingFunctionName, - NameDispenser& _nameDispenser + YulName const& _originalFunctionName, + YulName const& _linkingFunctionName, + YulNameRepository& _yulNameRepository ) { auto generateTypedName = [&](TypedName t) { return TypedName{ t.debugData, - _nameDispenser.newName(t.name), + _yulNameRepository.deriveName(t.name), t.type }; }; diff --git a/libyul/optimiser/UnusedFunctionsCommon.h b/libyul/optimiser/UnusedFunctionsCommon.h index 2b0f3000dfda..a04445b21911 100644 --- a/libyul/optimiser/UnusedFunctionsCommon.h +++ b/libyul/optimiser/UnusedFunctionsCommon.h @@ -18,7 +18,6 @@ #pragma once #include -#include #include @@ -52,9 +51,9 @@ inline bool tooSimpleToBePruned(FunctionDefinition const& _f) FunctionDefinition createLinkingFunction( FunctionDefinition const& _original, std::pair, std::vector> const& _usedParametersAndReturns, - YulString const& _originalFunctionName, - YulString const& _linkingFunctionName, - NameDispenser& _nameDispenser + YulName const& _originalFunctionName, + YulName const& _linkingFunctionName, + YulNameRepository& _yulNameRepository ); } diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index a64f37ebedeb..d2a4351be71a 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -35,18 +35,18 @@ using namespace solidity::yul; void UnusedPruner::run(OptimiserStepContext& _context, Block& _ast) { - UnusedPruner::runUntilStabilisedOnFullAST(_context.dialect, _ast, _context.reservedIdentifiers); + UnusedPruner::runUntilStabilisedOnFullAST(_context.yulNameRepository, _ast, _context.reservedIdentifiers); FunctionGrouper::run(_context, _ast); } UnusedPruner::UnusedPruner( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects, - std::set const& _externallyUsedFunctions + std::map const* _functionSideEffects, + std::set const& _externallyUsedFunctions ): - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_allowMSizeOptimization(_allowMSizeOptimization), m_functionSideEffects(_functionSideEffects) { @@ -56,12 +56,12 @@ UnusedPruner::UnusedPruner( } UnusedPruner::UnusedPruner( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, FunctionDefinition& _function, bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions + std::set const& _externallyUsedFunctions ): - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_allowMSizeOptimization(_allowMSizeOptimization) { m_references = ReferencesCounter::countReferences(_function); @@ -98,17 +98,17 @@ void UnusedPruner::operator()(Block& _block) if (!varDecl.value) statement = Block{std::move(varDecl.debugData), {}}; else if ( - SideEffectsCollector(m_dialect, *varDecl.value, m_functionSideEffects). + SideEffectsCollector(m_yulNameRepository, *varDecl.value, m_functionSideEffects). canBeRemoved(m_allowMSizeOptimization) ) { subtractReferences(ReferencesCounter::countReferences(*varDecl.value)); statement = Block{std::move(varDecl.debugData), {}}; } - else if (varDecl.variables.size() == 1 && m_dialect.discardFunction(varDecl.variables.front().type)) + else if (varDecl.variables.size() == 1 && m_yulNameRepository.discardFunction(varDecl.variables.front().type)) statement = ExpressionStatement{varDecl.debugData, FunctionCall{ varDecl.debugData, - {varDecl.debugData, m_dialect.discardFunction(varDecl.variables.front().type)->name}, + {varDecl.debugData, m_yulNameRepository.discardFunction(varDecl.variables.front().type)->name}, {*std::move(varDecl.value)} }}; } @@ -117,7 +117,7 @@ void UnusedPruner::operator()(Block& _block) { ExpressionStatement& exprStmt = std::get(statement); if ( - SideEffectsCollector(m_dialect, exprStmt.expression, m_functionSideEffects). + SideEffectsCollector(m_yulNameRepository, exprStmt.expression, m_functionSideEffects). canBeRemoved(m_allowMSizeOptimization) ) { @@ -132,17 +132,17 @@ void UnusedPruner::operator()(Block& _block) } void UnusedPruner::runUntilStabilised( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects, - std::set const& _externallyUsedFunctions + std::map const* _functionSideEffects, + std::set const& _externallyUsedFunctions ) { while (true) { UnusedPruner pruner( - _dialect, _ast, _allowMSizeOptimization, _functionSideEffects, + _yulNameRepository, _ast, _allowMSizeOptimization, _functionSideEffects, _externallyUsedFunctions); pruner(_ast); if (!pruner.shouldRunAgain()) @@ -151,39 +151,39 @@ void UnusedPruner::runUntilStabilised( } void UnusedPruner::runUntilStabilisedOnFullAST( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, - std::set const& _externallyUsedFunctions + std::set const& _externallyUsedFunctions ) { - std::map functionSideEffects = - SideEffectsPropagator::sideEffects(_dialect, CallGraphGenerator::callGraph(_ast)); - bool allowMSizeOptimization = !MSizeFinder::containsMSize(_dialect, _ast); - runUntilStabilised(_dialect, _ast, allowMSizeOptimization, &functionSideEffects, _externallyUsedFunctions); + std::map functionSideEffects = + SideEffectsPropagator::sideEffects(_yulNameRepository, CallGraphGenerator::callGraph(_ast)); + bool allowMSizeOptimization = !MSizeFinder::containsMSize(_yulNameRepository, _ast); + runUntilStabilised(_yulNameRepository, _ast, allowMSizeOptimization, &functionSideEffects, _externallyUsedFunctions); } void UnusedPruner::runUntilStabilised( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, FunctionDefinition& _function, bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions + std::set const& _externallyUsedFunctions ) { while (true) { - UnusedPruner pruner(_dialect, _function, _allowMSizeOptimization, _externallyUsedFunctions); + UnusedPruner pruner(_yulNameRepository, _function, _allowMSizeOptimization, _externallyUsedFunctions); pruner(_function); if (!pruner.shouldRunAgain()) return; } } -bool UnusedPruner::used(YulString _name) const +bool UnusedPruner::used(YulName _name) const { return m_references.count(_name) && m_references.at(_name) > 0; } -void UnusedPruner::subtractReferences(std::map const& _subtrahend) +void UnusedPruner::subtractReferences(std::map const& _subtrahend) { for (auto const& ref: _subtrahend) { diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index e4587d5d725b..277d93002bc2 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -61,20 +61,20 @@ class UnusedPruner: public ASTModifier // Run the pruner until the code does not change anymore. static void runUntilStabilised( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects = nullptr, - std::set const& _externallyUsedFunctions = {} + std::map const* _functionSideEffects = nullptr, + std::set const& _externallyUsedFunctions = {} ); static void run( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, - std::set const& _externallyUsedFunctions = {} + std::set const& _externallyUsedFunctions = {} ) { - runUntilStabilisedOnFullAST(_dialect, _ast, _externallyUsedFunctions); + runUntilStabilisedOnFullAST(_yulNameRepository, _ast, _externallyUsedFunctions); } /// Run the pruner until the code does not change anymore. @@ -82,9 +82,9 @@ class UnusedPruner: public ASTModifier /// The pruner itself determines if msize is used and which user-defined functions /// are side-effect free. static void runUntilStabilisedOnFullAST( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, - std::set const& _externallyUsedFunctions = {} + std::set const& _externallyUsedFunctions = {} ); // Run the pruner until the code does not change anymore. @@ -93,35 +93,35 @@ class UnusedPruner: public ASTModifier // whose only side-effect is a potential change of the return value of // the msize instruction. static void runUntilStabilised( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, FunctionDefinition& _functionDefinition, bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions = {} + std::set const& _externallyUsedFunctions = {} ); private: UnusedPruner( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block& _ast, bool _allowMSizeOptimization, - std::map const* _functionSideEffects = nullptr, - std::set const& _externallyUsedFunctions = {} + std::map const* _functionSideEffects = nullptr, + std::set const& _externallyUsedFunctions = {} ); UnusedPruner( - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, FunctionDefinition& _function, bool _allowMSizeOptimization, - std::set const& _externallyUsedFunctions = {} + std::set const& _externallyUsedFunctions = {} ); - bool used(YulString _name) const; - void subtractReferences(std::map const& _subtrahend); + bool used(YulName _name) const; + void subtractReferences(std::map const& _subtrahend); - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; bool m_allowMSizeOptimization = false; - std::map const* m_functionSideEffects = nullptr; + std::map const* m_functionSideEffects = nullptr; bool m_shouldRunAgain = false; - std::map m_references; + std::map m_references; }; } diff --git a/libyul/optimiser/UnusedStoreBase.h b/libyul/optimiser/UnusedStoreBase.h index 0d618d8d254f..2d7eaf1aa350 100644 --- a/libyul/optimiser/UnusedStoreBase.h +++ b/libyul/optimiser/UnusedStoreBase.h @@ -49,7 +49,7 @@ struct Dialect; class UnusedStoreBase: public ASTWalker { public: - explicit UnusedStoreBase(Dialect const& _dialect): m_dialect(_dialect) {} + explicit UnusedStoreBase(YulNameRepository const& _yulNameRepository): m_yulNameRepository(_yulNameRepository) {} using ASTWalker::operator(); void operator()(If const& _if) override; @@ -60,7 +60,7 @@ class UnusedStoreBase: public ASTWalker void operator()(Continue const&) override; protected: - using ActiveStores = std::map>; + using ActiveStores = std::map>; /// This function is called for a loop that is nested too deep to avoid /// horrible runtime and should just resolve the situation in a pragmatic @@ -76,7 +76,7 @@ class UnusedStoreBase: public ASTWalker static void merge(ActiveStores& _target, ActiveStores&& _source); static void merge(ActiveStores& _target, std::vector&& _source); - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; /// Set of all stores encountered during the traversal (in the current function). std::set m_allStores; /// Set of stores that are marked as being used (in the current function). diff --git a/libyul/optimiser/UnusedStoreEliminator.cpp b/libyul/optimiser/UnusedStoreEliminator.cpp index 6a0ab1518d08..5e06b0955cf8 100644 --- a/libyul/optimiser/UnusedStoreEliminator.cpp +++ b/libyul/optimiser/UnusedStoreEliminator.cpp @@ -43,36 +43,30 @@ using namespace solidity; using namespace solidity::yul; -/// Variable names for special constants that can never appear in actual Yul code. -static std::string const zero{"@ 0"}; -static std::string const one{"@ 1"}; -static std::string const thirtyTwo{"@ 32"}; - - void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) { - std::map functionSideEffects = SideEffectsPropagator::sideEffects( - _context.dialect, + std::map functionSideEffects = SideEffectsPropagator::sideEffects( + _context.yulNameRepository, CallGraphGenerator::callGraph(_ast) ); SSAValueTracker ssaValues; ssaValues(_ast); - std::map values; + std::map values; for (auto const& [name, expression]: ssaValues.values()) values[name] = AssignedValue{expression, {}}; Expression const zeroLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{0}), {}}}; Expression const oneLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{1}), {}}}; Expression const thirtyTwoLiteral{Literal{{}, LiteralKind::Number, LiteralValue(u256{32}), {}}}; - values[YulString{zero}] = AssignedValue{&zeroLiteral, {}}; - values[YulString{one}] = AssignedValue{&oneLiteral, {}}; - values[YulString{thirtyTwo}] = AssignedValue{&thirtyTwoLiteral, {}}; + values[_context.yulNameRepository.predefined().placeholder_zero] = AssignedValue{&zeroLiteral, {}}; + values[_context.yulNameRepository.predefined().placeholder_one] = AssignedValue{&oneLiteral, {}}; + values[_context.yulNameRepository.predefined().placeholder_thirtytwo] = AssignedValue{&thirtyTwoLiteral, {}}; - bool const ignoreMemory = MSizeFinder::containsMSize(_context.dialect, _ast); + bool const ignoreMemory = MSizeFinder::containsMSize(_context.yulNameRepository, _ast); UnusedStoreEliminator rse{ - _context.dialect, + _context.yulNameRepository, functionSideEffects, - ControlFlowSideEffectsCollector{_context.dialect, _ast}.functionSideEffectsNamed(), + ControlFlowSideEffectsCollector{_context.yulNameRepository, _ast}.functionSideEffectsNamed(), values, ignoreMemory }; @@ -92,18 +86,19 @@ void UnusedStoreEliminator::run(OptimiserStepContext& _context, Block& _ast) } UnusedStoreEliminator::UnusedStoreEliminator( - Dialect const& _dialect, - std::map const& _functionSideEffects, - std::map _controlFlowSideEffects, - std::map const& _ssaValues, + YulNameRepository const& _yulNameRepository, + std::map const& _functionSideEffects, + std::map _controlFlowSideEffects, + std::map const& _ssaValues, bool _ignoreMemory ): - UnusedStoreBase(_dialect), + UnusedStoreBase(_yulNameRepository), m_ignoreMemory(_ignoreMemory), m_functionSideEffects(_functionSideEffects), m_controlFlowSideEffects(_controlFlowSideEffects), m_ssaValues(_ssaValues), - m_knowledgeBase(_ssaValues) + m_knowledgeBase(_ssaValues, _yulNameRepository), + m_yulNameRepository(_yulNameRepository) {} void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) @@ -114,8 +109,8 @@ void UnusedStoreEliminator::operator()(FunctionCall const& _functionCall) applyOperation(op); ControlFlowSideEffects sideEffects; - if (auto builtin = m_dialect.builtin(_functionCall.functionName.name)) - sideEffects = builtin->controlFlowSideEffects; + if (auto builtin = m_yulNameRepository.builtin(_functionCall.functionName.name)) + sideEffects = builtin->data->controlFlowSideEffects; else sideEffects = m_controlFlowSideEffects.at(_functionCall.functionName.name); @@ -153,7 +148,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement) FunctionCall const* funCall = std::get_if(&exprStatement->expression); yulAssert(funCall); - std::optional instruction = toEVMInstruction(m_dialect, funCall->functionName.name); + std::optional instruction = toEVMInstruction(m_yulNameRepository, funCall->functionName.name); if (!instruction) return; @@ -201,7 +196,7 @@ void UnusedStoreEliminator::visit(Statement const& _statement) if ( m_knowledgeBase.knownToBeZero(*startOffset) && lengthCall && - toEVMInstruction(m_dialect, lengthCall->functionName.name) == Instruction::RETURNDATASIZE + toEVMInstruction(m_yulNameRepository, lengthCall->functionName.name) == Instruction::RETURNDATASIZE ) allowReturndatacopyToBeRemoved = true; } @@ -228,14 +223,14 @@ std::vector UnusedStoreEliminator::operationsF { using evmasm::Instruction; - YulString functionName = _functionCall.functionName.name; + YulName functionName = _functionCall.functionName.name; SideEffects sideEffects; - if (BuiltinFunction const* f = m_dialect.builtin(functionName)) - sideEffects = f->sideEffects; + if (auto const* f = m_yulNameRepository.builtin(functionName)) + sideEffects = f->data->sideEffects; else sideEffects = m_functionSideEffects.at(functionName); - std::optional instruction = toEVMInstruction(m_dialect, functionName); + std::optional instruction = toEVMInstruction(m_yulNameRepository, functionName); if (!instruction) { std::vector result; @@ -263,8 +258,8 @@ std::vector UnusedStoreEliminator::operationsF if (_op.lengthConstant) switch (*_op.lengthConstant) { - case 1: ourOp.length = YulString(one); break; - case 32: ourOp.length = YulString(thirtyTwo); break; + case 1: ourOp.length = m_yulNameRepository.predefined().placeholder_one; break; + case 32: ourOp.length = m_yulNameRepository.predefined().placeholder_thirtytwo; break; default: yulAssert(false); } return ourOp; @@ -435,7 +430,7 @@ void UnusedStoreEliminator::clearActive( activeStorageStores() = {}; } -std::optional UnusedStoreEliminator::identifierNameIfSSA(Expression const& _expression) const +std::optional UnusedStoreEliminator::identifierNameIfSSA(Expression const& _expression) const { if (Identifier const* identifier = std::get_if(&_expression)) if (m_ssaValues.count(identifier->name)) diff --git a/libyul/optimiser/UnusedStoreEliminator.h b/libyul/optimiser/UnusedStoreEliminator.h index 89dbabd78d2c..9d8d8fc10618 100644 --- a/libyul/optimiser/UnusedStoreEliminator.h +++ b/libyul/optimiser/UnusedStoreEliminator.h @@ -63,10 +63,10 @@ class UnusedStoreEliminator: public UnusedStoreBase static void run(OptimiserStepContext& _context, Block& _ast); explicit UnusedStoreEliminator( - Dialect const& _dialect, - std::map const& _functionSideEffects, - std::map _controlFlowSideEffects, - std::map const& _ssaValues, + YulNameRepository const& _yulNameRepository, + std::map const& _functionSideEffects, + std::map _controlFlowSideEffects, + std::map const& _ssaValues, bool _ignoreMemory ); @@ -85,15 +85,15 @@ class UnusedStoreEliminator: public UnusedStoreBase Location location; Effect effect; /// Start of affected area. Unknown if not provided. - std::optional start; + std::optional start; /// Length of affected area, unknown if not provided. /// Unused for storage. - std::optional length; + std::optional length; }; private: - std::set& activeMemoryStores() { return m_activeStores["m"_yulstring]; } - std::set& activeStorageStores() { return m_activeStores["s"_yulstring]; } + std::set& activeMemoryStores() { return m_activeStores[0]; } + std::set& activeStorageStores() { return m_activeStores[1]; } void shortcutNestedLoop(ActiveStores const&) override { @@ -113,16 +113,17 @@ class UnusedStoreEliminator: public UnusedStoreBase void markActiveAsUsed(std::optional _onlyLocation = std::nullopt); void clearActive(std::optional _onlyLocation = std::nullopt); - std::optional identifierNameIfSSA(Expression const& _expression) const; + std::optional identifierNameIfSSA(Expression const& _expression) const; bool const m_ignoreMemory; - std::map const& m_functionSideEffects; - std::map m_controlFlowSideEffects; - std::map const& m_ssaValues; + std::map const& m_functionSideEffects; + std::map m_controlFlowSideEffects; + std::map const& m_ssaValues; std::map m_storeOperations; KnowledgeBase mutable m_knowledgeBase; + YulNameRepository const& m_yulNameRepository; }; } diff --git a/libyul/optimiser/VarDeclInitializer.cpp b/libyul/optimiser/VarDeclInitializer.cpp index 845c7cc41c96..4c492afc2fed 100644 --- a/libyul/optimiser/VarDeclInitializer.cpp +++ b/libyul/optimiser/VarDeclInitializer.cpp @@ -40,7 +40,7 @@ void VarDeclInitializer::operator()(Block& _block) if (_varDecl.variables.size() == 1) { - _varDecl.value = std::make_unique(m_dialect.zeroLiteralForType(_varDecl.variables.front().type)); + _varDecl.value = std::make_unique(m_yulNameRepository.dialect().zeroLiteralForType(_varDecl.variables.front().type, m_yulNameRepository)); return {}; } else @@ -48,7 +48,7 @@ void VarDeclInitializer::operator()(Block& _block) OptionalStatements ret{std::vector{}}; for (auto& var: _varDecl.variables) { - std::unique_ptr expr = std::make_unique(m_dialect.zeroLiteralForType(var.type)); + std::unique_ptr expr = std::make_unique(m_yulNameRepository.dialect().zeroLiteralForType(var.type, m_yulNameRepository)); ret->emplace_back(VariableDeclaration{std::move(_varDecl.debugData), {std::move(var)}, std::move(expr)}); } return ret; diff --git a/libyul/optimiser/VarDeclInitializer.h b/libyul/optimiser/VarDeclInitializer.h index 4060878b15e6..59172ab22e82 100644 --- a/libyul/optimiser/VarDeclInitializer.h +++ b/libyul/optimiser/VarDeclInitializer.h @@ -35,14 +35,14 @@ class VarDeclInitializer: public ASTModifier { public: static constexpr char const* name{"VarDeclInitializer"}; - static void run(OptimiserStepContext& _ctx, Block& _ast) { VarDeclInitializer{_ctx.dialect}(_ast); } + static void run(OptimiserStepContext& _ctx, Block& _ast) { VarDeclInitializer{_ctx.yulNameRepository}(_ast); } void operator()(Block& _block) override; private: - explicit VarDeclInitializer(Dialect const& _dialect): m_dialect(_dialect) {} + explicit VarDeclInitializer(YulNameRepository const& _yulNameRepository): m_yulNameRepository(_yulNameRepository) {} - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; }; } diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp index b13dc8e6b49b..3cee65897f8b 100644 --- a/libyul/optimiser/VarNameCleaner.cpp +++ b/libyul/optimiser/VarNameCleaner.cpp @@ -30,7 +30,7 @@ #include using namespace solidity::yul; - +/* VarNameCleaner::VarNameCleaner( Block const& _ast, Dialect const& _dialect, @@ -123,3 +123,4 @@ YulString VarNameCleaner::stripSuffix(YulString const& _name) const return {YulString{suffixMatch.prefix().str()}}; return _name; } +*/ diff --git a/libyul/optimiser/VarNameCleaner.h b/libyul/optimiser/VarNameCleaner.h index 7823e5716c28..658c770fd89f 100644 --- a/libyul/optimiser/VarNameCleaner.h +++ b/libyul/optimiser/VarNameCleaner.h @@ -46,6 +46,7 @@ struct Dialect; * * Prerequisites: Disambiguator, FunctionHoister, FunctionGrouper */ + /* class VarNameCleaner: public ASTModifier { public: @@ -96,5 +97,5 @@ class VarNameCleaner: public ASTModifier /// Used to assert that a function definition cannot be inside another. bool m_insideFunction = false; }; - +*/ } diff --git a/test/cmdlineTests/ast_ir/output b/test/cmdlineTests/ast_ir/output index c68c77872969..ded9e22aa754 100644 --- a/test/cmdlineTests/ast_ir/output +++ b/test/cmdlineTests/ast_ir/output @@ -673,7 +673,7 @@ Optimized IR AST: }, "variables": [ { - "name": "_1", + "name": "_2", "nativeSrc": "122:16:0", "nodeType": "YulTypedName", "src": "60:13:0", @@ -693,7 +693,7 @@ Optimized IR AST: "value": "64" }, { - "name": "_1", + "name": "_2", "nativeSrc": "122:16:0", "nodeType": "YulIdentifier", "src": "60:13:0" @@ -799,7 +799,7 @@ Optimized IR AST: }, "variables": [ { - "name": "_2", + "name": "_1", "nativeSrc": "363:24:0", "nodeType": "YulTypedName", "src": "60:13:0", @@ -811,7 +811,7 @@ Optimized IR AST: "expression": { "arguments": [ { - "name": "_1", + "name": "_2", "nativeSrc": "331:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" @@ -839,7 +839,7 @@ Optimized IR AST: "src": "60:13:0" }, { - "name": "_2", + "name": "_1", "nativeSrc": "363:24:0", "nodeType": "YulIdentifier", "src": "60:13:0" @@ -863,13 +863,13 @@ Optimized IR AST: "expression": { "arguments": [ { - "name": "_1", + "name": "_2", "nativeSrc": "405:2:0", "nodeType": "YulIdentifier", "src": "60:13:0" }, { - "name": "_2", + "name": "_1", "nativeSrc": "409:24:0", "nodeType": "YulIdentifier", "src": "60:13:0" diff --git a/test/cmdlineTests/constant_optimizer_yul/output b/test/cmdlineTests/constant_optimizer_yul/output index 9c7faa732272..1c740b3385c8 100644 --- a/test/cmdlineTests/constant_optimizer_yul/output +++ b/test/cmdlineTests/constant_optimizer_yul/output @@ -4,15 +4,15 @@ object "C_12" { code { { /// @src 0:61:418 "contract C {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } /// @src 0:103:238 "assembly {..." sstore(0, shl(180, 1)) /// @src 0:61:418 "contract C {..." - let _2 := datasize("C_12_deployed") - codecopy(_1, dataoffset("C_12_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_12_deployed") + codecopy(_2, dataoffset("C_12_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"constant_optimizer_yul/input.sol" diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output index a232fed8fc3b..a96214a5ba4f 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_all/output @@ -174,12 +174,12 @@ object "C_6" { code { { /// @src 0:60:101 "contract C {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_6_deployed") - codecopy(_1, dataoffset("C_6_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_6_deployed") + codecopy(_2, dataoffset("C_6_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_all/input.sol" diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output index 00a6b290f826..10edc6bc64d3 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_location_only/output @@ -173,12 +173,12 @@ object "C_6" { code { { /// @src 0:60:101 - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_6_deployed") - codecopy(_1, dataoffset("C_6_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_6_deployed") + codecopy(_2, dataoffset("C_6_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_location_only/input.sol" diff --git a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output index c8715df15051..5b9fe4b5b04d 100644 --- a/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output +++ b/test/cmdlineTests/debug_info_in_yul_and_evm_asm_print_none/output @@ -163,12 +163,12 @@ Optimized IR: object "C_6" { code { { - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_6_deployed") - codecopy(_1, dataoffset("C_6_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_6_deployed") + codecopy(_2, dataoffset("C_6_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"debug_info_in_yul_and_evm_asm_print_none/input.sol" diff --git a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output index d5c02fc82151..2f1f023cf46f 100644 --- a/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output +++ b/test/cmdlineTests/debug_info_in_yul_snippet_escaping/output @@ -68,12 +68,12 @@ object "C_2" { code { { /// @src 0:265:278 "contract C {}" - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_2_deployed") - codecopy(_1, dataoffset("C_2_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_2_deployed") + codecopy(_2, dataoffset("C_2_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" @@ -414,12 +414,12 @@ object "D_27" { code { { /// @src 0:279:599 "contract D /** @src 0:96:165 \"contract D {...\" *\/ {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("D_27_deployed") - codecopy(_1, dataoffset("D_27_deployed"), _2) - return(_1, _2) + let _1 := datasize("D_27_deployed") + codecopy(_2, dataoffset("D_27_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" @@ -503,12 +503,12 @@ object "D_27" { code { { /// @src 0:265:278 "contract C {}" - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_2_deployed") - codecopy(_1, dataoffset("C_2_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_2_deployed") + codecopy(_2, dataoffset("C_2_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"debug_info_in_yul_snippet_escaping/input.sol" diff --git a/test/cmdlineTests/inline_assembly_function_name_clash/output b/test/cmdlineTests/inline_assembly_function_name_clash/output index d7c7bf9e09d9..f0538678707c 100644 --- a/test/cmdlineTests/inline_assembly_function_name_clash/output +++ b/test/cmdlineTests/inline_assembly_function_name_clash/output @@ -2,64 +2,64 @@ "contracts": { "inline_assembly_function_name_clash/input.sol:C": { "function-debug-runtime": { - "abi_decode": { + "abi_decode_tuple_": { "entryPoint": 80, "parameterSlots": 2, "returnSlots": 0 }, - "abi_encode_uint256": { - "entryPoint": 111, - "parameterSlots": 2, - "returnSlots": 1 - }, - "abi_encode_uint256_to_uint256": { + "abi_encode_t_uint256_to_t_uint256_fromStack": { "entryPoint": 98, "parameterSlots": 2, "returnSlots": 0 }, + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack": { + "entryPoint": 111, + "parameterSlots": 2, + "returnSlots": 1 + }, "allocate_unbounded": { "entryPoint": 66, "parameterSlots": 0, "returnSlots": 1 }, - "cleanup_uint256": { + "cleanup_t_uint256": { "entryPoint": 95, "parameterSlots": 1, "returnSlots": 1 }, - "convert_uint256_to_uint256": { + "convert_t_uint256_to_t_uint256": { "entryPoint": 276, "parameterSlots": 1, "returnSlots": 1 }, - "external_fun_f": { + "external_fun_f_25": { "entryPoint": 132, "parameterSlots": 0, "returnSlots": 0 }, - "external_fun_g": { + "external_fun_g_36": { "entryPoint": 185, "parameterSlots": 0, "returnSlots": 0 }, - "fun_f": { + "fun_f_25": { "entryPoint": 442, "id": 25, "parameterSlots": 0, "returnSlots": 1 }, - "fun_f_inner": { + "fun_f_25_inner": { "entryPoint": 430, "parameterSlots": 1, "returnSlots": 1 }, - "fun_g": { + "fun_g_36": { "entryPoint": 564, "id": 36, "parameterSlots": 0, "returnSlots": 1 }, - "fun_g_inner": { + "fun_g_36_inner": { "entryPoint": 552, "parameterSlots": 1, "returnSlots": 1 @@ -69,12 +69,6 @@ "parameterSlots": 1, "returnSlots": 1 }, - "modifier_m": { - "entryPoint": 509, - "id": 14, - "parameterSlots": 1, - "returnSlots": 1 - }, "modifier_m_17": { "entryPoint": 344, "id": 14, @@ -93,7 +87,13 @@ "parameterSlots": 1, "returnSlots": 1 }, - "prepare_store_uint256": { + "modifier_m_30": { + "entryPoint": 509, + "id": 14, + "parameterSlots": 1, + "returnSlots": 1 + }, + "prepare_store_t_uint256": { "entryPoint": 304, "parameterSlots": 1, "returnSlots": 1 @@ -113,22 +113,22 @@ "parameterSlots": 0, "returnSlots": 0 }, - "shift_left": { + "shift_left_0": { "entryPoint": 246, "parameterSlots": 1, "returnSlots": 1 }, - "shift_right_unsigned": { + "shift_right_224_unsigned": { "entryPoint": 60, "parameterSlots": 1, "returnSlots": 1 }, - "update_byte_slice_shift": { + "update_byte_slice_32_shift_0": { "entryPoint": 251, "parameterSlots": 2, "returnSlots": 1 }, - "update_storage_value_offsett_uint256_to_uint256": { + "update_storage_value_offset_0t_uint256_to_t_uint256": { "entryPoint": 307, "parameterSlots": 2, "returnSlots": 0 @@ -138,32 +138,32 @@ "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_17": { + "usr$f_1": { "entryPoint": 382, "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_22": { + "usr$f_2": { "entryPoint": 425, "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_26": { + "usr$f_3": { "entryPoint": 461, "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_32": { + "usr$f_4": { "entryPoint": 504, "parameterSlots": 0, "returnSlots": 1 }, - "usr$f_37": { + "usr$f_5": { "entryPoint": 547, "parameterSlots": 0, "returnSlots": 1 }, - "zero_value_for_split_uint256": { + "zero_value_for_split_t_uint256": { "entryPoint": 242, "parameterSlots": 0, "returnSlots": 1 diff --git a/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output b/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output index 84fd9d0bc35f..d71263d61794 100644 --- a/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output +++ b/test/cmdlineTests/ir_compiler_inheritance_nosubobjects/output @@ -4,12 +4,12 @@ object "C_7" { code { { /// @src 0:82:117 "contract C {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_7_deployed") - codecopy(_1, dataoffset("C_7_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_7_deployed") + codecopy(_2, dataoffset("C_7_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"ir_compiler_inheritance_nosubobjects/input.sol" @@ -30,12 +30,12 @@ object "D_10" { code { { /// @src 0:118:137 "contract D is C {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("D_10_deployed") - codecopy(_1, dataoffset("D_10_deployed"), _2) - return(_1, _2) + let _1 := datasize("D_10_deployed") + codecopy(_2, dataoffset("D_10_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"ir_compiler_inheritance_nosubobjects/input.sol" diff --git a/test/cmdlineTests/ir_compiler_subobjects/output b/test/cmdlineTests/ir_compiler_subobjects/output index 39ef53f5529b..df474366932d 100644 --- a/test/cmdlineTests/ir_compiler_subobjects/output +++ b/test/cmdlineTests/ir_compiler_subobjects/output @@ -4,12 +4,12 @@ object "C_3" { code { { /// @src 0:82:95 "contract C {}" - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_3_deployed") - codecopy(_1, dataoffset("C_3_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_3_deployed") + codecopy(_2, dataoffset("C_3_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"ir_compiler_subobjects/input.sol" @@ -30,12 +30,12 @@ object "D_16" { code { { /// @src 0:96:165 "contract D {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("D_16_deployed") - codecopy(_1, dataoffset("D_16_deployed"), _2) - return(_1, _2) + let _1 := datasize("D_16_deployed") + codecopy(_2, dataoffset("D_16_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"ir_compiler_subobjects/input.sol" @@ -53,8 +53,8 @@ object "D_16" { if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } /// @src 0:149:156 "new C()" let _2 := datasize("C_3") - let _3 := add(_1, _2) - if or(gt(_3, 0xffffffffffffffff), lt(_3, _1)) + let _2_1 := add(_1, _2) + if or(gt(_2_1, 0xffffffffffffffff), lt(_2_1, _1)) { /// @src 0:96:165 "contract D {..." mstore(0, shl(224, 0x4e487b71)) @@ -63,7 +63,7 @@ object "D_16" { } /// @src 0:149:156 "new C()" datacopy(_1, dataoffset("C_3"), _2) - if iszero(create(/** @src 0:96:165 "contract D {..." */ 0, /** @src 0:149:156 "new C()" */ _1, sub(_3, _1))) + if iszero(create(/** @src 0:96:165 "contract D {..." */ 0, /** @src 0:149:156 "new C()" */ _1, sub(_2_1, _1))) { /// @src 0:96:165 "contract D {..." let pos := mload(64) @@ -81,12 +81,12 @@ object "D_16" { code { { /// @src 0:82:95 "contract C {}" - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_3_deployed") - codecopy(_1, dataoffset("C_3_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_3_deployed") + codecopy(_2, dataoffset("C_3_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"ir_compiler_subobjects/input.sol" diff --git a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output index f6be1493ec79..383a1770e503 100644 --- a/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output +++ b/test/cmdlineTests/ir_with_assembly_no_memoryguard_runtime/output @@ -4,12 +4,12 @@ object "D_8" { code { { /// @src 0:82:166 "contract D {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("D_8_deployed") - codecopy(_1, dataoffset("D_8_deployed"), _2) - return(_1, _2) + let _1 := datasize("D_8_deployed") + codecopy(_2, dataoffset("D_8_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"ir_with_assembly_no_memoryguard_runtime/input.sol" diff --git a/test/cmdlineTests/keccak_optimization_low_runs/output b/test/cmdlineTests/keccak_optimization_low_runs/output index c308d737b2f5..29d43d8c706b 100644 --- a/test/cmdlineTests/keccak_optimization_low_runs/output +++ b/test/cmdlineTests/keccak_optimization_low_runs/output @@ -4,12 +4,12 @@ object "C_7" { code { { /// @src 0:62:285 "contract C {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_7_deployed") - codecopy(_1, dataoffset("C_7_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_7_deployed") + codecopy(_2, dataoffset("C_7_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"keccak_optimization_low_runs/input.sol" diff --git a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output index 170cdf1a7a3a..55197ea0e48f 100644 --- a/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output +++ b/test/cmdlineTests/mcopy_bytes_array_returned_from_function/output @@ -3,12 +3,12 @@ Optimized IR: object "C_14" { code { { - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_14_deployed") - codecopy(_1, dataoffset("C_14_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_14_deployed") + codecopy(_2, dataoffset("C_14_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"mcopy_bytes_array_returned_from_function/input.sol" diff --git a/test/cmdlineTests/mcopy_string_literal_returned_from_function/output b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output index 548c34de8628..a7f341d0e35a 100644 --- a/test/cmdlineTests/mcopy_string_literal_returned_from_function/output +++ b/test/cmdlineTests/mcopy_string_literal_returned_from_function/output @@ -3,12 +3,12 @@ Optimized IR: object "C_10" { code { { - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_10_deployed") - codecopy(_1, dataoffset("C_10_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_10_deployed") + codecopy(_2, dataoffset("C_10_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"mcopy_string_literal_returned_from_function/input.sol" diff --git a/test/cmdlineTests/name_simplifier/output b/test/cmdlineTests/name_simplifier/output index 04abaf600103..813010d90d87 100644 --- a/test/cmdlineTests/name_simplifier/output +++ b/test/cmdlineTests/name_simplifier/output @@ -4,12 +4,12 @@ object "C_59" { code { { /// @src 0:346:625 "contract C {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_59_deployed") - codecopy(_1, dataoffset("C_59_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_59_deployed") + codecopy(_2, dataoffset("C_59_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"name_simplifier/input.sol" diff --git a/test/cmdlineTests/optimizer_array_sload/output b/test/cmdlineTests/optimizer_array_sload/output index c1e0796f56fa..7f563eb9d8c6 100644 --- a/test/cmdlineTests/optimizer_array_sload/output +++ b/test/cmdlineTests/optimizer_array_sload/output @@ -4,12 +4,12 @@ object "Arraysum_34" { code { { /// @src 0:80:429 "contract Arraysum {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("Arraysum_34_deployed") - codecopy(_1, dataoffset("Arraysum_34_deployed"), _2) - return(_1, _2) + let _1 := datasize("Arraysum_34_deployed") + codecopy(_2, dataoffset("Arraysum_34_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"optimizer_array_sload/input.sol" @@ -24,11 +24,11 @@ object "Arraysum_34" { { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let var_sum := 0 + let var_sum_8 := 0 /// @src 0:175:182 "sum = 0" - var_sum := /** @src 0:80:429 "contract Arraysum {..." */ 0 + var_sum_8 := /** @src 0:80:429 "contract Arraysum {..." */ 0 /// @src 0:368:378 "uint i = 0" - let var_i := /** @src 0:80:429 "contract Arraysum {..." */ 0 + let var_i_15 := /** @src 0:80:429 "contract Arraysum {..." */ 0 let _1 := sload(0) /// @src 0:364:423 "for(uint i = 0; i < values.length; i++)..." for { } @@ -36,29 +36,29 @@ object "Arraysum_34" { /// @src 0:368:378 "uint i = 0" { /// @src 0:399:402 "i++" - var_i := /** @src 0:80:429 "contract Arraysum {..." */ add(/** @src 0:399:402 "i++" */ var_i, /** @src 0:80:429 "contract Arraysum {..." */ 1) + var_i_15 := /** @src 0:80:429 "contract Arraysum {..." */ add(/** @src 0:399:402 "i++" */ var_i_15, /** @src 0:80:429 "contract Arraysum {..." */ 1) } /// @src 0:399:402 "i++" { /// @src 0:380:397 "i < values.length" - let _2 := iszero(lt(var_i, _1)) + let _2 := iszero(lt(var_i_15, _1)) if _2 { break } /// @src 0:80:429 "contract Arraysum {..." _2 := 0 mstore(0, 0) - let sum := add(var_sum, sload(add(18569430475105882587588266137607568536673111973893317399460219858819262702947, var_i))) - if gt(var_sum, sum) + let sum := add(var_sum_8, sload(add(18569430475105882587588266137607568536673111973893317399460219858819262702947, var_i_15))) + if gt(var_sum_8, sum) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } /// @src 0:407:423 "sum += values[i]" - var_sum := sum + var_sum_8 := sum } /// @src 0:80:429 "contract Arraysum {..." let memPos := mload(64) - mstore(memPos, var_sum) + mstore(memPos, var_sum_8) return(memPos, 0x20) } } diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json index 9489a75bf3df..869590997077 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_all/output.json @@ -175,12 +175,12 @@ object \"C_6\" { code { { /// @src 0:60:101 \"contract C {...\" - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize(\"C_6_deployed\") - codecopy(_1, dataoffset(\"C_6_deployed\"), _2) - return(_1, _2) + let _1 := datasize(\"C_6_deployed\") + codecopy(_2, dataoffset(\"C_6_deployed\"), _1) + return(_2, _1) } } /// @use-src 0:\"C\" diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json index f8f2958b0384..cff699a7028c 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_location_only/output.json @@ -174,12 +174,12 @@ object \"C_6\" { code { { /// @src 0:60:101 - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize(\"C_6_deployed\") - codecopy(_1, dataoffset(\"C_6_deployed\"), _2) - return(_1, _2) + let _1 := datasize(\"C_6_deployed\") + codecopy(_2, dataoffset(\"C_6_deployed\"), _1) + return(_2, _1) } } /// @use-src 0:\"C\" diff --git a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json index 2a5a2bc2ae15..7b432f1a7ed1 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_and_evm_asm_print_none/output.json @@ -164,12 +164,12 @@ object \"C_6\" { object \"C_6\" { code { { - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize(\"C_6_deployed\") - codecopy(_1, dataoffset(\"C_6_deployed\"), _2) - return(_1, _2) + let _1 := datasize(\"C_6_deployed\") + codecopy(_2, dataoffset(\"C_6_deployed\"), _1) + return(_2, _1) } } /// @use-src 0:\"C\" diff --git a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json index 8f0d5b5b5d6d..eef2a3be49d8 100644 --- a/test/cmdlineTests/standard_debug_info_in_yul_location/output.json +++ b/test/cmdlineTests/standard_debug_info_in_yul_location/output.json @@ -614,35 +614,35 @@ object \"C_54\" { code { { /// @src 0:79:510 \"contract C...\" - let _1 := memoryguard(0xa0) + let _3 := memoryguard(0xa0) if callvalue() { revert(0, 0) } let programSize := datasize(\"C_54\") let argSize := sub(codesize(), programSize) - let newFreePtr := add(_1, and(add(argSize, 31), not(31))) - if or(gt(newFreePtr, sub(shl(64, 1), 1)), lt(newFreePtr, _1)) + let newFreePtr := add(_3, and(add(argSize, 31), not(31))) + if or(gt(newFreePtr, sub(shl(64, 1), 1)), lt(newFreePtr, _3)) { mstore(/** @src -1:-1:-1 */ 0, /** @src 0:79:510 \"contract C...\" */ shl(224, 0x4e487b71)) mstore(4, 0x41) revert(/** @src -1:-1:-1 */ 0, /** @src 0:79:510 \"contract C...\" */ 0x24) } mstore(64, newFreePtr) - codecopy(_1, programSize, argSize) - if slt(sub(add(_1, argSize), _1), 32) + codecopy(_3, programSize, argSize) + if slt(sub(add(_3, argSize), _3), 32) { revert(/** @src -1:-1:-1 */ 0, 0) } /// @src 0:79:510 \"contract C...\" - let value := mload(_1) + let value := mload(_3) /// @src 0:160:162 \"42\" mstore(128, 0x2a) /// @src 0:79:510 \"contract C...\" sstore(/** @src -1:-1:-1 */ 0, /** @src 0:79:510 \"contract C...\" */ value) let _2 := mload(64) - let _3 := datasize(\"C_54_deployed\") - codecopy(_2, dataoffset(\"C_54_deployed\"), _3) + let _1 := datasize(\"C_54_deployed\") + codecopy(_2, dataoffset(\"C_54_deployed\"), _1) setimmutable(_2, \"8\", mload(/** @src 0:160:162 \"42\" */ 128)) /// @src 0:79:510 \"contract C...\" - return(_2, _3) + return(_2, _1) } } /// @use-src 0:\"C\" @@ -658,47 +658,47 @@ object \"C_54\" { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } /// @src 0:333:341 \"immutVar\" - let _1 := loadimmutable(\"8\") + let _3 := loadimmutable(\"8\") /// @src 0:322:341 \"constVar + immutVar\" - let sum := /** @src 0:79:510 \"contract C...\" */ 0 - sum := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 0:79:510 \"contract C...\" */ _1) - if and(1, slt(sum, _1)) + let sum_1 := /** @src 0:79:510 \"contract C...\" */ 0 + sum_1 := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 0:79:510 \"contract C...\" */ _3) + if and(1, slt(sum_1, _3)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } let memPos := mload(64) - mstore(memPos, sum) + mstore(memPos, sum_1) return(memPos, 32) } case 0x793816ec { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _2 := sload(0) + let _4 := sload(0) let memPos_1 := mload(64) - mstore(memPos_1, _2) + mstore(memPos_1, _4) return(memPos_1, 32) } case 0x9942ec6f { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _3 := sload(0) - if eq(_3, sub(shl(255, 1), 1)) + let _5 := sload(0) + if eq(_5, sub(shl(255, 1), 1)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } - let ret := add(_3, 1) + let ret := add(_5, 1) sstore(0, ret) /// @src 0:482:490 \"this.f()\" - let _4 := /** @src 0:79:510 \"contract C...\" */ mload(64) + let _10 := /** @src 0:79:510 \"contract C...\" */ mload(64) /// @src 0:482:490 \"this.f()\" - mstore(_4, /** @src 0:79:510 \"contract C...\" */ shl(228, 0x026121ff)) + mstore(_10, /** @src 0:79:510 \"contract C...\" */ shl(228, 0x026121ff)) /// @src 0:482:490 \"this.f()\" - let _5 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _4, /** @src 0:79:510 \"contract C...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _4, 32) - if iszero(_5) + let _12 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _10, /** @src 0:79:510 \"contract C...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _10, 32) + if iszero(_12) { /// @src 0:79:510 \"contract C...\" let pos := mload(64) @@ -706,34 +706,34 @@ object \"C_54\" { revert(pos, returndatasize()) } /// @src 0:482:490 \"this.f()\" - let expr := /** @src 0:79:510 \"contract C...\" */ 0 + let expr_47 := /** @src 0:79:510 \"contract C...\" */ 0 /// @src 0:482:490 \"this.f()\" - if _5 + if _12 { - let _6 := 32 - if gt(32, returndatasize()) { _6 := returndatasize() } + let _13 := 32 + if gt(32, returndatasize()) { _13 := returndatasize() } /// @src 0:79:510 \"contract C...\" - let newFreePtr := add(_4, and(add(_6, 31), not(31))) - if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _4)) + let newFreePtr := add(_10, and(add(_13, 31), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _10)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x41) revert(0, 0x24) } mstore(64, newFreePtr) - if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_4, _6), /** @src 0:79:510 \"contract C...\" */ _4), /** @src 0:482:490 \"this.f()\" */ 32) + if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_10, _13), /** @src 0:79:510 \"contract C...\" */ _10), /** @src 0:482:490 \"this.f()\" */ 32) /// @src 0:79:510 \"contract C...\" { revert(0, 0) } /// @src 0:482:490 \"this.f()\" - expr := /** @src 0:79:510 \"contract C...\" */ mload(_4) + expr_47 := /** @src 0:79:510 \"contract C...\" */ mload(_10) } /// @src 0:471:490 \"stateVar + this.f()\" - let expr_1 := checked_add_int256(ret, expr) + let expr_48 := checked_add_t_int256(ret, expr_47) /// @src 0:464:501 \"return stateVar + this.f() + immutVar\" - let var := /** @src 0:471:501 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:493:501 \"immutVar\" */ loadimmutable(\"8\")) + let var__42 := /** @src 0:471:501 \"stateVar + this.f() + immutVar\" */ checked_add_t_int256(expr_48, /** @src 0:493:501 \"immutVar\" */ loadimmutable(\"8\")) /// @src 0:79:510 \"contract C...\" let memPos_2 := mload(64) - mstore(memPos_2, var) + mstore(memPos_2, var__42) return(memPos_2, /** @src 0:482:490 \"this.f()\" */ 32) } case /** @src 0:79:510 \"contract C...\" */ 0xa00b982b { @@ -747,7 +747,7 @@ object \"C_54\" { } revert(0, 0) } - function checked_add_int256(x, y) -> sum + function checked_add_t_int256(x, y) -> sum { sum := add(x, y) let _1 := slt(sum, y) @@ -1450,25 +1450,25 @@ object \"D_72\" { code { { /// @src 1:91:181 \"contract D is C(3)...\" - let _1 := memoryguard(0xa0) + let _3 := memoryguard(0xa0) if callvalue() { revert(0, 0) } let programSize := datasize(\"D_72\") let argSize := sub(codesize(), programSize) - let newFreePtr := add(_1, and(add(argSize, 31), not(31))) - if or(gt(newFreePtr, sub(shl(64, 1), 1)), lt(newFreePtr, _1)) + let newFreePtr := add(_3, and(add(argSize, 31), not(31))) + if or(gt(newFreePtr, sub(shl(64, 1), 1)), lt(newFreePtr, _3)) { mstore(/** @src -1:-1:-1 */ 0, /** @src 1:91:181 \"contract D is C(3)...\" */ shl(224, 0x4e487b71)) mstore(4, 0x41) revert(/** @src -1:-1:-1 */ 0, /** @src 1:91:181 \"contract D is C(3)...\" */ 0x24) } mstore(64, newFreePtr) - codecopy(_1, programSize, argSize) - if slt(sub(add(_1, argSize), _1), 32) + codecopy(_3, programSize, argSize) + if slt(sub(add(_3, argSize), _3), 32) { revert(/** @src -1:-1:-1 */ 0, 0) } /// @src 1:91:181 \"contract D is C(3)...\" - let value := mload(_1) + let value := mload(_3) /// @src 0:160:162 \"42\" mstore(128, 0x2a) /// @src 1:91:181 \"contract D is C(3)...\" @@ -1481,11 +1481,11 @@ object \"D_72\" { } sstore(/** @src -1:-1:-1 */ 0, /** @src 1:91:181 \"contract D is C(3)...\" */ sum) let _2 := mload(64) - let _3 := datasize(\"D_72_deployed\") - codecopy(_2, dataoffset(\"D_72_deployed\"), _3) + let _1 := datasize(\"D_72_deployed\") + codecopy(_2, dataoffset(\"D_72_deployed\"), _1) setimmutable(_2, \"8\", mload(/** @src 0:160:162 \"42\" */ 128)) /// @src 1:91:181 \"contract D is C(3)...\" - return(_2, _3) + return(_2, _1) } } /// @use-src 0:\"C\", 1:\"D\" @@ -1501,47 +1501,47 @@ object \"D_72\" { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } /// @src 0:333:341 \"immutVar\" - let _1 := loadimmutable(\"8\") + let _3 := loadimmutable(\"8\") /// @src 0:322:341 \"constVar + immutVar\" - let sum := /** @src 1:91:181 \"contract D is C(3)...\" */ 0 - sum := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 1:91:181 \"contract D is C(3)...\" */ _1) - if and(1, slt(sum, _1)) + let sum_1 := /** @src 1:91:181 \"contract D is C(3)...\" */ 0 + sum_1 := add(/** @src 0:127:129 \"41\" */ 0x29, /** @src 1:91:181 \"contract D is C(3)...\" */ _3) + if and(1, slt(sum_1, _3)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } let memPos := mload(64) - mstore(memPos, sum) + mstore(memPos, sum_1) return(memPos, 32) } case 0x793816ec { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _2 := sload(0) + let _4 := sload(0) let memPos_1 := mload(64) - mstore(memPos_1, _2) + mstore(memPos_1, _4) return(memPos_1, 32) } case 0x9942ec6f { if callvalue() { revert(0, 0) } if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } - let _3 := sload(0) - if eq(_3, sub(shl(255, 1), 1)) + let _5 := sload(0) + if eq(_5, sub(shl(255, 1), 1)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x11) revert(0, 0x24) } - let ret := add(_3, 1) + let ret := add(_5, 1) sstore(0, ret) /// @src 0:482:490 \"this.f()\" - let _4 := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(64) + let _10 := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(64) /// @src 0:482:490 \"this.f()\" - mstore(_4, /** @src 1:91:181 \"contract D is C(3)...\" */ shl(228, 0x026121ff)) + mstore(_10, /** @src 1:91:181 \"contract D is C(3)...\" */ shl(228, 0x026121ff)) /// @src 0:482:490 \"this.f()\" - let _5 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _4, /** @src 1:91:181 \"contract D is C(3)...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _4, 32) - if iszero(_5) + let _12 := staticcall(gas(), /** @src 0:482:486 \"this\" */ address(), /** @src 0:482:490 \"this.f()\" */ _10, /** @src 1:91:181 \"contract D is C(3)...\" */ 4, /** @src 0:482:490 \"this.f()\" */ _10, 32) + if iszero(_12) { /// @src 1:91:181 \"contract D is C(3)...\" let pos := mload(64) @@ -1549,34 +1549,34 @@ object \"D_72\" { revert(pos, returndatasize()) } /// @src 0:482:490 \"this.f()\" - let expr := /** @src 1:91:181 \"contract D is C(3)...\" */ 0 + let expr_47 := /** @src 1:91:181 \"contract D is C(3)...\" */ 0 /// @src 0:482:490 \"this.f()\" - if _5 + if _12 { - let _6 := 32 - if gt(32, returndatasize()) { _6 := returndatasize() } + let _13 := 32 + if gt(32, returndatasize()) { _13 := returndatasize() } /// @src 1:91:181 \"contract D is C(3)...\" - let newFreePtr := add(_4, and(add(_6, 31), not(31))) - if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _4)) + let newFreePtr := add(_10, and(add(_13, 31), not(31))) + if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, _10)) { mstore(0, shl(224, 0x4e487b71)) mstore(4, 0x41) revert(0, 0x24) } mstore(64, newFreePtr) - if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_4, _6), /** @src 1:91:181 \"contract D is C(3)...\" */ _4), /** @src 0:482:490 \"this.f()\" */ 32) + if slt(sub(/** @src 0:482:490 \"this.f()\" */ add(_10, _13), /** @src 1:91:181 \"contract D is C(3)...\" */ _10), /** @src 0:482:490 \"this.f()\" */ 32) /// @src 1:91:181 \"contract D is C(3)...\" { revert(0, 0) } /// @src 0:482:490 \"this.f()\" - expr := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(_4) + expr_47 := /** @src 1:91:181 \"contract D is C(3)...\" */ mload(_10) } /// @src 0:471:490 \"stateVar + this.f()\" - let expr_1 := checked_add_int256(ret, expr) + let expr_48 := checked_add_t_int256(ret, expr_47) /// @src 0:464:501 \"return stateVar + this.f() + immutVar\" - let var := /** @src 0:471:501 \"stateVar + this.f() + immutVar\" */ checked_add_int256(expr_1, /** @src 0:493:501 \"immutVar\" */ loadimmutable(\"8\")) + let var__42 := /** @src 0:471:501 \"stateVar + this.f() + immutVar\" */ checked_add_t_int256(expr_48, /** @src 0:493:501 \"immutVar\" */ loadimmutable(\"8\")) /// @src 1:91:181 \"contract D is C(3)...\" let memPos_2 := mload(64) - mstore(memPos_2, var) + mstore(memPos_2, var__42) return(memPos_2, /** @src 0:482:490 \"this.f()\" */ 32) } case /** @src 1:91:181 \"contract D is C(3)...\" */ 0xa00b982b { @@ -1590,7 +1590,7 @@ object \"D_72\" { } revert(0, 0) } - function checked_add_int256(x, y) -> sum + function checked_add_t_int256(x, y) -> sum { sum := add(x, y) let _1 := slt(sum, y) diff --git a/test/cmdlineTests/standard_irOptimized_requested/output.json b/test/cmdlineTests/standard_irOptimized_requested/output.json index 849b436b24a5..fa0bea9d9b5a 100644 --- a/test/cmdlineTests/standard_irOptimized_requested/output.json +++ b/test/cmdlineTests/standard_irOptimized_requested/output.json @@ -29,14 +29,14 @@ object \"C_7\" { mstore(64, memoryguard(0x80)) if iszero(lt(calldatasize(), 4)) { - let selector := shift_right_unsigned(calldataload(0)) + let selector := shift_right_224_unsigned(calldataload(0)) switch selector - case 0x26121ff0 { external_fun_f() } + case 0x26121ff0 { external_fun_f_6() } default { } } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() } - function shift_right_unsigned(value) -> newValue + function shift_right_224_unsigned(value) -> newValue { newValue := shr(224, value) } function allocate_unbounded() -> memPtr { memPtr := mload(64) } @@ -44,24 +44,24 @@ object \"C_7\" { { revert(0, 0) } function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { revert(0, 0) } - function abi_decode(headStart, dataEnd) + function abi_decode_tuple_(headStart, dataEnd) { if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } } - function abi_encode_tuple(headStart) -> tail - { tail := add(headStart, 0) } - function external_fun_f() + function abi_encode_tuple__to__fromStack(headStart_1) -> tail + { tail := add(headStart_1, 0) } + function external_fun_f_6() { if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode(4, calldatasize()) + abi_decode_tuple_(4, calldatasize()) let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple(memPos) + let memEnd := abi_encode_tuple__to__fromStack(memPos) return(memPos, sub(memEnd, memPos)) } function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() diff --git a/test/cmdlineTests/standard_optimizer_generatedSources/output.json b/test/cmdlineTests/standard_optimizer_generatedSources/output.json index e5b276b1b9b6..ed8c410c00db 100644 --- a/test/cmdlineTests/standard_optimizer_generatedSources/output.json +++ b/test/cmdlineTests/standard_optimizer_generatedSources/output.json @@ -11,9 +11,9 @@ "generatedSources": [ { "ast": { - "nativeSrc": "0:1505:1", + "nativeSrc": "0:1515:1", "nodeType": "YulBlock", - "src": "0:1505:1", + "src": "0:1515:1", "statements": [ { "nativeSrc": "6:3:1", @@ -1419,47 +1419,47 @@ }, { "body": { - "nativeSrc": "1427:76:1", + "nativeSrc": "1431:82:1", "nodeType": "YulBlock", - "src": "1427:76:1", + "src": "1431:82:1", "statements": [ { - "nativeSrc": "1437:26:1", + "nativeSrc": "1441:28:1", "nodeType": "YulAssignment", - "src": "1437:26:1", + "src": "1441:28:1", "value": { "arguments": [ { - "name": "headStart", - "nativeSrc": "1449:9:1", + "name": "headStart_1", + "nativeSrc": "1453:11:1", "nodeType": "YulIdentifier", - "src": "1449:9:1" + "src": "1453:11:1" }, { "kind": "number", - "nativeSrc": "1460:2:1", + "nativeSrc": "1466:2:1", "nodeType": "YulLiteral", - "src": "1460:2:1", + "src": "1466:2:1", "type": "", "value": "32" } ], "functionName": { "name": "add", - "nativeSrc": "1445:3:1", + "nativeSrc": "1449:3:1", "nodeType": "YulIdentifier", - "src": "1445:3:1" + "src": "1449:3:1" }, - "nativeSrc": "1445:18:1", + "nativeSrc": "1449:20:1", "nodeType": "YulFunctionCall", - "src": "1445:18:1" + "src": "1449:20:1" }, "variableNames": [ { "name": "tail", - "nativeSrc": "1437:4:1", + "nativeSrc": "1441:4:1", "nodeType": "YulIdentifier", - "src": "1437:4:1" + "src": "1441:4:1" } ] }, @@ -1467,63 +1467,63 @@ "expression": { "arguments": [ { - "name": "headStart", - "nativeSrc": "1479:9:1", + "name": "headStart_1", + "nativeSrc": "1485:11:1", "nodeType": "YulIdentifier", - "src": "1479:9:1" + "src": "1485:11:1" }, { - "name": "value0", - "nativeSrc": "1490:6:1", + "name": "value0_1", + "nativeSrc": "1498:8:1", "nodeType": "YulIdentifier", - "src": "1490:6:1" + "src": "1498:8:1" } ], "functionName": { "name": "mstore", - "nativeSrc": "1472:6:1", + "nativeSrc": "1478:6:1", "nodeType": "YulIdentifier", - "src": "1472:6:1" + "src": "1478:6:1" }, - "nativeSrc": "1472:25:1", + "nativeSrc": "1478:29:1", "nodeType": "YulFunctionCall", - "src": "1472:25:1" + "src": "1478:29:1" }, - "nativeSrc": "1472:25:1", + "nativeSrc": "1478:29:1", "nodeType": "YulExpressionStatement", - "src": "1472:25:1" + "src": "1478:29:1" } ] }, "name": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed", - "nativeSrc": "1326:177:1", + "nativeSrc": "1326:187:1", "nodeType": "YulFunctionDefinition", "parameters": [ { - "name": "headStart", - "nativeSrc": "1396:9:1", + "name": "headStart_1", + "nativeSrc": "1396:11:1", "nodeType": "YulTypedName", - "src": "1396:9:1", + "src": "1396:11:1", "type": "" }, { - "name": "value0", - "nativeSrc": "1407:6:1", + "name": "value0_1", + "nativeSrc": "1409:8:1", "nodeType": "YulTypedName", - "src": "1407:6:1", + "src": "1409:8:1", "type": "" } ], "returnVariables": [ { "name": "tail", - "nativeSrc": "1418:4:1", + "nativeSrc": "1422:4:1", "nodeType": "YulTypedName", - "src": "1418:4:1", + "src": "1422:4:1", "type": "" } ], - "src": "1326:177:1" + "src": "1326:187:1" } ] }, @@ -1564,10 +1564,10 @@ } value0 := memPtr } - function abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed(headStart, value0) -> tail + function abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed(headStart_1, value0_1) -> tail { - tail := add(headStart, 32) - mstore(headStart, value0) + tail := add(headStart_1, 32) + mstore(headStart_1, value0_1) } }", "id": 1, diff --git a/test/cmdlineTests/strict_asm_debug_info_print_all/output b/test/cmdlineTests/strict_asm_debug_info_print_all/output index 0e58baf578e6..9efd584831ba 100644 --- a/test/cmdlineTests/strict_asm_debug_info_print_all/output +++ b/test/cmdlineTests/strict_asm_debug_info_print_all/output @@ -8,10 +8,10 @@ object "C_6_deployed" { { /// @src 0:60:101 mstore(64, 128) - fun_f() + fun_f_5() } /// @src 0:77:99 - function fun_f() + function fun_f_5() { sstore(0, 42) } } } diff --git a/test/cmdlineTests/strict_asm_debug_info_print_location_only/output b/test/cmdlineTests/strict_asm_debug_info_print_location_only/output index 17d2f50e2e15..31dd920f6b69 100644 --- a/test/cmdlineTests/strict_asm_debug_info_print_location_only/output +++ b/test/cmdlineTests/strict_asm_debug_info_print_location_only/output @@ -8,10 +8,10 @@ object "C_6_deployed" { { /// @src 0:60:101 mstore(64, 128) - fun_f() + fun_f_5() } /// @src 0:77:99 - function fun_f() + function fun_f_5() { sstore(0, 42) } } } diff --git a/test/cmdlineTests/strict_asm_debug_info_print_none/output b/test/cmdlineTests/strict_asm_debug_info_print_none/output index 51f779490ab7..de535e7c42c9 100644 --- a/test/cmdlineTests/strict_asm_debug_info_print_none/output +++ b/test/cmdlineTests/strict_asm_debug_info_print_none/output @@ -7,9 +7,9 @@ object "C_6_deployed" { code { { mstore(64, 128) - fun_f() + fun_f_5() } - function fun_f() + function fun_f_5() { sstore(0, 42) } } } diff --git a/test/cmdlineTests/viair_subobjects/output b/test/cmdlineTests/viair_subobjects/output index 7a6bc8e6570b..0dbcba8ff181 100644 --- a/test/cmdlineTests/viair_subobjects/output +++ b/test/cmdlineTests/viair_subobjects/output @@ -10,12 +10,12 @@ object "C_3" { code { { /// @src 0:82:95 "contract C {}" - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_3_deployed") - codecopy(_1, dataoffset("C_3_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_3_deployed") + codecopy(_2, dataoffset("C_3_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"viair_subobjects/input.sol" @@ -42,12 +42,12 @@ object "D_16" { code { { /// @src 0:96:165 "contract D {..." - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("D_16_deployed") - codecopy(_1, dataoffset("D_16_deployed"), _2) - return(_1, _2) + let _1 := datasize("D_16_deployed") + codecopy(_2, dataoffset("D_16_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"viair_subobjects/input.sol" @@ -65,8 +65,8 @@ object "D_16" { if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) } /// @src 0:149:156 "new C()" let _2 := datasize("C_3") - let _3 := add(_1, _2) - if or(gt(_3, 0xffffffffffffffff), lt(_3, _1)) + let _2_1 := add(_1, _2) + if or(gt(_2_1, 0xffffffffffffffff), lt(_2_1, _1)) { /// @src 0:96:165 "contract D {..." mstore(0, shl(224, 0x4e487b71)) @@ -75,7 +75,7 @@ object "D_16" { } /// @src 0:149:156 "new C()" datacopy(_1, dataoffset("C_3"), _2) - if iszero(create(/** @src 0:96:165 "contract D {..." */ 0, /** @src 0:149:156 "new C()" */ _1, sub(_3, _1))) + if iszero(create(/** @src 0:96:165 "contract D {..." */ 0, /** @src 0:149:156 "new C()" */ _1, sub(_2_1, _1))) { /// @src 0:96:165 "contract D {..." let pos := mload(64) @@ -93,12 +93,12 @@ object "D_16" { code { { /// @src 0:82:95 "contract C {}" - let _1 := memoryguard(0x80) - mstore(64, _1) + let _2 := memoryguard(0x80) + mstore(64, _2) if callvalue() { revert(0, 0) } - let _2 := datasize("C_3_deployed") - codecopy(_1, dataoffset("C_3_deployed"), _2) - return(_1, _2) + let _1 := datasize("C_3_deployed") + codecopy(_2, dataoffset("C_3_deployed"), _1) + return(_2, _1) } } /// @use-src 0:"viair_subobjects/input.sol" diff --git a/test/cmdlineTests/yul_function_name_clashes/output b/test/cmdlineTests/yul_function_name_clashes/output index 2c54b6f50893..7d077da74c86 100644 --- a/test/cmdlineTests/yul_function_name_clashes/output +++ b/test/cmdlineTests/yul_function_name_clashes/output @@ -13,8 +13,8 @@ object "object" { } function z() -> y { y := calldataload(0) } - function z_1() -> y - { y := calldataload(0x20) } + function z_1() -> y_1 + { y_1 := calldataload(0x20) } } } diff --git a/test/cmdlineTests/yul_function_name_clashes_different_params/output b/test/cmdlineTests/yul_function_name_clashes_different_params/output index 22cee64c1f48..06d6bd99ba08 100644 --- a/test/cmdlineTests/yul_function_name_clashes_different_params/output +++ b/test/cmdlineTests/yul_function_name_clashes_different_params/output @@ -13,8 +13,8 @@ object "object" { } function z() -> y { y := calldataload(0) } - function z_1(r) -> y - { y := calldataload(r) } + function z_1(r) -> y_1 + { y_1 := calldataload(r) } } } diff --git a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output index 9687abf643b3..eacc86582581 100644 --- a/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output +++ b/test/cmdlineTests/yul_optimizer_steps_nested_brackets/output @@ -29,12 +29,12 @@ object "C_6" { mstore(64, memoryguard(0x80)) if iszero(lt(calldatasize(), 4)) { - let selector := shift_right_unsigned(calldataload(0)) - if eq(0x26121ff0, selector) { external_fun_f() } + let selector := shift_right_224_unsigned(calldataload(0)) + if eq(0x26121ff0, selector) { external_fun_f_5() } } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() } - function shift_right_unsigned(value) -> newValue + function shift_right_224_unsigned(value) -> newValue { let newValue_1 := shr(224, value) newValue := newValue_1 @@ -48,27 +48,27 @@ object "C_6" { { revert(0, 0) } function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { revert(0, 0) } - function abi_decode(headStart, dataEnd) + function abi_decode_tuple_(headStart, dataEnd) { if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } } - function abi_encode_tuple(headStart) -> tail + function abi_encode_tuple__to__fromStack(headStart_1) -> tail { - let tail_1 := add(headStart, 0) + let tail_1 := add(headStart_1, 0) tail := tail_1 } - function external_fun_f() + function external_fun_f_5() { if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode(4, calldatasize()) + abi_decode_tuple_(4, calldatasize()) let memPos := allocate_unbounded() - let memEnd := abi_encode_tuple(memPos) + let memEnd := abi_encode_tuple__to__fromStack(memPos) return(memPos, sub(memEnd, memPos)) } function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() diff --git a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output index 6873abe60e47..87485511dc06 100644 --- a/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output +++ b/test/cmdlineTests/yul_optimizer_steps_without_optimize_empty_sequence/output @@ -11,7 +11,7 @@ object "C_28" { { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - constructor_C() + constructor_C_28() let _1 := allocate_unbounded() codecopy(_1, dataoffset("C_28_deployed"), datasize("C_28_deployed")) return(_1, datasize("C_28_deployed")) @@ -21,7 +21,7 @@ object "C_28" { function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() { revert(0, 0) } /// @ast-id 5 @src 0:77:93 "constructor() {}" - function constructor_C() + function constructor_C_28() { } } /// @use-src 0:"yul_optimizer_steps_without_optimize_empty_sequence/input.sol" @@ -32,14 +32,14 @@ object "C_28" { mstore(64, memoryguard(0x80)) if iszero(lt(calldatasize(), 4)) { - let selector := shift_right_unsigned(calldataload(0)) + let selector := shift_right_224_unsigned(calldataload(0)) switch selector - case 0xc2985578 { external_fun_foo() } + case 0xc2985578 { external_fun_foo_27() } default { } } revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() } - function shift_right_unsigned(value) -> newValue + function shift_right_224_unsigned(value) -> newValue { newValue := shr(224, value) } function allocate_unbounded() -> memPtr { memPtr := mload(64) } @@ -47,81 +47,81 @@ object "C_28" { { revert(0, 0) } function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() { revert(0, 0) } - function abi_decode(headStart, dataEnd) + function abi_decode_tuple_(headStart, dataEnd) { if slt(sub(dataEnd, headStart), 0) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() } } - function cleanup_bool(value) -> cleaned + function cleanup_t_bool(value_1) -> cleaned { - cleaned := iszero(iszero(value)) + cleaned := iszero(iszero(value_1)) } - function abi_encode_bool_to_bool(value, pos) + function abi_encode_t_bool_to_t_bool_fromStack(value_2, pos) { - mstore(pos, cleanup_bool(value)) + mstore(pos, cleanup_t_bool(value_2)) } - function abi_encode_bool(headStart, value0) -> tail + function abi_encode_tuple_t_bool__to_t_bool__fromStack(headStart_1, value0) -> tail { - tail := add(headStart, 32) - abi_encode_bool_to_bool(value0, add(headStart, 0)) + tail := add(headStart_1, 32) + abi_encode_t_bool_to_t_bool_fromStack(value0, add(headStart_1, 0)) } - function external_fun_foo() + function external_fun_foo_27() { if callvalue() { revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb() } - abi_decode(4, calldatasize()) - let ret := fun_foo() + abi_decode_tuple_(4, calldatasize()) + let ret_0 := fun_foo_27() let memPos := allocate_unbounded() - let memEnd := abi_encode_bool(memPos, ret) + let memEnd := abi_encode_tuple_t_bool__to_t_bool__fromStack(memPos, ret_0) return(memPos, sub(memEnd, memPos)) } function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74() { revert(0, 0) } - function zero_value_for_split_bool() -> ret + function zero_value_for_split_t_bool() -> ret { ret := 0 } - function cleanup_rational_by(value) -> cleaned - { cleaned := value } - function cleanup_uint256(value) -> cleaned - { cleaned := value } - function identity(value) -> ret - { ret := value } - function convert_rational_by_to_uint256(value) -> converted + function cleanup_t_rational_100_by_1(value_3) -> cleaned_1 + { cleaned_1 := value_3 } + function cleanup_t_uint256(value_4) -> cleaned_2 + { cleaned_2 := value_4 } + function identity(value_5) -> ret_1 + { ret_1 := value_5 } + function convert_t_rational_100_by_1_to_t_uint256(value_6) -> converted { - converted := cleanup_uint256(identity(cleanup_rational_by(value))) + converted := cleanup_t_uint256(identity(cleanup_t_rational_100_by_1(value_6))) } /// @ast-id 27 @src 0:99:408 "function foo() public pure returns (bool)..." - function fun_foo() -> var + function fun_foo_27() -> var__8 { /// @src 0:135:139 "bool" - let zero_bool := zero_value_for_split_bool() - var := zero_bool + let zero_t_bool_1 := zero_value_for_split_t_bool() + var__8 := zero_t_bool_1 /// @src 0:332:335 "100" - let expr := 0x64 + let expr_12 := 0x64 /// @src 0:323:335 "uint a = 100" - let var_a := convert_rational_by_to_uint256(expr) + let var_a_11 := convert_t_rational_100_by_1_to_t_uint256(expr_12) /// @src 0:354:355 "a" - let _1 := var_a - let expr_1 := _1 + let _2 := var_a_11 + let expr_16 := _2 /// @src 0:345:355 "uint b = a" - let var_b := expr_1 + let var_b_15 := expr_16 /// @src 0:374:375 "a" - let _2 := var_a - let expr_2 := _2 + let _3 := var_a_11 + let expr_20 := _3 /// @src 0:365:375 "uint c = a" - let var_c := expr_2 + let var_c_19 := expr_20 /// @src 0:393:394 "a" - let _3 := var_a - let expr_3 := _3 + let _4 := var_a_11 + let expr_22 := _4 /// @src 0:398:401 "100" - let expr_4 := 0x64 + let expr_23 := 0x64 /// @src 0:393:401 "a == 100" - let expr_5 := eq(cleanup_uint256(expr_3), convert_rational_by_to_uint256(expr_4)) + let expr_24 := eq(cleanup_t_uint256(expr_22), convert_t_rational_100_by_1_to_t_uint256(expr_23)) /// @src 0:386:401 "return a == 100" - var := expr_5 + var__8 := expr_24 leave } } diff --git a/test/cmdlineTests/~assembler_modes/test.sh b/test/cmdlineTests/~assembler_modes/test.sh index 5ca1bb40f82b..f3bc22c8d745 100755 --- a/test/cmdlineTests/~assembler_modes/test.sh +++ b/test/cmdlineTests/~assembler_modes/test.sh @@ -36,8 +36,8 @@ echo '{}' | "$SOLC" - --yul --optimize &>/dev/null && fail "solc --yul --optimiz # Test yul and strict assembly output # Non-empty code results in non-empty binary representation with optimizations turned off, # while it results in empty binary representation with optimizations turned on. -test_solc_assembly_output "{ let x:u256 := 0:u256 mstore(0, x) }" "{ { let x := 0 mstore(0, x) } }" "--yul" -test_solc_assembly_output "{ let x:u256 := bitnot(7:u256) mstore(0, x) }" "{ { let x := bitnot(7) mstore(0, x) } }" "--yul" -test_solc_assembly_output "{ let t:bool := not(true) if t { mstore(0, 1) } }" "{ { let t:bool := not(true) if t { mstore(0, 1) } } }" "--yul" +test_solc_assembly_output "{ let x:u256 := 0:u256 mstore(0, x) }" "{ { let x:u256 := 0:u256 mstore(0:u256, x) } }" "--yul" +test_solc_assembly_output "{ let x:u256 := bitnot(7:u256) mstore(0, x) }" "{ { let x:u256 := bitnot(7:u256) mstore(0:u256, x) } }" "--yul" +test_solc_assembly_output "{ let t:bool := not(true) if t { mstore(0, 1) } }" "{ { let t:bool := not(true:bool) if t { mstore(0:u256, 1:u256) } } }" "--yul" test_solc_assembly_output "{ let x := 0 mstore(0, x) }" "{ { let x := 0 mstore(0, x) } }" "--strict-assembly" test_solc_assembly_output "{ let x := 0 mstore(0, x) }" "{ { } }" "--strict-assembly --optimize" diff --git a/test/cmdlineTests/~name_dependent_cse_bug/test.sh b/test/cmdlineTests/~name_dependent_cse_bug/test.sh index 96c3ac23ed97..710e82b1e7a0 100755 --- a/test/cmdlineTests/~name_dependent_cse_bug/test.sh +++ b/test/cmdlineTests/~name_dependent_cse_bug/test.sh @@ -19,7 +19,7 @@ function assemble_with_variable_name { local variable_name="$2" sed -e "s|__placeholder__|${variable_name}|g" "$input_file" | msg_on_error --no-stderr \ - "$SOLC" --strict-assembly - --optimize --debug-info none | + "$SOLC" --strict-assembly - --optimize --debug-info none --asm | stripCLIDecorations } diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 7f0914cc4ef4..8941d42f5326 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -59,9 +59,10 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con for (std::string contractName: compiler().contractNames()) { ErrorList errors; + YulNameRepository repository (EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion())); auto [object, analysisInfo] = yul::test::parse( compiler().yulIR(contractName), - EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion()), + repository, errors ); @@ -75,7 +76,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con auto handleObject = [&](std::string const& _kind, Object const& _object) { m_obtainedResult += contractName + "(" + _kind + ") " + (FunctionCallFinder::run( *_object.code, - "memoryguard"_yulstring + repository.predefined().memoryguard ).empty() ? "false" : "true") + "\n"; }; handleObject("creation", *object); diff --git a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol index ab3c172d3399..10f7ec17922f 100644 --- a/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol +++ b/test/libsolidity/semanticTests/array/copying/array_of_function_external_storage_to_storage_dynamic.sol @@ -45,7 +45,7 @@ contract C { } // ---- // copyExternalStorageArrayOfFunctionType() -> true -// gas irOptimized: 104566 +// gas irOptimized: 104629 // gas legacy: 108554 // gas legacyOptimized: 102405 // copyInternalArrayOfFunctionType() -> true diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 10d7d12adddd..0387bdf323d3 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -42,15 +42,7 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::langutil; -namespace -{ -Dialect const& defaultDialect(bool _yul) -{ - return _yul ? yul::Dialect::yulDeprecated() : yul::EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()); -} -} - -std::pair, std::shared_ptr> yul::test::parse(std::string const& _source, bool _yul) +std::tuple, std::shared_ptr, std::shared_ptr> yul::test::parse(std::string const& _source, bool _yul) { YulStack stack( solidity::test::CommonOptions::get().evmVersion(), @@ -63,40 +55,43 @@ std::pair, std::shared_ptr> yul::te ); if (!stack.parseAndAnalyze("", _source) || !stack.errors().empty()) BOOST_FAIL("Invalid source."); - return make_pair(stack.parserResult()->code, stack.parserResult()->analysisInfo); + return std::make_tuple(stack.parserResult()->code, stack.parserResult()->analysisInfo, stack.yulNameRepository()); } std::pair, std::shared_ptr> yul::test::parse( std::string const& _source, - Dialect const& _dialect, + YulNameRepository& _yulNameRepository, ErrorList& _errors ) { ErrorReporter errorReporter(_errors); CharStream stream(_source, ""); std::shared_ptr scanner = std::make_shared(stream); - std::shared_ptr parserResult = yul::ObjectParser(errorReporter, _dialect).parse(scanner, false); + std::shared_ptr parserResult = yul::ObjectParser(errorReporter, _yulNameRepository).parse(scanner, false); if (!parserResult) return {}; if (!parserResult->code || errorReporter.hasErrors()) return {}; std::shared_ptr analysisInfo = std::make_shared(); - AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect, {}, parserResult->qualifiedDataNames()); + AsmAnalyzer analyzer(*analysisInfo, errorReporter, _yulNameRepository, {}, parserResult->qualifiedDataNames()); // TODO this should be done recursively. if (!analyzer.analyze(*parserResult->code) || errorReporter.hasErrors()) return {}; return {std::move(parserResult), std::move(analysisInfo)}; } -yul::Block yul::test::disambiguate(std::string const& _source, bool _yul) +std::tuple> yul::test::disambiguate(std::string const& _source, bool _yul) { auto result = parse(_source, _yul); - return std::get(Disambiguator(defaultDialect(_yul), *result.second, {})(*result.first)); + auto const& [code, analysisInfo, nameRepository] = result; + return std::make_tuple(std::get(Disambiguator(*nameRepository, *analysisInfo, {})(*code)), nameRepository); } std::string yul::test::format(std::string const& _source, bool _yul) { - return yul::AsmPrinter()(*parse(_source, _yul).first); + auto result = parse(_source, _yul); + auto const& [code, analysisInfo, nameRepository] = result; + return yul::AsmPrinter(*nameRepository)(*code); } namespace diff --git a/test/libyul/Common.h b/test/libyul/Common.h index f6c63feb9bb2..fa663fb2930a 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -39,18 +39,20 @@ struct AsmAnalysisInfo; struct Block; struct Object; struct Dialect; +class YulStack; +class YulNameRepository; } namespace solidity::yul::test { -std::pair, std::shared_ptr> +std::tuple, std::shared_ptr, std::shared_ptr> parse(std::string const& _source, bool _yul = true); std::pair, std::shared_ptr> -parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors); +parse(std::string const& _source, YulNameRepository& _yulNameRepository, langutil::ErrorList& _errors); -Block disambiguate(std::string const& _source, bool _yul = true); +std::tuple> disambiguate(std::string const& _source, bool _yul = true); std::string format(std::string const& _source, bool _yul = true); solidity::yul::Dialect const& dialect(std::string const& _name, langutil::EVMVersion _evmVersion); diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 27310cd898c2..9c1d17f2eda1 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -18,10 +18,8 @@ * Unit tests for the compilability checker. */ -#include - #include -#include +#include #include @@ -34,13 +32,18 @@ namespace { std::string check(std::string const& _input) { + std::shared_ptr nameRepository; Object obj; - std::tie(obj.code, obj.analysisInfo) = yul::test::parse(_input, false); + std::tie(obj.code, obj.analysisInfo, nameRepository) = yul::test::parse(_input, false); BOOST_REQUIRE(obj.code); - auto functions = CompilabilityChecker(EVMDialect::strictAssemblyForEVM(solidity::test::CommonOptions::get().evmVersion()), obj, true).stackDeficit; + auto functions = CompilabilityChecker(*nameRepository, obj, true).stackDeficit; + // recast into map string -> int s.t. order is predictable + std::map labelledFunctions; + for(const auto& [k, v] : functions) + labelledFunctions[std::string(nameRepository->labelOf(k))] = v; std::string out; - for (auto const& function: functions) - out += function.first.str() + ": " + std::to_string(function.second) + " "; + for (auto const& function: labelledFunctions) + out += function.first + ": " + std::to_string(function.second) + " "; return out; } } @@ -168,7 +171,7 @@ BOOST_AUTO_TEST_CASE(multiple_functions_used_arguments) x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1) } })"); - BOOST_CHECK_EQUAL(out, "h: 9 g: 5 f: 5 "); + BOOST_CHECK_EQUAL(out, "f: 5 g: 5 h: 9 "); } BOOST_AUTO_TEST_CASE(multiple_functions_unused_arguments) @@ -200,7 +203,7 @@ BOOST_AUTO_TEST_CASE(multiple_functions_unused_arguments) x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1) } })"); - BOOST_CHECK_EQUAL(out, "h: 9 f: 3 "); + BOOST_CHECK_EQUAL(out, "f: 3 h: 9 "); } BOOST_AUTO_TEST_CASE(nested_used_arguments) @@ -236,7 +239,7 @@ BOOST_AUTO_TEST_CASE(nested_used_arguments) x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1) } })"); - BOOST_CHECK_EQUAL(out, "h: 9 g: 5 f: 5 "); + BOOST_CHECK_EQUAL(out, "f: 5 g: 5 h: 9 "); } @@ -269,7 +272,7 @@ BOOST_AUTO_TEST_CASE(nested_unused_arguments) x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1) } })"); - BOOST_CHECK_EQUAL(out, "h: 9 f: 3 "); + BOOST_CHECK_EQUAL(out, "f: 3 h: 9 "); } @@ -301,7 +304,7 @@ BOOST_AUTO_TEST_CASE(also_in_outer_block_used_arguments) sstore(s1, s2) } })"); - BOOST_CHECK_EQUAL(out, "g: 5 : 9 "); + BOOST_CHECK_EQUAL(out, ": 9 g: 5 "); } BOOST_AUTO_TEST_CASE(also_in_outer_block_unused_arguments) diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index 9a0e6f092ff7..10f7a051da0d 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -46,22 +46,23 @@ ControlFlowGraphTest::ControlFlowGraphTest(std::string const& _filename): m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_yulNameRepository = std::make_unique(*m_dialect); m_expectation = m_reader.simpleExpectations(); } namespace { -static std::string variableSlotToString(VariableSlot const& _slot) +static std::string variableSlotToString(VariableSlot const& _slot, YulNameRepository const& _yulNameRepository) { - return _slot.variable.get().name.str(); + return std::string{_yulNameRepository.labelOf(_slot.variable.get().name)}; } } class ControlFlowGraphPrinter { public: - ControlFlowGraphPrinter(std::ostream& _stream): - m_stream(_stream) + ControlFlowGraphPrinter(std::ostream& _stream, YulNameRepository const& _yulNameRepository): + m_stream(_stream), m_yulNameRepository(_yulNameRepository) { } void operator()(CFG::BasicBlock const& _block, bool _isMainEntry = true) @@ -83,17 +84,17 @@ class ControlFlowGraphPrinter CFG::FunctionInfo const& _info ) { - m_stream << "FunctionEntry_" << _info.function.name.str() << "_" << getBlockId(*_info.entry) << " [label=\""; - m_stream << "function " << _info.function.name.str() << "("; - m_stream << joinHumanReadable(_info.parameters | ranges::views::transform(variableSlotToString)); + m_stream << "FunctionEntry_" << m_yulNameRepository.labelOf(_info.function.name) << "_" << getBlockId(*_info.entry) << " [label=\""; + m_stream << "function " << m_yulNameRepository.labelOf(_info.function.name) << "("; + m_stream << joinHumanReadable(_info.parameters | ranges::views::transform([&](auto const& var) { return variableSlotToString(var, m_yulNameRepository); })); m_stream << ")"; if (!_info.returnVariables.empty()) { m_stream << " -> "; - m_stream << joinHumanReadable(_info.returnVariables | ranges::views::transform(variableSlotToString)); + m_stream << joinHumanReadable(_info.returnVariables | ranges::views::transform([&](auto const& var) { return variableSlotToString(var, m_yulNameRepository); })); } m_stream << "\"];\n"; - m_stream << "FunctionEntry_" << _info.function.name.str() << "_" << getBlockId(*_info.entry) << " -> Block" << getBlockId(*_info.entry) << ";\n"; + m_stream << "FunctionEntry_" << m_yulNameRepository.labelOf(_info.function.name) << "_" << getBlockId(*_info.entry) << " -> Block" << getBlockId(*_info.entry) << ";\n"; (*this)(*_info.entry, false); } @@ -126,19 +127,19 @@ class ControlFlowGraphPrinter { std::visit(util::GenericVisitor{ [&](CFG::FunctionCall const& _call) { - m_stream << _call.function.get().name.str() << ": "; + m_stream << m_yulNameRepository.labelOf(_call.function.get().name) << ": "; }, [&](CFG::BuiltinCall const& _call) { - m_stream << _call.functionCall.get().functionName.name.str() << ": "; + m_stream << m_yulNameRepository.labelOf(_call.functionCall.get().functionName.name) << ": "; }, [&](CFG::Assignment const& _assignment) { m_stream << "Assignment("; - m_stream << joinHumanReadable(_assignment.variables | ranges::views::transform(variableSlotToString)); + m_stream << joinHumanReadable(_assignment.variables | ranges::views::transform([&](auto const& var) { return variableSlotToString(var, m_yulNameRepository); })); m_stream << "): "; } }, operation.operation); - m_stream << stackToString(operation.input) << " => " << stackToString(operation.output) << "\\l\\\n"; + m_stream << stackToString(operation.input, m_yulNameRepository) << " => " << stackToString(operation.output, m_yulNameRepository) << "\\l\\\n"; } m_stream << "\"];\n"; std::visit(util::GenericVisitor{ @@ -160,7 +161,7 @@ class ControlFlowGraphPrinter { m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; m_stream << "Block" << getBlockId(_block) << "Exit [label=\"{ "; - m_stream << stackSlotToString(_conditionalJump.condition); + m_stream << stackSlotToString(_conditionalJump.condition, m_yulNameRepository); m_stream << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; m_stream << "Block" << getBlockId(_block); m_stream << "Exit:0 -> Block" << getBlockId(*_conditionalJump.zero) << ";\n"; @@ -169,7 +170,7 @@ class ControlFlowGraphPrinter }, [&](CFG::BasicBlock::FunctionReturn const& _return) { - m_stream << "Block" << getBlockId(_block) << "Exit [label=\"FunctionReturn[" << _return.info->function.name.str() << "]\"];\n"; + m_stream << "Block" << getBlockId(_block) << "Exit [label=\"FunctionReturn[" << m_yulNameRepository.labelOf(_return.info->function.name) << "]\"];\n"; m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; }, [&](CFG::BasicBlock::Terminated const&) @@ -192,12 +193,13 @@ class ControlFlowGraphPrinter std::map m_blockIds; size_t m_blockCount = 0; std::list m_blocksToPrint; + YulNameRepository const& m_yulNameRepository; }; TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); + auto [object, analysisInfo] = parse(m_source, *m_yulNameRepository, errors); if (!object || !analysisInfo || Error::containsErrors(errors)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; @@ -206,10 +208,11 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, *object->code); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_yulNameRepository, *object->code); + m_yulNameRepository->generateLabels(*object->code); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - ControlFlowGraphPrinter printer{output}; + ControlFlowGraphPrinter printer{output, *m_yulNameRepository}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/ControlFlowGraphTest.h b/test/libyul/ControlFlowGraphTest.h index 44cea06d3f7c..265e8d9d38c2 100644 --- a/test/libyul/ControlFlowGraphTest.h +++ b/test/libyul/ControlFlowGraphTest.h @@ -23,6 +23,7 @@ namespace solidity::yul { struct Dialect; +class YulNameRepository; namespace test { @@ -38,6 +39,7 @@ class ControlFlowGraphTest: public solidity::frontend::test::TestCase TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: Dialect const* m_dialect = nullptr; + std::unique_ptr m_yulNameRepository; }; } } diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 6ac5a7b0ad59..d4631249bdc2 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -56,19 +57,20 @@ ControlFlowSideEffectsTest::ControlFlowSideEffectsTest(std::string const& _filen TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { + std::shared_ptr nameRepository; Object obj; - std::tie(obj.code, obj.analysisInfo) = yul::test::parse(m_source, false); + std::tie(obj.code, obj.analysisInfo, nameRepository) = yul::test::parse(m_source, false); if (!obj.code) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); ControlFlowSideEffectsCollector sideEffects( - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + *nameRepository, *obj.code ); m_obtainedResult.clear(); forEach(*obj.code, [&](FunctionDefinition const& _fun) { std::string effectStr = toString(sideEffects.functionSideEffects().at(&_fun)); - m_obtainedResult += _fun.name.str() + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; + m_obtainedResult += std::string(nameRepository->labelOf(_fun.name)) + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; }); return checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 4c2eecab05fe..487464097cf1 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -72,7 +72,8 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin EVMObjectCompiler::compile( *stack.parserResult(), adapter, - EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}), + *stack.yulNameRepository(), + dynamic_cast(stack.yulNameRepository()->dialect()), m_stackOpt, std::nullopt ); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index a57ec9807843..2eba3e46614f 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -82,23 +82,24 @@ FunctionSideEffects::FunctionSideEffects(std::string const& _filename): TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { + std::shared_ptr nameRepository; Object obj; - std::tie(obj.code, obj.analysisInfo) = yul::test::parse(m_source, false); + std::tie(obj.code, obj.analysisInfo, nameRepository) = yul::test::parse(m_source, false); if (!obj.code) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); - std::map functionSideEffects = SideEffectsPropagator::sideEffects( - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + std::map functionSideEffects = SideEffectsPropagator::sideEffects( + *nameRepository, CallGraphGenerator::callGraph(*obj.code) ); - std::map functionSideEffectsStr; + std::map functionSideEffectsStr; for (auto const& fun: functionSideEffects) - functionSideEffectsStr[fun.first.str()] = toString(fun.second); + functionSideEffectsStr[nameRepository->labelOf(fun.first)] = toString(fun.second); m_obtainedResult.clear(); for (auto const& fun: functionSideEffectsStr) - m_obtainedResult += fun.first + ":" + (fun.second.empty() ? "" : " ") + fun.second + "\n"; + m_obtainedResult += std::string(fun.first) + ":" + (fun.second.empty() ? "" : " ") + fun.second + "\n"; return checkResult(_stream, _linePrefix, _formatted); } diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp index 6f622b41a4f4..d884efdca4fc 100644 --- a/test/libyul/Inliner.cpp +++ b/test/libyul/Inliner.cpp @@ -42,14 +42,15 @@ namespace { std::string inlinableFunctions(std::string const& _source) { - auto ast = disambiguate(_source); + auto [ast, repository] = disambiguate(_source); InlinableExpressionFunctionFinder funFinder; funFinder(ast); std::vector functionNames; for (auto const& f: funFinder.inlinableFunctions()) - functionNames.emplace_back(f.first.str()); + functionNames.emplace_back(repository->baseLabelOf(f.first)); + std::sort(functionNames.begin(), functionNames.end()); return boost::algorithm::join(functionNames, ","); } @@ -69,7 +70,7 @@ BOOST_AUTO_TEST_CASE(simple) BOOST_CHECK_EQUAL(inlinableFunctions("{" "function g(a:u256) -> b:u256 { b := a }" "function f() -> x:u256 { x := g(2:u256) }" - "}"), "g,f"); + "}"), "f,g"); } BOOST_AUTO_TEST_CASE(simple_inside_structures) @@ -80,7 +81,7 @@ BOOST_AUTO_TEST_CASE(simple_inside_structures) "function g(a:u256) -> b:u256 { b := a }" "function f() -> x:u256 { x := g(2:u256) }" "}" - "}"), "g,f"); + "}"), "f,g"); BOOST_CHECK_EQUAL(inlinableFunctions("{" "function g(a:u256) -> b:u256 { b := a }" "for {" @@ -90,7 +91,7 @@ BOOST_AUTO_TEST_CASE(simple_inside_structures) "{" "function h() -> y:u256 { y := 2:u256 }" "}" - "}"), "h,g,f"); + "}"), "f,g,h"); } BOOST_AUTO_TEST_CASE(negative) diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index b1dd0e6d19c5..b825e6a4f4a0 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -45,25 +44,25 @@ class KnowledgeBaseTest { ErrorList errorList; std::shared_ptr analysisInfo; - std::tie(m_object, analysisInfo) = yul::test::parse(_source, m_dialect, errorList); + std::tie(m_object, analysisInfo) = yul::test::parse(_source, m_yulNameRepository, errorList); BOOST_REQUIRE(m_object && errorList.empty() && m_object->code); - NameDispenser dispenser(m_dialect, *m_object->code); - std::set reserved; - OptimiserStepContext context{m_dialect, dispenser, reserved, 0}; + std::set reserved{}; + OptimiserStepContext context{m_yulNameRepository.dialect(), m_yulNameRepository, reserved, 0}; CommonSubexpressionEliminator::run(context, *m_object->code); m_ssaValues(*m_object->code); for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; - return KnowledgeBase([this](YulString _var) { return util::valueOrNullptr(m_values, _var); }); + return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }, m_yulNameRepository); } EVMDialect m_dialect{EVMVersion{}, true}; + YulNameRepository m_yulNameRepository {m_dialect}; std::shared_ptr m_object; SSAValueTracker m_ssaValues; - std::map m_values; + std::map m_values; }; BOOST_FIXTURE_TEST_SUITE(KnowledgeBase, KnowledgeBaseTest) @@ -79,14 +78,14 @@ BOOST_AUTO_TEST_CASE(basic) let e := sub(a, b) })"); - BOOST_CHECK(!kb.knownToBeDifferent("a"_yulstring, "b"_yulstring)); + BOOST_CHECK(!kb.knownToBeDifferent(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("b"))); // This only works if the variable names are the same. // It assumes that SSA+CSE+Simplifier actually replaces the variables. - BOOST_CHECK(!kb.valueIfKnownConstant("a"_yulstring)); - BOOST_CHECK(kb.valueIfKnownConstant("zero"_yulstring) == u256(0)); - BOOST_CHECK(kb.differenceIfKnownConstant("a"_yulstring, "b"_yulstring) == u256(0)); - BOOST_CHECK(kb.differenceIfKnownConstant("a"_yulstring, "c"_yulstring) == u256(0)); - BOOST_CHECK(kb.valueIfKnownConstant("e"_yulstring) == u256(0)); + BOOST_CHECK(!kb.valueIfKnownConstant(m_yulNameRepository.nameOfLabel("a"))); + BOOST_CHECK(kb.valueIfKnownConstant(m_yulNameRepository.nameOfLabel("zero")) == u256(0)); + BOOST_CHECK(kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("b")) == u256(0)); + BOOST_CHECK(kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("c")) == u256(0)); + BOOST_CHECK(kb.valueIfKnownConstant(m_yulNameRepository.nameOfLabel("e")) == u256(0)); } BOOST_AUTO_TEST_CASE(difference) @@ -100,29 +99,29 @@ BOOST_AUTO_TEST_CASE(difference) })"); BOOST_CHECK( - kb.differenceIfKnownConstant("c"_yulstring, "b"_yulstring) == + kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("c"), m_yulNameRepository.nameOfLabel("b")) == u256(20) ); BOOST_CHECK( - kb.differenceIfKnownConstant("b"_yulstring, "c"_yulstring) == + kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("c")) == u256(-20) ); - BOOST_CHECK(!kb.knownToBeDifferentByAtLeast32("b"_yulstring, "c"_yulstring)); - BOOST_CHECK(kb.knownToBeDifferentByAtLeast32("b"_yulstring, "d"_yulstring)); - BOOST_CHECK(kb.knownToBeDifferentByAtLeast32("a"_yulstring, "b"_yulstring)); - BOOST_CHECK(kb.knownToBeDifferentByAtLeast32("b"_yulstring, "a"_yulstring)); + BOOST_CHECK(!kb.knownToBeDifferentByAtLeast32(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("c"))); + BOOST_CHECK(kb.knownToBeDifferentByAtLeast32(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("d"))); + BOOST_CHECK(kb.knownToBeDifferentByAtLeast32(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("b"))); + BOOST_CHECK(kb.knownToBeDifferentByAtLeast32(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("a"))); BOOST_CHECK( - kb.differenceIfKnownConstant("e"_yulstring, "a"_yulstring) == u256(208) + kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("e"), m_yulNameRepository.nameOfLabel("a")) == u256(208) ); BOOST_CHECK( - kb.differenceIfKnownConstant("e"_yulstring, "b"_yulstring) == u256(8) + kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("e"), m_yulNameRepository.nameOfLabel("b")) == u256(8) ); BOOST_CHECK( - kb.differenceIfKnownConstant("a"_yulstring, "e"_yulstring) == u256(-208) + kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("e")) == u256(-208) ); BOOST_CHECK( - kb.differenceIfKnownConstant("b"_yulstring, "e"_yulstring) == u256(-8) + kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("e")) == u256(-8) ); } diff --git a/test/libyul/Metrics.cpp b/test/libyul/Metrics.cpp index ac3153433f56..4d710123692f 100644 --- a/test/libyul/Metrics.cpp +++ b/test/libyul/Metrics.cpp @@ -37,7 +37,7 @@ namespace size_t codeSize(std::string const& _source, CodeWeights const _weights = {}) { - std::shared_ptr ast = parse(_source, false).first; + std::shared_ptr ast = std::get<0>(parse(_source, false)); BOOST_REQUIRE(ast); return CodeSize::codeSize(*ast, _weights); } diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index b23e530601da..9d616d294fbb 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -113,7 +113,8 @@ std::tuple, ErrorList> tryGetSourceLocationMapping( ErrorList errors; ErrorReporter reporter(errors); Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(EVMVersion::berlin()); - ObjectParser objectParser{reporter, dialect}; + YulNameRepository repository (dialect); + ObjectParser objectParser{reporter, repository}; CharStream stream(std::move(source), ""); auto object = objectParser.parse(std::make_shared(stream), false); BOOST_REQUIRE(object && object->debugData); diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index ca8784ddb6ef..6cf52b22cd6a 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -40,6 +40,7 @@ #include #include #include +#include using namespace solidity; using namespace solidity::util; @@ -54,7 +55,7 @@ namespace solidity::yul::test namespace { -std::shared_ptr parse(std::string const& _source, Dialect const& _dialect, ErrorReporter& errorReporter) +std::shared_ptr parse(std::string const& _source, YulNameRepository& _yulNameRepository, ErrorReporter& errorReporter) { auto stream = CharStream(_source, ""); std::map> indicesToSourceNames; @@ -63,7 +64,7 @@ std::shared_ptr parse(std::string const& _source, Dialect const& _dialect auto parserResult = yul::Parser( errorReporter, - _dialect, + _yulNameRepository, std::move(indicesToSourceNames) ).parse(stream); if (parserResult) @@ -72,18 +73,18 @@ std::shared_ptr parse(std::string const& _source, Dialect const& _dialect if (yul::AsmAnalyzer( analysisInfo, errorReporter, - _dialect + _yulNameRepository ).analyze(*parserResult)) return parserResult; } return {}; } -std::optional parseAndReturnFirstError(std::string const& _source, Dialect const& _dialect, bool _allowWarningsAndInfos = true) +std::optional parseAndReturnFirstError(std::string const& _source, YulNameRepository& _yulNameRepository, bool _allowWarningsAndInfos = true) { ErrorList errors; ErrorReporter errorReporter(errors); - if (!parse(_source, _dialect, errorReporter)) + if (!parse(_source, _yulNameRepository, errorReporter)) { BOOST_REQUIRE(!errors.empty()); BOOST_CHECK_EQUAL(errors.size(), 1); @@ -106,13 +107,14 @@ std::optional parseAndReturnFirstError(std::string const& _source, Dialec bool successParse(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarningsAndInfos = true) { - return !parseAndReturnFirstError(_source, _dialect, _allowWarningsAndInfos); + YulNameRepository repository (_dialect); + return !parseAndReturnFirstError(_source, repository, _allowWarningsAndInfos); } Error expectError(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarningsAndInfos = false) { - - auto error = parseAndReturnFirstError(_source, _dialect, _allowWarningsAndInfos); + YulNameRepository repository (_dialect); + auto error = parseAndReturnFirstError(_source, repository, _allowWarningsAndInfos); BOOST_REQUIRE(error); return *error; } @@ -135,11 +137,25 @@ BOOST_AUTO_TEST_CASE(builtins_analysis) { struct SimpleDialect: public Dialect { - BuiltinFunction const* builtin(YulString _name) const override + BuiltinFunction const* builtin(std::string_view _name) const override { - return _name == "builtin"_yulstring ? &f : nullptr; + return _name == "builtin" ? &f : nullptr; } - BuiltinFunction f{"builtin"_yulstring, std::vector(2), std::vector(3), {}, {}, false, {}}; + + std::set builtinNames() const override { return {"builtin"}; } + + BuiltinFunction f = []() + { + BuiltinFunction fun; + fun.name = "builtin"; + fun.parameters = std::vector(2); + fun.returns = std::vector(3); + fun.sideEffects = {}; + fun.controlFlowSideEffects = {}; + fun.isMSize = false; + fun.literalArguments = {}; + return fun; + }(); }; SimpleDialect dialect; @@ -150,6 +166,7 @@ BOOST_AUTO_TEST_CASE(builtins_analysis) BOOST_AUTO_TEST_CASE(default_types_set) { + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); ErrorList errorList; ErrorReporter reporter(errorList); std::shared_ptr result = parse( @@ -159,14 +176,14 @@ BOOST_AUTO_TEST_CASE(default_types_set) "let y := add(1, 2) " "switch y case 0 {} default {} " "}", - EVMDialectTyped::instance(EVMVersion{}), + repository, reporter ); BOOST_REQUIRE(!!result && errorList.size() == 0); - // Use no dialect so that all types are printed. + // By default, all types are printed. // This tests that the default types are properly assigned. - BOOST_CHECK_EQUAL(AsmPrinter{}(*result), + BOOST_CHECK_EQUAL(AsmPrinter{repository}(*result), "{\n" " let x:bool := true:bool\n" " let z:bool := true:bool\n" @@ -177,9 +194,9 @@ BOOST_AUTO_TEST_CASE(default_types_set) "}" ); - // Now test again with type dialect. Now the default types - // should be omitted. - BOOST_CHECK_EQUAL(AsmPrinter{EVMDialectTyped::instance(EVMVersion{})}(*result), + // got to declare the string representation outside the check due to macro weirdness + std::string stringRepr = AsmPrinter{repository, AsmPrinter::Mode::OmitDefaultType}(*result); + BOOST_CHECK_EQUAL(stringRepr, "{\n" " let x:bool := true\n" " let z:bool := true\n" @@ -205,8 +222,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_empty_block) auto const sourceText = "/// @src 0:234:543\n" "{}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository (EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); } @@ -223,8 +240,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_with_children) "let z:bool := true\n" "let y := add(1, 2)\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); BOOST_REQUIRE_EQUAL(3, result->statements.size()); @@ -246,8 +263,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_different_sources) "let z:bool := true\n" "let y := add(1, 2)\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); BOOST_REQUIRE_EQUAL(3, result->statements.size()); @@ -268,8 +285,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_nested) "/// @src 0:343:434\n" "switch y case 0 {} default {}\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); BOOST_REQUIRE_EQUAL(2, result->statements.size()); @@ -292,8 +309,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_switch_case) " let z := add(3, 4)\n" "}\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); @@ -324,8 +341,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_inherit_into_outer_scope) "let z:bool := true\n" "let y := add(1, 2)\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source0", 1, 100); @@ -355,8 +372,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_assign_empty) "/// @src 1:1:10\n" "a := true:bool\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // should still parse BOOST_REQUIRE_EQUAL(2, result->statements.size()); CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 123, 432); @@ -376,8 +393,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_source_index) "let b:bool := true:bool\n" "\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); // should still parse BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -396,8 +413,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_1) "/// @src 0:234:2026\n" ":= true:bool\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->statements.size()); @@ -419,8 +436,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_2) 2) } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->statements.size()); CHECK_LOCATION(result->debugData->originLocation, "source0", 0, 5); @@ -453,8 +470,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_3) mstore(1, 2) // FunctionCall } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(2, result->statements.size()); CHECK_LOCATION(result->debugData->originLocation, "source1", 23, 45); @@ -489,8 +506,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_comments_after_valid) let a:bool := true } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(1, result->statements.size()); CHECK_LOCATION(result->debugData->originLocation, "source1", 23, 45); @@ -508,8 +525,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_suffix) /// @src 0:420:680foo {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -525,8 +542,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_prefix) /// abc@src 0:111:222 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); } @@ -539,8 +556,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_unspecified) /// @src -1:-1:-1 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); } @@ -553,8 +570,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_non_integer) /// @src a:b:c {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -570,8 +587,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_bad_integer) /// @src 111111111111111111111:222222222222222222222:333333333333333333333 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -591,8 +608,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_ensure_last_match) let x:bool := true } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); VariableDeclaration const& varDecl = std::get(result->statements.at(0)); @@ -609,8 +626,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_no_whitespace) /// @src 0:111:222@src 1:333:444 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -626,8 +643,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_s /// @src 0:111:222 @src 1:333:444 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source1", 333, 444); } @@ -637,8 +654,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace) ErrorList errorList; ErrorReporter reporter(errorList); auto const sourceText = "/// @src 0:111:222 \n{}"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); } @@ -654,8 +671,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc) let x:bool := true } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); VariableDeclaration const& varDecl = std::get(result->statements.at(0)); @@ -676,8 +693,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets) let y := /** @src 1:96:165 "contract D {..." */ 128 } )~~~"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->statements.size(), 2); @@ -701,8 +718,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_empty_snippet) /// @src 0:111:222 "" {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); } @@ -715,8 +732,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_befo /// @src 0:111:222"abc" def {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -732,8 +749,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_afte /// @src 0:111:222 "abc"def {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); } @@ -746,8 +763,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whites /// @src 0:111:222 "abc"@src 1:333:444 "abc" {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source1", 333, 444); } @@ -760,8 +777,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_untermina /// @src 0:111:222 " abc @src 1:333:444 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -778,8 +795,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) /// {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -795,8 +812,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) /// @src 0:111:222 hex"abc"@src 1:333:444 "abc" {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // the second source location is not parsed as such, as the hex string isn't interpreted as snippet but // as the beginning of the tail in AsmParser @@ -811,8 +828,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) /// @src 0:111:222 "\n\\x\x\w\uö\xy\z\y\fq" {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); } @@ -826,8 +843,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces /// @src 1 : 222 : 333 '\x33\u1234\t\n' {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); CHECK_LOCATION(result->debugData->originLocation, "source1", 222, 333); } @@ -841,8 +858,8 @@ BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_ar /// @src 1:222:333 {{}} )", invalid); - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->debugData->originLocation, "source1", 222, 333); } @@ -859,8 +876,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) /// " @src 0:333:444 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.empty()); CHECK_LOCATION(result->debugData->originLocation, "source0", 333, 444); } @@ -877,8 +894,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locati let y := /** @src 1:96:165 "function f() internal { \"\/** @src 0:6:7 *\/\"; }" */ 128 } )~~~"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->statements.size(), 2); @@ -906,8 +923,8 @@ BOOST_AUTO_TEST_CASE(astid) mstore(1, 2) } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->debugData->astID == int64_t(7)); auto const& funDef = std::get(result->statements.at(0)); @@ -928,8 +945,8 @@ BOOST_AUTO_TEST_CASE(astid_reset) mstore(1, 2) } )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->debugData->astID == int64_t(7)); auto const& funDef = std::get(result->statements.at(0)); @@ -946,8 +963,8 @@ BOOST_AUTO_TEST_CASE(astid_multi) /// @src -1:-1:-1 @ast-id 7 @src 1:1:1 @ast-id 8 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_CHECK(result->debugData->astID == int64_t(8)); } @@ -960,8 +977,8 @@ BOOST_AUTO_TEST_CASE(astid_invalid) /// @src -1:-1:-1 @ast-id abc @src 1:1:1 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -977,8 +994,8 @@ BOOST_AUTO_TEST_CASE(astid_too_large) /// @ast-id 9223372036854775808 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -993,8 +1010,8 @@ BOOST_AUTO_TEST_CASE(astid_way_too_large) /// @ast-id 999999999999999999999999999999999999999 {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -1009,8 +1026,8 @@ BOOST_AUTO_TEST_CASE(astid_not_fully_numeric) /// @ast-id 9x {} )"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -1031,8 +1048,8 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line) "\n" " let x := 123\n" "}\n"; - EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{}); - std::shared_ptr result = parse(sourceText, dialect, reporter); + YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); + std::shared_ptr result = parse(sourceText, repository, reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); BOOST_REQUIRE_EQUAL(result->statements.size(), 1); diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 02b03ccea76d..34d541f78de2 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -49,23 +49,23 @@ StackLayoutGeneratorTest::StackLayoutGeneratorTest(std::string const& _filename) { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_yulNameRepository = std::make_unique(dialect(dialectName, solidity::test::CommonOptions::get().evmVersion())); m_expectation = m_reader.simpleExpectations(); } namespace { -static std::string variableSlotToString(VariableSlot const& _slot) +static std::string variableSlotToString(VariableSlot const& _slot, YulNameRepository const& _yulNameRepository) { - return _slot.variable.get().name.str(); + return std::string(_yulNameRepository.labelOf(_slot.variable.get().name)); } } class StackLayoutPrinter { public: - StackLayoutPrinter(std::ostream& _stream, StackLayout const& _stackLayout): - m_stream(_stream), m_stackLayout(_stackLayout) + StackLayoutPrinter(std::ostream& _stream, StackLayout const& _stackLayout, YulNameRepository const& _yulNameRepository): + m_stream(_stream), m_stackLayout(_stackLayout), m_yulNameRepository(_yulNameRepository) { } void operator()(CFG::BasicBlock const& _block, bool _isMainEntry = true) @@ -87,20 +87,20 @@ class StackLayoutPrinter CFG::FunctionInfo const& _info ) { - m_stream << "FunctionEntry_" << _info.function.name.str() << " [label=\""; - m_stream << "function " << _info.function.name.str() << "("; - m_stream << joinHumanReadable(_info.parameters | ranges::views::transform(variableSlotToString)); + m_stream << "FunctionEntry_" << m_yulNameRepository.labelOf(_info.function.name) << " [label=\""; + m_stream << "function " << m_yulNameRepository.labelOf(_info.function.name) << "("; + m_stream << joinHumanReadable(_info.parameters | ranges::views::transform([&](auto const& var) { return variableSlotToString(var, m_yulNameRepository); })); m_stream << ")"; if (!_info.returnVariables.empty()) { m_stream << " -> "; - m_stream << joinHumanReadable(_info.returnVariables | ranges::views::transform(variableSlotToString)); + m_stream << joinHumanReadable(_info.returnVariables | ranges::views::transform([&](auto const& var) { return variableSlotToString(var, m_yulNameRepository); })); } m_stream << "\\l\\\n"; Stack functionEntryStack = {FunctionReturnLabelSlot{_info.function}}; functionEntryStack += _info.parameters | ranges::views::reverse; - m_stream << stackToString(functionEntryStack) << "\"];\n"; - m_stream << "FunctionEntry_" << _info.function.name.str() << " -> Block" << getBlockId(*_info.entry) << ";\n"; + m_stream << stackToString(functionEntryStack, m_yulNameRepository) << "\"];\n"; + m_stream << "FunctionEntry_" << m_yulNameRepository.labelOf(_info.function.name) << " -> Block" << getBlockId(*_info.entry) << ";\n"; (*this)(*_info.entry, false); } @@ -130,22 +130,22 @@ class StackLayoutPrinter }, entry->exit); auto const& blockInfo = m_stackLayout.blockInfos.at(&_block); - m_stream << stackToString(blockInfo.entryLayout) << "\\l\\\n"; + m_stream << stackToString(blockInfo.entryLayout, m_yulNameRepository) << "\\l\\\n"; for (auto const& operation: _block.operations) { auto entryLayout = m_stackLayout.operationEntryLayout.at(&operation); - m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation)) << "\\l\\\n"; + m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation), m_yulNameRepository) << "\\l\\\n"; std::visit(util::GenericVisitor{ [&](CFG::FunctionCall const& _call) { - m_stream << _call.function.get().name.str(); + m_stream << m_yulNameRepository.labelOf(_call.function.get().name); }, [&](CFG::BuiltinCall const& _call) { - m_stream << _call.functionCall.get().functionName.name.str(); + m_stream << m_yulNameRepository.labelOf(_call.functionCall.get().functionName.name); }, [&](CFG::Assignment const& _assignment) { m_stream << "Assignment("; - m_stream << joinHumanReadable(_assignment.variables | ranges::views::transform(variableSlotToString)); + m_stream << joinHumanReadable(_assignment.variables | ranges::views::transform([&](auto const& var) { return variableSlotToString(var, m_yulNameRepository); })); m_stream << ")"; } }, operation.operation); @@ -154,9 +154,9 @@ class StackLayoutPrinter for (size_t i = 0; i < operation.input.size(); ++i) entryLayout.pop_back(); entryLayout += operation.output; - m_stream << stackToString(entryLayout) << "\\l\\\n"; + m_stream << stackToString(entryLayout, m_yulNameRepository) << "\\l\\\n"; } - m_stream << stackToString(blockInfo.exitLayout) << "\\l\\\n"; + m_stream << stackToString(blockInfo.exitLayout, m_yulNameRepository) << "\\l\\\n"; m_stream << "\"];\n"; std::visit(util::GenericVisitor{ [&](CFG::BasicBlock::MainExit const&) @@ -177,7 +177,7 @@ class StackLayoutPrinter { m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; m_stream << "Block" << getBlockId(_block) << "Exit [label=\"{ "; - m_stream << stackSlotToString(_conditionalJump.condition); + m_stream << stackSlotToString(_conditionalJump.condition, m_yulNameRepository); m_stream << "| { <0> Zero | <1> NonZero }}\" shape=Mrecord];\n"; m_stream << "Block" << getBlockId(_block); m_stream << "Exit:0 -> Block" << getBlockId(*_conditionalJump.zero) << ";\n"; @@ -186,7 +186,7 @@ class StackLayoutPrinter }, [&](CFG::BasicBlock::FunctionReturn const& _return) { - m_stream << "Block" << getBlockId(_block) << "Exit [label=\"FunctionReturn[" << _return.info->function.name.str() << "]\"];\n"; + m_stream << "Block" << getBlockId(_block) << "Exit [label=\"FunctionReturn[" << m_yulNameRepository.labelOf(_return.info->function.name) << "]\"];\n"; m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; }, [&](CFG::BasicBlock::Terminated const&) @@ -210,12 +210,13 @@ class StackLayoutPrinter std::map m_blockIds; size_t m_blockCount = 0; std::list m_blocksToPrint; + YulNameRepository const& m_yulNameRepository; }; TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); + auto [object, analysisInfo] = parse(m_source, *m_yulNameRepository, errors); if (!object || !analysisInfo || Error::containsErrors(errors)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; @@ -224,11 +225,12 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_dialect, *object->code); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_yulNameRepository, *object->code); StackLayout stackLayout = StackLayoutGenerator::run(*cfg); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - StackLayoutPrinter printer{output, stackLayout}; + StackLayoutPrinter printer{output, stackLayout, *m_yulNameRepository}; + m_yulNameRepository->generateLabels(*object->code); // todo need more? printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/StackLayoutGeneratorTest.h b/test/libyul/StackLayoutGeneratorTest.h index 9f570045f78e..a6cb9573188e 100644 --- a/test/libyul/StackLayoutGeneratorTest.h +++ b/test/libyul/StackLayoutGeneratorTest.h @@ -22,7 +22,7 @@ namespace solidity::yul { -struct Dialect; +class YulNameRepository; namespace test { @@ -37,7 +37,7 @@ class StackLayoutGeneratorTest: public solidity::frontend::test::TestCase explicit StackLayoutGeneratorTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: - Dialect const* m_dialect = nullptr; + std::unique_ptr m_yulNameRepository; }; } } diff --git a/test/libyul/StackShufflingTest.cpp b/test/libyul/StackShufflingTest.cpp index e53eeafbb03c..d5d634831566 100644 --- a/test/libyul/StackShufflingTest.cpp +++ b/test/libyul/StackShufflingTest.cpp @@ -55,12 +55,13 @@ bool StackShufflingTest::parse(std::string const& _source) { scanner.next(); std::string functionName = scanner.currentLiteral(); + auto const funcYulName = m_yulNameRepository.defineName(functionName); auto call = yul::FunctionCall{ - {}, yul::Identifier{{}, YulString(functionName)}, {} + {}, yul::Identifier{{}, funcYulName}, {} }; stack.emplace_back(FunctionCallReturnLabelSlot{ m_functions.insert( - make_pair(functionName, call) + std::make_pair(funcYulName, call) ).first->second }); expectToken(Token::RBrack); @@ -77,14 +78,15 @@ bool StackShufflingTest::parse(std::string const& _source) expectToken(Token::LBrack); scanner.next(); std::string functionName = scanner.currentLiteral(); + auto const functionYulName = m_yulNameRepository.defineName(functionName); auto call = yul::FunctionCall{ - {}, yul::Identifier{{}, YulString(functionName)}, {} + {}, yul::Identifier{{}, functionYulName}, {} }; expectToken(Token::Comma); scanner.next(); size_t index = size_t(atoi(scanner.currentLiteral().c_str())); stack.emplace_back(TemporarySlot{ - m_functions.insert(make_pair(functionName, call)).first->second, + m_functions.insert(std::make_pair(functionYulName, call)).first->second, index }); expectToken(Token::RBrack); @@ -102,7 +104,7 @@ bool StackShufflingTest::parse(std::string const& _source) expectToken(Token::LBrack); scanner.next(); // read number of ghost variables as ghostVariableId std::string ghostVariableId = scanner.currentLiteral(); - Scope::Variable ghostVar = Scope::Variable{""_yulstring, YulString(literal + "[" + ghostVariableId + "]")}; + Scope::Variable ghostVar = Scope::Variable{YulNameRepository::emptyName(), m_yulNameRepository.defineName(literal + "[" + ghostVariableId + "]")}; stack.emplace_back(VariableSlot{ m_variables.insert(std::make_pair(ghostVar.name, ghostVar)).first->second }); @@ -110,10 +112,11 @@ bool StackShufflingTest::parse(std::string const& _source) } else { - Scope::Variable var = Scope::Variable{""_yulstring, YulString(literal)}; + auto const literalName = m_yulNameRepository.defineName(literal); + Scope::Variable var = Scope::Variable{YulNameRepository::emptyName(), literalName}; stack.emplace_back(VariableSlot{ m_variables.insert( - make_pair(literal, var) + std::make_pair(literalName, var) ).first->second }); } @@ -129,7 +132,7 @@ bool StackShufflingTest::parse(std::string const& _source) } StackShufflingTest::StackShufflingTest(std::string const& _filename): - TestCase(_filename) + TestCase(_filename), m_yulNameRepository(Dialect::yulDeprecated()) { m_source = m_reader.source(); m_expectation = m_reader.simpleExpectations(); @@ -149,14 +152,14 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string m_targetStack, [&](unsigned _swapDepth) // swap { - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, m_yulNameRepository) << std::endl; output << "SWAP" << _swapDepth << std::endl; }, [&](StackSlot const& _slot) // dupOrPush { - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, m_yulNameRepository) << std::endl; if (canBeFreelyGenerated(_slot)) - output << "PUSH " << stackSlotToString(_slot) << std::endl; + output << "PUSH " << stackSlotToString(_slot, m_yulNameRepository) << std::endl; else { if (auto depth = util::findOffset(m_sourceStack | ranges::views::reverse, _slot)) @@ -166,12 +169,12 @@ TestCase::TestResult StackShufflingTest::run(std::ostream& _stream, std::string } }, [&](){ // pop - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, m_yulNameRepository) << std::endl; output << "POP" << std::endl; } ); - output << stackToString(m_sourceStack) << std::endl; + output << stackToString(m_sourceStack, m_yulNameRepository) << std::endl; m_obtainedResult = output.str(); return checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/StackShufflingTest.h b/test/libyul/StackShufflingTest.h index 75715d25b90f..51e11ae591a6 100644 --- a/test/libyul/StackShufflingTest.h +++ b/test/libyul/StackShufflingTest.h @@ -41,7 +41,8 @@ class StackShufflingTest: public TestCase Stack m_sourceStack; Stack m_targetStack; - std::map m_functions; - std::map m_variables; + std::map m_functions; + std::map m_variables; + YulNameRepository m_yulNameRepository; }; } diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index 0201e047d847..31ee98b9b5c2 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -45,9 +45,9 @@ void SyntaxTest::parseAndAnalyze() std::string const& source = m_sources.sources.begin()->second; ErrorList errorList{}; - soltestAssert(m_dialect, ""); + soltestAssert(m_yulNameRepository, ""); // Silently ignoring the results. - yul::test::parse(source, *m_dialect, errorList); + yul::test::parse(source, *m_yulNameRepository, errorList); for (auto const& error: errorList) { int locationStart = -1; @@ -75,5 +75,5 @@ SyntaxTest::SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVe CommonSyntaxTest(_filename, _evmVersion) { std::string dialectName = m_reader.stringSetting("dialect", "evmTyped"); - m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_yulNameRepository = std::make_unique(dialect(dialectName, solidity::test::CommonOptions::get().evmVersion())); } diff --git a/test/libyul/SyntaxTest.h b/test/libyul/SyntaxTest.h index 27e59ee61439..453729941cdb 100644 --- a/test/libyul/SyntaxTest.h +++ b/test/libyul/SyntaxTest.h @@ -39,7 +39,7 @@ class SyntaxTest: public solidity::test::CommonSyntaxTest void parseAndAnalyze() override; private: - Dialect const* m_dialect = nullptr; + std::unique_ptr m_yulNameRepository; }; } diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index eb6a447d1273..cc5c61356431 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -72,6 +72,7 @@ bool YulInterpreterTest::parse(std::ostream& _stream, std::string const& _linePr solidity::frontend::OptimiserSettings::none(), DebugInfoSelection::All() ); + m_yulNameRepository = stack.yulNameRepository(); if (stack.parseAndAnalyze("", m_source)) { m_ast = stack.parserResult()->code; @@ -97,7 +98,7 @@ std::string YulInterpreterTest::interpret() { Interpreter::run( state, - EVMDialect::strictAssemblyForEVMObjects(solidity::test::CommonOptions::get().evmVersion()), + *m_yulNameRepository, *m_ast, /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false diff --git a/test/libyul/YulInterpreterTest.h b/test/libyul/YulInterpreterTest.h index a20b0688a236..63b746ec19e7 100644 --- a/test/libyul/YulInterpreterTest.h +++ b/test/libyul/YulInterpreterTest.h @@ -24,6 +24,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; struct Block; +class YulNameRepository; } namespace solidity::yul::test @@ -47,6 +48,7 @@ class YulInterpreterTest: public solidity::frontend::test::EVMVersionRestrictedT std::shared_ptr m_ast; std::shared_ptr m_analysisInfo; + std::shared_ptr m_yulNameRepository; bool m_simulateExternalCallsToSelf = false; }; diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 82e2549809e2..aab5715a5a4e 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -56,6 +56,7 @@ YulOptimizerTest::YulOptimizerTest(std::string const& _filename): auto dialectName = m_reader.stringSetting("dialect", "evm"); m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); + m_yulNameRepository = std::make_unique(*m_dialect); m_expectation = m_reader.simpleExpectations(); } @@ -69,7 +70,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co soltestAssert(m_dialect, "Dialect not set."); m_object->analysisInfo = m_analysisInfo; - YulOptimizerTestCommon tester(m_object, *m_dialect); + YulOptimizerTestCommon tester(m_object, *m_yulNameRepository); tester.setStep(m_optimizerStep); if (!tester.runStep()) @@ -78,7 +79,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co return TestResult::FatalError; } - auto const printed = (m_object->subObjects.empty() ? AsmPrinter{ *m_dialect }(*m_object->code) : m_object->toString(m_dialect)); + auto const printed = (m_object->subObjects.empty() ? AsmPrinter{ *m_yulNameRepository, AsmPrinter::Mode::OmitDefaultType }(*m_object->code) : m_object->toString(*m_yulNameRepository)); // Re-parse new code for compilability if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printed))) @@ -105,7 +106,7 @@ std::pair, std::shared_ptr> YulOptimize soltestAssert(m_dialect, ""); std::shared_ptr object; std::shared_ptr analysisInfo; - std::tie(object, analysisInfo) = yul::test::parse(_source, *m_dialect, errors); + std::tie(object, analysisInfo) = yul::test::parse(_source, *m_yulNameRepository, errors); if (!object || !analysisInfo || Error::containsErrors(errors)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 832b5dfb8f7c..91642c182e1a 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -31,6 +31,7 @@ namespace solidity::yul struct AsmAnalysisInfo; struct Object; struct Dialect; +class YulNameRepository; } namespace solidity::yul::test @@ -55,6 +56,7 @@ class YulOptimizerTest: public solidity::frontend::test::EVMVersionRestrictedTes std::string m_optimizerStep; Dialect const* m_dialect = nullptr; + std::unique_ptr m_yulNameRepository; std::shared_ptr m_object; std::shared_ptr m_analysisInfo; diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 091a9a0b6cff..06e1933213b7 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -75,88 +75,110 @@ using namespace solidity::frontend; YulOptimizerTestCommon::YulOptimizerTestCommon( std::shared_ptr _obj, - Dialect const& _dialect -) + YulNameRepository& _yulNameRepository +): m_yulNameRepository(_yulNameRepository) { m_object = _obj; m_ast = m_object->code; m_analysisInfo = m_object->analysisInfo; - m_dialect = &_dialect; m_namedSteps = { - {"disambiguator", [&]() { disambiguate(); }}, + {"disambiguator", [&]() { + disambiguate(); + m_context->yulNameRepository.generateLabels(*m_ast); + }}, {"nameDisplacer", [&]() { disambiguate(); NameDisplacer{ - *m_nameDispenser, - {"illegal1"_yulstring, "illegal2"_yulstring, "illegal3"_yulstring, "illegal4"_yulstring, "illegal5"_yulstring} + { + m_yulNameRepository.defineName("illegal1"), m_yulNameRepository.defineName("illegal2"), + m_yulNameRepository.defineName("illegal3"), m_yulNameRepository.defineName("illegal4"), + m_yulNameRepository.defineName("illegal5") + }, + m_yulNameRepository }(*m_ast); + m_context->yulNameRepository.generateLabels(*m_ast, {"illegal1", "illegal2", "illegal3", "illegal4", "illegal5"}); }}, {"blockFlattener", [&]() { disambiguate(); FunctionGrouper::run(*m_context, *m_ast); BlockFlattener::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"constantOptimiser", [&]() { - GasMeter meter(dynamic_cast(*m_dialect), false, 200); - ConstantOptimiser{dynamic_cast(*m_dialect), meter}(*m_ast); + GasMeter meter(m_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), false, 200); + ConstantOptimiser{_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), meter}(*m_ast); }}, {"varDeclInitializer", [&]() { VarDeclInitializer::run(*m_context, *m_ast); }}, {"varNameCleaner", [&]() { disambiguate(); FunctionHoister::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_ast); - VarNameCleaner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"forLoopConditionIntoBody", [&]() { disambiguate(); ForLoopConditionIntoBody::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"forLoopInitRewriter", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"commonSubexpressionEliminator", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast); CommonSubexpressionEliminator::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"conditionalUnsimplifier", [&]() { disambiguate(); ConditionalUnsimplifier::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"conditionalSimplifier", [&]() { disambiguate(); ConditionalSimplifier::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); + }}, + {"expressionSplitter", [&]() { + ExpressionSplitter::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, - {"expressionSplitter", [&]() { ExpressionSplitter::run(*m_context, *m_ast); }}, {"expressionJoiner", [&]() { disambiguate(); ExpressionJoiner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"splitJoin", [&]() { disambiguate(); ExpressionSplitter::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"functionGrouper", [&]() { disambiguate(); FunctionGrouper::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"functionHoister", [&]() { disambiguate(); FunctionHoister::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"functionSpecializer", [&]() { disambiguate(); FunctionHoister::run(*m_context, *m_object->code); FunctionSpecializer::run(*m_context, *m_object->code); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"expressionInliner", [&]() { disambiguate(); ExpressionInliner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"fullInliner", [&]() { disambiguate(); @@ -165,18 +187,21 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( ExpressionSplitter::run(*m_context, *m_ast); FullInliner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"fullInlinerWithoutSplitter", [&]() { disambiguate(); FunctionHoister::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_ast); FullInliner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"rematerialiser", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast); Rematerialiser::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"expressionSimplifier", [&]() { disambiguate(); @@ -190,6 +215,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( UnusedPruner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"fullSimplify", [&]() { disambiguate(); @@ -205,6 +231,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( DeadCodeEliminator::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"unusedFunctionParameterPruner", [&]() { disambiguate(); @@ -212,30 +239,36 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( FunctionHoister::run(*m_context, *m_object->code); LiteralRematerialiser::run(*m_context, *m_object->code); UnusedFunctionParameterPruner::run(*m_context, *m_object->code); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"unusedPruner", [&]() { disambiguate(); UnusedPruner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"circularReferencesPruner", [&]() { disambiguate(); FunctionHoister::run(*m_context, *m_ast); CircularReferencesPruner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"deadCodeEliminator", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); DeadCodeEliminator::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"ssaTransform", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); SSATransform::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"unusedAssignEliminator", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); UnusedAssignEliminator::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"unusedStoreEliminator", [&]() { disambiguate(); @@ -245,18 +278,21 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( UnusedStoreEliminator::run(*m_context, *m_ast); SSAReverser::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"equalStoreEliminator", [&]() { disambiguate(); FunctionHoister::run(*m_context, *m_ast); ForLoopInitRewriter::run(*m_context, *m_ast); EqualStoreEliminator::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"ssaPlusCleanup", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); SSATransform::run(*m_context, *m_ast); UnusedAssignEliminator::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"loadResolver", [&]() { disambiguate(); @@ -273,17 +309,20 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( UnusedPruner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); ExpressionJoiner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"loopInvariantCodeMotion", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast); LoopInvariantCodeMotion::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"controlFlowSimplifier", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); ControlFlowSimplifier::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"structuralSimplifier", [&]() { disambiguate(); @@ -291,16 +330,19 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( FunctionHoister::run(*m_context, *m_ast); LiteralRematerialiser::run(*m_context, *m_ast); StructuralSimplifier::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"equivalentFunctionCombiner", [&]() { disambiguate(); ForLoopInitRewriter::run(*m_context, *m_ast); FunctionHoister::run(*m_context, *m_ast); EquivalentFunctionCombiner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"ssaReverser", [&]() { disambiguate(); SSAReverser::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"ssaAndBack", [&]() { disambiguate(); @@ -313,6 +355,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( FunctionHoister::run(*m_context, *m_ast); CommonSubexpressionEliminator::run(*m_context, *m_ast); UnusedPruner::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"stackCompressor", [&]() { disambiguate(); @@ -320,13 +363,14 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( FunctionHoister::run(*m_context, *m_ast); FunctionGrouper::run(*m_context, *m_ast); size_t maxIterations = 16; - StackCompressor::run(*m_dialect, *m_object, true, maxIterations); + StackCompressor::run(m_yulNameRepository, *m_object, true, maxIterations); BlockFlattener::run(*m_context, *m_ast); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"fullSuite", [&]() { - GasMeter meter(dynamic_cast(*m_dialect), false, 200); + GasMeter meter(m_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), false, 200); OptimiserSuite::run( - *m_dialect, + m_yulNameRepository, &meter, *m_object, true, @@ -334,25 +378,29 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( frontend::OptimiserSettings::DefaultYulOptimiserCleanupSteps, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment ); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"stackLimitEvader", [&]() { disambiguate(); + m_context->yulNameRepository.generateLabels(*m_ast); StackLimitEvader::run(*m_context, *m_object, CompilabilityChecker{ - *m_dialect, + m_yulNameRepository, *m_object, true }.unreachableVariables); + m_context->yulNameRepository.generateLabels(*m_ast); }}, {"fakeStackLimitEvader", [&]() { disambiguate(); // Mark all variables with a name starting with "$" for escalation to memory. struct FakeUnreachableGenerator: ASTWalker { - std::map> fakeUnreachables; + FakeUnreachableGenerator(YulNameRepository const& _yulNameRepository): m_yulNameRepository(_yulNameRepository) {} + std::map> fakeUnreachables; using ASTWalker::operator(); void operator()(FunctionDefinition const& _function) override { - YulString originalFunctionName = m_currentFunction; + auto originalFunctionName = m_currentFunction; m_currentFunction = _function.name; for (TypedName const& _argument: _function.parameters) visitVariableName(_argument.name); @@ -361,9 +409,9 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( ASTWalker::operator()(_function); m_currentFunction = originalFunctionName; } - void visitVariableName(YulString _var) + void visitVariableName(YulName _var) { - if (!_var.empty() && _var.str().front() == '$') + if (_var != YulNameRepository::emptyName() && m_yulNameRepository.baseLabelOf(_var).front() == '$') if (!util::contains(fakeUnreachables[m_currentFunction], _var)) fakeUnreachables[m_currentFunction].emplace_back(_var); } @@ -378,11 +426,13 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( visitVariableName(_identifier.name); ASTWalker::operator()(_identifier); } - YulString m_currentFunction = YulString{}; + YulName m_currentFunction = YulNameRepository::emptyName(); + YulNameRepository const& m_yulNameRepository; }; - FakeUnreachableGenerator fakeUnreachableGenerator; + FakeUnreachableGenerator fakeUnreachableGenerator (m_yulNameRepository); fakeUnreachableGenerator(*m_ast); StackLimitEvader::run(*m_context, *m_object, fakeUnreachableGenerator.fakeUnreachables); + m_context->yulNameRepository.generateLabels(*m_ast); }} }; } @@ -394,8 +444,6 @@ void YulOptimizerTestCommon::setStep(std::string const& _optimizerStep) bool YulOptimizerTestCommon::runStep() { - yulAssert(m_dialect, "Dialect not set."); - updateContext(); if (m_namedSteps.count(m_optimizerStep)) @@ -442,18 +490,18 @@ std::shared_ptr YulOptimizerTestCommon::run() void YulOptimizerTestCommon::disambiguate() { - *m_object->code = std::get(Disambiguator(*m_dialect, *m_analysisInfo)(*m_object->code)); + *m_object->code = std::get(Disambiguator(m_yulNameRepository, *m_analysisInfo)(*m_object->code)); m_analysisInfo.reset(); updateContext(); } void YulOptimizerTestCommon::updateContext() { - m_nameDispenser = std::make_unique(*m_dialect, *m_object->code, m_reservedIdentifiers); + static std::set nothingReserved {}; m_context = std::make_unique(OptimiserStepContext{ - *m_dialect, - *m_nameDispenser, - m_reservedIdentifiers, + m_yulNameRepository.dialect(), + m_yulNameRepository, + nothingReserved, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }); } diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index 3dce998c56cc..3b1faab0ad23 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -19,7 +19,6 @@ #pragma once #include -#include #include @@ -28,9 +27,8 @@ namespace solidity::yul { - struct AsmAnalysisInfo; - struct Object; - struct Dialect; +struct AsmAnalysisInfo; +struct Object; } namespace solidity::yul::test @@ -40,7 +38,7 @@ class YulOptimizerTestCommon public: explicit YulOptimizerTestCommon( std::shared_ptr _obj, - Dialect const& _dialect + YulNameRepository& _yulNameRepository ); /// Sets optimiser step to be run to @param /// _optimiserStep. @@ -62,9 +60,7 @@ class YulOptimizerTestCommon std::string m_optimizerStep; - Dialect const* m_dialect = nullptr; - std::set m_reservedIdentifiers; - std::unique_ptr m_nameDispenser; + YulNameRepository& m_yulNameRepository; std::unique_ptr m_context; std::shared_ptr m_object; diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/movable_functions.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/movable_functions.yul index d6041eb5e244..a5fa77b07b37 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/movable_functions.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/movable_functions.yul @@ -18,9 +18,9 @@ // let d := double_with_se(i) // function double(x) -> y // { y := add(x, x) } -// function double_with_se(x_1) -> y_2 +// function double_with_se(x_1) -> y_1 // { -// y_2 := add(x_1, x_1) +// y_1 := add(x_1, x_1) // mstore(40, 4) // } // } diff --git a/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul index 30f2e54794a0..bbe081cb347d 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/for_statement.yul @@ -18,6 +18,6 @@ // function eq(x, y) -> z:bool // { } // for { let a_1 } eq(a_1, a_1) { a_1 := a_1 } -// { let b_2 := a_1 } +// { let b_1 := a_1 } // } // } diff --git a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul index f99c4e4476de..ae89ae26a9b2 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/funtion_call.yul @@ -14,7 +14,7 @@ // { // { let a, b, c, d, f } // { -// function f_1(a_2) -> c_3, d_4 -// { let b_5, c_1 := f_1(a_2) } +// function f_1(a_1) -> c_1, d_1 +// { let b_1, c_1_1 := f_1(a_1) } // } // } diff --git a/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul index 6b6da1f189fa..f8da034b9ae1 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/if_statement.yul @@ -14,6 +14,6 @@ // { let a, b, c } // { // let a_1:bool -// if a_1 { let b_2:bool := a_1 } +// if a_1 { let b_1:bool := a_1 } // } // } diff --git a/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul index 16ee5353f79b..74690af039da 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/switch_statement.yul @@ -17,7 +17,7 @@ // { // let a_1 // switch a_1 -// case 0 { let b_2 := a_1 } -// default { let c_3 := a_1 } +// case 0 { let b_1 := a_1 } +// default { let c_1 := a_1 } // } // } diff --git a/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul index a78af7dabcab..2edeb16391a1 100644 --- a/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul +++ b/test/libyul/yulOptimizerTests/disambiguator/variables_inside_functions.yul @@ -15,10 +15,10 @@ // let c // let b // } -// function f(a, c_1) -> b_2 +// function f(a, c_1) -> b_1 // { let x } // { -// let a_3 -// let x_4 +// let a_1 +// let x_1 // } // } diff --git a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/simple_different_vars.yul b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/simple_different_vars.yul index 5967adc0e13c..e03da0f351f4 100644 --- a/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/simple_different_vars.yul +++ b/test/libyul/yulOptimizerTests/equivalentFunctionCombiner/simple_different_vars.yul @@ -17,7 +17,7 @@ // } // function g() -> a_1 // { -// let b_2 := mload(0) -// a_1 := b_2 +// let b_1 := mload(0) +// a_1 := b_1 // } // } diff --git a/test/libyul/yulOptimizerTests/expressionInliner/argument_duplication_heuristic.yul b/test/libyul/yulOptimizerTests/expressionInliner/argument_duplication_heuristic.yul index 12228009ab83..c37cf6a5327f 100644 --- a/test/libyul/yulOptimizerTests/expressionInliner/argument_duplication_heuristic.yul +++ b/test/libyul/yulOptimizerTests/expressionInliner/argument_duplication_heuristic.yul @@ -22,9 +22,9 @@ // { // function ref1(a) -> x // { x := add(a, 1) } -// function ref3(a_1) -> x_2 +// function ref3(a_1) -> x_1 // { -// x_2 := add(a_1, mul(a_1, a_1)) +// x_1 := add(a_1, mul(a_1, a_1)) // } // let y1 := add(calldatasize(), 1) // let y2 := add(calldatasize(), mul(calldatasize(), calldatasize())) diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_add_and_mod_constant.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_add_and_mod_constant.yul index f462486ea196..dcf7e0006255 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_add_and_mod_constant.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_add_and_mod_constant.yul @@ -6,8 +6,8 @@ // // { // { -// let _3 := mload(1) -// let _4 := 0 -// mstore(_4, addmod(mload(_4), _3, 32)) +// let _1 := mload(1) +// let _2 := 0 +// mstore(_2, addmod(mload(_2), _1, 32)) // } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_mul_and_mod_constant.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_mul_and_mod_constant.yul index 93edb5319658..b0e7c1be89b3 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_mul_and_mod_constant.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_mul_and_mod_constant.yul @@ -6,8 +6,8 @@ // // { // { -// let _3 := mload(1) -// let _4 := 0 -// mstore(_4, mulmod(mload(_4), _3, 32)) +// let _1 := mload(1) +// let _2 := 0 +// mstore(_2, mulmod(mload(_2), _1, 32)) // } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_2.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_2.yul index 6e39f2a1dc36..c0dea8b3ebdc 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_2.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_2.yul @@ -26,25 +26,25 @@ // { // { // let x := calldataload(0) -// let _2 := 0xf -// let _5 := and(shr(248, x), 0) -// let _10 := 0xff -// let a := and(_5, 255) -// let _14 := and(shr(4, x), 3855) -// let _15 := 12 -// let b := shl(_15, _14) -// let _19 := and(shr(4, x), 3855) -// let c := shl(_15, _19) -// let d := shl(_15, and(shr(255, x), 0)) -// let e := shl(_10, _19) +// let _1 := 0xf +// let _2 := and(shr(248, x), 0) +// let _3 := 0xff +// let a := and(_2, 255) +// let _4 := and(shr(4, x), 3855) +// let _5 := 12 +// let b := shl(_5, _4) +// let _6 := and(shr(4, x), 3855) +// let c := shl(_5, _6) +// let d := shl(_5, and(shr(255, x), 0)) +// let e := shl(_3, _6) // let f := 0 // let g := 0 // sstore(10, a) // sstore(11, b) -// sstore(_15, c) +// sstore(_5, c) // sstore(13, d) // sstore(14, e) -// sstore(_2, f) +// sstore(_1, f) // sstore(16, g) // } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_3.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_3.yul index 9df15b4e9c6f..1c2609e15386 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_3.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/combine_shift_and_and_3.yul @@ -27,8 +27,8 @@ // let b := and(shr(8, x), 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0) // let c := and(shr(8, x), 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) // let d := and(shl(8, x), 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00) -// let _14 := 150 -// let e := shl(_14, and(shl(148, x), 0x3ffffffffffffffffffffffffff0000000000000000000000000000000000000)) +// let _1 := 150 +// let e := shl(_1, and(shl(148, x), 0x3ffffffffffffffffffffffffff0000000000000000000000000000000000000)) // sstore(15, x) // sstore(16, a) // sstore(17, b) diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul index 3710cbebdf48..9f5c82a4e24f 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/create_and_mask.yul @@ -15,8 +15,8 @@ // let _1 := 0x20 // let _2 := 0 // let c := create(_2, _2, _1) -// let _4 := 0xffffffffffffffffffffffffffffffffffffffff -// let a := and(c, _4) -// sstore(a, and(_4, create(_2, _2, _1))) +// let _3 := 0xffffffffffffffffffffffffffffffffffffffff +// let a := and(c, _3) +// sstore(a, and(_3, create(_2, _2, _1))) // } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/exp_simplifications.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/exp_simplifications.yul index 4a5d218053c0..ac1cbf9de5e6 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/exp_simplifications.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/exp_simplifications.yul @@ -18,8 +18,8 @@ // let t := calldataload(_1) // sstore(_1, iszero(t)) // sstore(1, 1) -// let _8 := 2 -// sstore(_8, shl(t, 1)) +// let _2 := 2 +// sstore(_2, shl(t, 1)) // sstore(3, exp(8, t)) // sstore(4, sub(iszero(and(t, 1)), and(t, 1))) // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.sol b/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.sol index 410b7df536b3..b9f46f1d3454 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.sol +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/mcopy_non_zero_size.sol @@ -15,8 +15,8 @@ // let _1 := 0x60 // let _2 := 0 // calldatacopy(_2, _2, _1) -// let _4 := 0x20 -// mcopy(_4, 0x40, _4) +// let _3 := 0x20 +// mcopy(_3, 0x40, _3) // return(_2, _1) // } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul index 88ed926b18f7..669b799e898f 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_1.yul @@ -6,7 +6,7 @@ // // { // { -// let _4 := 0 -// mstore(_4, and(calldataload(_4), 255)) +// let _1 := 0 +// mstore(_1, and(calldataload(_1), 255)) // } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul index a62c5904cfd5..c08f0b2ce5ae 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/mod_and_2.yul @@ -6,7 +6,7 @@ // // { // { -// let _4 := 0 -// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// let _1 := 0 +// mstore(_1, and(calldataload(_1), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) // } // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul index c4269352191c..e62392c9e1bb 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul @@ -8,9 +8,9 @@ // // { // { -// let _2 := f(1) -// let _3 := 0 -// sstore(_3, sub(f(_3), _2)) +// let _1 := f(1) +// let _2 := 0 +// sstore(_2, sub(f(_2), _1)) // } // function f(a) -> b // { } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/remove_redundant_shift_masking.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/remove_redundant_shift_masking.yul index a4d3012c33b1..fdad31caae72 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/remove_redundant_shift_masking.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/remove_redundant_shift_masking.yul @@ -13,12 +13,12 @@ // // { // { -// let _2 := calldataload(0) -// let _5 := 0xff -// let a := shr(248, _2) -// let b := shr(248, _2) -// let c := and(shr(249, _2), 0xfa) -// let d := and(shr(247, _2), _5) +// let _1 := calldataload(0) +// let _2 := 0xff +// let a := shr(248, _1) +// let b := shr(248, _1) +// let c := and(shr(249, _1), 0xfa) +// let d := and(shr(247, _1), _2) // sstore(a, b) // sstore(c, d) // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/replace_too_large_shift.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/replace_too_large_shift.yul index 85c86f0e4b99..448edbb5a48f 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/replace_too_large_shift.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/replace_too_large_shift.yul @@ -15,10 +15,10 @@ // { // let a := 0 // let b := 0 -// let _8 := calldataload(2) -// let _9 := 255 -// let c := shl(_9, _8) -// let d := shr(_9, calldataload(3)) +// let _1 := calldataload(2) +// let _2 := 255 +// let c := shl(_2, _1) +// let d := shr(_2, calldataload(3)) // sstore(a, b) // sstore(c, d) // } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul index a15cca231d42..e2a63ba28698 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul @@ -10,6 +10,6 @@ // { // { // let c, d -// sstore(d, 7) +// sstore(c, 7) // } // } diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul index 99e92c183edc..0ba73fbf09be 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/connected.yul @@ -29,34 +29,34 @@ // { // a := 21 // mstore(0x60, 1) -// let b_1, a_2, $c_3 := z() -// mstore(0x60, $c_3) -// a := a_2 -// b := b_1 +// let b_2, a_3, $c := z() +// mstore(0x60, $c) +// a := a_3 +// b := b_2 // } // function f() -> x // { // mstore(0x40, 0) // mstore(0x40, 42) -// let $x3_4, $x4_5 := g() -// mstore(0x00, $x4_5) -// mstore(0x20, $x3_4) +// let $x3, $x4 := g() +// mstore(0x00, $x4) +// mstore(0x20, $x3) // x := mul(add(mload(0x40), mload(0x20)), h(mload(0x00))) // sstore(mload(0x20), mload(0x00)) // } // function h(v) -> a_1 // { -// let x_2_6, $z_7, y_8 := z() -// mstore(0x60, $z_7) -// let y := y_8 -// let x_2 := x_2_6 -// let a_1_9, $z_10, v_11 := z() -// mstore(0x60, $z_10) -// v := v_11 -// a_1 := a_1_9 +// let x_3, $z, y_2 := z() +// mstore(0x60, $z) +// let y := y_2 +// let x_1 := x_3 +// let a_4, $z_1, v_1 := z() +// mstore(0x60, $z_1) +// v := v_1 +// a_1 := a_4 // } -// function z() -> a_3, b_4, c +// function z() -> a_2, b_1, c // { mstore(0x80, 0) } // sstore(0, f()) -// let x_5, y_6 := g() +// let x_2, y_1 := g() // } diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul index 5650b580da5f..c0aa21fbd37c 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/multi_variable_declaration_without_value.yul @@ -14,8 +14,8 @@ // mstore(0x40, memoryguard(0x80)) // { let x, y } // { -// let z_1, $w_2 -// mstore(0x60, $w_2) +// let z_1, $w +// mstore(0x60, $w) // let z := z_1 // } // } diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul index 3b43bd534309..459bab72d9be 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_leave.yul @@ -36,13 +36,13 @@ // mstore(0x80, 0) // if calldataload(0) // { -// let $b1_1, $b2_2 := g(1) -// mstore(0x80, $b2_2) -// mstore(0xa0, $b1_1) +// let $b1, $b2 := g(1) +// mstore(0x80, $b2) +// mstore(0xa0, $b1) // leave // } -// let $b1_3, $b2_4 := g(2) -// mstore(0x80, $b2_4) -// mstore(0xa0, $b1_3) +// let $b1_1, $b2_1 := g(2) +// mstore(0x80, $b2_1) +// mstore(0xa0, $b1_1) // } // } diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul index 706a46c6280c..108388e9620c 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/return_one_with_args.yul @@ -20,10 +20,10 @@ // mstore(0x40, memoryguard(0xa0)) // sstore(0, f(1, 2, 3)) // } -// function f(a_2, b_3, c_4) -> $b1 +// function f(a_1, b_1, c_1) -> $b1 // { // mstore(0x80, 0) -// f_1(a_2, b_3, c_4) +// f_1(a_1, b_1, c_1) // $b1 := mload(0x80) // } // function f_1(a, b, c) diff --git a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul index e86619e464b2..25f86938872a 100644 --- a/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul +++ b/test/libyul/yulOptimizerTests/fakeStackLimitEvader/stub.yul @@ -37,50 +37,50 @@ // } // function g(gx) // { -// let $gx_1, $gy_2 := tuple2() -// mstore(0x40, $gy_2) -// mstore(0x60, $gx_1) +// let $gx, $gy := tuple2() +// mstore(0x40, $gy) +// mstore(0x60, $gx) // { -// let $gx_3, $gy_4 := tuple2() -// mstore(0x40, $gy_4) -// mstore(0x60, $gx_3) +// let $gx_1, $gy_1 := tuple2() +// mstore(0x40, $gy_1) +// mstore(0x60, $gx_1) // } // { -// let $gx_5, gx_6 := tuple2() -// mstore(0x60, $gx_5) -// gx := gx_6 +// let $gx_2, gx_1 := tuple2() +// mstore(0x60, $gx_2) +// gx := gx_1 // } // { -// let gx_7, $gy_8 := tuple2() -// mstore(0x40, $gy_8) -// gx := gx_7 +// let gx_2, $gy_2 := tuple2() +// mstore(0x40, $gy_2) +// gx := gx_2 // } // } // function h(hx, hy, hz, hw) // { -// let $hx_9, $hy_10, $hz_11, $hw_12 := tuple4() -// mstore(0x00, $hw_12) -// mstore(0x20, $hz_11) -// mstore(0x40, $hy_10) -// mstore(0x60, $hx_9) +// let $hx, $hy, $hz, $hw := tuple4() +// mstore(0x00, $hw) +// mstore(0x20, $hz) +// mstore(0x40, $hy) +// mstore(0x60, $hx) // { -// let hx_13, $hy_14, hz_15, $hw_16 := tuple4() -// mstore(0x00, $hw_16) -// mstore(0x40, $hy_14) -// hz := hz_15 -// hx := hx_13 +// let hx_1, $hy_1, hz_1, $hw_1 := tuple4() +// mstore(0x00, $hw_1) +// mstore(0x40, $hy_1) +// hz := hz_1 +// hx := hx_1 // } // { -// let $hx_17, $hy_18, hz_19, hw_20 := tuple4() -// mstore(0x40, $hy_18) -// mstore(0x60, $hx_17) -// hw := hw_20 -// hz := hz_19 +// let $hx_1, $hy_2, hz_2, hw_1 := tuple4() +// mstore(0x40, $hy_2) +// mstore(0x60, $hx_1) +// hw := hw_1 +// hz := hz_2 // } // } // function tuple2() -> a, b // { } -// function tuple4() -> a_1, b_2, c, d +// function tuple4() -> a_1, b_1, c, d // { } // f() // g(0) diff --git a/test/libyul/yulOptimizerTests/fullInliner/call_arguments_with_side_effects.yul b/test/libyul/yulOptimizerTests/fullInliner/call_arguments_with_side_effects.yul index 94b0c72d2934..ac6e50f15189 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/call_arguments_with_side_effects.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/call_arguments_with_side_effects.yul @@ -11,14 +11,14 @@ // // { // { -// let ret_7 := 0 +// let ret_2 := 0 // revert(0, 0) -// let _1 := ret_7 -// let ret_1_10 := 0 +// let _1 := ret_2 +// let ret_3 := 0 // return(0, 0) -// let _2 := ret_1_10 -// let b_13 := _1 -// let a_14 := _2 +// let _2 := ret_3 +// let b_1 := _1 +// let a_1 := _2 // } // function fun_revert() -> ret // { revert(0, 0) } diff --git a/test/libyul/yulOptimizerTests/fullInliner/call_arguments_without_side_effects.yul b/test/libyul/yulOptimizerTests/fullInliner/call_arguments_without_side_effects.yul index 747ac8084912..416f41b265c5 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/call_arguments_without_side_effects.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/call_arguments_without_side_effects.yul @@ -25,26 +25,26 @@ // let _1 := 333 // let _2 := 222 // let _3 := 111 -// let c_13 := _1 -// let b_14 := _2 -// let a_15 := _3 +// let c_1 := _1 +// let b_1 := _2 +// let a_2 := _3 // let x := 111 // let y := 222 -// let c_16 := 333 -// let b_17 := y -// let a_18 := x -// let _5 := calldataload(333) -// let _7 := sload(222) -// let _9 := mload(111) -// let c_19 := _5 -// let b_20 := _7 -// let a_21 := _9 +// let c_2 := 333 +// let b_2 := y +// let a_3 := x +// let _4 := calldataload(333) +// let _5 := sload(222) +// let _6 := mload(111) +// let c_3 := _4 +// let b_3 := _5 +// let a_4 := _6 // let a_1 := 222 -// let _11 := mload(333) -// let _12 := 111 -// let c_22 := _11 -// let b_23 := a_1 -// let a_24 := _12 +// let _7 := mload(333) +// let _8 := 111 +// let c_4 := _7 +// let b_4 := a_1 +// let a_5 := _8 // } // function empty(a, b, c) // { } diff --git a/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul index 259e4aeda4c6..37f0b530bf3b 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul @@ -9,19 +9,19 @@ // // { // { -// let a_2 := calldataload(0) -// let b_3 := 0 -// let c_4 := 0 -// b_3 := sload(mload(a_2)) -// c_4 := 3 -// let b3 := b_3 -// let a_6 := c_4 -// let b_7 := 0 -// let c_8 := 0 -// b_7 := sload(mload(a_6)) -// c_8 := 3 -// let b4 := b_7 -// let c4 := c_8 +// let a_1 := calldataload(0) +// let b_1 := 0 +// let c_1 := 0 +// b_1 := sload(mload(a_1)) +// c_1 := 3 +// let b3 := b_1 +// let a_2 := c_1 +// let b_2 := 0 +// let c_2 := 0 +// b_2 := sload(mload(a_2)) +// c_2 := 3 +// let b4 := b_2 +// let c4 := c_2 // } // function f(a) -> b, c // { diff --git a/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul index 39c3bb2950c7..ff0b5a476767 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul @@ -13,12 +13,12 @@ // // { // { -// let _2 := mload(0) -// let a_10 := mload(1) -// let r_11 := 0 -// a_10 := mload(a_10) -// r_11 := add(a_10, calldatasize()) -// if gt(r_11, _2) { sstore(0, 2) } +// let _1 := mload(0) +// let a_1 := mload(1) +// let r_1 := 0 +// a_1 := mload(a_1) +// r_1 := add(a_1, calldatasize()) +// if gt(r_1, _1) { sstore(0, 2) } // } // function f(a) -> r // { diff --git a/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul index 151b7596ca43..44f59ae56414 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul @@ -22,28 +22,28 @@ // { // let a_1 := mload(2) // let a2 := 2 -// let a_3 := a_1 -// let b_4 := 0 -// let x_5 := mload(a_3) -// b_4 := sload(x_5) -// let y_6 := add(a_3, x_5) -// sstore(y_6, 10) -// let r := b_4 -// let a_8 := a2 -// let b_9 := 0 -// let x_10 := mload(a_8) -// b_9 := sload(x_10) -// let y_11 := add(a_8, x_10) -// sstore(y_11, 10) -// let t := b_9 +// let a_2 := a_1 +// let b_1 := 0 +// let x_1 := mload(a_2) +// b_1 := sload(x_1) +// let y_1 := add(a_2, x_1) +// sstore(y_1, 10) +// let r := b_1 +// let a_3 := a2 +// let b_2 := 0 +// let x_2 := mload(a_3) +// b_2 := sload(x_2) +// let y_2 := add(a_3, x_2) +// sstore(y_2, 10) +// let t := b_2 // let a3 -// let a_13 := a3 -// let b_14 := 0 -// let x_15 := mload(a_13) -// b_14 := sload(x_15) -// let y_16 := add(a_13, x_15) -// sstore(y_16, 10) -// let s := b_14 +// let a_4 := a3 +// let b_3 := 0 +// let x_3 := mload(a_4) +// b_3 := sload(x_3) +// let y_3 := add(a_4, x_3) +// sstore(y_3, 10) +// let s := b_3 // } // function f(a) -> b // { diff --git a/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul b/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul index 4bcfe6f19465..bc0a85a0e2d3 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul @@ -15,15 +15,15 @@ // // { // { -// let a_6 := mload(1) -// let b_7 := 0 -// let x_8 := mload(a_6) -// b_7 := sload(x_8) -// let c_9 := 3 -// mstore(mul(a_6, b_7), mload(x_8)) -// let y_12 := add(a_6, x_8) -// sstore(y_12, 10) -// let r := b_7 +// let a_1 := mload(1) +// let b_1 := 0 +// let x_1 := mload(a_1) +// b_1 := sload(x_1) +// let c_1 := 3 +// mstore(mul(a_1, b_1), mload(x_1)) +// let y_1 := add(a_1, x_1) +// sstore(y_1, 10) +// let r := b_1 // } // function f(a) -> b // { diff --git a/test/libyul/yulOptimizerTests/fullInliner/long_names.yul b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul index b2162c520ec9..d5765452a123 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/long_names.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul @@ -13,10 +13,10 @@ // { // { // let verylongvariablename2_1 := 3 -// let verylongvariablename_4 := verylongvariablename2_1 -// let verylongvariablename2_5 := 0 -// verylongvariablename2_5 := add(verylongvariablename_4, verylongvariablename_4) -// mstore(0, verylongvariablename2_5) +// let verylongvariablename_1 := verylongvariablename2_1 +// let verylongvariablename2_2 := 0 +// verylongvariablename2_2 := add(verylongvariablename_1, verylongvariablename_1) +// mstore(0, verylongvariablename2_2) // mstore(1, verylongvariablename2_1) // } // function verylongfunctionname(verylongvariablename) -> verylongvariablename2 diff --git a/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul index 1f777237ac82..8168804c3b5c 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul @@ -10,18 +10,18 @@ // // { // { -// let _2 := mload(5) -// let _4 := mload(4) -// let _6 := mload(3) -// let _8 := mload(2) -// let c_13 := _4 -// let b_14 := _6 -// let a_15 := _8 -// let x_16 := 0 -// x_16 := add(a_15, b_14) -// x_16 := mul(x_16, c_13) -// let _10 := add(x_16, _2) -// let y := add(mload(1), _10) +// let _1 := mload(5) +// let _2 := mload(4) +// let _3 := mload(3) +// let _4 := mload(2) +// let c_1 := _2 +// let b_1 := _3 +// let a_1 := _4 +// let x_1 := 0 +// x_1 := add(a_1, b_1) +// x_1 := mul(x_1, c_1) +// let _5 := add(x_1, _1) +// let y := add(mload(1), _5) // } // function f(a, b, c) -> x // { diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul index b30078cb61f4..f7cd70e883d2 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul @@ -9,26 +9,26 @@ // { // { // let _1 := 7 -// let a_8 := 3 -// let x_9 := 0 -// x_9 := add(a_8, a_8) -// let _3 := x_9 -// let c_10 := _1 -// let b_11 := _3 -// let y_12 := 0 -// let a_6_13 := b_11 -// let x_7_14 := 0 -// x_7_14 := add(a_6_13, a_6_13) -// y_12 := mul(mload(c_10), x_7_14) -// let y_1 := y_12 +// let a_2 := 3 +// let x_2 := 0 +// x_2 := add(a_2, a_2) +// let _2 := x_2 +// let c_1 := _1 +// let b_1 := _2 +// let y_2 := 0 +// let a_3 := b_1 +// let x_3 := 0 +// x_3 := add(a_3, a_3) +// y_2 := mul(mload(c_1), x_3) +// let y_1 := y_2 // } // function f(a) -> x // { x := add(a, a) } // function g(b, c) -> y // { -// let a_6 := b -// let x_7 := 0 -// x_7 := add(a_6, a_6) -// y := mul(mload(c), x_7) +// let a_1 := b +// let x_1 := 0 +// x_1 := add(a_1, a_1) +// y := mul(mload(c), x_1) // } // } diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul index 14e977dd3a67..c24ce6c7708b 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul @@ -30,10 +30,10 @@ // function f(x) // { // mstore(0, x) -// let t_8 := 0 -// t_8 := 2 -// mstore(7, t_8) -// let x_1_9 := 10 +// let t_1 := 0 +// t_1 := 2 +// mstore(7, t_1) +// let x_2 := 10 // f(1) // mstore(1, x) // } diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul index 21369f10b683..9458f90ec02e 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul @@ -11,13 +11,13 @@ // // { // { -// let a_3 := mload(0) -// let x_4 := 0 -// let y_5 := 0 -// x_4 := mul(a_3, a_3) -// y_5 := add(a_3, x_4) -// let r := x_4 -// mstore(r, y_5) +// let a_1 := mload(0) +// let x_1 := 0 +// let y_1 := 0 +// x_1 := mul(a_1, a_1) +// y_1 := add(a_1, x_1) +// let r := x_1 +// mstore(r, y_1) // } // function f(a) -> x, y // { diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_return_typed.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_return_typed.yul index 143ae35b27b8..32a559f9f2a2 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/multi_return_typed.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_return_typed.yul @@ -11,12 +11,12 @@ // // { // { -// let a_3 := mload(3) -// let x_4:bool := false -// let y_5 := 0 -// y_5 := mul(a_3, a_3) -// let r:bool := x_4 -// let s := y_5 +// let a_1 := mload(3) +// let x_1:bool := false +// let y_1 := 0 +// y_1 := mul(a_1, a_1) +// let r:bool := x_1 +// let s := y_1 // } // function f(a) -> x:bool, y // { y := mul(a, a) } diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul index d120d0152947..966ff54cc7df 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul @@ -18,47 +18,47 @@ // { } // function f(a) -> b // { b := sload(mload(a)) } -// function g() -> x_1 +// function g() -> x // { -// let a_20 := 2 -// let b_21 := 0 -// b_21 := sload(mload(a_20)) -// let a_23 := b_21 -// let b_24 := 0 -// b_24 := sload(mload(a_23)) -// let a_26 := b_24 -// let b_27 := 0 -// b_27 := sload(mload(a_26)) -// let a_29 := b_27 -// let b_30 := 0 -// b_30 := sload(mload(a_29)) -// let a_32 := b_30 -// let b_33 := 0 -// b_33 := sload(mload(a_32)) -// let a_35 := b_33 -// let b_36 := 0 -// b_36 := sload(mload(a_35)) -// let a_38 := b_36 -// let b_39 := 0 -// b_39 := sload(mload(a_38)) -// let a_41 := b_39 -// let b_42 := 0 -// b_42 := sload(mload(a_41)) -// let a_44 := b_42 -// let b_45 := 0 -// b_45 := sload(mload(a_44)) -// let a_47 := b_45 -// let b_48 := 0 -// b_48 := sload(mload(a_47)) -// let a_50 := b_48 -// let b_51 := 0 -// b_51 := sload(mload(a_50)) -// let a_53 := b_51 -// let b_54 := 0 -// b_54 := sload(mload(a_53)) -// let a_56 := b_54 -// let b_57 := 0 -// b_57 := sload(mload(a_56)) -// x_1 := f(f(f(f(f(f(b_57)))))) +// let a_1 := 2 +// let b_1 := 0 +// b_1 := sload(mload(a_1)) +// let a_2 := b_1 +// let b_2 := 0 +// b_2 := sload(mload(a_2)) +// let a_3 := b_2 +// let b_3 := 0 +// b_3 := sload(mload(a_3)) +// let a_4 := b_3 +// let b_4 := 0 +// b_4 := sload(mload(a_4)) +// let a_5 := b_4 +// let b_5 := 0 +// b_5 := sload(mload(a_5)) +// let a_6 := b_5 +// let b_6 := 0 +// b_6 := sload(mload(a_6)) +// let a_7 := b_6 +// let b_7 := 0 +// b_7 := sload(mload(a_7)) +// let a_8 := b_7 +// let b_8 := 0 +// b_8 := sload(mload(a_8)) +// let a_9 := b_8 +// let b_9 := 0 +// b_9 := sload(mload(a_9)) +// let a_10 := b_9 +// let b_10 := 0 +// b_10 := sload(mload(a_10)) +// let a_11 := b_10 +// let b_11 := 0 +// b_11 := sload(mload(a_11)) +// let a_12 := b_11 +// let b_12 := 0 +// b_12 := sload(mload(a_12)) +// let a_13 := b_12 +// let b_13 := 0 +// b_13 := sload(mload(a_13)) +// x := f(f(f(f(f(f(b_13)))))) // } // } diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul index 875d715c5cb0..34d03d94ec58 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul @@ -14,46 +14,46 @@ // // { // { -// let a_20 := 2 -// let b_21 := 0 -// b_21 := sload(mload(a_20)) -// let a_23 := b_21 -// let b_24 := 0 -// b_24 := sload(mload(a_23)) -// let a_26 := b_24 -// let b_27 := 0 -// b_27 := sload(mload(a_26)) -// let a_29 := b_27 -// let b_30 := 0 -// b_30 := sload(mload(a_29)) -// let a_32 := b_30 -// let b_33 := 0 -// b_33 := sload(mload(a_32)) -// let a_35 := b_33 -// let b_36 := 0 -// b_36 := sload(mload(a_35)) -// let a_38 := b_36 -// let b_39 := 0 -// b_39 := sload(mload(a_38)) -// let a_41 := b_39 -// let b_42 := 0 -// b_42 := sload(mload(a_41)) -// let a_44 := b_42 -// let b_45 := 0 -// b_45 := sload(mload(a_44)) -// let a_47 := b_45 -// let b_48 := 0 -// b_48 := sload(mload(a_47)) -// let a_50 := b_48 -// let b_51 := 0 -// b_51 := sload(mload(a_50)) -// let a_53 := b_51 -// let b_54 := 0 -// b_54 := sload(mload(a_53)) -// let a_56 := b_54 -// let b_57 := 0 -// b_57 := sload(mload(a_56)) -// let x_1 := f(f(f(f(f(f(b_57)))))) +// let a_1 := 2 +// let b_1 := 0 +// b_1 := sload(mload(a_1)) +// let a_2 := b_1 +// let b_2 := 0 +// b_2 := sload(mload(a_2)) +// let a_3 := b_2 +// let b_3 := 0 +// b_3 := sload(mload(a_3)) +// let a_4 := b_3 +// let b_4 := 0 +// b_4 := sload(mload(a_4)) +// let a_5 := b_4 +// let b_5 := 0 +// b_5 := sload(mload(a_5)) +// let a_6 := b_5 +// let b_6 := 0 +// b_6 := sload(mload(a_6)) +// let a_7 := b_6 +// let b_7 := 0 +// b_7 := sload(mload(a_7)) +// let a_8 := b_7 +// let b_8 := 0 +// b_8 := sload(mload(a_8)) +// let a_9 := b_8 +// let b_9 := 0 +// b_9 := sload(mload(a_9)) +// let a_10 := b_9 +// let b_10 := 0 +// b_10 := sload(mload(a_10)) +// let a_11 := b_10 +// let b_11 := 0 +// b_11 := sload(mload(a_11)) +// let a_12 := b_11 +// let b_12 := 0 +// b_12 := sload(mload(a_12)) +// let a_13 := b_12 +// let b_13 := 0 +// b_13 := sload(mload(a_13)) +// let x := f(f(f(f(f(f(b_13)))))) // } // function f(a) -> b // { b := sload(mload(a)) } diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_inline_leave.yul b/test/libyul/yulOptimizerTests/fullInliner/no_inline_leave.yul index a22025c4b385..58431428c4b6 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/no_inline_leave.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/no_inline_leave.yul @@ -9,8 +9,8 @@ // // { // { -// let a_2 := calldataload(0) -// a_2 := g() +// let a_1 := calldataload(0) +// a_1 := g() // } // function g() -> x // { diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_return.yul b/test/libyul/yulOptimizerTests/fullInliner/no_return.yul index 2897b5151d08..4e4f00a3a731 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/no_return.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/no_return.yul @@ -9,8 +9,8 @@ // // { // { -// let a_3 := mload(0) -// sstore(a_3, a_3) +// let a_1 := mload(0) +// sstore(a_1, a_1) // } // function f(a) // { sstore(a, a) } diff --git a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul index 5678a13fd9a1..5d6fa3a34219 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul @@ -14,26 +14,26 @@ // // { // { -// let a_3 := 0 -// let r_4 := 0 -// sstore(a_3, 0) -// r_4 := a_3 -// let x := r_4 +// let a_1 := 0 +// let r_1 := 0 +// sstore(a_1, 0) +// r_1 := a_1 +// let x := r_1 // for { } // f(x) // { -// let a_6 := x -// let r_7 := 0 -// sstore(a_6, 0) -// r_7 := a_6 -// x := r_7 +// let a_2 := x +// let r_2 := 0 +// sstore(a_2, 0) +// r_2 := a_2 +// x := r_2 // } // { -// let a_9 := x -// let r_10 := 0 -// sstore(a_9, 0) -// r_10 := a_9 -// let t := r_10 +// let a_3 := x +// let r_3 := 0 +// sstore(a_3, 0) +// r_3 := a_3 +// let t := r_3 // } // } // function f(a) -> r diff --git a/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul index c46505c79a17..15c6dc2ad632 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul @@ -14,11 +14,11 @@ // { // { // let _1 := 2 -// let a_5 := 7 -// let x_6 := 0 -// let r_7 := mul(a_5, a_5) -// x_6 := add(r_7, r_7) -// pop(add(x_6, _1)) +// let a_1 := 7 +// let x_1 := 0 +// let r_1 := mul(a_1, a_1) +// x_1 := add(r_1, r_1) +// pop(add(x_1, _1)) // } // function f(a) -> x // { diff --git a/test/libyul/yulOptimizerTests/fullInliner/simple.yul b/test/libyul/yulOptimizerTests/fullInliner/simple.yul index 2c9d979b5832..e12a61dc6fcc 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/simple.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/simple.yul @@ -10,12 +10,12 @@ // // { // { -// let _2 := mload(7) -// let a_7 := sload(mload(2)) -// let x_8 := 0 -// let r_9 := mul(a_7, a_7) -// x_8 := add(r_9, r_9) -// let y := add(x_8, _2) +// let _1 := mload(7) +// let a_1 := sload(mload(2)) +// let x_1 := 0 +// let r_1 := mul(a_1, a_1) +// x_1 := add(r_1, r_1) +// let y := add(x_1, _1) // } // function f(a) -> x // { diff --git a/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/call_arguments_without_side_effects.yul b/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/call_arguments_without_side_effects.yul index 8f903b48445d..9292960d3865 100644 --- a/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/call_arguments_without_side_effects.yul +++ b/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/call_arguments_without_side_effects.yul @@ -23,14 +23,14 @@ // { // { // let c_1 := 333 -// let b_2 := 222 -// let a_3 := 111 +// let b_1 := 222 +// let a_2 := 111 // let x := 111 // let y := 222 // let z := 333 -// let c_4 := z -// let b_5 := y -// let a_6 := x +// let c_2 := z +// let b_2 := y +// let a_3 := x // empty(mload(111), sload(222), calldataload(333)) // let a_1 := 222 // empty(111, a_1, mload(333)) diff --git a/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.sol b/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.sol index 80b975903ca7..64935ee1ab25 100644 --- a/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.sol +++ b/test/libyul/yulOptimizerTests/fullInlinerWithoutSplitter/simple.sol @@ -10,9 +10,9 @@ // { // { // let a_1 := 2 -// let x_2 := 0 -// x_2 := add(a_1, a_1) -// let y := x_2 +// let x_1 := 0 +// x_1 := add(a_1, a_1) +// let y := x_1 // } // function f(a) -> x // { x := add(a, a) } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul b/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul index a13ad9395314..f899bd109bc2 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/constant_propagation.yul @@ -7,7 +7,7 @@ // // { // { -// let _2 := 0 -// mstore(mload(_2), _2) +// let _1 := 0 +// mstore(mload(_1), _1) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul b/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul index 0ab5cc6ed88f..07edc381d37d 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/invariant.yul @@ -13,8 +13,8 @@ // { // { // let a := calldataload(0) -// let _4 := 0 +// let _1 := 0 // let b := a -// mstore(b, eq(calldataload(_4), a)) +// mstore(b, eq(calldataload(_1), a)) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul index c10345e4ee56..f02797730fcf 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_1.yul @@ -6,7 +6,7 @@ // // { // { -// let _4 := 0 -// mstore(_4, and(calldataload(_4), 255)) +// let _1 := 0 +// mstore(_1, and(calldataload(_1), 255)) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul index fc171337f9b1..d05f3db3cadd 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/mod_and_2.yul @@ -6,7 +6,7 @@ // // { // { -// let _4 := 0 -// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// let _1 := 0 +// mstore(_1, and(calldataload(_1), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul index e42b6c098600..c168ddb5094f 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/not_applied_function_call_different_arguments.yul @@ -7,9 +7,9 @@ // // { // { -// let _2 := f(1) -// let _3 := 0 -// mstore(_3, sub(f(_3), _2)) +// let _1 := f(1) +// let _2 := 0 +// mstore(_2, sub(f(_2), _1)) // } // function f(a) -> b // { } diff --git a/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul b/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul index 38e5ab2108d7..7a8830757413 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/scoped_var_ref_in_function_call.yul @@ -11,10 +11,10 @@ // // { // { -// let x_1 -// let _2 := calldataload(x_1) -// let _3 := 1 -// x_1 := add(_3, _2) -// pop(call(2, 0, _3, addmod(_3, _2, 8), _3, _3, _3)) +// let x +// let _1 := calldataload(x) +// let _2 := 1 +// x := add(_2, _1) +// pop(call(2, 0, _2, addmod(_2, _1, 8), _2, _2, _2)) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi2.yul b/test/libyul/yulOptimizerTests/fullSuite/abi2.yul index 2f2e060be089..e04e81d04db8 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/abi2.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/abi2.yul @@ -1081,47 +1081,47 @@ // let _2 := mload(0) // if slt(sub(_1, _2), 64) { revert(0, 0) } // sstore(0, and(calldataload(_2), sub(shl(160, 1), 1))) -// let x0, x1, x2, x3, x4 := abi_decode_addresst_uint256t_bytes_calldatat_enum_Operation(mload(7), mload(8)) +// let x0, x1, x2, x3, x4 := abi_decode_tuple_t_addresst_uint256t_bytes_calldata_ptrt_enum$_Operation_$1949(mload(7), mload(8)) // sstore(x1, x0) // sstore(x3, x2) // sstore(1, x4) -// pop(abi_encode_bytes32_address_uint256_bytes32_enum_Operation_uint256_uint256_uint256_address_address_uint256(mload(30), mload(31), mload(32), mload(33), mload(34), mload(35), mload(36), mload(37), mload(38), mload(39), mload(40), mload(41))) +// pop(abi_encode_tuple_t_bytes32_t_address_t_uint256_t_bytes32_t_enum$_Operation_$1949_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint256__to_t_bytes32_t_address_t_uint256_t_bytes32_t_uint8_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint256_(mload(30), mload(31), mload(32), mload(33), mload(34), mload(35), mload(36), mload(37), mload(38), mload(39), mload(40), mload(41))) // } -// function abi_decode_addresst_uint256t_bytes_calldatat_enum_Operation(headStart, dataEnd) -> value0, value1, value2, value3, value4 +// function abi_decode_tuple_t_addresst_uint256t_bytes_calldata_ptrt_enum$_Operation_$1949(headStart_55, dataEnd_56) -> value0_57, value1_58, value2_59, value3, value4 // { -// if slt(sub(dataEnd, headStart), 128) { revert(0, 0) } -// value0 := and(calldataload(headStart), sub(shl(160, 1), 1)) -// value1 := calldataload(add(headStart, 32)) -// let offset := calldataload(add(headStart, 64)) -// if gt(offset, 0xffffffffffffffff) { revert(0, 0) } -// let _1 := add(headStart, offset) -// if iszero(slt(add(_1, 0x1f), dataEnd)) { revert(0, 0) } -// let length := calldataload(_1) -// if gt(length, 0xffffffffffffffff) { revert(0, 0) } -// if gt(add(add(_1, length), 32), dataEnd) { revert(0, 0) } -// value2 := add(_1, 32) -// value3 := length -// value4 := cleanup_revert_enum_Operation(calldataload(add(headStart, 96))) +// if slt(sub(dataEnd_56, headStart_55), 128) { revert(0, 0) } +// value0_57 := and(calldataload(headStart_55), sub(shl(160, 1), 1)) +// value1_58 := calldataload(add(headStart_55, 32)) +// let offset_62 := calldataload(add(headStart_55, 64)) +// if gt(offset_62, 0xffffffffffffffff) { revert(0, 0) } +// let _3 := add(headStart_55, offset_62) +// if iszero(slt(add(_3, 0x1f), dataEnd_56)) { revert(0, 0) } +// let length_15 := calldataload(_3) +// if gt(length_15, 0xffffffffffffffff) { revert(0, 0) } +// if gt(add(add(_3, length_15), 32), dataEnd_56) { revert(0, 0) } +// value2_59 := add(_3, 32) +// value3 := length_15 +// value4 := cleanup_revert_t_enum$_Operation_$1949(calldataload(add(headStart_55, 96))) // } -// function abi_encode_bytes32_address_uint256_bytes32_enum_Operation_uint256_uint256_uint256_address_address_uint256(headStart, value10, value9, value8, value7, value6, value5, value4, value3, value2, value1, value0) -> tail +// function abi_encode_tuple_t_bytes32_t_address_t_uint256_t_bytes32_t_enum$_Operation_$1949_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint256__to_t_bytes32_t_address_t_uint256_t_bytes32_t_uint8_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint256_(headStart_252, value10_253, value9_254, value8_255, value7_256, value6_257, value5_258, value4_259, value3_260, value2_261, value1_262, value0_263) -> tail_264 // { -// tail := add(headStart, 352) -// mstore(headStart, value0) -// mstore(add(headStart, 32), and(value1, sub(shl(160, 1), 1))) -// mstore(add(headStart, 64), value2) -// mstore(add(headStart, 96), value3) -// if iszero(lt(value4, 3)) { invalid() } -// mstore(add(headStart, 128), value4) -// mstore(add(headStart, 160), value5) -// mstore(add(headStart, 192), value6) -// mstore(add(headStart, 224), value7) -// mstore(add(headStart, 256), and(value8, sub(shl(160, 1), 1))) -// mstore(add(headStart, 288), and(value9, sub(shl(160, 1), 1))) -// mstore(add(headStart, 320), value10) +// tail_264 := add(headStart_252, 352) +// mstore(headStart_252, value0_263) +// mstore(add(headStart_252, 32), and(value1_262, sub(shl(160, 1), 1))) +// mstore(add(headStart_252, 64), value2_261) +// mstore(add(headStart_252, 96), value3_260) +// if iszero(lt(value4_259, 3)) { invalid() } +// mstore(add(headStart_252, 128), value4_259) +// mstore(add(headStart_252, 160), value5_258) +// mstore(add(headStart_252, 192), value6_257) +// mstore(add(headStart_252, 224), value7_256) +// mstore(add(headStart_252, 256), and(value8_255, sub(shl(160, 1), 1))) +// mstore(add(headStart_252, 288), and(value9_254, sub(shl(160, 1), 1))) +// mstore(add(headStart_252, 320), value10_253) // } -// function cleanup_revert_enum_Operation(value) -> cleaned +// function cleanup_revert_t_enum$_Operation_$1949(value_369) -> cleaned_370 // { -// if iszero(lt(value, 3)) { revert(0, 0) } -// cleaned := value +// if iszero(lt(value_369, 3)) { revert(0, 0) } +// cleaned_370 := value_369 // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul index dbb87439f637..fd345142f351 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul @@ -465,18 +465,18 @@ // { // let _1 := mload(0) // let pos := 0x20 -// let length := mload(_1) -// mstore(pos, length) +// let length_3 := mload(_1) +// mstore(pos, length_3) // pos := 64 // let srcPtr := add(_1, 0x20) -// let i := 0 -// for { } lt(i, length) { i := add(i, 1) } +// let i_3 := 0 +// for { } lt(i_3, length_3) { i_3 := add(i_3, 1) } // { -// let _2 := mload(srcPtr) +// let _4 := mload(srcPtr) // let pos_1 := pos -// let srcPtr_1 := _2 -// let i_1 := 0 -// for { } lt(i_1, 0x3) { i_1 := add(i_1, 1) } +// let srcPtr_1 := _4 +// let i_4 := 0 +// for { } lt(i_4, 0x3) { i_4 := add(i_4, 1) } // { // mstore(pos_1, and(mload(srcPtr_1), sub(shl(160, 1), 1))) // srcPtr_1 := add(srcPtr_1, 0x20) @@ -485,16 +485,16 @@ // srcPtr := add(srcPtr, 0x20) // pos := add(pos, 0x60) // } -// let a, b, c, d := abi_decode_uint256t_uint256t_array_uint256_dynt_array_array_uint256_memory_dyn(mload(0x20), mload(64)) +// let a, b, c, d := abi_decode_tuple_t_uint256t_uint256t_array$_t_uint256_$dyn_memory_ptrt_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(mload(0x20), mload(64)) // sstore(a, b) // sstore(c, d) // sstore(0, pos) // } -// function abi_decode_array_array_uint256_memory_dyn(offset, end) -> array +// function abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(offset, end) -> array // { // if iszero(slt(add(offset, 0x1f), end)) { revert(0, 0) } // let length := calldataload(offset) -// array := allocateMemory(array_allocation_size_array_address_dyn_memory(length)) +// array := allocateMemory(array_allocation_size_t_array$_t_address_$dyn_memory(length)) // let dst := array // mstore(array, length) // dst := add(array, 0x20) @@ -504,11 +504,11 @@ // for { } lt(i, length) { i := add(i, 1) } // { // if iszero(slt(add(src, 0x1f), end)) { revert(0, 0) } -// let dst_1 := allocateMemory_823() +// let dst_1 := allocateMemory_1() // let array_1 := dst_1 // let src_1 := src -// let _1 := add(src, 64) -// if gt(_1, end) { revert(0, 0) } +// let _3 := add(src, 64) +// if gt(_3, end) { revert(0, 0) } // let i_1 := 0 // for { } lt(i_1, 0x2) { i_1 := add(i_1, 1) } // { @@ -518,43 +518,43 @@ // } // mstore(dst, array_1) // dst := add(dst, 0x20) -// src := _1 +// src := _3 // } // } -// function abi_decode_uint256t_uint256t_array_uint256_dynt_array_array_uint256_memory_dyn(headStart, dataEnd) -> value0, value1, value2, value3 +// function abi_decode_tuple_t_uint256t_uint256t_array$_t_uint256_$dyn_memory_ptrt_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(headStart, dataEnd) -> value0, value1, value2, value3 // { // if slt(sub(dataEnd, headStart), 128) { revert(0, 0) } // value0 := calldataload(headStart) // value1 := calldataload(add(headStart, 32)) -// let offset := calldataload(add(headStart, 64)) -// if gt(offset, 0xffffffffffffffff) { revert(0, 0) } -// let _1 := add(headStart, offset) -// if iszero(slt(add(_1, 0x1f), dataEnd)) { revert(0, 0) } -// let length := calldataload(_1) -// let dst := allocateMemory(array_allocation_size_array_address_dyn_memory(length)) -// let array := dst -// mstore(dst, length) -// dst := add(dst, 32) -// let src := add(_1, 32) -// if gt(add(add(_1, shl(5, length)), 32), dataEnd) { revert(0, 0) } -// let i := 0 -// for { } lt(i, length) { i := add(i, 1) } +// let offset_1 := calldataload(add(headStart, 64)) +// if gt(offset_1, 0xffffffffffffffff) { revert(0, 0) } +// let _2 := add(headStart, offset_1) +// if iszero(slt(add(_2, 0x1f), dataEnd)) { revert(0, 0) } +// let length_2 := calldataload(_2) +// let dst_2 := allocateMemory(array_allocation_size_t_array$_t_address_$dyn_memory(length_2)) +// let array_2 := dst_2 +// mstore(dst_2, length_2) +// dst_2 := add(dst_2, 32) +// let src_2 := add(_2, 32) +// if gt(add(add(_2, shl(5, length_2)), 32), dataEnd) { revert(0, 0) } +// let i_2 := 0 +// for { } lt(i_2, length_2) { i_2 := add(i_2, 1) } // { -// mstore(dst, calldataload(src)) -// dst := add(dst, 32) -// src := add(src, 32) +// mstore(dst_2, calldataload(src_2)) +// dst_2 := add(dst_2, 32) +// src_2 := add(src_2, 32) // } -// value2 := array -// let offset_1 := calldataload(add(headStart, 96)) -// if gt(offset_1, 0xffffffffffffffff) { revert(0, 0) } -// value3 := abi_decode_array_array_uint256_memory_dyn(add(headStart, offset_1), dataEnd) +// value2 := array_2 +// let offset_2 := calldataload(add(headStart, 96)) +// if gt(offset_2, 0xffffffffffffffff) { revert(0, 0) } +// value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(headStart, offset_2), dataEnd) // } -// function allocateMemory_823() -> memPtr +// function allocateMemory_1() -> memPtr_1 // { -// memPtr := mload(64) -// let newFreePtr := add(memPtr, 64) -// if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } -// mstore(64, newFreePtr) +// memPtr_1 := mload(64) +// let newFreePtr_1 := add(memPtr_1, 64) +// if or(gt(newFreePtr_1, 0xffffffffffffffff), lt(newFreePtr_1, memPtr_1)) { revert(0, 0) } +// mstore(64, newFreePtr_1) // } // function allocateMemory(size) -> memPtr // { @@ -563,9 +563,9 @@ // if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { revert(0, 0) } // mstore(64, newFreePtr) // } -// function array_allocation_size_array_address_dyn_memory(length) -> size +// function array_allocation_size_t_array$_t_address_$dyn_memory(length_1) -> size_1 // { -// if gt(length, 0xffffffffffffffff) { revert(0, 0) } -// size := add(shl(5, length), 0x20) +// if gt(length_1, 0xffffffffffffffff) { revert(0, 0) } +// size_1 := add(shl(5, length_1), 0x20) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul index 8b26a7ba3723..a3b1f65827fd 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/aztec.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/aztec.yul @@ -238,11 +238,11 @@ // mstore(0x80, 7673901602397024137095011250362199966051872585513276903826533215767972925880) // mstore(0xa0, 8489654445897228341090914135473290831551238522473825886865492707826370766375) // let _1 := calldataload(0x04) -// let notes := add(0x04, _1) +// let notes_1 := add(0x04, _1) // let m := calldataload(0x24) -// let n := calldataload(notes) +// let n_1 := calldataload(notes_1) // let challenge := mod(calldataload(0x44), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) -// if gt(m, n) +// if gt(m, n_1) // { // mstore(0x00, 404) // revert(0x00, 0x20) @@ -252,57 +252,59 @@ // mstore(0x2c0, kn) // mstore(0x2e0, m) // kn := mulmod(sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, kn), challenge, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) -// hashCommitments(notes, n) -// let b := add(0x300, shl(7, n)) -// let i := 0 -// for { } lt(i, n) { i := add(i, 0x01) } +// hashCommitments(notes_1, n_1) +// let b := add(0x300, shl(7, n_1)) +// let i_1 := 0 +// for { } lt(i_1, n_1) { i_1 := add(i_1, 0x01) } // { -// let _2 := add(_1, mul(i, 0xc0)) +// let _2 := add(_1, mul(i_1, 0xc0)) // let noteIndex := add(_2, 0x24) -// let k := 0 -// let a := calldataload(add(_2, 0x44)) +// let k_1 := 0 +// let a_1 := calldataload(add(_2, 0x44)) // let c := challenge -// let _3 := add(i, 0x01) -// switch eq(_3, n) +// let _3 := add(i_1, 0x01) +// switch eq(_3, n_1) // case 1 { -// k := kn -// if eq(m, n) +// k_1 := kn +// if eq(m, n_1) // { -// k := sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, kn) +// k_1 := sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, kn) // } // } -// case 0 { k := calldataload(noteIndex) } -// validateCommitment(noteIndex, k, a) +// case 0 { +// k_1 := calldataload(noteIndex) +// } +// validateCommitment(noteIndex, k_1, a_1) // switch gt(_3, m) // case 1 { -// kn := addmod(kn, sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, k), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) +// kn := addmod(kn, sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, k_1), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // let x := mod(mload(0), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) -// k := mulmod(k, x, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) -// a := mulmod(a, x, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) +// k_1 := mulmod(k_1, x, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) +// a_1 := mulmod(a_1, x, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // c := mulmod(challenge, x, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // mstore(0, keccak256(0, 0x20)) // } // case 0 { -// kn := addmod(kn, k, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) +// kn := addmod(kn, k_1, 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001) // } // calldatacopy(0xe0, add(_2, 164), 0x40) // calldatacopy(0x20, add(_2, 100), 0x40) // mstore(0x120, sub(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001, c)) -// mstore(0x60, k) -// mstore(0xc0, a) +// mstore(0x60, k_1) +// mstore(0xc0, a_1) // let result := call(gas(), 7, 0, 0xe0, 0x60, 0x1a0, 0x40) // let result_1 := and(result, call(gas(), 7, 0, 0x20, 0x60, 0x120, 0x40)) // let result_2 := and(result_1, call(gas(), 7, 0, 0x80, 0x60, 0x160, 0x40)) // let result_3 := and(result_2, call(gas(), 6, 0, 0x120, 0x80, 0x160, 0x40)) // result := and(result_3, call(gas(), 6, 0, 0x160, 0x80, b, 0x40)) -// if eq(i, m) +// if eq(i_1, m) // { // mstore(0x260, mload(0x20)) // mstore(0x280, mload(0x40)) // mstore(0x1e0, mload(0xe0)) // mstore(0x200, sub(0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47, mload(0x100))) // } -// if gt(i, m) +// if gt(i_1, m) // { // mstore(0x60, c) // let result_4 := and(result, call(gas(), 7, 0, 0x20, 0x60, 0x220, 0x40)) @@ -316,7 +318,7 @@ // } // b := add(b, 0x40) // } -// if lt(m, n) { validatePairing() } +// if lt(m, n_1) { validatePairing() } // if iszero(eq(mod(keccak256(0x2a0, add(b, not(671))), 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001), challenge)) // { // mstore(0, 404) @@ -327,11 +329,11 @@ // } // function validatePairing() // { -// let t2_x := calldataload(0x64) -// let t2_x_1 := calldataload(132) -// let t2_y := calldataload(164) -// let t2_y_1 := calldataload(196) -// if or(or(or(or(or(or(or(iszero(t2_x), iszero(t2_x_1)), iszero(t2_y)), iszero(t2_y_1)), eq(t2_x, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed)), eq(t2_x_1, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2)), eq(t2_y, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa)), eq(t2_y_1, 0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b)) +// let t2_x_1 := calldataload(0x64) +// let t2_x_2 := calldataload(132) +// let t2_y_1 := calldataload(164) +// let t2_y_2 := calldataload(196) +// if or(or(or(or(or(or(or(iszero(t2_x_1), iszero(t2_x_2)), iszero(t2_y_1)), iszero(t2_y_2)), eq(t2_x_1, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed)), eq(t2_x_2, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2)), eq(t2_y_1, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa)), eq(t2_y_2, 0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b)) // { // mstore(0x00, 400) // revert(0x00, 0x20) @@ -344,10 +346,10 @@ // mstore(0xa0, 0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) // mstore(0xe0, mload(0x260)) // mstore(0x100, mload(0x280)) -// mstore(0x140, t2_x) -// mstore(0x120, t2_x_1) -// mstore(0x180, t2_y) -// mstore(0x160, t2_y_1) +// mstore(0x140, t2_x_1) +// mstore(0x120, t2_x_2) +// mstore(0x180, t2_y_1) +// mstore(0x160, t2_y_2) // let success := call(gas(), 8, 0, 0x20, 0x180, 0x20, 0x20) // if or(iszero(success), iszero(mload(0x20))) // { diff --git a/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul b/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul index a0be61939b1f..9076107fea1f 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/loopInvariantCodeMotion.yul @@ -28,13 +28,13 @@ // let sum := 0 // let length := calldataload(_1) // let i := 0 -// let _2 := calldataload(7) +// let _3 := calldataload(7) // for { } 1 { i := add(i, 1) } // { -// let _3 := iszero(lt(i, length)) -// if _3 { break } -// _3 := 0 -// sum := add(sum, add(calldataload(add(add(_1, shl(5, i)), 0x20)), _2)) +// let _2 := iszero(lt(i, length)) +// if _2 { break } +// _2 := 0 +// sum := add(sum, add(calldataload(add(add(_1, shl(5, i)), 0x20)), _3)) // } // sstore(0, sum) // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/name_cleaner_reserved.yul b/test/libyul/yulOptimizerTests/fullSuite/name_cleaner_reserved.yul index 05cf04a71024..f1cf9fe29a3b 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/name_cleaner_reserved.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/name_cleaner_reserved.yul @@ -18,16 +18,16 @@ // { // { // pop(mstore_(7)) -// nonmstore(70) +// nonmstore_(70) // } -// function nonmstore(x) +// function nonmstore_(x) // { -// if calldataload(0) { nonmstore(x) } +// if calldataload(0) { nonmstore_(x) } // sstore(10, calldataload(2)) // } -// function mstore_(x) -> y +// function mstore_(x_1) -> y // { -// if calldataload(0) { pop(mstore_(x)) } +// if calldataload(0) { pop(mstore_(x_1)) } // y := 8 // sstore(8, calldataload(8)) // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2.yul b/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2.yul index 879f84834e96..7e0384e1ab87 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2.yul @@ -35,8 +35,8 @@ // let a := 0 // for { } a { } // { -// let _1 := add(a, a) -// let var := add(_1, _1) +// let _2 := add(a, a) +// let var := add(_2, _2) // switch a // case 0 { a := var } // default { sstore(0, var) } diff --git a/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2_pre_shanghai.yul b/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2_pre_shanghai.yul index 3161dc2efac4..f8e14d95ab02 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2_pre_shanghai.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/name_dependent_cse_bug_part_2_pre_shanghai.yul @@ -35,8 +35,8 @@ // let a := 0 // for { } a { } // { -// let _1 := add(a, a) -// let var := add(_1, _1) +// let _2 := add(a, a) +// let var := add(_2, _2) // switch a // case 0 { a := var } // default { sstore(0, var) } diff --git a/test/libyul/yulOptimizerTests/fullSuite/reserved_identifiers.yul b/test/libyul/yulOptimizerTests/fullSuite/reserved_identifiers.yul index e8ddcf98539c..afc9c7c1349a 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/reserved_identifiers.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/reserved_identifiers.yul @@ -17,16 +17,19 @@ // { // { // let dataoffset_ := datasize_(7) -// sstore(dataoffset_, g(9)) +// sstore(dataoffset_, g_(9)) // } -// function g(x) -> z +// function g_(x) -> z_ // { -// if calldataload(1) { z := g(x) } -// sstore(z, calldataload(add(x, 1))) +// if calldataload(1) { z_ := g_(x) } +// sstore(z_, calldataload(add(x, 1))) // } -// function datasize_(x) -> linkersymbol_ +// function datasize_(x_1) -> linkersymbol_ // { -// if calldataload(0) { linkersymbol_ := datasize_(x) } +// if calldataload(0) +// { +// linkersymbol_ := datasize_(x_1) +// } // sstore(linkersymbol_, calldataload(linkersymbol_)) // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul b/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul index a7ecc0e46ba1..066d977e7f5f 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/ssaReverse.yul @@ -36,21 +36,21 @@ // // { // { -// let a, b := abi_decode_bytes_calldata(mload(0), mload(1)) -// let a_1, b_1 := abi_decode_bytes_calldata(a, b) -// let a_2, b_2 := abi_decode_bytes_calldata(a_1, b_1) -// let a_3, b_3 := abi_decode_bytes_calldata(a_2, b_2) -// let a_4, b_4 := abi_decode_bytes_calldata(a_3, b_3) -// let a_5, b_5 := abi_decode_bytes_calldata(a_4, b_4) -// let a_6, b_6 := abi_decode_bytes_calldata(a_5, b_5) +// let a, b := abi_decode_t_bytes_calldata_ptr(mload(0), mload(1)) +// let a_1, b_1 := abi_decode_t_bytes_calldata_ptr(a, b) +// let a_2, b_2 := abi_decode_t_bytes_calldata_ptr(a_1, b_1) +// let a_3, b_3 := abi_decode_t_bytes_calldata_ptr(a_2, b_2) +// let a_4, b_4 := abi_decode_t_bytes_calldata_ptr(a_3, b_3) +// let a_5, b_5 := abi_decode_t_bytes_calldata_ptr(a_4, b_4) +// let a_6, b_6 := abi_decode_t_bytes_calldata_ptr(a_5, b_5) // sstore(a_6, b_6) // } -// function abi_decode_bytes_calldata(offset, end) -> arrayPos, length +// function abi_decode_t_bytes_calldata_ptr(offset_12, end_13) -> arrayPos_14, length_15 // { -// if iszero(slt(add(offset, 0x1f), end)) { revert(0, 0) } -// length := calldataload(offset) -// if gt(length, 0xffffffffffffffff) { revert(0, 0) } -// arrayPos := add(offset, 0x20) -// if gt(add(add(offset, length), 0x20), end) { revert(0, 0) } +// if iszero(slt(add(offset_12, 0x1f), end_13)) { revert(0, 0) } +// length_15 := calldataload(offset_12) +// if gt(length_15, 0xffffffffffffffff) { revert(0, 0) } +// arrayPos_14 := add(offset_12, 0x20) +// if gt(add(add(offset_12, length_15), 0x20), end_13) { revert(0, 0) } // } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul index 5fbe8d22e615..8ecfb1cc6a10 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/stack_compressor_msize.yul @@ -49,7 +49,7 @@ // mstore(lt(or(gt(1, or(or(gt(or(or(or(gt(or(gt(not(0), _5), 1), _4), _3), _2), 1), 1), _1), 1)), 1), 1), 1) // sstore(not(gcd(10, 15)), 1) // sstore(2, 1) -// foo_singlereturn() +// foo_singlereturn_1() // sstore(0, 0) // sstore(3, 1) // } @@ -59,6 +59,6 @@ // case 0 { out := _a } // default { out := gcd(_b, mod(_a, _b)) } // } -// function foo_singlereturn() +// function foo_singlereturn_1() // { extcodecopy(1, msize(), 1, 1) } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul index 6f82ab27a6d8..a5a1fe4034a8 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner.yul @@ -19,9 +19,9 @@ // // { // { -// let out1, out2 := foo(sload(32)) -// sstore(0, out2) -// let out1_1, out2_1 := foo(sload(8)) +// let out1_1, out2_1 := foo(sload(32)) +// sstore(0, out2_1) +// let out1_2, out2_2 := foo(sload(8)) // } // function foo(b) -> out1, out2 // { diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_recursion.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_recursion.yul index 92d251cabe1a..4420949c551f 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_recursion.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_recursion.yul @@ -16,9 +16,9 @@ // // { // { -// let x, y, z := f() -// sstore(0, x) -// sstore(1, z) +// let x_2, y_2, z_2 := f() +// sstore(0, x_2) +// sstore(1, z_2) // } // function f() -> x, y, z // { diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul index b066d998bafe..c921c6bb4ce8 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionParameterPruner_return.yul @@ -21,9 +21,9 @@ // // { // { -// let out1, out2 := foo(sload(32)) +// let out1_1, out2_1 := foo(sload(32)) // sstore(0, 0) -// let out1_1, out2_1 := foo(sload(8)) +// let out1_2, out2_2 := foo(sload(8)) // } // function foo(b) -> out1, out2 // { diff --git a/test/libyul/yulOptimizerTests/functionSpecializer/multiple.yul b/test/libyul/yulOptimizerTests/functionSpecializer/multiple.yul index d4df4053729c..ea6b958e136e 100644 --- a/test/libyul/yulOptimizerTests/functionSpecializer/multiple.yul +++ b/test/libyul/yulOptimizerTests/functionSpecializer/multiple.yul @@ -21,14 +21,14 @@ // f(calldataload(0), calldataload(1)) // function f_1() // { -// let a_4 := 1 -// let b_3 := 2 -// sstore(a_4, b_3) +// let a_1 := 1 +// let b_1 := 2 +// sstore(a_1, b_1) // } -// function f_2(a_6) +// function f_2(a_2) // { -// let b_5 := 2 -// sstore(a_6, b_5) +// let b_2 := 2 +// sstore(a_2, b_2) // } // function f(a, b) // { sstore(a, b) } diff --git a/test/libyul/yulOptimizerTests/functionSpecializer/partial.yul b/test/libyul/yulOptimizerTests/functionSpecializer/partial.yul index 6b18da019dea..793a47b46424 100644 --- a/test/libyul/yulOptimizerTests/functionSpecializer/partial.yul +++ b/test/libyul/yulOptimizerTests/functionSpecializer/partial.yul @@ -16,12 +16,12 @@ // { // let x := 2 // f_1(x) -// function f_1(b_3) +// function f_1(b_1) // { -// let a_4 := 1 -// let c_2 := 3 -// sstore(a_4, b_3) -// sstore(b_3, c_2) +// let a_1 := 1 +// let c_1 := 3 +// sstore(a_1, b_1) +// sstore(b_1, c_1) // if calldataload(0) { leave } // } // function f(a, b, c) diff --git a/test/libyul/yulOptimizerTests/functionSpecializer/simple.yul b/test/libyul/yulOptimizerTests/functionSpecializer/simple.yul index 3ec298ebd953..c46fee77528c 100644 --- a/test/libyul/yulOptimizerTests/functionSpecializer/simple.yul +++ b/test/libyul/yulOptimizerTests/functionSpecializer/simple.yul @@ -14,11 +14,11 @@ // f_1() // function f_1() // { -// let a_4 := 1 -// let b_3 := 2 -// let c_2 := 3 -// sstore(a_4, b_3) -// sstore(b_3, c_2) +// let a_1 := 1 +// let b_1 := 2 +// let c_1 := 3 +// sstore(a_1, b_1) +// sstore(b_1, c_1) // } // function f(a, b, c) // { diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_expr_mstore.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_expr_mstore.yul index 7b37f8c95f58..9cf18437837e 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_expr_mstore.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_expr_mstore.yul @@ -16,10 +16,10 @@ // { // let _1 := 0 // let a := calldataload(_1) +// let _2 := keccak256(_1, a) +// sstore(f(_2), _2) // let _3 := keccak256(_1, a) // sstore(f(_3), _3) -// let _8 := keccak256(_1, a) -// sstore(f(_8), _8) // sstore(keccak256(_1, a), f(keccak256(_1, a))) // } // function f(x) -> y diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_in_expression.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_in_expression.yul index f4d37d90e7b8..7d3391b39c6d 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_in_expression.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_in_expression.yul @@ -8,7 +8,7 @@ // { // { // let _1 := 0 -// let _3 := keccak256(_1, calldataload(_1)) -// sstore(_3, _3) +// let _2 := keccak256(_1, calldataload(_1)) +// sstore(_2, _2) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_reassigned_branch.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_reassigned_branch.yul index b780d62b0a18..bba48b0e2566 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_reassigned_branch.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_reassigned_branch.yul @@ -26,12 +26,12 @@ // let x := calldataload(0) // let y := calldataload(1) // let a := keccak256(x, y) -// let _3 := 2 -// if calldataload(_3) { a := 8 } -// sstore(keccak256(x, y), _3) +// let _1 := 2 +// if calldataload(_1) { a := 8 } +// sstore(keccak256(x, y), _1) // if calldataload(3) { x := 8 } -// sstore(keccak256(x, y), _3) +// sstore(keccak256(x, y), _1) // if calldataload(4) { y := 8 } -// sstore(keccak256(x, y), _3) +// sstore(keccak256(x, y), _1) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_reassigned_value.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_reassigned_value.yul index 232d76f14575..d18fb365c49b 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_reassigned_value.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_reuse_reassigned_value.yul @@ -28,13 +28,13 @@ // let y := calldataload(1) // let a := keccak256(x, y) // sstore(a, 2) -// let _4 := 10 -// a := calldataload(_4) +// let _1 := 10 +// a := calldataload(_1) // sstore(keccak256(x, y), 3) -// x := _4 -// sstore(keccak256(_4, y), 4) +// x := _1 +// sstore(keccak256(_1, y), 4) // y := 9 -// let d := keccak256(_4, y) +// let d := keccak256(_1, y) // sstore(d, 5) // sstore(d, 6) // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul b/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul index 58cb7c264ce9..85bba886c4b3 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/keccak_short.yul @@ -25,9 +25,9 @@ // mstore(_2, _1) // sstore(_2, 9948786400348073077032572701554570401043517428989726124163377057770909578447) // sstore(1, 110945455955148346822663466543669633859020391897956790847617069135813044810108) -// let _13 := 85131057757245807317576516368191972321038229705283732634690444270750521936266 -// let _14 := 2 -// sstore(_14, _13) -// sstore(_14, 89477152217924674838424037953991966239322087453347756267410168184682657981552) +// let _3 := 85131057757245807317576516368191972321038229705283732634690444270750521936266 +// let _4 := 2 +// sstore(_4, _3) +// sstore(_4, 89477152217924674838424037953991966239322087453347756267410168184682657981552) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul index 840f19005b06..b293d1d6d3a2 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_different_kinds_of_invalidation.yul @@ -22,16 +22,16 @@ // let _1 := 9 // let _2 := 2 // mstore(_2, _1) -// let _4 := _1 -// let _5 := 0 -// sstore(_5, _4) -// pop(call(_5, _5, _5, _5, _5, _5, _5)) -// sstore(_5, mload(_2)) -// let _17 := 10 -// mstore(_2, _17) -// mstore8(calldataload(_5), 4) -// sstore(_5, mload(_2)) -// mstore(_2, _17) -// sstore(_5, _17) +// let _3 := _1 +// let _4 := 0 +// sstore(_4, _3) +// pop(call(_4, _4, _4, _4, _4, _4, _4)) +// sstore(_4, mload(_2)) +// let _5 := 10 +// mstore(_2, _5) +// mstore8(calldataload(_4), 4) +// sstore(_4, mload(_2)) +// mstore(_2, _5) +// sstore(_4, _5) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/memory_with_msize.yul b/test/libyul/yulOptimizerTests/loadResolver/memory_with_msize.yul index f54053bb10f2..6486599a5dc3 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/memory_with_msize.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/memory_with_msize.yul @@ -11,9 +11,9 @@ // { // { // let _1 := msize() -// let _3 := calldataload(0) -// mstore(_3, _1) +// let _2 := calldataload(0) +// mstore(_2, _1) // let t := mload(calldataload(10)) -// sstore(t, mload(_3)) +// sstore(t, mload(_2)) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_known_write.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_known_write.yul index acb96c07b102..0576874b1fd4 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_known_write.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_known_write.yul @@ -12,13 +12,13 @@ // // { // { -// let _2 := calldataload(10) -// let _3 := 0 -// let _4 := calldataload(_3) -// mstore(_4, _2) -// let _5 := 1 -// if calldataload(_5) { mstore(_4, _5) } -// let t := mload(_3) -// sstore(t, mload(_4)) +// let _1 := calldataload(10) +// let _2 := 0 +// let _3 := calldataload(_2) +// mstore(_3, _1) +// let _4 := 1 +// if calldataload(_4) { mstore(_3, _4) } +// let t := mload(_2) +// sstore(t, mload(_3)) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_known_write_with_distance.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_known_write_with_distance.yul index 1659949a3caf..47ce59a7973c 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_known_write_with_distance.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_known_write_with_distance.yul @@ -12,11 +12,11 @@ // // { // { -// let _2 := calldataload(10) -// let _4 := calldataload(0) -// mstore(_4, _2) -// let _5 := 1 -// if calldataload(_5) { mstore(add(_4, 0x20), _5) } -// sstore(mload(add(_4, 0x20)), _2) +// let _1 := calldataload(10) +// let _2 := calldataload(0) +// mstore(_2, _1) +// let _3 := 1 +// if calldataload(_3) { mstore(add(_2, 0x20), _3) } +// sstore(mload(add(_2, 0x20)), _1) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_known_distance.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_known_distance.yul index 18740c049095..6497224dcd66 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_known_distance.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_mload_with_known_distance.yul @@ -12,10 +12,10 @@ // // { // { -// let _2 := calldataload(0) -// let x := mload(_2) -// let _3 := 1 -// if calldataload(_3) { mstore(add(_2, 0x20), _3) } -// sstore(mload(add(_2, 0x20)), x) +// let _1 := calldataload(0) +// let x := mload(_1) +// let _2 := 1 +// if calldataload(_2) { mstore(add(_1, 0x20), _2) } +// sstore(mload(add(_1, 0x20)), x) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/merge_unknown_write.yul b/test/libyul/yulOptimizerTests/loadResolver/merge_unknown_write.yul index e8cc3cf4b010..6c73872e34fb 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/merge_unknown_write.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/merge_unknown_write.yul @@ -12,13 +12,13 @@ // // { // { -// let _2 := calldataload(10) -// let _3 := 0 -// let _4 := calldataload(_3) -// mstore(_4, _2) -// let _5 := 1 -// if calldataload(_5) { mstore(_3, _5) } -// let t := mload(_3) -// sstore(t, mload(_4)) +// let _1 := calldataload(10) +// let _2 := 0 +// let _3 := calldataload(_2) +// mstore(_3, _1) +// let _4 := 1 +// if calldataload(_4) { mstore(_2, _4) } +// let t := mload(_2) +// sstore(t, mload(_3)) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul b/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul index b76d071ae8f2..b33b0e61acf9 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mload_in_function.yul @@ -22,9 +22,9 @@ // for { } // x // { -// let _7 := 0 -// x := mload(_7) -// mstore(_7, _7) +// let _3 := 0 +// x := mload(_3) +// mstore(_3, _3) // } // { } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul index 901ea12efc8c..5752be65878d 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_body.yul @@ -29,8 +29,8 @@ // for { } // userNot(x_1) // { -// let _7 := 0 -// mstore(_7, _7) +// let _3 := 0 +// mstore(_3, _3) // } // { } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul index 6fb0fdcba99a..c986e65fdada 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/mstore_in_function_loop_init.yul @@ -26,8 +26,8 @@ // { y := iszero(x) } // function funcWithLoop(x_1) // { -// let _7 := 0 -// mstore(_7, _7) +// let _3 := 0 +// mstore(_3, _3) // for { } userNot(x_1) { } // { } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/multi_sload_loop.yul b/test/libyul/yulOptimizerTests/loadResolver/multi_sload_loop.yul index c367059eb90c..40673c5d753b 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/multi_sload_loop.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/multi_sload_loop.yul @@ -19,7 +19,7 @@ // let x := calldataload(_1) // let len := sload(x) // let sum -// let i := _1 +// let i := sum // for { } lt(i, len) { i := add(i, 1) } // { // let p := add(add(x, i), 1) diff --git a/test/libyul/yulOptimizerTests/loadResolver/reassign_value_expression.yul b/test/libyul/yulOptimizerTests/loadResolver/reassign_value_expression.yul index 402987acb4ae..30c3b988bba5 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/reassign_value_expression.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/reassign_value_expression.yul @@ -21,14 +21,14 @@ // { // let x := calldataload(1) // let a := add(x, 10) -// let _3 := 7 -// sstore(a, _3) +// let _1 := 7 +// sstore(a, _1) // x := 9 -// let _4 := 11 -// mstore(_3, _4) +// let _2 := 11 +// mstore(_1, _2) // a := 33 -// mstore(sload(a), _4) +// mstore(sload(a), _2) // a := 39 -// mstore(sload(a), _4) +// mstore(sload(a), _2) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/second_mstore_with_delta.yul b/test/libyul/yulOptimizerTests/loadResolver/second_mstore_with_delta.yul index 8f1cf338f66d..c1473cc6e804 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/second_mstore_with_delta.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/second_mstore_with_delta.yul @@ -17,10 +17,10 @@ // let x := calldataload(1) // let a := add(x, 10) // let b := add(x, 42) -// let _4 := 7 -// mstore(a, _4) -// let _5 := 8 -// mstore(b, _5) -// sstore(_4, _5) +// let _1 := 7 +// mstore(a, _1) +// let _2 := 8 +// mstore(b, _2) +// sstore(_1, _2) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/second_store.yul b/test/libyul/yulOptimizerTests/loadResolver/second_store.yul index eb960a9f6e5c..6b1ce65ca03a 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/second_store.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/second_store.yul @@ -13,9 +13,9 @@ // { // let x := calldataload(1) // sstore(x, 7) -// let _3 := 6 -// let _4 := 0 -// sstore(calldataload(_4), _3) -// mstore(_4, sload(x)) +// let _1 := 6 +// let _2 := 0 +// sstore(calldataload(_2), _1) +// mstore(_2, sload(x)) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/second_store_same_value.yul b/test/libyul/yulOptimizerTests/loadResolver/second_store_same_value.yul index e13b8aa5f64f..88fc5aeb7865 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/second_store_same_value.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/second_store_same_value.yul @@ -12,10 +12,10 @@ // { // { // let x := calldataload(1) -// let _2 := 7 -// sstore(x, _2) -// let _4 := 0 -// sstore(calldataload(_4), _2) -// mstore(_4, _2) +// let _1 := 7 +// sstore(x, _1) +// let _2 := 0 +// sstore(calldataload(_2), _1) +// mstore(_2, _1) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/second_store_with_delta.yul b/test/libyul/yulOptimizerTests/loadResolver/second_store_with_delta.yul index f301737ecaa1..e180e339862e 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/second_store_with_delta.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/second_store_with_delta.yul @@ -17,10 +17,10 @@ // let x := calldataload(1) // let a := add(x, 10) // let b := add(x, 20) -// let _4 := 7 -// sstore(a, _4) -// let _5 := 8 -// sstore(b, _5) -// mstore(_4, _5) +// let _1 := 7 +// sstore(a, _1) +// let _2 := 8 +// sstore(b, _2) +// mstore(_1, _2) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul b/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul index b1eefd0890d6..72ab69ea5d31 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/side_effects_of_user_functions.yul @@ -17,11 +17,11 @@ // let _2 := 2 // mstore(_2, _1) // reads() -// let _4 := _1 -// let _5 := 0 -// sstore(_5, _4) +// let _3 := _1 +// let _4 := 0 +// sstore(_4, _3) // stores() -// sstore(_5, mload(_2)) +// sstore(_4, mload(_2)) // } // function stores() // { mstore(0, 1) } diff --git a/test/libyul/yulOptimizerTests/loadResolver/simple.yul b/test/libyul/yulOptimizerTests/loadResolver/simple.yul index a20025bcdf09..3a2990a78f73 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/simple.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/simple.yul @@ -9,8 +9,8 @@ // // { // { -// let _2 := calldataload(10) -// sstore(calldataload(0), _2) -// mstore(sload(_2), _2) +// let _1 := calldataload(10) +// sstore(calldataload(0), _1) +// mstore(sload(_1), _1) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/simple_memory.yul b/test/libyul/yulOptimizerTests/loadResolver/simple_memory.yul index 3aa1d740f496..32dc5f590731 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/simple_memory.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/simple_memory.yul @@ -9,8 +9,8 @@ // // { // { -// let _2 := calldataload(10) -// mstore(calldataload(0), _2) -// sstore(mload(_2), _2) +// let _1 := calldataload(10) +// mstore(calldataload(0), _1) +// sstore(mload(_1), _1) // } // } diff --git a/test/libyul/yulOptimizerTests/loadResolver/verbatim_sload.yul b/test/libyul/yulOptimizerTests/loadResolver/verbatim_sload.yul index 81479a509249..ffe3292783b0 100644 --- a/test/libyul/yulOptimizerTests/loadResolver/verbatim_sload.yul +++ b/test/libyul/yulOptimizerTests/loadResolver/verbatim_sload.yul @@ -14,10 +14,10 @@ // let _1 := 20 // let _2 := 10 // sstore(_2, _1) -// let _4 := _1 -// let _5 := 30 -// sstore(_5, _4) +// let _3 := _1 +// let _4 := 30 +// sstore(_4, _3) // verbatim_0i_0o("test") -// sstore(_5, sload(_2)) +// sstore(_4, sload(_2)) // } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul index 942a3c5802cb..8d88df001142 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory.yul @@ -28,11 +28,11 @@ // mstore(a, inv) // } // let a_1 := 1 -// let inv_2 := add(b, 42) +// let inv_1 := add(b, 42) // for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } // { -// let x_3 := extcodesize(mload(mul(inv_2, 3))) -// a_1 := add(x_3, 1) -// mstore(a_1, inv_2) +// let x_1 := extcodesize(mload(mul(inv_1, 3))) +// a_1 := add(x_1, 1) +// mstore(a_1, inv_1) // } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul index 2033a9be91a4..8505bb02f728 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_memory_msize.yul @@ -26,10 +26,10 @@ // a := add(x, 1) // } // let a_1 := 1 -// let inv_2 := add(b, 42) +// let inv_1 := add(b, 42) // for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } // { -// let x_3 := extcodesize(mload(mul(inv_2, 3))) -// a_1 := add(x_3, 1) +// let x_1 := extcodesize(mload(mul(inv_1, 3))) +// a_1 := add(x_1, 1) // } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul index fa6c985b4f8a..a6aea977b7d9 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_state.yul @@ -43,20 +43,20 @@ // mstore(a, inv) // } // let a_1 := 1 -// let inv_2 := add(b, 42) +// let inv_1 := add(b, 42) // for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } // { // pop(create(0x08, 0x00, 0x02)) -// let x_3 := extcodesize(mul(inv_2, 3)) -// a_1 := add(x_3, 1) -// mstore(a_1, inv_2) +// let x_1 := extcodesize(mul(inv_1, 3)) +// a_1 := add(x_1, 1) +// mstore(a_1, inv_1) // } -// let a_4 := 1 -// let inv_5 := add(b, 42) -// for { } iszero(create(0x08, 0x00, 0x02)) { a_4 := add(a_4, 1) } +// let a_2 := 1 +// let inv_2 := add(b, 42) +// for { } iszero(create(0x08, 0x00, 0x02)) { a_2 := add(a_2, 1) } // { -// let x_6 := extcodesize(mul(inv_5, 3)) -// a_4 := add(x_6, 1) -// mstore(a_4, inv_5) +// let x_2 := extcodesize(mul(inv_2, 3)) +// a_2 := add(x_2, 1) +// mstore(a_2, inv_2) // } // } diff --git a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul index 0ef2fd78ad40..482b67e8f1b8 100644 --- a/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul +++ b/test/libyul/yulOptimizerTests/loopInvariantCodeMotion/no_move_storage.yul @@ -39,19 +39,19 @@ // mstore(a, inv) // } // let a_1 := 1 -// let inv_2 := add(b, 42) +// let inv_1 := add(b, 42) // for { } iszero(eq(a_1, 10)) { a_1 := add(a_1, 1) } // { -// let x_3 := sload(mul(inv_2, 3)) -// a_1 := add(x_3, 1) -// sstore(a_1, inv_2) +// let x_1 := sload(mul(inv_1, 3)) +// a_1 := add(x_1, 1) +// sstore(a_1, inv_1) // } -// let a_4 := 1 -// let inv_5 := add(b, 42) -// for { } iszero(eq(a_4, 10)) { a_4 := add(a_4, 1) } +// let a_2 := 1 +// let inv_2 := add(b, 42) +// for { } iszero(eq(a_2, 10)) { a_2 := add(a_2, 1) } // { // pop(callcode(100, 0x010, 10, 0x00, 32, 0x0100, 32)) -// let x_6 := sload(mul(inv_5, 3)) -// a_4 := add(x_6, 1) +// let x_2 := sload(mul(inv_2, 3)) +// a_2 := add(x_2, 1) // } // } diff --git a/test/libyul/yulOptimizerTests/nameDisplacer/funtion_call.yul b/test/libyul/yulOptimizerTests/nameDisplacer/funtion_call.yul index 54045ce379f1..a9b00527f1d5 100644 --- a/test/libyul/yulOptimizerTests/nameDisplacer/funtion_call.yul +++ b/test/libyul/yulOptimizerTests/nameDisplacer/funtion_call.yul @@ -11,15 +11,15 @@ // // { // let x := illegal4_1(1, 2) -// function illegal4_1(illegal1_2, illegal2_3) -> illegal3_4 +// function illegal4_1(illegal1_1, illegal2_1) -> illegal3_1 // { -// illegal3_4 := add(illegal1_2, illegal2_3) +// illegal3_1 := add(illegal1_1, illegal2_1) // } // { -// let y := illegal5_5(3, 4) -// function illegal5_5(illegal1_1, illegal2_2) -> illegal3_3 +// let y := illegal5_1(3, 4) +// function illegal5_1(illegal1_2, illegal2_2) -> illegal3_2 // { -// illegal3_3 := add(illegal1_1, illegal2_2) +// illegal3_2 := add(illegal1_2, illegal2_2) // } // } // } diff --git a/test/libyul/yulOptimizerTests/nameDisplacer/variables.yul b/test/libyul/yulOptimizerTests/nameDisplacer/variables.yul index 08b7bc43121d..208adc19373c 100644 --- a/test/libyul/yulOptimizerTests/nameDisplacer/variables.yul +++ b/test/libyul/yulOptimizerTests/nameDisplacer/variables.yul @@ -5,7 +5,7 @@ // { // { let illegal1_1 := 1 } // { -// let illegal2_2 := 2 -// let illegal3_3, illegal4_4 +// let illegal2_1 := 2 +// let illegal3_1, illegal4_1 // } // } diff --git a/test/libyul/yulOptimizerTests/nameDisplacer/variables_inside_functions.yul b/test/libyul/yulOptimizerTests/nameDisplacer/variables_inside_functions.yul index 472aa6a33e8f..55171e5f2403 100644 --- a/test/libyul/yulOptimizerTests/nameDisplacer/variables_inside_functions.yul +++ b/test/libyul/yulOptimizerTests/nameDisplacer/variables_inside_functions.yul @@ -8,9 +8,9 @@ // step: nameDisplacer // // { -// function f(illegal1_1, illegal2_2) -> illegal3_3 +// function f(illegal1_1, illegal2_1) -> illegal3_1 // { -// let illegal4_4 := illegal1_1 -// illegal3_3 := add(illegal1_1, illegal2_2) +// let illegal4_1 := illegal1_1 +// illegal3_1 := add(illegal1_1, illegal2_1) // } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul index 19b3ba44ea02..e917705c29d6 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul @@ -24,8 +24,8 @@ // let b := mload(1) // for { } lt(mload(a), mload(b)) { a := mload(b) } // { -// let b_4 := mload(a) -// a := mload(b_4) +// let b_1 := mload(a) +// a := mload(b_1) // b := mload(a) // } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul index 1bfd89cd8384..9703e4679dfb 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign.yul @@ -11,7 +11,7 @@ // // { // { -// let a_5 := mload(4) -// mstore(a_5, 0) +// let a := mload(4) +// mstore(a, 0) // } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul index e3a671028207..9bc1231838ca 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_if.yul @@ -18,9 +18,9 @@ // let b := mload(1) // if mload(2) // { -// let a_3 := mload(b) -// let b_4 := mload(a_3) -// a := mload(b_4) +// let a_1 := mload(b) +// let b_1 := mload(a_1) +// a := mload(b_1) // b := mload(a) // } // mstore(a, b) diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul index 89f3acaa63c9..f747847f5158 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/multi_assign_multi_var_switch.yul @@ -25,15 +25,15 @@ // let b := mload(1) // switch mload(2) // case 0 { -// let a_3 := mload(b) -// let b_4 := mload(a_3) -// a := mload(b_4) +// let a_1 := mload(b) +// let b_1 := mload(a_1) +// a := mload(b_1) // b := mload(a) // } // default { -// let b_7 := mload(a) -// let a_8 := mload(b_7) -// b := mload(a_8) +// let b_2 := mload(a) +// let a_2 := mload(b_2) +// b := mload(a_2) // a := mload(b) // } // mstore(a, b) diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul b/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul index b2979e76d2e8..dc315347c51a 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/simple.yul @@ -8,7 +8,7 @@ // // { // { -// let a_2 := mload(1) -// mstore(a_2, 0) +// let a := mload(1) +// mstore(a, 0) // } // } diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul b/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul index 1205993567b2..2a3ad893683b 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/two_vars.yul @@ -12,12 +12,12 @@ // // { // { -// let a_1 := mload(0) -// let b_2 := mload(a_1) -// let a_3 := mload(b_2) -// let b_4 := mload(a_3) -// let a_5 := mload(b_4) -// let b_6 := mload(a_5) -// mstore(a_5, b_6) +// let a := mload(0) +// let b := mload(a) +// let a_1 := mload(b) +// let b_1 := mload(a_1) +// let a_2 := mload(b_1) +// let b_2 := mload(a_2) +// mstore(a_2, b_2) // } // } diff --git a/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul b/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul index 104dc2822ea0..547dddcc5e20 100644 --- a/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul +++ b/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul @@ -16,25 +16,25 @@ // { // function copy(from, to) -> length // { -// let from_6 := from -// let to_7 := to -// let length_1 := mload(from_6) +// let from_2 := from +// let to_2 := to +// let length_1 := mload(from_2) // length := length_1 -// mstore(to_7, length_1) -// let from_2 := add(from_6, 0x20) -// let to_3 := add(to_7, 0x20) -// let x_4 := 1 -// let x := x_4 +// mstore(to_2, length_1) +// let from_1 := add(from_2, 0x20) +// let to_1 := add(to_2, 0x20) +// let x_1 := 1 +// let x := x_1 // for { } // lt(x, length_1) // { -// let x_9 := x -// let x_5 := add(x_9, 0x20) -// x := x_5 +// let x_4 := x +// let x_2 := add(x_4, 0x20) +// x := x_2 // } // { -// let x_8 := x -// mstore(add(to_3, x_8), mload(add(from_2, x_8))) +// let x_3 := x +// mstore(add(to_1, x_3), mload(add(from_1, x_3))) // } // } // } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/for_def_in_init.yul b/test/libyul/yulOptimizerTests/ssaTransform/for_def_in_init.yul index 40fce8613e27..3ccf8c746093 100644 --- a/test/libyul/yulOptimizerTests/ssaTransform/for_def_in_init.yul +++ b/test/libyul/yulOptimizerTests/ssaTransform/for_def_in_init.yul @@ -13,20 +13,20 @@ // for { } // 1 // { -// let x_7 := x +// let x_4 := x // let x_2 := 2 // x := x_2 // } // { -// let x_5 := x -// let y_3 := 0 -// let y := y_3 +// let x_3 := x +// let y_1 := 0 +// let y := y_1 // for { } // 1 // { -// let y_6 := y -// let y_4 := 6 -// y := y_4 +// let y_3 := y +// let y_2 := 6 +// y := y_2 // } // { } // } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/function.yul b/test/libyul/yulOptimizerTests/ssaTransform/function.yul index 341d18cc12ce..79aa2721fbf0 100644 --- a/test/libyul/yulOptimizerTests/ssaTransform/function.yul +++ b/test/libyul/yulOptimizerTests/ssaTransform/function.yul @@ -12,15 +12,15 @@ // { // function f(a, b) -> c, d // { -// let a_5 := a -// let b_6 := b -// let b_1 := add(b_6, a_5) +// let a_2 := a +// let b_2 := b +// let b_1 := add(b_2, a_2) // b := b_1 -// let c_2 := add(c, b_1) -// c := c_2 -// let d_3 := add(d, c_2) -// d := d_3 -// let a_4 := add(a_5, d_3) -// a := a_4 +// let c_1 := add(c, b_1) +// c := c_1 +// let d_1 := add(d, c_1) +// d := d_1 +// let a_1 := add(a_2, d_1) +// a := a_1 // } // } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/multi_assign.yul b/test/libyul/yulOptimizerTests/ssaTransform/multi_assign.yul index ff4a0eb1de8a..eff6d55dd10d 100644 --- a/test/libyul/yulOptimizerTests/ssaTransform/multi_assign.yul +++ b/test/libyul/yulOptimizerTests/ssaTransform/multi_assign.yul @@ -13,16 +13,16 @@ // { // let a_1 := mload(0) // let a := a_1 -// let b_2 := mload(1) -// let b := b_2 -// let a_3, b_4 := f() +// let b_1 := mload(1) +// let b := b_1 +// let a_2, b_2 := f() +// a := a_2 +// b := b_2 +// sstore(a_2, b_2) +// let a_3 := mload(5) // a := a_3 -// b := b_4 -// sstore(a_3, b_4) -// let a_5 := mload(5) -// a := a_5 -// let b_6 := mload(a_5) -// b := b_6 +// let b_3 := mload(a_3) +// b := b_3 // function f() -> x, y // { } // } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/multi_decl.yul b/test/libyul/yulOptimizerTests/ssaTransform/multi_decl.yul index 06847711e465..da4f2243ec30 100644 --- a/test/libyul/yulOptimizerTests/ssaTransform/multi_decl.yul +++ b/test/libyul/yulOptimizerTests/ssaTransform/multi_decl.yul @@ -10,14 +10,14 @@ // step: ssaTransform // // { -// let x_1, y_2 := f(1, 2) +// let x_1, y_1 := f(1, 2) // let x := x_1 -// let y := y_2 -// let x_3 := mload(y_2) -// x := x_3 -// let y_4 := mload(x_3) -// y := y_4 -// let a, b := f(x_3, y_4) +// let y := y_1 +// let x_2 := mload(y_1) +// x := x_2 +// let y_2 := mload(x_2) +// y := y_2 +// let a, b := f(x_2, y_2) // sstore(a, b) // function f(t, v) -> w, z // { } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/nested.yul b/test/libyul/yulOptimizerTests/ssaTransform/nested.yul index e075f06a2462..b3e9bd21c4ce 100644 --- a/test/libyul/yulOptimizerTests/ssaTransform/nested.yul +++ b/test/libyul/yulOptimizerTests/ssaTransform/nested.yul @@ -18,17 +18,17 @@ // let a := a_1 // let a_2 := 2 // a := a_2 -// let b_3 := 3 -// let b := b_3 -// let b_4 := 4 -// b := b_4 +// let b_1 := 3 +// let b := b_1 +// let b_2 := 4 +// b := b_2 // { -// let a_5 := 3 -// a := a_5 -// let a_6 := 4 -// a := a_6 +// let a_3 := 3 +// a := a_3 +// let a_4 := 4 +// a := a_4 // } -// let a_8 := a -// let a_7 := add(b_4, a_8) -// a := a_7 +// let a_6 := a +// let a_5 := add(b_2, a_6) +// a := a_5 // } diff --git a/test/libyul/yulOptimizerTests/ssaTransform/typed.yul b/test/libyul/yulOptimizerTests/ssaTransform/typed.yul index 4b1aa164371c..747dee3fc771 100644 --- a/test/libyul/yulOptimizerTests/ssaTransform/typed.yul +++ b/test/libyul/yulOptimizerTests/ssaTransform/typed.yul @@ -20,23 +20,23 @@ // { // let b_1:bool := true // let b:bool := b_1 -// let c_2:bool := false -// let c:bool := c_2 -// let c_3:bool := b_1 -// c := c_3 -// let b_4:bool := false -// b := b_4 -// let a_5 := 1 -// let a := a_5 -// let a_6 := add(a_5, 1) -// a := a_6 -// if c_3 +// let c_1:bool := false +// let c:bool := c_1 +// let c_2:bool := b_1 +// c := c_2 +// let b_2:bool := false +// b := b_2 +// let a_1 := 1 +// let a := a_1 +// let a_2 := add(a_1, 1) +// a := a_2 +// if c_2 // { -// let a_7 := add(a_6, 1) -// a := a_7 +// let a_3 := add(a_2, 1) +// a := a_3 // } -// let a_9 := a -// let a_8 := add(a_9, 1) -// a := a_8 -// mstore(a_8, 1) +// let a_5 := a +// let a_4 := add(a_5, 1) +// a := a_4 +// mstore(a_4, 1) // } diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul index a0259b1800ef..2ab2450ef78a 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/cycle_before_2.yul @@ -64,9 +64,9 @@ // case 0 { v := h(x) } // case 1 { v := g(sub(x, f())) } // } -// function h(x_1) -> v_2 -// { v_2 := g(x_1) } -// function f() -> v_3 +// function h(x_1) -> v_1 +// { v_1 := g(x_1) } +// function f() -> v_2 // { // mstore(0x80, calldataload(mul(1, 4))) // let a2 := calldataload(mul(2, 4)) diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul index 8407df5d0497..4c78382f76fc 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/tree.yul @@ -214,126 +214,126 @@ // function g() -> v_1 // { // mstore(0xc0, calldataload(mul(1, 4))) -// let a2_3 := calldataload(mul(2, 4)) -// let a3_4 := calldataload(mul(3, 4)) -// let a4_5 := calldataload(mul(4, 4)) -// let a5_6 := calldataload(mul(5, 4)) -// let a6_7 := calldataload(mul(6, 4)) -// let a7_8 := calldataload(mul(7, 4)) -// let a8_9 := calldataload(mul(8, 4)) -// let a9_10 := calldataload(mul(9, 4)) +// let a2_1 := calldataload(mul(2, 4)) +// let a3_1 := calldataload(mul(3, 4)) +// let a4_1 := calldataload(mul(4, 4)) +// let a5_1 := calldataload(mul(5, 4)) +// let a6_1 := calldataload(mul(6, 4)) +// let a7_1 := calldataload(mul(7, 4)) +// let a8_1 := calldataload(mul(8, 4)) +// let a9_1 := calldataload(mul(9, 4)) // mstore(0xc0, calldataload(mul(0, 4))) -// let a10_11 := calldataload(mul(10, 4)) -// let a11_12 := calldataload(mul(11, 4)) -// let a12_13 := calldataload(mul(12, 4)) -// let a13_14 := calldataload(mul(13, 4)) -// let a14_15 := calldataload(mul(14, 4)) -// let a15_16 := calldataload(mul(15, 4)) -// let a16_17 := calldataload(mul(16, 4)) -// let a17_18 := calldataload(mul(17, 4)) +// let a10_1 := calldataload(mul(10, 4)) +// let a11_1 := calldataload(mul(11, 4)) +// let a12_1 := calldataload(mul(12, 4)) +// let a13_1 := calldataload(mul(13, 4)) +// let a14_1 := calldataload(mul(14, 4)) +// let a15_1 := calldataload(mul(15, 4)) +// let a16_1 := calldataload(mul(16, 4)) +// let a17_1 := calldataload(mul(17, 4)) // sstore(0, mload(0xc0)) -// sstore(mul(17, 4), a17_18) -// sstore(mul(16, 4), a16_17) -// sstore(mul(15, 4), a15_16) -// sstore(mul(14, 4), a14_15) -// sstore(mul(13, 4), a13_14) -// sstore(mul(12, 4), a12_13) -// sstore(mul(11, 4), a11_12) -// sstore(mul(10, 4), a10_11) -// sstore(mul(9, 4), a9_10) -// sstore(mul(8, 4), a8_9) -// sstore(mul(7, 4), a7_8) -// sstore(mul(6, 4), a6_7) -// sstore(mul(5, 4), a5_6) -// sstore(mul(4, 4), a4_5) -// sstore(mul(3, 4), a3_4) -// sstore(mul(2, 4), a2_3) +// sstore(mul(17, 4), a17_1) +// sstore(mul(16, 4), a16_1) +// sstore(mul(15, 4), a15_1) +// sstore(mul(14, 4), a14_1) +// sstore(mul(13, 4), a13_1) +// sstore(mul(12, 4), a12_1) +// sstore(mul(11, 4), a11_1) +// sstore(mul(10, 4), a10_1) +// sstore(mul(9, 4), a9_1) +// sstore(mul(8, 4), a8_1) +// sstore(mul(7, 4), a7_1) +// sstore(mul(6, 4), a6_1) +// sstore(mul(5, 4), a5_1) +// sstore(mul(4, 4), a4_1) +// sstore(mul(3, 4), a3_1) +// sstore(mul(2, 4), a2_1) // sstore(mul(1, 4), mload(0xc0)) // v_1 := i() // } -// function h() -> v_19 +// function h() -> v_2 // { // mstore(0xa0, calldataload(mul(1, 4))) // mstore(0xc0, calldataload(mul(2, 4))) -// let a3_22 := calldataload(mul(3, 4)) -// let a4_23 := calldataload(mul(4, 4)) -// let a5_24 := calldataload(mul(5, 4)) -// let a6_25 := calldataload(mul(6, 4)) -// let a7_26 := calldataload(mul(7, 4)) -// let a8_27 := calldataload(mul(8, 4)) -// let a9_28 := calldataload(mul(9, 4)) -// let a10_29 := calldataload(mul(10, 4)) -// let a11_30 := calldataload(mul(10, 4)) +// let a3_2 := calldataload(mul(3, 4)) +// let a4_2 := calldataload(mul(4, 4)) +// let a5_2 := calldataload(mul(5, 4)) +// let a6_2 := calldataload(mul(6, 4)) +// let a7_2 := calldataload(mul(7, 4)) +// let a8_2 := calldataload(mul(8, 4)) +// let a9_2 := calldataload(mul(9, 4)) +// let a10_2 := calldataload(mul(10, 4)) +// let a11_2 := calldataload(mul(10, 4)) // mstore(0xa0, calldataload(mul(0, 4))) // mstore(0xc0, calldataload(mul(1, 4))) -// let a12_31 := calldataload(mul(12, 4)) -// let a13_32 := calldataload(mul(13, 4)) -// let a14_33 := calldataload(mul(14, 4)) -// let a15_34 := calldataload(mul(15, 4)) -// let a16_35 := calldataload(mul(16, 4)) -// let a17_36 := calldataload(mul(17, 4)) +// let a12_2 := calldataload(mul(12, 4)) +// let a13_2 := calldataload(mul(13, 4)) +// let a14_2 := calldataload(mul(14, 4)) +// let a15_2 := calldataload(mul(15, 4)) +// let a16_2 := calldataload(mul(16, 4)) +// let a17_2 := calldataload(mul(17, 4)) // let a18 := calldataload(mul(18, 4)) // let a19 := calldataload(mul(19, 4)) // sstore(0, add(mload(0xa0), mload(0xc0))) // sstore(mul(17, 4), a19) // sstore(mul(17, 4), a18) -// sstore(mul(17, 4), a17_36) -// sstore(mul(16, 4), a16_35) -// sstore(mul(15, 4), a15_34) -// sstore(mul(14, 4), a14_33) -// sstore(mul(13, 4), a13_32) -// sstore(mul(12, 4), a12_31) -// sstore(mul(11, 4), a11_30) -// sstore(mul(10, 4), a10_29) -// sstore(mul(9, 4), a9_28) -// sstore(mul(8, 4), a8_27) -// sstore(mul(7, 4), a7_26) -// sstore(mul(6, 4), a6_25) -// sstore(mul(5, 4), a5_24) -// sstore(mul(4, 4), a4_23) -// sstore(mul(3, 4), a3_22) +// sstore(mul(17, 4), a17_2) +// sstore(mul(16, 4), a16_2) +// sstore(mul(15, 4), a15_2) +// sstore(mul(14, 4), a14_2) +// sstore(mul(13, 4), a13_2) +// sstore(mul(12, 4), a12_2) +// sstore(mul(11, 4), a11_2) +// sstore(mul(10, 4), a10_2) +// sstore(mul(9, 4), a9_2) +// sstore(mul(8, 4), a8_2) +// sstore(mul(7, 4), a7_2) +// sstore(mul(6, 4), a6_2) +// sstore(mul(5, 4), a5_2) +// sstore(mul(4, 4), a4_2) +// sstore(mul(3, 4), a3_2) // sstore(mul(2, 4), mload(0xc0)) // sstore(mul(1, 4), mload(0xa0)) -// v_19 := i() +// v_2 := i() // } -// function i() -> v_37 +// function i() -> v_3 // { // mstore(0xe0, calldataload(mul(1, 4))) -// let a2_39 := calldataload(mul(2, 4)) -// let a3_40 := calldataload(mul(3, 4)) -// let a4_41 := calldataload(mul(4, 4)) -// let a5_42 := calldataload(mul(5, 4)) -// let a6_43 := calldataload(mul(6, 4)) -// let a7_44 := calldataload(mul(7, 4)) -// let a8_45 := calldataload(mul(8, 4)) -// let a9_46 := calldataload(mul(9, 4)) +// let a2_3 := calldataload(mul(2, 4)) +// let a3_3 := calldataload(mul(3, 4)) +// let a4_3 := calldataload(mul(4, 4)) +// let a5_3 := calldataload(mul(5, 4)) +// let a6_3 := calldataload(mul(6, 4)) +// let a7_3 := calldataload(mul(7, 4)) +// let a8_3 := calldataload(mul(8, 4)) +// let a9_3 := calldataload(mul(9, 4)) // mstore(0xe0, calldataload(mul(0, 4))) -// let a10_47 := calldataload(mul(10, 4)) -// let a11_48 := calldataload(mul(11, 4)) -// let a12_49 := calldataload(mul(12, 4)) -// let a13_50 := calldataload(mul(13, 4)) -// let a14_51 := calldataload(mul(14, 4)) -// let a15_52 := calldataload(mul(15, 4)) -// let a16_53 := calldataload(mul(16, 4)) -// let a17_54 := calldataload(mul(17, 4)) +// let a10_3 := calldataload(mul(10, 4)) +// let a11_3 := calldataload(mul(11, 4)) +// let a12_3 := calldataload(mul(12, 4)) +// let a13_3 := calldataload(mul(13, 4)) +// let a14_3 := calldataload(mul(14, 4)) +// let a15_3 := calldataload(mul(15, 4)) +// let a16_3 := calldataload(mul(16, 4)) +// let a17_3 := calldataload(mul(17, 4)) // sstore(0, mload(0xe0)) -// sstore(mul(17, 4), a17_54) -// sstore(mul(16, 4), a16_53) -// sstore(mul(15, 4), a15_52) -// sstore(mul(14, 4), a14_51) -// sstore(mul(13, 4), a13_50) -// sstore(mul(12, 4), a12_49) -// sstore(mul(11, 4), a11_48) -// sstore(mul(10, 4), a10_47) -// sstore(mul(9, 4), a9_46) -// sstore(mul(8, 4), a8_45) -// sstore(mul(7, 4), a7_44) -// sstore(mul(6, 4), a6_43) -// sstore(mul(5, 4), a5_42) -// sstore(mul(4, 4), a4_41) -// sstore(mul(3, 4), a3_40) -// sstore(mul(2, 4), a2_39) +// sstore(mul(17, 4), a17_3) +// sstore(mul(16, 4), a16_3) +// sstore(mul(15, 4), a15_3) +// sstore(mul(14, 4), a14_3) +// sstore(mul(13, 4), a13_3) +// sstore(mul(12, 4), a12_3) +// sstore(mul(11, 4), a11_3) +// sstore(mul(10, 4), a10_3) +// sstore(mul(9, 4), a9_3) +// sstore(mul(8, 4), a8_3) +// sstore(mul(7, 4), a7_3) +// sstore(mul(6, 4), a6_3) +// sstore(mul(5, 4), a5_3) +// sstore(mul(4, 4), a4_3) +// sstore(mul(3, 4), a3_3) +// sstore(mul(2, 4), a2_3) // sstore(mul(1, 4), mload(0xe0)) -// v_37 := sload(mul(42, 8)) +// v_3 := sload(mul(42, 8)) // } // } diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul index 46435dd210dc..05b400a5d2b5 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_arguments_and_returns.yul @@ -71,27 +71,27 @@ // let a_18 := 18 // let a_19 := 19 // let a_20 := 20 -// let b_1_1, b_2_2, b_3_3, b_4_4, b_5_5, b_6_6, b_7_7, b_8_8, b_9_9, b_10_10, b_11_11, b_12_12, b_13_13, b_14_14, b_15_15, b_16_16, b_17_17, b_18_18, b_19_19, b_20_20 := verbatim_20i_20o("test", mload(0x0100), mload(0x0120), mload(0x0140), mload(0x0160), mload(0x0180), mload(0x01a0), mload(0x01c0), mload(0x01e0), mload(0x0200), mload(0x0220), mload(0x0240), mload(0x0260), a_13, a_14, a_15, a_16, a_17, a_18, a_19, a_20) -// mstore(0x80, b_4_4) -// mstore(0xa0, b_3_3) -// mstore(0xc0, b_2_2) -// mstore(0xe0, b_1_1) -// let b_20 := b_20_20 -// let b_19 := b_19_19 -// let b_18 := b_18_18 -// let b_17 := b_17_17 -// let b_16 := b_16_16 -// let b_15 := b_15_15 -// let b_14 := b_14_14 -// let b_13 := b_13_13 -// let b_12 := b_12_12 -// let b_11 := b_11_11 -// let b_10 := b_10_10 -// let b_9 := b_9_9 -// let b_8 := b_8_8 -// let b_7 := b_7_7 -// let b_6 := b_6_6 -// let b_5 := b_5_5 +// let b_1, b_2, b_3, b_4, b_5_1, b_6_1, b_7_1, b_8_1, b_9_1, b_10_1, b_11_1, b_12_1, b_13_1, b_14_1, b_15_1, b_16_1, b_17_1, b_18_1, b_19_1, b_20_1 := verbatim_20i_20o("test", mload(0x0100), mload(0x0120), mload(0x0140), mload(0x0160), mload(0x0180), mload(0x01a0), mload(0x01c0), mload(0x01e0), mload(0x0200), mload(0x0220), mload(0x0240), mload(0x0260), a_13, a_14, a_15, a_16, a_17, a_18, a_19, a_20) +// mstore(0x80, b_4) +// mstore(0xa0, b_3) +// mstore(0xc0, b_2) +// mstore(0xe0, b_1) +// let b_20 := b_20_1 +// let b_19 := b_19_1 +// let b_18 := b_18_1 +// let b_17 := b_17_1 +// let b_16 := b_16_1 +// let b_15 := b_15_1 +// let b_14 := b_14_1 +// let b_13 := b_13_1 +// let b_12 := b_12_1 +// let b_11 := b_11_1 +// let b_10 := b_10_1 +// let b_9 := b_9_1 +// let b_8 := b_8_1 +// let b_7 := b_7_1 +// let b_6 := b_6_1 +// let b_5 := b_5_1 // sstore(1, mload(0xe0)) // sstore(2, mload(0xc0)) // sstore(3, mload(0xa0)) diff --git a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul index 47db17e21198..cc06f4629cbb 100644 --- a/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul +++ b/test/libyul/yulOptimizerTests/stackLimitEvader/verbatim_many_returns.yul @@ -13,40 +13,40 @@ // { // { // mstore(0x40, memoryguard(0xa0)) -// let a1_1, a2_2, a3_3, a4_4, a5_5, a6_6, a7_7, a8_8, a9_9, a10_10, a13_11, a14_12, a15_13, a16_14, a17_15, a18_16 := verbatim_0i_16o("test") +// let a1, a2_1, a3_1, a4_1, a5_1, a6_1, a7_1, a8_1, a9_1, a10_1, a13_1, a14_1, a15_1, a16_1, a17_1, a18_1 := verbatim_0i_16o("test") +// mstore(0x80, a1) +// let a18 := a18_1 +// let a17 := a17_1 +// let a16 := a16_1 +// let a15 := a15_1 +// let a14 := a14_1 +// let a13 := a13_1 +// let a10 := a10_1 +// let a9 := a9_1 +// let a8 := a8_1 +// let a7 := a7_1 +// let a6 := a6_1 +// let a5 := a5_1 +// let a4 := a4_1 +// let a3 := a3_1 +// let a2 := a2_1 +// let a1_1, a2_2, a3_2, a4_2, a5_2, a6_2, a7_2, a8_2, a9_2, a10_2, a13_2, a14_2, a15_2, a16_2, a17_2, a18_2 := verbatim_0i_16o("test") // mstore(0x80, a1_1) -// let a18 := a18_16 -// let a17 := a17_15 -// let a16 := a16_14 -// let a15 := a15_13 -// let a14 := a14_12 -// let a13 := a13_11 -// let a10 := a10_10 -// let a9 := a9_9 -// let a8 := a8_8 -// let a7 := a7_7 -// let a6 := a6_6 -// let a5 := a5_5 -// let a4 := a4_4 -// let a3 := a3_3 -// let a2 := a2_2 -// let a1_17, a2_18, a3_19, a4_20, a5_21, a6_22, a7_23, a8_24, a9_25, a10_26, a13_27, a14_28, a15_29, a16_30, a17_31, a18_32 := verbatim_0i_16o("test") -// mstore(0x80, a1_17) -// a18 := a18_32 -// a17 := a17_31 -// a16 := a16_30 -// a15 := a15_29 -// a14 := a14_28 -// a13 := a13_27 -// a10 := a10_26 -// a9 := a9_25 -// a8 := a8_24 -// a7 := a7_23 -// a6 := a6_22 -// a5 := a5_21 -// a4 := a4_20 -// a3 := a3_19 -// a2 := a2_18 +// a18 := a18_2 +// a17 := a17_2 +// a16 := a16_2 +// a15 := a15_2 +// a14 := a14_2 +// a13 := a13_2 +// a10 := a10_2 +// a9 := a9_2 +// a8 := a8_2 +// a7 := a7_2 +// a6 := a6_2 +// a5 := a5_2 +// a4 := a4_2 +// a3 := a3_2 +// a2 := a2_2 // sstore(mload(0x80), 10) // sstore(a18, 20) // } diff --git a/test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul b/test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul index 82bf493470c8..302ca3e865eb 100644 --- a/test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul +++ b/test/libyul/yulOptimizerTests/unusedAssignEliminator/leave.yul @@ -31,10 +31,10 @@ // if b { leave } // x := 8 // } -// function g(a_1, b_2) -> x_3 +// function g(a_1, b_1) -> x_1 // { -// let t_4 -// if b_2 { } -// x_3 := 8 +// let t_1 +// if b_1 { } +// x_1 := 8 // } // } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/LiteralRematerialiser.yul b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/LiteralRematerialiser.yul index e11ea2a96f9e..7af5e37bc2a4 100644 --- a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/LiteralRematerialiser.yul +++ b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/LiteralRematerialiser.yul @@ -22,6 +22,6 @@ // if iszero(x) { revert(0, 0) } // if iszero(add(x, 1)) { revert(0, 0) } // } -// function f_1(x_2) -> y_3 -// { f(x_2) } +// function f_1(x_1) -> y +// { f(x_1) } // } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/multiple_param.yul b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/multiple_param.yul index f2a036459817..0718b67d0202 100644 --- a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/multiple_param.yul +++ b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/multiple_param.yul @@ -19,6 +19,6 @@ // y := mload(a) // z := mload(c) // } -// function f_1(a_2, b_3, c_4) -> x_5, y_6, z_7 -// { y_6, z_7 := f(a_2, c_4) } +// function f_1(a_1, b, c_1) -> x, y_1, z_1 +// { y_1, z_1 := f(a_1, c_1) } // } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/multiple_return.yul b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/multiple_return.yul index 51612a699b0f..1edd68c5e7e1 100644 --- a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/multiple_return.yul +++ b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/multiple_return.yul @@ -19,6 +19,6 @@ // y := mload(1) // z := mload(2) // } -// function f_1(d_2) -> x_3, y_4, z_5 -// { y_4, z_5 := f() } +// function f_1(d) -> x, y_1, z_1 +// { y_1, z_1 := f() } // } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/nested_function.yul b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/nested_function.yul index d09ba44a6634..497cb21e747d 100644 --- a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/nested_function.yul +++ b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/nested_function.yul @@ -42,15 +42,15 @@ // x := g(1) // x := add(x, 1) // } -// function f_1(a_3) -> x_4 -// { x_4 := f() } +// function f_1(a) -> x_1 +// { x_1 := f() } // function j() -> w // { // w := 13 // w := add(13, 1) // } -// function j_2(d_5) -> w_6 -// { w_6 := j() } +// function j_1(d) -> w_1 +// { w_1 := j() } // function h(c) -> u -// { u := j_2(c) } +// { u := j_1(c) } // } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/nested_function_name_collision.yul b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/nested_function_name_collision.yul index 8ce80f140edb..6eb892aaa4fa 100644 --- a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/nested_function_name_collision.yul +++ b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/nested_function_name_collision.yul @@ -36,17 +36,17 @@ // w := 13 // sstore(0, 13) // } -// function g_1(d_3) -> w_4 -// { w_4 := g() } +// function g_2(d) -> w_2 +// { w_2 := g() } // function f(c) -> u -// { u := g_1(c) } -// function g_3() -> w_5 +// { u := g_2(c) } +// function g_1() -> w_1 // { -// w_5 := 13 +// w_1 := 13 // sstore(0, 13) // } -// function g_3_2(d_4_5) -> w_5_6 -// { w_5_6 := g_3() } -// function h(c_1) -> u_2 -// { u_2 := g_3_2(c_1) } +// function g_3(d_1) -> w_3 +// { w_3 := g_1() } +// function h(c_1) -> u_1 +// { u_1 := g_3(c_1) } // } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/no_return.yul b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/no_return.yul index 1cf059da2979..96d24ee4c638 100644 --- a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/no_return.yul +++ b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/no_return.yul @@ -16,6 +16,6 @@ // sstore(a, 0) // a := add(a, 1) // } -// function f_1(a_2, b_3) -// { f(a_2) } +// function f_1(a_1, b) +// { f(a_1) } // } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/recursion.yul b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/recursion.yul index 4a2c5b6ccc30..6acab50336a5 100644 --- a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/recursion.yul +++ b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/recursion.yul @@ -16,6 +16,6 @@ // x, y, z := f_1(1, 2, 3) // x := add(x, 1) // } -// function f_1(a_2, b_3, c_4) -> x_5, y_6, z_7 -// { x_5, y_6, z_7 := f() } +// function f_1(a, b, c) -> x_1, y_1, z_1 +// { x_1, y_1, z_1 := f() } // } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/simple.yul b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/simple.yul index 873eef9777ab..6ee9e4f3b42e 100644 --- a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/simple.yul +++ b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/simple.yul @@ -16,6 +16,6 @@ // let w := mload(1) // y := mload(w) // } -// function f_1(x_2) -> y_3 -// { y_3 := f() } +// function f_1(x) -> y_1 +// { y_1 := f() } // } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/too_many_arguments.yul b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/too_many_arguments.yul index 720489d57328..0ed95f76e099 100644 --- a/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/too_many_arguments.yul +++ b/test/libyul/yulOptimizerTests/unusedFunctionParameterPruner/too_many_arguments.yul @@ -18,6 +18,6 @@ // y := mload(x3) // z := mload(x7) // } -// function f_1(x1_2, x2_3, x3_4, x4_5, x5_6, x6_7, x7_8, x8_9, x9_10, x10_11, x11_12, x12_13, x13_14, x14_15, x15_16, x16_17, x17_18, x18_19) -> y_20, z_21 -// { y_20, z_21 := f(x3_4, x7_8) } +// function f_1(x1, x2, x3_1, x4, x5, x6, x7_1, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18) -> y_1, z_1 +// { y_1, z_1 := f(x3_1, x7_1) } // } diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/covering_calldatacopy.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/covering_calldatacopy.yul index 7fd227089b83..9ca1d879b4d7 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/covering_calldatacopy.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/covering_calldatacopy.yul @@ -30,28 +30,28 @@ // let start := calldataload(0x10) // if calldataload(0) // { -// let _4 := 7 -// mstore(add(start, 2), _4) +// let _1 := 7 +// mstore(add(start, 2), _1) // calldatacopy(start, 0, 0x20) // } // if calldataload(1) // { -// let _11 := 9 -// mstore(add(start, 2), _11) -// let _14 := 0x21 -// let _15 := 0 -// calldatacopy(add(start, 1), _15, _14) +// let _2 := 9 +// mstore(add(start, 2), _2) +// let _3 := 0x21 +// let _4 := 0 +// calldatacopy(add(start, 1), _4, _3) // } // if calldataload(2) // { -// let _20 := 7 -// mstore8(add(start, 2), _20) +// let _5 := 7 +// mstore8(add(start, 2), _5) // calldatacopy(start, 0, 3) // } // if calldataload(3) // { -// let _27 := 7 -// mstore8(add(start, 3), _27) +// let _6 := 7 +// mstore8(add(start, 3), _6) // calldatacopy(start, 0, 3) // } // sstore(0, keccak256(start, 0x40)) diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/covering_calldatacopy_fixed.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/covering_calldatacopy_fixed.yul index 47e0b95fa3a3..3c0b8dcbddfd 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/covering_calldatacopy_fixed.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/covering_calldatacopy_fixed.yul @@ -33,14 +33,14 @@ // } // if calldataload(1) // { -// let _10 := 9 -// let _11 := 2 +// let _1 := 9 +// let _2 := 2 // calldatacopy(1, 0, 0x21) // } // if calldataload(2) // { -// let _17 := 7 -// let _18 := 2 +// let _3 := 7 +// let _4 := 2 // calldatacopy(0, 0, 3) // } // if calldataload(3) diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/function_end.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/function_end.yul index cb69be363594..23586187f49e 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/function_end.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/function_end.yul @@ -14,7 +14,7 @@ // function f() // { // let x := calldataload(2) -// let _2 := 2 +// let _1 := 2 // mstore(x, 3) // } // } diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/if_overwrite_all_branches.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/if_overwrite_all_branches.yul index 7054dc255464..b15fecd84a91 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/if_overwrite_all_branches.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/if_overwrite_all_branches.yul @@ -13,8 +13,8 @@ // { // { // let c := calldataload(0) -// let _2 := 1 -// if c { let _3 := 2 } +// let _1 := 1 +// if c { let _2 := 2 } // sstore(c, 3) // } // } diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/leave.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/leave.yul index 92a75155410b..66e31e9eb3d1 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/leave.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/leave.yul @@ -16,8 +16,8 @@ // { // mstore(0, 5) // if calldataload(0) { leave } -// let _5 := 5 -// let _6 := 0x20 +// let _1 := 5 +// let _2 := 0x20 // revert(0, 0) // } // } diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/memoryguard.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/memoryguard.yul index 466cd02e5331..83aa7ac0a23d 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/memoryguard.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/memoryguard.yul @@ -15,9 +15,9 @@ // { // mstore(0x40, memoryguard(100)) // let free_mem_ptr := mload(0x40) -// let _4 := 100 -// let _5 := 200 -// mstore8(add(free_mem_ptr, 31), _5) +// let _1 := 100 +// let _2 := 200 +// mstore8(add(free_mem_ptr, 31), _2) // mstore(free_mem_ptr, 300) // return(free_mem_ptr, add(free_mem_ptr, 100)) // } diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/no_storage_inside_function.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/no_storage_inside_function.yul index 524b328e9e7e..204a90019da9 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/no_storage_inside_function.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/no_storage_inside_function.yul @@ -14,7 +14,7 @@ // { // { // let x := 5 -// let _2 := 10 +// let _1 := 10 // mstore(0, 42) // pop(f()) // sstore(x, 10) @@ -22,6 +22,6 @@ // function f() -> r // { // r := mload(0x20) -// let r_7 := r +// let r_1 := r // } // } diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/remove_before_revert.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/remove_before_revert.yul index e7777964c20e..3d23316f964c 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/remove_before_revert.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/remove_before_revert.yul @@ -13,8 +13,8 @@ // { // { // let c := calldataload(0) -// let _2 := 4 -// if c { let _3 := 2 } +// let _1 := 4 +// if c { let _2 := 2 } // let d := 0 // revert(d, d) // } diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/tstore.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/tstore.yul index f3befb79d0ad..4eb4cc2dbbb7 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/tstore.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/tstore.yul @@ -15,7 +15,7 @@ // { // let x := 5 // tstore(x, 10) -// let _2 := 10 +// let _1 := 10 // pop(mload(0)) // tstore(x, 10) // sstore(x, 20) diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/unknown_length2.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/unknown_length2.yul index db5f060a634d..e02b34bb78e5 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/unknown_length2.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/unknown_length2.yul @@ -13,21 +13,21 @@ // // { // { -// let a_9 -// let a := a_9 +// let a_1 +// let a := a_1 // switch calldataload(0) // case 0 { // a := calldataload(9) -// let a_10 := a +// let a_2 := a // } // case 1 { -// let a_12 := a +// let a_4 := a // a := calldataload(10) -// let a_11 := a +// let a_3 := a // } -// let a_13 := a -// let _5 := 0 -// let _6 := 0x20 +// let a_5 := a +// let _1 := 0 +// let _2 := 0x20 // sstore(0, mload(0)) // } // } diff --git a/test/libyul/yulOptimizerTests/unusedStoreEliminator/unrelated_relative.yul b/test/libyul/yulOptimizerTests/unusedStoreEliminator/unrelated_relative.yul index b0b42060f49c..b3fb063ca0a7 100644 --- a/test/libyul/yulOptimizerTests/unusedStoreEliminator/unrelated_relative.yul +++ b/test/libyul/yulOptimizerTests/unusedStoreEliminator/unrelated_relative.yul @@ -13,11 +13,11 @@ // { // let c := calldataload(0) // mstore(c, 4) -// let _3 := 8 -// let _5 := add(c, 0x20) +// let _1 := 8 +// let _2 := add(c, 0x20) // sstore(0, mload(c)) -// let _8 := 9 -// let _9 := 20 -// let _11 := add(c, 0x20) +// let _3 := 9 +// let _4 := 20 +// let _5 := add(c, 0x20) // } // } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/builtins.yul b/test/libyul/yulOptimizerTests/varNameCleaner/builtins.yul index 43c30137a869..fdfec56162d4 100644 --- a/test/libyul/yulOptimizerTests/varNameCleaner/builtins.yul +++ b/test/libyul/yulOptimizerTests/varNameCleaner/builtins.yul @@ -4,4 +4,4 @@ // ---- // step: varNameCleaner // -// { { let datasize_1 := 1 } } +// { { let datasize_256 := 1 } } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/function_names.yul b/test/libyul/yulOptimizerTests/varNameCleaner/function_names.yul index c8b2bef2429f..5dc0206d7649 100644 --- a/test/libyul/yulOptimizerTests/varNameCleaner/function_names.yul +++ b/test/libyul/yulOptimizerTests/varNameCleaner/function_names.yul @@ -8,8 +8,8 @@ // // { // { -// let f_1 // let f_2 +// let f_10 // } // function f() // { let f_1 } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/function_parameters.yul b/test/libyul/yulOptimizerTests/varNameCleaner/function_parameters.yul index c0656056eec0..7b504f84896a 100644 --- a/test/libyul/yulOptimizerTests/varNameCleaner/function_parameters.yul +++ b/test/libyul/yulOptimizerTests/varNameCleaner/function_parameters.yul @@ -13,13 +13,13 @@ // // { // { -// let f_1 // let f_2 +// let f_10 // } -// function f(x) -> x_1, y +// function f(x_12) -> x, y_14 // { -// let y_1 := x -// y := y_1 -// x_1 := y +// let y := x_12 +// y_14 := y +// x := y_14 // } // } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/function_scopes.yul b/test/libyul/yulOptimizerTests/varNameCleaner/function_scopes.yul index 2882459dbe93..b7ce91f7034f 100644 --- a/test/libyul/yulOptimizerTests/varNameCleaner/function_scopes.yul +++ b/test/libyul/yulOptimizerTests/varNameCleaner/function_scopes.yul @@ -8,7 +8,7 @@ // { // { } // function f() -// { let x := 0 } +// { let x_1 := 0 } // function g() -// { let x := 0 } +// { let x_2 := 0 } // } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/instructions.yul b/test/libyul/yulOptimizerTests/varNameCleaner/instructions.yul index 325ec7d8414a..7b7b1e77782c 100644 --- a/test/libyul/yulOptimizerTests/varNameCleaner/instructions.yul +++ b/test/libyul/yulOptimizerTests/varNameCleaner/instructions.yul @@ -4,4 +4,4 @@ // ---- // step: varNameCleaner // -// { { let mul_1 := 1 } } +// { { let mul_256 := 1 } } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/name_stripping.yul b/test/libyul/yulOptimizerTests/varNameCleaner/name_stripping.yul index 7d7d763c5424..10254f82b5e3 100644 --- a/test/libyul/yulOptimizerTests/varNameCleaner/name_stripping.yul +++ b/test/libyul/yulOptimizerTests/varNameCleaner/name_stripping.yul @@ -9,9 +9,9 @@ // // { // { -// let a := 1 -// let a_1 := 2 -// let a_2 := 0xdeadbeef -// let _1 := 21718 +// let a_1 := 1 +// let a_2_1 := 2 +// let a_4312 := 0xdeadbeef +// let _42 := 21718 // } // } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/reshuffling-inverse.yul b/test/libyul/yulOptimizerTests/varNameCleaner/reshuffling-inverse.yul index 237ab8612e92..294471b7004d 100644 --- a/test/libyul/yulOptimizerTests/varNameCleaner/reshuffling-inverse.yul +++ b/test/libyul/yulOptimizerTests/varNameCleaner/reshuffling-inverse.yul @@ -9,9 +9,9 @@ // // { // { -// let x := 1 -// let x_1 := 2 +// let x_4 := 1 +// let x_3 := 2 // let x_2 := 3 -// let x_3 := 4 +// let x_1 := 4 // } // } diff --git a/test/libyul/yulOptimizerTests/varNameCleaner/reshuffling.yul b/test/libyul/yulOptimizerTests/varNameCleaner/reshuffling.yul index 0df1715d739b..7b168c2e90ef 100644 --- a/test/libyul/yulOptimizerTests/varNameCleaner/reshuffling.yul +++ b/test/libyul/yulOptimizerTests/varNameCleaner/reshuffling.yul @@ -8,8 +8,8 @@ // // { // { -// let x := 1 -// let x_1 := 2 -// let x_2 := 3 +// let x_1 := 1 +// let x_2 := 2 +// let x_3 := 3 // } // } diff --git a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp index 25559bc66f27..309eb3779e60 100644 --- a/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp +++ b/test/tools/ossfuzz/StackReuseCodegenFuzzer.cpp @@ -52,11 +52,11 @@ static evmc::VM evmone = evmc::VM{evmc_create_evmone()}; namespace { /// @returns true if there are recursive functions, false otherwise. -bool recursiveFunctionExists(Dialect const& _dialect, yul::Object& _object) +bool recursiveFunctionExists(YulNameRepository const& _nameRepository, yul::Object& _object) { auto recursiveFunctions = CallGraphGenerator::callGraph(*_object.code).recursiveFunctions(); for(auto&& [function, variables]: CompilabilityChecker{ - _dialect, + _nameRepository, _object, true }.unreachableVariables @@ -93,6 +93,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) } YulStringRepository::reset(); + YulNameRepository nameRepository (EVMDialect::strictAssemblyForEVMObjects(version)); solidity::frontend::OptimiserSettings settings = solidity::frontend::OptimiserSettings::full(); settings.runYulOptimiser = false; @@ -106,7 +107,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) unoptimisedByteCode = assembler.assemble(); auto yulObject = assembler.object(); recursiveFunction = recursiveFunctionExists( - EVMDialect::strictAssemblyForEVMObjects(version), + nameRepository, *yulObject ); } diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index e31391b0e15b..f0e79d146697 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -89,7 +89,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, stack.parserResult()->code, - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + *stack.yulNameRepository(), /*disableMemoryTracing=*/true ); if (yulFuzzerUtil::resourceLimitsExceeded(termReason)) @@ -99,7 +99,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) termReason = yulFuzzerUtil::interpret( os2, stack.parserResult()->code, - EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion()), + *stack.yulNameRepository(), /*disableMemoryTracing=*/true ); diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp index 4f7a871ac8bf..d40bd30a65e6 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.cpp +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -24,7 +24,7 @@ using namespace solidity::yul::test::yul_fuzzer; yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( std::ostream& _os, std::shared_ptr _ast, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, bool _disableMemoryTracing, bool _outputStorageOnly, size_t _maxSteps, @@ -52,7 +52,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( TerminationReason reason = TerminationReason::None; try { - Interpreter::run(state, _dialect, *_ast, true, _disableMemoryTracing); + Interpreter::run(state, _yulNameRepository, *_ast, true, _disableMemoryTracing); } catch (StepLimitReached const&) { diff --git a/test/tools/ossfuzz/yulFuzzerCommon.h b/test/tools/ossfuzz/yulFuzzerCommon.h index 4c8f665f616c..63af29b84102 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.h +++ b/test/tools/ossfuzz/yulFuzzerCommon.h @@ -41,7 +41,7 @@ struct yulFuzzerUtil static TerminationReason interpret( std::ostream& _os, std::shared_ptr _ast, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, bool _disableMemoryTracing = false, bool _outputStorageOnly = false, size_t _maxSteps = maxSteps, diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index b27d879d5606..a44c0ec790ad 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -81,7 +81,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // Optimize YulOptimizerTestCommon optimizerTest( stack.parserResult(), - EVMDialect::strictAssemblyForEVMObjects(version) + *stack.yulNameRepository() ); optimizerTest.setStep(optimizerTest.randomOptimiserStep(_input.step())); std::shared_ptr astBlock = optimizerTest.run(); diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index d2cbdb11b360..91008caa0599 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -505,7 +505,7 @@ u256 EVMInstructionInterpreter::evalBuiltin( if (_fun.instruction) return eval(*_fun.instruction, _evaluatedArguments); - std::string fun = _fun.name.str(); + std::string fun = _fun.name; // Evaluate datasize/offset/copy instructions if (fun == "datasize" || fun == "dataoffset") { diff --git a/test/tools/yulInterpreter/Inspector.cpp b/test/tools/yulInterpreter/Inspector.cpp index 7746483a367a..f9d8bcf1d1e4 100644 --- a/test/tools/yulInterpreter/Inspector.cpp +++ b/test/tools/yulInterpreter/Inspector.cpp @@ -31,9 +31,9 @@ using namespace solidity::yul::test; namespace { -void printVariable(YulString const& _name, u256 const& _value) +void printVariable(std::string_view const _name, u256 const& _value) { - std::cout << "\t" << _name.str() << " = " << _value.str(); + std::cout << "\t" << _name << " = " << _value.str(); if (_value != 0) std::cout << " (" << toCompactHexWithPrefix(_value) << ")"; @@ -46,17 +46,17 @@ void printVariable(YulString const& _name, u256 const& _value) void InspectedInterpreter::run( std::shared_ptr _inspector, InterpreterState& _state, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block const& _ast, bool _disableExternalCalls, bool _disableMemoryTrace ) { Scope scope; - InspectedInterpreter{_inspector, _state, _dialect, scope, _disableExternalCalls, _disableMemoryTrace}(_ast); + InspectedInterpreter{_inspector, _state, _yulNameRepository, scope, _disableExternalCalls, _disableMemoryTrace}(_ast); } -Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std::map const& _variables) +Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std::map const& _variables) { if (m_stepMode == NodeAction::RunNode) { @@ -98,8 +98,8 @@ Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std m_state.dumpTraceAndState(std::cout, false); else if (input == "variables" || input == "v") { - for (auto &&[yulStr, val]: _variables) - printVariable(yulStr, val); + for (auto &&[yulName, val]: _variables) + printVariable(m_yulNameRepository.labelOf(yulName), val); std::cout << std::endl; } else if ( @@ -117,13 +117,16 @@ Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std std::vector candidates; bool found = false; - for (auto &&[yulStr, val]: _variables) - if (yulStr.str() == varname) + for (auto &&[yulName, val]: _variables) + { + auto const yulStr = m_yulNameRepository.labelOf(yulName); + if (yulStr == varname) { printVariable(yulStr, val); found = true; break; } + } if (!found) std::cout << varname << " not found." << std::endl; @@ -141,14 +144,14 @@ std::string Inspector::currentSource(langutil::DebugData const& _data) const u256 InspectedInterpreter::evaluate(Expression const& _expression) { - InspectedExpressionEvaluator ev(m_inspector, m_state, m_dialect, *m_scope, m_variables, m_disableExternalCalls, m_disableMemoryTrace); + InspectedExpressionEvaluator ev(m_inspector, m_state, m_yulNameRepository, *m_scope, m_variables, m_disableExternalCalls, m_disableMemoryTrace); ev.visit(_expression); return ev.value(); } std::vector InspectedInterpreter::evaluateMulti(Expression const& _expression) { - InspectedExpressionEvaluator ev(m_inspector, m_state, m_dialect, *m_scope, m_variables, m_disableExternalCalls, m_disableMemoryTrace); + InspectedExpressionEvaluator ev(m_inspector, m_state, m_yulNameRepository, *m_scope, m_variables, m_disableExternalCalls, m_disableMemoryTrace); ev.visit(_expression); return ev.values(); } diff --git a/test/tools/yulInterpreter/Inspector.h b/test/tools/yulInterpreter/Inspector.h index f4518c7087d3..b6a224e6e082 100644 --- a/test/tools/yulInterpreter/Inspector.h +++ b/test/tools/yulInterpreter/Inspector.h @@ -46,20 +46,20 @@ class Inspector StepThroughNode, }; - Inspector(std::string const& _source, InterpreterState const& _state) - :m_source(_source), m_state(_state) {} + Inspector(std::string const& _source, InterpreterState const& _state, YulNameRepository const& _yulNameRepository) + :m_source(_source), m_state(_state), m_yulNameRepository(_yulNameRepository) {} /* Asks the user what action to take. * @returns NodeAction::RunNode if the current AST node (and all children nodes!) should be * processed without stopping, else NodeAction::StepThroughNode. */ - NodeAction queryUser(langutil::DebugData const& _data, std::map const& _variables); + NodeAction queryUser(langutil::DebugData const& _data, std::map const& _variables); void stepMode(NodeAction _action) { m_stepMode = _action; } std::string const& source() const { return m_source; } - void interactiveVisit(langutil::DebugData const& _debugData, std::map const& _variables, std::function _visitNode) + void interactiveVisit(langutil::DebugData const& _debugData, std::map const& _variables, std::function _visitNode) { Inspector::NodeAction action = queryUser(_debugData, _variables); @@ -91,6 +91,7 @@ class Inspector /// Used to run AST nodes without user interaction NodeAction m_stepMode = NodeAction::StepThroughNode; + YulNameRepository const& m_yulNameRepository; }; /** @@ -103,7 +104,7 @@ class InspectedInterpreter: public Interpreter static void run( std::shared_ptr _inspector, InterpreterState& _state, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block const& _ast, bool _disableExternalCalls, bool _disableMemoryTracing @@ -112,13 +113,13 @@ class InspectedInterpreter: public Interpreter InspectedInterpreter( std::shared_ptr _inspector, InterpreterState& _state, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Scope& _scope, bool _disableExternalCalls, bool _disableMemoryTracing, - std::map _variables = {} + std::map _variables = {} ): - Interpreter(_state, _dialect, _scope, _disableExternalCalls, _disableMemoryTracing, _variables), + Interpreter(_state, _yulNameRepository, _scope, _disableExternalCalls, _disableMemoryTracing, _variables), m_inspector(_inspector) { } @@ -158,13 +159,13 @@ class InspectedExpressionEvaluator: public ExpressionEvaluator InspectedExpressionEvaluator( std::shared_ptr _inspector, InterpreterState& _state, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Scope& _scope, - std::map const& _variables, + std::map const& _variables, bool _disableExternalCalls, bool _disableMemoryTrace ): - ExpressionEvaluator(_state, _dialect, _scope, _variables, _disableExternalCalls, _disableMemoryTrace), + ExpressionEvaluator(_state, _yulNameRepository, _scope, _variables, _disableExternalCalls, _disableMemoryTrace), m_inspector(_inspector) {} @@ -180,12 +181,12 @@ class InspectedExpressionEvaluator: public ExpressionEvaluator void operator()(Identifier const& _node) override { helper(_node); } void operator()(FunctionCall const& _node) override { helper(_node); } protected: - std::unique_ptr makeInterpreterCopy(std::map _variables = {}) const override + std::unique_ptr makeInterpreterCopy(std::map _variables = {}) const override { return std::make_unique( m_inspector, m_state, - m_dialect, + m_yulNameRepository, m_scope, m_disableExternalCalls, m_disableMemoryTrace, @@ -197,10 +198,11 @@ class InspectedExpressionEvaluator: public ExpressionEvaluator return std::make_unique( std::make_unique( m_inspector->source(), - _state + _state, + m_yulNameRepository ), _state, - m_dialect, + m_yulNameRepository, _scope, m_disableExternalCalls, m_disableMemoryTrace diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index 6a0f3a9997ef..7a995355298c 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -109,14 +109,14 @@ void InterpreterState::dumpTraceAndState(std::ostream& _out, bool _disableMemory void Interpreter::run( InterpreterState& _state, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block const& _ast, bool _disableExternalCalls, bool _disableMemoryTrace ) { Scope scope; - Interpreter{_state, _dialect, scope, _disableExternalCalls, _disableMemoryTrace}(_ast); + Interpreter{_state, _yulNameRepository, scope, _disableExternalCalls, _disableMemoryTrace}(_ast); } void Interpreter::operator()(ExpressionStatement const& _expressionStatement) @@ -131,7 +131,7 @@ void Interpreter::operator()(Assignment const& _assignment) solAssert(values.size() == _assignment.variableNames.size(), ""); for (size_t i = 0; i < values.size(); ++i) { - YulString varName = _assignment.variableNames.at(i).name; + auto varName = _assignment.variableNames.at(i).name; solAssert(m_variables.count(varName), ""); m_variables[varName] = values.at(i); } @@ -146,7 +146,7 @@ void Interpreter::operator()(VariableDeclaration const& _declaration) solAssert(values.size() == _declaration.variables.size(), ""); for (size_t i = 0; i < values.size(); ++i) { - YulString varName = _declaration.variables.at(i).name; + auto varName = _declaration.variables.at(i).name; solAssert(!m_variables.count(varName), ""); m_variables[varName] = values.at(i); m_scope->names.emplace(varName, nullptr); @@ -251,14 +251,14 @@ void Interpreter::operator()(Block const& _block) u256 Interpreter::evaluate(Expression const& _expression) { - ExpressionEvaluator ev(m_state, m_dialect, *m_scope, m_variables, m_disableExternalCalls, m_disableMemoryTrace); + ExpressionEvaluator ev(m_state, m_yulNameRepository, *m_scope, m_variables, m_disableExternalCalls, m_disableMemoryTrace); ev.visit(_expression); return ev.value(); } std::vector Interpreter::evaluateMulti(Expression const& _expression) { - ExpressionEvaluator ev(m_state, m_dialect, *m_scope, m_variables, m_disableExternalCalls, m_disableMemoryTrace); + ExpressionEvaluator ev(m_state, m_yulNameRepository, *m_scope, m_variables, m_disableExternalCalls, m_disableMemoryTrace); ev.visit(_expression); return ev.values(); } @@ -309,29 +309,25 @@ void ExpressionEvaluator::operator()(Identifier const& _identifier) void ExpressionEvaluator::operator()(FunctionCall const& _funCall) { std::vector> const* literalArguments = nullptr; - if (BuiltinFunction const* builtin = m_dialect.builtin(_funCall.functionName.name)) - if (!builtin->literalArguments.empty()) - literalArguments = &builtin->literalArguments; + if (auto const* builtin = m_yulNameRepository.builtin(_funCall.functionName.name)) + if (!builtin->data->literalArguments.empty()) + literalArguments = &builtin->data->literalArguments; evaluateArgs(_funCall.arguments, literalArguments); - if (EVMDialect const* dialect = dynamic_cast(&m_dialect)) + if (EVMDialect const* dialect = dynamic_cast(&m_yulNameRepository.dialect())) { - if (BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name)) - { - EVMInstructionInterpreter interpreter(dialect->evmVersion(), m_state, m_disableMemoryTrace); - - u256 const value = interpreter.evalBuiltin(*fun, _funCall.arguments, values()); + if (auto const* fun = m_yulNameRepository.builtin(_funCall.functionName.name)) + if(auto const* evmFun = dynamic_cast(fun->data)) + { + EVMInstructionInterpreter interpreter(dialect->evmVersion(), m_state, m_disableMemoryTrace); + u256 const value = interpreter.evalBuiltin(*evmFun, _funCall.arguments, values()); - if ( - !m_disableExternalCalls && - fun->instruction && - evmasm::isCallInstruction(*fun->instruction) - ) - runExternalCall(*fun->instruction); + if (!m_disableExternalCalls && evmFun->instruction && evmasm::isCallInstruction(*evmFun->instruction)) + runExternalCall(*evmFun->instruction); - setValue(value); - return; - } + setValue(value); + return; + } } Scope* scope = &m_scope; @@ -343,7 +339,7 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall) FunctionDefinition const* fun = scope->names.at(_funCall.functionName.name); yulAssert(fun, "Function not found."); yulAssert(m_values.size() == fun->parameters.size(), ""); - std::map variables; + std::map variables; for (size_t i = 0; i < fun->parameters.size(); ++i) variables[fun->parameters.at(i).name] = m_values.at(i); for (size_t i = 0; i < fun->returnVariables.size(); ++i) diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h index 23a98ca5c350..b37d026952d0 100644 --- a/test/tools/yulInterpreter/Interpreter.h +++ b/test/tools/yulInterpreter/Interpreter.h @@ -145,7 +145,7 @@ struct InterpreterState struct Scope { /// Used for variables and functions. Value is nullptr for variables. - std::map names; + std::map names; std::map> subScopes; Scope* parent = nullptr; }; @@ -162,7 +162,7 @@ class Interpreter: public ASTWalker /// activated e.g., Redundant store eliminator, Equal store eliminator. static void run( InterpreterState& _state, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Block const& _ast, bool _disableExternalCalls, bool _disableMemoryTracing @@ -170,13 +170,13 @@ class Interpreter: public ASTWalker Interpreter( InterpreterState& _state, - Dialect const& _dialect, + YulNameRepository const& _yulNameRepository, Scope& _scope, bool _disableExternalCalls, bool _disableMemoryTracing, - std::map _variables = {} + std::map _variables = {} ): - m_dialect(_dialect), + m_yulNameRepository(_yulNameRepository), m_state(_state), m_variables(std::move(_variables)), m_scope(&_scope), @@ -200,7 +200,7 @@ class Interpreter: public ASTWalker bytes returnData() const { return m_state.returndata; } std::vector const& trace() const { return m_state.trace; } - u256 valueOfVariable(YulString _name) const { return m_variables.at(_name); } + u256 valueOfVariable(YulName _name) const { return m_variables.at(_name); } protected: /// Asserts that the expression evaluates to exactly one value and returns it. @@ -215,10 +215,10 @@ class Interpreter: public ASTWalker /// is reached. void incrementStep(); - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; InterpreterState& m_state; /// Values of variables. - std::map m_variables; + std::map m_variables; Scope* m_scope; /// If not set, external calls (e.g. using `call()`) to the same contract /// are evaluated in a new parser instance. @@ -234,14 +234,14 @@ class ExpressionEvaluator: public ASTWalker public: ExpressionEvaluator( InterpreterState& _state, - Dialect const& _dialect, + YulNameRepository const& m_yulNameRepository, Scope& _scope, - std::map const& _variables, + std::map const& _variables, bool _disableExternalCalls, bool _disableMemoryTrace ): m_state(_state), - m_dialect(_dialect), + m_yulNameRepository(m_yulNameRepository), m_variables(_variables), m_scope(_scope), m_disableExternalCalls(_disableExternalCalls), @@ -259,11 +259,11 @@ class ExpressionEvaluator: public ASTWalker protected: void runExternalCall(evmasm::Instruction _instruction); - virtual std::unique_ptr makeInterpreterCopy(std::map _variables = {}) const + virtual std::unique_ptr makeInterpreterCopy(std::map _variables = {}) const { return std::make_unique( m_state, - m_dialect, + m_yulNameRepository, m_scope, m_disableExternalCalls, m_disableMemoryTrace, @@ -274,7 +274,7 @@ class ExpressionEvaluator: public ASTWalker { return std::make_unique( _state, - m_dialect, + m_yulNameRepository, _scope, m_disableExternalCalls, m_disableMemoryTrace @@ -296,9 +296,9 @@ class ExpressionEvaluator: public ASTWalker void incrementStep(); InterpreterState& m_state; - Dialect const& m_dialect; + YulNameRepository const& m_yulNameRepository; /// Values of variables. - std::map const& m_variables; + std::map const& m_variables; Scope& m_scope; /// Current value of the expression std::vector m_values; diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index d16b1da1969b..52b7e9d345d2 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -92,7 +92,7 @@ class YulOpti CharStream _charStream(_input, ""); try { - m_ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); + m_ast = yul::Parser(errorReporter, m_yulNameRepository).parse(_charStream); if (!m_ast || !errorReporter.errors().empty()) { std::cerr << "Error parsing source." << std::endl; @@ -103,7 +103,7 @@ class YulOpti AsmAnalyzer analyzer( *m_analysisInfo, errorReporter, - m_dialect + m_yulNameRepository ); if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) { @@ -171,9 +171,8 @@ class YulOpti void disambiguate() { - *m_ast = std::get(Disambiguator(m_dialect, *m_analysisInfo)(*m_ast)); + *m_ast = std::get(Disambiguator(m_yulNameRepository, *m_analysisInfo)(*m_ast)); m_analysisInfo.reset(); - m_nameDispenser.reset(*m_ast); } void runSteps(std::string _source, std::string _steps) @@ -181,7 +180,7 @@ class YulOpti parse(_source); disambiguate(); OptimiserSuite{m_context}.runSequence(_steps, *m_ast); - std::cout << AsmPrinter{m_dialect}(*m_ast) << std::endl; + std::cout << AsmPrinter{m_yulNameRepository}(*m_ast) << std::endl; } void runInteractive(std::string _source, bool _disambiguated = false) @@ -212,7 +211,7 @@ class YulOpti case '#': return; case ',': - VarNameCleaner::run(m_context, *m_ast); + // VarNameCleaner::run(m_context, *m_ast); // VarNameCleaner destroys the unique names guarantee of the disambiguator. disambiguated = false; break; @@ -220,7 +219,7 @@ class YulOpti { Object obj; obj.code = m_ast; - StackCompressor::run(m_dialect, obj, true, 16); + StackCompressor::run(m_yulNameRepository, obj, true, 16); break; } default: @@ -229,7 +228,8 @@ class YulOpti *m_ast ); } - _source = AsmPrinter{m_dialect}(*m_ast); + m_yulNameRepository.generateLabels(*m_ast); + _source = AsmPrinter{m_yulNameRepository}(*m_ast); } catch (...) { @@ -243,13 +243,12 @@ class YulOpti private: std::shared_ptr m_ast; - Dialect const& m_dialect{EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; + YulNameRepository m_yulNameRepository {EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; std::unique_ptr m_analysisInfo; - std::set const m_reservedIdentifiers = {}; - NameDispenser m_nameDispenser{m_dialect, m_reservedIdentifiers}; + std::set const m_reservedIdentifiers = {}; OptimiserStepContext m_context{ - m_dialect, - m_nameDispenser, + m_yulNameRepository.dialect(), + m_yulNameRepository, m_reservedIdentifiers, solidity::frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }; diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index fb18b4e598ee..df82f483b198 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -88,12 +88,13 @@ void interpret(std::string const& _source, bool _inspect, bool _disableExternalC try { Dialect const& dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{})); + YulNameRepository repository (dialect); if (_inspect) - InspectedInterpreter::run(std::make_shared(_source, state), state, dialect, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); + InspectedInterpreter::run(std::make_shared(_source, state, repository), state, repository, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); else - Interpreter::run(state, dialect, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); + Interpreter::run(state, repository, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); } catch (InterpreterTerminatedGeneric const&) { diff --git a/test/yulPhaser/Program.cpp b/test/yulPhaser/Program.cpp index 018de32ee2e7..97813949b122 100644 --- a/test/yulPhaser/Program.cpp +++ b/test/yulPhaser/Program.cpp @@ -76,6 +76,8 @@ BOOST_AUTO_TEST_CASE(copy_constructor_should_make_deep_copy_of_ast) // There might be a more direct way to compare ASTs but converting to JSON should be good enough // as long as the conversion is deterministic. A very nice side effect of doing it this way is // that BOOST_TEST will print the complete AST structure of both programs in case of a mismatch. + program.toJson(); + programCopy.toJson(); BOOST_TEST(programCopy.toJson() == program.toJson()); } @@ -119,8 +121,9 @@ BOOST_AUTO_TEST_CASE(load_should_disambiguate) VariableDeclaration const& declaration1 = get(innerBlock1.statements[0]); VariableDeclaration const& declaration2 = get(innerBlock2.statements[0]); - BOOST_TEST(declaration1.variables[0].name.str() == "x"); - BOOST_TEST(declaration2.variables[0].name.str() != "x"); + BOOST_TEST(declaration1.variables[0].name != declaration2.variables[0].name); + BOOST_TEST(program.nameRepository().labelOf(declaration1.variables[0].name) == "x"); + BOOST_TEST(program.nameRepository().labelOf(declaration2.variables[0].name) != "x"); } BOOST_AUTO_TEST_CASE(load_should_do_function_grouping_and_hoisting) @@ -344,7 +347,7 @@ BOOST_AUTO_TEST_CASE(optimise) BOOST_AUTO_TEST_CASE(output_operator) { - std::string sourceCode( + std::string const sourceCode( "{\n" " let factor := 13\n" " {\n" diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 00abcc8e5c31..489f01e0ae15 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -60,8 +60,7 @@ std::ostream& operator<<(std::ostream& _stream, Program const& _program); Program::Program(Program const& program): m_ast(std::make_unique(std::get(ASTCopier{}(*program.m_ast)))), - m_dialect{program.m_dialect}, - m_nameDispenser(program.m_nameDispenser) + m_yulNameRepository(std::make_unique(*program.m_yulNameRepository)) { } @@ -69,58 +68,67 @@ std::variant Program::load(CharStream& _sourceCode) { // ASSUMPTION: parseSource() rewinds the stream on its own Dialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}); + auto nameRepository = std::make_unique(dialect); - std::variant, ErrorList> astOrErrors = parseObject(dialect, _sourceCode); + std::variant, ErrorList> astOrErrors = parseObject(*nameRepository, _sourceCode); if (std::holds_alternative(astOrErrors)) return std::get(astOrErrors); std::variant, ErrorList> analysisInfoOrErrors = analyzeAST( - dialect, + *nameRepository, *std::get>(astOrErrors) ); if (std::holds_alternative(analysisInfoOrErrors)) return std::get(analysisInfoOrErrors); + auto ast = disambiguateAST( + *nameRepository, + *std::get>(astOrErrors), + *std::get>(analysisInfoOrErrors) + ); Program program( - dialect, - disambiguateAST( - dialect, - *std::get>(astOrErrors), - *std::get>(analysisInfoOrErrors) - ) + std::move(nameRepository), + std::move(ast) ); program.optimise({ FunctionHoister::name, FunctionGrouper::name, ForLoopInitRewriter::name, }); + program.m_yulNameRepository->generateLabels(*program.m_ast); return program; } void Program::optimise(std::vector const& _optimisationSteps) { - m_ast = applyOptimisationSteps(m_dialect, m_nameDispenser, std::move(m_ast), _optimisationSteps); + m_ast = applyOptimisationSteps(*m_yulNameRepository, std::move(m_ast), _optimisationSteps); } std::ostream& phaser::operator<<(std::ostream& _stream, Program const& _program) { - return _stream << AsmPrinter()(*_program.m_ast); + _program.m_yulNameRepository->generateLabels(*_program.m_ast); + return _stream << AsmPrinter(*_program.m_yulNameRepository)(*_program.m_ast); } std::string Program::toJson() const { - Json serializedAst = AsmJsonConverter(0)(*m_ast); + Json serializedAst = AsmJsonConverter(0, *m_yulNameRepository)(*m_ast); return jsonPrettyPrint(removeNullMembers(std::move(serializedAst))); } -std::variant, ErrorList> Program::parseObject(Dialect const& _dialect, CharStream _source) +yul::YulNameRepository const& Program::nameRepository() const +{ + return *m_yulNameRepository; +} + +std::variant, ErrorList> Program::parseObject(yul::YulNameRepository& _yulNameRepository, CharStream _source) { ErrorList errors; ErrorReporter errorReporter(errors); auto scanner = std::make_shared(_source); - ObjectParser parser(errorReporter, _dialect); + ObjectParser parser(errorReporter, _yulNameRepository); std::shared_ptr object = parser.parse(scanner, false); if (object == nullptr || !errorReporter.errors().empty()) // NOTE: It's possible to get errors even if the returned object is non-null. @@ -154,12 +162,12 @@ std::variant, ErrorList> Program::parseObject(Dialect con return std::variant, ErrorList>(std::move(astCopy)); } -std::variant, ErrorList> Program::analyzeAST(Dialect const& _dialect, Block const& _ast) +std::variant, ErrorList> Program::analyzeAST(yul::YulNameRepository const& _yulNameRepository, Block const& _ast) { ErrorList errors; ErrorReporter errorReporter(errors); auto analysisInfo = std::make_unique(); - AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect); + AsmAnalyzer analyzer(*analysisInfo, errorReporter, _yulNameRepository); bool analysisSuccessful = analyzer.analyze(_ast); if (!analysisSuccessful) @@ -170,30 +178,29 @@ std::variant, ErrorList> Program::analyzeAST(Di } std::unique_ptr Program::disambiguateAST( - Dialect const& _dialect, + yul::YulNameRepository& _yulNameRepository, Block const& _ast, AsmAnalysisInfo const& _analysisInfo ) { - std::set const externallyUsedIdentifiers = {}; - Disambiguator disambiguator(_dialect, _analysisInfo, externallyUsedIdentifiers); + std::set const externallyUsedIdentifiers = {}; + Disambiguator disambiguator(_yulNameRepository, _analysisInfo, externallyUsedIdentifiers); return std::make_unique(std::get(disambiguator(_ast))); } std::unique_ptr Program::applyOptimisationSteps( - Dialect const& _dialect, - NameDispenser& _nameDispenser, + yul::YulNameRepository& _yulNameRepository, std::unique_ptr _ast, std::vector const& _optimisationSteps ) { // An empty set of reserved identifiers. It could be a constructor parameter but I don't // think it would be useful in this tool. Other tools (like yulopti) have it empty too. - std::set const externallyUsedIdentifiers = {}; + std::set const externallyUsedIdentifiers = {}; OptimiserStepContext context{ - _dialect, - _nameDispenser, + _yulNameRepository.dialect(), + _yulNameRepository, externallyUsedIdentifiers, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }; diff --git a/tools/yulPhaser/Program.h b/tools/yulPhaser/Program.h index e42471d77947..b0d6e8a13abe 100644 --- a/tools/yulPhaser/Program.h +++ b/tools/yulPhaser/Program.h @@ -18,7 +18,6 @@ #pragma once -#include #include #include @@ -66,8 +65,7 @@ class Program Program(Program const& program); Program(Program&& program): m_ast(std::move(program.m_ast)), - m_dialect{program.m_dialect}, - m_nameDispenser(std::move(program.m_nameDispenser)) + m_yulNameRepository(std::move(program.m_yulNameRepository)) {} Program operator=(Program const& program) = delete; Program operator=(Program&& program) = delete; @@ -81,40 +79,39 @@ class Program friend std::ostream& operator<<(std::ostream& _stream, Program const& _program); std::string toJson() const; + yul::YulNameRepository const& nameRepository() const; + private: Program( - yul::Dialect const& _dialect, + std::unique_ptr _yulNameRepository, std::unique_ptr _ast ): m_ast(std::move(_ast)), - m_dialect{_dialect}, - m_nameDispenser(_dialect, *m_ast, {}) + m_yulNameRepository(std::move(_yulNameRepository)) {} static std::variant, langutil::ErrorList> parseObject( - yul::Dialect const& _dialect, + yul::YulNameRepository& _yulNameRepository, langutil::CharStream _source ); static std::variant, langutil::ErrorList> analyzeAST( - yul::Dialect const& _dialect, + yul::YulNameRepository const& _yulNameRepository, yul::Block const& _ast ); static std::unique_ptr disambiguateAST( - yul::Dialect const& _dialect, + yul::YulNameRepository& _yulNameRepository, yul::Block const& _ast, yul::AsmAnalysisInfo const& _analysisInfo ); static std::unique_ptr applyOptimisationSteps( - yul::Dialect const& _dialect, - yul::NameDispenser& _nameDispenser, + yul::YulNameRepository& _yulNameRepository, std::unique_ptr _ast, std::vector const& _optimisationSteps ); static size_t computeCodeSize(yul::Block const& _ast, yul::CodeWeights const& _weights); std::unique_ptr m_ast; - yul::Dialect const& m_dialect; - yul::NameDispenser m_nameDispenser; + std::unique_ptr m_yulNameRepository; }; } From 40f8435b558edcefae8367ea5e7d1982de80ed89 Mon Sep 17 00:00:00 2001 From: clonker Date: Tue, 2 Jul 2024 13:45:26 +0200 Subject: [PATCH 03/15] remove yulstring and yulstringrepository --- libsolc/libsolc.cpp | 2 - libsolidity/codegen/CompilerContext.cpp | 1 - libsolidity/codegen/ContractCompiler.cpp | 1 - libsolidity/interface/CompilerStack.cpp | 1 - libsolidity/interface/StandardCompiler.cpp | 4 +- libyul/AST.h | 1 - libyul/AsmAnalysis.cpp | 2 +- libyul/AsmAnalysis.h | 4 +- libyul/AsmPrinter.h | 1 - libyul/CMakeLists.txt | 3 - libyul/Dialect.cpp | 1 - libyul/Dialect.h | 1 - libyul/Exceptions.h | 1 - libyul/Object.cpp | 42 ++-- libyul/Object.h | 11 +- libyul/ObjectParser.cpp | 14 +- libyul/ObjectParser.h | 5 +- libyul/YulStack.cpp | 2 +- libyul/YulString.h | 200 ------------------ libyul/backends/evm/ConstantOptimiser.h | 1 - libyul/backends/evm/EVMDialect.cpp | 11 +- libyul/backends/evm/EVMDialect.h | 3 +- libyul/backends/evm/EVMObjectCompiler.cpp | 6 +- libyul/optimiser/ASTWalker.h | 1 - libyul/optimiser/BlockHasher.h | 1 - libyul/optimiser/DataFlowAnalyzer.h | 1 - libyul/optimiser/DeadCodeEliminator.h | 1 - libyul/optimiser/OptimiserStep.h | 1 - libyul/optimiser/OptimizerUtilities.cpp | 6 - libyul/optimiser/OptimizerUtilities.h | 5 - libyul/optimiser/Substitution.h | 1 - libyul/optimiser/Suite.cpp | 1 - libyul/optimiser/Suite.h | 1 - .../UnusedFunctionParameterPruner.cpp | 1 - libyul/optimiser/UnusedPruner.h | 1 - libyul/optimiser/VarNameCleaner.cpp | 126 ----------- libyul/optimiser/VarNameCleaner.h | 101 --------- test/libsolidity/MemoryGuardTest.cpp | 2 +- test/libyul/YulOptimizerTestCommon.cpp | 1 - test/libyul/YulOptimizerTestCommon.h | 2 - .../ossfuzz/strictasm_assembly_ossfuzz.cpp | 2 - test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 2 - test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp | 2 - .../EVMInstructionInterpreter.h | 1 - test/tools/yulopti.cpp | 1 - tools/yulPhaser/Program.cpp | 3 +- 46 files changed, 50 insertions(+), 532 deletions(-) delete mode 100644 libyul/YulString.h delete mode 100644 libyul/optimiser/VarNameCleaner.cpp delete mode 100644 libyul/optimiser/VarNameCleaner.h diff --git a/libsolc/libsolc.cpp b/libsolc/libsolc.cpp index 105949253260..1b8555775278 100644 --- a/libsolc/libsolc.cpp +++ b/libsolc/libsolc.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -153,7 +152,6 @@ extern void solidity_reset() noexcept { // This is called right before each compilation, but not at the end, so additional memory // can be freed here. - yul::YulStringRepository::reset(); solidityAllocations.clear(); } } diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 3a0d19e9a563..bdbe70369466 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index c4707d29f460..ecb23b8092d0 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 603fef445181..30ea615b8716 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -66,7 +66,6 @@ #include -#include #include #include #include diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 5510b543077c..7adeb8950c62 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -1638,7 +1638,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) return output; } - std::string contractName = stack.parserResult()->name.str(); + std::string const& contractName = stack.parserResult()->name; bool const wildcardMatchesExperimental = true; if (isArtifactRequested(_inputsAndSettings.outputSelection, sourceName, contractName, "ir", wildcardMatchesExperimental)) @@ -1700,8 +1700,6 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings) Json StandardCompiler::compile(Json const& _input) noexcept { - YulStringRepository::reset(); - try { auto parsed = parseInput(_input); diff --git a/libyul/AST.h b/libyul/AST.h index ad28cfa59937..fb3723326635 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -25,7 +25,6 @@ #include #include -#include #include diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index a27260d93ae9..5eb2e7cddc34 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -440,7 +440,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) if (functionName == m_yulNameRepository.predefined().datasize || functionName == m_yulNameRepository.predefined().dataoffset) { auto const& argumentAsLiteral = std::get(arg); - if (!m_dataNames.count(YulString(formatLiteral(argumentAsLiteral)))) + if (!m_dataNames.count(formatLiteral(argumentAsLiteral))) m_errorReporter.typeError( 3517_error, nativeLocationOf(arg), diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 00c5fc8e4446..a58a5a6c9e28 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -61,7 +61,7 @@ class AsmAnalyzer langutil::ErrorReporter& _errorReporter, YulNameRepository const& _yulNameRepository, ExternalIdentifierAccess::Resolver _resolver = ExternalIdentifierAccess::Resolver(), - std::set _dataNames = {} + std::set _dataNames = {} ): m_resolver(std::move(_resolver)), m_info(_analysisInfo), @@ -128,7 +128,7 @@ class AsmAnalyzer langutil::EVMVersion m_evmVersion; YulNameRepository const& m_yulNameRepository; /// Names of data objects to be referenced by builtin functions with literal arguments. - std::set m_dataNames; + std::set m_dataNames; ForLoop const* m_currentForLoop = nullptr; /// Worst side effects encountered during analysis (including within defined functions). SideEffects m_sideEffects; diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index bd6a54a361c2..89381abd6c2d 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -24,7 +24,6 @@ #pragma once #include -#include #include #include diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index b45be894d98e..0aa3ea86d53e 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -39,7 +39,6 @@ add_library(yul Utilities.h YulName.cpp YulName.h - YulString.h YulName.cpp YulName.h backends/evm/AbstractAssembly.h @@ -184,8 +183,6 @@ add_library(yul optimiser/UnusedPruner.h optimiser/VarDeclInitializer.cpp optimiser/VarDeclInitializer.h - optimiser/VarNameCleaner.cpp - optimiser/VarNameCleaner.h ) target_link_libraries(yul PUBLIC evmasm solutil langutil smtutil fmt::fmt-header-only) diff --git a/libyul/Dialect.cpp b/libyul/Dialect.cpp index 054c999c7a96..b50ed742231b 100644 --- a/libyul/Dialect.cpp +++ b/libyul/Dialect.cpp @@ -52,7 +52,6 @@ bool Dialect::validTypeForLiteral(LiteralKind _kind, LiteralValue const&, Type _ Dialect const& Dialect::yulDeprecated() { static std::unique_ptr dialect; - static YulStringRepository::ResetCallback callback{[&] { dialect.reset(); }}; if (!dialect) { diff --git a/libyul/Dialect.h b/libyul/Dialect.h index c6f873db7de3..361077322407 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -32,7 +32,6 @@ namespace solidity::yul { -class YulString; enum class LiteralKind; class LiteralValue; struct Literal; diff --git a/libyul/Exceptions.h b/libyul/Exceptions.h index 4f7569b73812..59a806fb0674 100644 --- a/libyul/Exceptions.h +++ b/libyul/Exceptions.h @@ -24,7 +24,6 @@ #include #include -#include #include #include diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 59ace66da38c..bdc9a97b7880 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -40,7 +40,7 @@ using namespace solidity::yul; std::string Data::toString(YulNameRepository const&, AsmPrinter::Mode, DebugInfoSelection const&, CharStreamProvider const*) const { - return "data \"" + name.str() + "\" hex\"" + util::toHex(data) + "\""; + return "data \"" + name + "\" hex\"" + util::toHex(data) + "\""; } std::string Object::toString( @@ -74,7 +74,7 @@ std::string Object::toString( for (auto const& obj: subObjects) inner += "\n" + obj->toString(_yulNameRepository, _printingMode, _debugInfoSelection, _soliditySourceProvider); - return useSrcComment + "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; + return useSrcComment + "object \"" + name + "\" {\n" + indent(inner) + "\n}"; } Json Data::toJson(YulNameRepository const&) const @@ -98,63 +98,63 @@ Json Object::toJson(YulNameRepository const& _yulNameRepository) const Json ret; ret["nodeType"] = "YulObject"; - ret["name"] = name.str(); + ret["name"] = name; codeJson["nodeType"] = "YulCode"; ret["code"] = codeJson; ret["subObjects"] = subObjectsJson; return ret; } -std::set Object::qualifiedDataNames() const +std::set Object::qualifiedDataNames() const { - std::set qualifiedNames = - name.empty() || util::contains(name.str(), '.') ? - std::set{} : - std::set{name}; + std::set qualifiedNames = + name.empty() || util::contains(name, '.') ? + std::set{} : + std::set{name}; for (std::shared_ptr const& subObjectNode: subObjects) { yulAssert(qualifiedNames.count(subObjectNode->name) == 0, ""); - if (util::contains(subObjectNode->name.str(), '.')) + if (util::contains(subObjectNode->name, '.')) continue; qualifiedNames.insert(subObjectNode->name); if (auto const* subObject = dynamic_cast(subObjectNode.get())) - for (YulString const& subSubObj: subObject->qualifiedDataNames()) + for (auto const& subSubObj: subObject->qualifiedDataNames()) if (subObject->name != subSubObj) { - yulAssert(qualifiedNames.count(YulString{subObject->name.str() + "." + subSubObj.str()}) == 0, ""); - qualifiedNames.insert(YulString{subObject->name.str() + "." + subSubObj.str()}); + yulAssert(qualifiedNames.count(subObject->name + "." + subSubObj) == 0, ""); + qualifiedNames.insert(subObject->name + "." + subSubObj); } } - yulAssert(qualifiedNames.count(YulString{}) == 0, ""); - qualifiedNames.erase(YulString{}); + yulAssert(qualifiedNames.count("") == 0, ""); + qualifiedNames.erase(""); return qualifiedNames; } -std::vector Object::pathToSubObject(YulString _qualifiedName) const +std::vector Object::pathToSubObject(std::string_view _qualifiedName) const { yulAssert(_qualifiedName != name, ""); yulAssert(subIndexByName.count(name) == 0, ""); - if (boost::algorithm::starts_with(_qualifiedName.str(), name.str() + ".")) - _qualifiedName = YulString{_qualifiedName.str().substr(name.str().length() + 1)}; + if (boost::algorithm::starts_with(_qualifiedName, name + ".")) + _qualifiedName = _qualifiedName.substr(name.length() + 1); yulAssert(!_qualifiedName.empty(), ""); std::vector subObjectPathComponents; - boost::algorithm::split(subObjectPathComponents, _qualifiedName.str(), boost::is_any_of(".")); + boost::algorithm::split(subObjectPathComponents, _qualifiedName, boost::is_any_of(".")); std::vector path; Object const* object = this; for (std::string const& currentSubObjectName: subObjectPathComponents) { yulAssert(!currentSubObjectName.empty(), ""); - auto subIndexIt = object->subIndexByName.find(YulString{currentSubObjectName}); + auto subIndexIt = object->subIndexByName.find(currentSubObjectName); yulAssert( subIndexIt != object->subIndexByName.end(), - "Assembly object <" + _qualifiedName.str() + "> not found or does not contain code." + "Assembly object <" + std::string(_qualifiedName) + "> not found or does not contain code." ); object = dynamic_cast(object->subObjects[subIndexIt->second].get()); - yulAssert(object, "Assembly object <" + _qualifiedName.str() + "> not found or does not contain code."); + yulAssert(object, "Assembly object <" + std::string(_qualifiedName) + "> not found or does not contain code."); yulAssert(object->subId != std::numeric_limits::max(), ""); path.push_back({object->subId}); } diff --git a/libyul/Object.h b/libyul/Object.h index 711b1e628126..83780b38bd39 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -54,7 +53,7 @@ struct ObjectNode /// Name of the object. /// Can be empty since .yul files can also just contain code, without explicitly placing it in an object. - YulString name; + std::string name; virtual std::string toString( YulNameRepository const& _yulNameRepository, AsmPrinter::Mode printingMode, @@ -69,7 +68,7 @@ struct ObjectNode */ struct Data: public ObjectNode { - Data(YulString _name, bytes _data): data(std::move(_data)) { name = _name; } + Data(std::string _name, bytes _data): data(std::move(_data)) { name = _name; } bytes data; @@ -107,7 +106,7 @@ struct Object: public ObjectNode /// @returns the set of names of data objects accessible from within the code of /// this object, including the name of object itself /// Handles all names containing dots as reserved identifiers, not accessible as data. - std::set qualifiedDataNames() const; + std::set qualifiedDataNames() const; /// @returns vector of subIDs if possible to reach subobject with @a _qualifiedName, throws otherwise /// For "B.C" should return vector of two values if success (subId of B and subId of C in B). @@ -119,14 +118,14 @@ struct Object: public ObjectNode /// pathToSubObject("E2.F3.H4") == {1, 0, 2} /// pathToSubObject("A1.E2") == {1} /// The path must not lead to a @a Data object (will throw in that case). - std::vector pathToSubObject(YulString _qualifiedName) const; + std::vector pathToSubObject(std::string_view _qualifiedName) const; /// sub id for object if it is subobject of another object, max value if it is not subobject size_t subId = std::numeric_limits::max(); std::shared_ptr code; std::vector> subObjects; - std::map subIndexByName; + std::map> subIndexByName; std::shared_ptr analysisInfo; std::shared_ptr debugData; diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index dcc71194e2c1..798568a18bdd 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -50,7 +50,7 @@ std::shared_ptr ObjectParser::parse(std::shared_ptr const& _sca { // Special case: Code-only form. object = std::make_shared(); - object->name = "object"_yulstring; + object->name = "object"; auto sourceNameMapping = tryParseSourceNameMapping(); object->debugData = std::make_shared(ObjectDebugData{sourceNameMapping}); object->code = parseBlock(sourceNameMapping); @@ -185,7 +185,7 @@ void ObjectParser::parseData(Object& _containingObject) ); advance(); - YulString name = parseUniqueName(&_containingObject); + auto const name = parseUniqueName(&_containingObject); if (currentToken() == Token::HexStringLiteral) expectToken(Token::HexStringLiteral, false); @@ -195,22 +195,22 @@ void ObjectParser::parseData(Object& _containingObject) advance(); } -YulString ObjectParser::parseUniqueName(Object const* _containingObject) +std::string ObjectParser::parseUniqueName(Object const* _containingObject) { expectToken(Token::StringLiteral, false); - YulString name{currentLiteral()}; + auto const name = currentLiteral(); if (name.empty()) parserError(3287_error, "Object name cannot be empty."); else if (_containingObject && _containingObject->name == name) parserError(8311_error, "Object name cannot be the same as the name of the containing object."); else if (_containingObject && _containingObject->subIndexByName.count(name)) - parserError(8794_error, "Object name \"" + name.str() + "\" already exists inside the containing object."); + parserError(8794_error, "Object name \"" + name + "\" already exists inside the containing object."); advance(); return name; } -void ObjectParser::addNamedSubObject(Object& _container, YulString _name, std::shared_ptr _subObject) +void ObjectParser::addNamedSubObject(Object& _container, std::string_view const _name, std::shared_ptr _subObject) { - _container.subIndexByName[_name] = _container.subObjects.size(); + _container.subIndexByName.emplace(std::piecewise_construct, std::forward_as_tuple(_name), std::forward_as_tuple(_container.subObjects.size())); _container.subObjects.emplace_back(std::move(_subObject)); } diff --git a/libyul/ObjectParser.h b/libyul/ObjectParser.h index 836cb0cb8d90..f06f0b5850d8 100644 --- a/libyul/ObjectParser.h +++ b/libyul/ObjectParser.h @@ -21,7 +21,6 @@ #pragma once -#include #include #include @@ -63,8 +62,8 @@ class ObjectParser: public langutil::ParserBase void parseData(Object& _containingObject); /// Tries to parse a name that is non-empty and unique inside the containing object. - YulString parseUniqueName(Object const* _containingObject); - void addNamedSubObject(Object& _container, YulString _name, std::shared_ptr _subObject); + std::string parseUniqueName(Object const* _containingObject); + void addNamedSubObject(Object& _container, std::string_view _name, std::shared_ptr _subObject); YulNameRepository& m_yulNameRepository; }; diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 4536619ace03..71a0de2232bb 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -200,7 +200,7 @@ void YulStack::optimize(Object& _object, bool _isCreation) for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) { - bool isCreation = !boost::ends_with(subObject->name.str(), "_deployed"); + bool isCreation = !boost::ends_with(subObject->name, "_deployed"); optimize(*subObject, isCreation); } diff --git a/libyul/YulString.h b/libyul/YulString.h deleted file mode 100644 index 7dbaf1b84a03..000000000000 --- a/libyul/YulString.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - 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 -/** - * String abstraction that avoids copies. - */ - -#pragma once - -#include - -#include -#include -#include -#include -#include - -namespace solidity::yul -{ - -/// Repository for YulStrings. -/// Owns the string data for all YulStrings, which can be referenced by a Handle. -/// A Handle consists of an ID (that depends on the insertion order of YulStrings and is potentially -/// non-deterministic) and a deterministic string hash. -class YulStringRepository -{ -public: - struct Handle - { - size_t id; - std::uint64_t hash; - }; - - static YulStringRepository& instance() - { - static YulStringRepository inst; - return inst; - } - - Handle stringToHandle(std::string const& _string) - { - if (_string.empty()) - return { 0, emptyHash() }; - std::uint64_t h = hash(_string); - auto range = m_hashToID.equal_range(h); - for (auto it = range.first; it != range.second; ++it) - if (*m_strings[it->second] == _string) - return Handle{it->second, h}; - m_strings.emplace_back(std::make_shared(_string)); - size_t id = m_strings.size() - 1; - m_hashToID.emplace_hint(range.second, std::make_pair(h, id)); - - return Handle{id, h}; - } - std::string const& idToString(size_t _id) const { return *m_strings.at(_id); } - - static std::uint64_t hash(std::string const& v) - { - // FNV hash - can be replaced by a better one, e.g. xxhash64 - std::uint64_t hash = emptyHash(); - for (char c: v) - { - hash *= 1099511628211u; - hash ^= static_cast(c); - } - - return hash; - } - static constexpr std::uint64_t emptyHash() { return 14695981039346656037u; } - /// Clear the repository. - /// Use with care - there cannot be any dangling YulString references. - /// If references need to be cleared manually, register the callback via - /// resetCallback. - static void reset() - { - for (auto const& cb: resetCallbacks()) - cb(); - instance() = YulStringRepository{}; - } - /// Struct that registers a reset callback as a side-effect of its construction. - /// Useful as static local variable to register a reset callback once. - struct ResetCallback - { - ResetCallback(std::function _fun) - { - YulStringRepository::resetCallbacks().emplace_back(std::move(_fun)); - } - }; - -private: - YulStringRepository() = default; - YulStringRepository(YulStringRepository const&) = delete; - YulStringRepository(YulStringRepository&&) = default; - YulStringRepository& operator=(YulStringRepository const& _rhs) = delete; - YulStringRepository& operator=(YulStringRepository&& _rhs) = default; - - static std::vector>& resetCallbacks() - { - static std::vector> callbacks; - return callbacks; - } - - std::vector> m_strings = {std::make_shared()}; - std::unordered_multimap m_hashToID = {{emptyHash(), 0}}; -}; - -/// Wrapper around handles into the YulString repository. -/// Equality of two YulStrings is determined by comparing their ID. -/// The <-operator depends on the string hash and is not consistent -/// with string comparisons (however, it is still deterministic). -class YulString -{ -public: - YulString() = default; - explicit YulString(std::string const& _s): m_handle(YulStringRepository::instance().stringToHandle(_s)) {} - YulString(YulString const&) = default; - YulString(YulString&&) = default; - YulString& operator=(YulString const&) = default; - YulString& operator=(YulString&&) = default; - - /// This is not consistent with the string <-operator! - /// First compares the string hashes. If they are equal - /// it checks for identical IDs (only identical strings have - /// identical IDs and identical strings do not compare as "less"). - /// If the hashes are identical and the strings are distinct, it - /// falls back to string comparison. - bool operator<(YulString const& _other) const - { - if (m_handle.hash < _other.m_handle.hash) return true; - if (_other.m_handle.hash < m_handle.hash) return false; - if (m_handle.id == _other.m_handle.id) return false; - return str() < _other.str(); - } - /// Equality is determined based on the string ID. - bool operator==(YulString const& _other) const { return m_handle.id == _other.m_handle.id; } - bool operator!=(YulString const& _other) const { return m_handle.id != _other.m_handle.id; } - - bool empty() const { return m_handle.id == 0; } - std::string const& str() const - { - return YulStringRepository::instance().idToString(m_handle.id); - } - - uint64_t hash() const { return m_handle.hash; } - -private: - /// Handle of the string. Assumes that the empty string has ID zero. - YulStringRepository::Handle m_handle{ 0, YulStringRepository::emptyHash() }; -}; - -inline YulString operator "" _yulstring(char const* _string, std::size_t _size) -{ - return YulString(std::string(_string, _size)); -} - -} - -namespace fmt -{ -template <> -struct formatter -{ - template - constexpr auto parse(ParseContext& _context) - { - return _context.begin(); - } - - template - auto format(solidity::yul::YulString _value, FormatContext& _context) - { - return format_to(_context.out(), "{}", _value.str()); - } -}; -} - -namespace std -{ -template<> struct hash -{ - size_t operator()(solidity::yul::YulString const& x) const - { - return static_cast(x.hash()); - } -}; -} diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index 0fe03b021569..b9eacd220f6a 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -22,7 +22,6 @@ #pragma once #include -#include #include #include #include diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index a7e80632da46..7aca938fa872 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -249,7 +249,7 @@ EVMDialect::BuiltinsMap createBuiltins(langutil::EVMVersion _evmVersion, bool _o yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); - YulString const dataName (formatLiteral(std::get(arg))); + auto const dataName = formatLiteral(std::get(arg)); if (_context.currentObject->name == dataName) _assembly.appendAssemblySize(); else @@ -258,7 +258,7 @@ EVMDialect::BuiltinsMap createBuiltins(langutil::EVMVersion _evmVersion, bool _o _context.subIDs.count(dataName) == 0 ? _context.currentObject->pathToSubObject(dataName) : std::vector{_context.subIDs.at(dataName)}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName + ">."); _assembly.appendDataSize(subIdPath); } })); @@ -270,7 +270,7 @@ EVMDialect::BuiltinsMap createBuiltins(langutil::EVMVersion _evmVersion, bool _o yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); Expression const& arg = _call.arguments.front(); - YulString const dataName (formatLiteral(std::get(arg))); + auto const dataName = formatLiteral(std::get(arg)); if (_context.currentObject->name == dataName) _assembly.appendConstant(0); else @@ -279,7 +279,7 @@ EVMDialect::BuiltinsMap createBuiltins(langutil::EVMVersion _evmVersion, bool _o _context.subIDs.count(dataName) == 0 ? _context.currentObject->pathToSubObject(dataName) : std::vector{_context.subIDs.at(dataName)}; - yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName + ">."); _assembly.appendDataOffset(subIdPath); } })); @@ -402,7 +402,6 @@ bool EVMDialect::reservedIdentifier(std::string_view const _name) const EVMDialect const& EVMDialect::strictAssemblyForEVM(langutil::EVMVersion _version) { static std::map> dialects; - static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }}; if (!dialects[_version]) dialects[_version] = std::make_unique(_version, false); return *dialects[_version]; @@ -411,7 +410,6 @@ EVMDialect const& EVMDialect::strictAssemblyForEVM(langutil::EVMVersion _version EVMDialect const& EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion _version) { static std::map> dialects; - static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }}; if (!dialects[_version]) dialects[_version] = std::make_unique(_version, true); return *dialects[_version]; @@ -594,7 +592,6 @@ BuiltinFunctionForEVM const* EVMDialectTyped::equalityFunction(std::string_view EVMDialectTyped const& EVMDialectTyped::instance(langutil::EVMVersion _version) { static std::map> dialects; - static YulStringRepository::ResetCallback callback{[&] { dialects.clear(); }}; if (!dialects[_version]) dialects[_version] = std::make_unique(_version, true); return *dialects[_version]; diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 1546e0281694..3e7e67204ac9 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -33,7 +33,6 @@ namespace solidity::yul { -class YulString; struct FunctionCall; struct Object; @@ -44,7 +43,7 @@ struct BuiltinContext { Object const* currentObject = nullptr; /// Mapping from named objects to abstract assembly sub IDs. - std::map subIDs; + std::map subIDs; }; struct BuiltinFunctionForEVM: public BuiltinFunction diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index f3bf8a9b078a..c403bebf5680 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -56,8 +56,8 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) for (auto const& subNode: _object.subObjects) if (auto* subObject = dynamic_cast(subNode.get())) { - bool isCreation = !boost::ends_with(subObject->name.str(), "_deployed"); - auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name.str()); + bool isCreation = !boost::ends_with(subObject->name, "_deployed"); + auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name); context.subIDs[subObject->name] = subAssemblyAndID.second; subObject->subId = subAssemblyAndID.second; compile(*subObject, *subAssemblyAndID.first, m_yulNameRepository, m_dialect, _optimize, m_eofVersion); @@ -66,7 +66,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) { Data const& data = dynamic_cast(*subNode); // Special handling of metadata. - if (data.name.str() == Object::metadataName()) + if (data.name == Object::metadataName()) m_assembly.appendToAuxiliaryData(data.data); else context.subIDs[data.name] = m_assembly.appendData(data.data); diff --git a/libyul/optimiser/ASTWalker.h b/libyul/optimiser/ASTWalker.h index b937f7eae423..a158593a93b9 100644 --- a/libyul/optimiser/ASTWalker.h +++ b/libyul/optimiser/ASTWalker.h @@ -24,7 +24,6 @@ #include #include -#include #include #include diff --git a/libyul/optimiser/BlockHasher.h b/libyul/optimiser/BlockHasher.h index 82ca7cf22bbb..283b1fb63e29 100644 --- a/libyul/optimiser/BlockHasher.h +++ b/libyul/optimiser/BlockHasher.h @@ -22,7 +22,6 @@ #include #include -#include namespace solidity::yul { diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index 5deec31c0cfd..871d24c6d4d6 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -25,7 +25,6 @@ #include #include -#include #include // Needed for m_zero below. #include diff --git a/libyul/optimiser/DeadCodeEliminator.h b/libyul/optimiser/DeadCodeEliminator.h index e7268455fb41..9e936a62668c 100644 --- a/libyul/optimiser/DeadCodeEliminator.h +++ b/libyul/optimiser/DeadCodeEliminator.h @@ -22,7 +22,6 @@ #pragma once #include -#include #include #include diff --git a/libyul/optimiser/OptimiserStep.h b/libyul/optimiser/OptimiserStep.h index 91f34e52c086..67d93881afcd 100644 --- a/libyul/optimiser/OptimiserStep.h +++ b/libyul/optimiser/OptimiserStep.h @@ -29,7 +29,6 @@ namespace solidity::yul struct Dialect; struct Block; -class YulString; struct OptimiserStepContext { diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index ed5c48b2d9b7..909c859e1ac0 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -55,12 +55,6 @@ void yul::removeEmptyBlocks(Block& _block) ranges::actions::remove_if(_block.statements, isEmptyBlock); } -bool yul::isRestrictedIdentifier(Dialect const& /*_dialect*/, YulString const& /*_identifier*/) -{ - //return _identifier.empty() || hasLeadingOrTrailingDot(_identifier.str()) || TokenTraits::isYulKeyword(_identifier.str()) || _dialect.reservedIdentifier(_identifier); - return false; //todo -} - std::optional yul::toEVMInstruction(YulNameRepository const& _yulNameRepository, YulName const& _name) { if (_yulNameRepository.isEvmDialect()) diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index 8c260cb560b6..66db15fd73b5 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -43,10 +42,6 @@ namespace solidity::yul /// the canonical form. void removeEmptyBlocks(Block& _block); -/// Returns true if a given literal can not be used as an identifier. -/// This includes Yul keywords and builtins of the given dialect. -bool isRestrictedIdentifier(Dialect const& _dialect, YulString const& _identifier); - /// Helper function that returns the instruction, if the `_name` is a BuiltinFunction std::optional toEVMInstruction(YulNameRepository const& _yulNameRepository, YulName const& _name); diff --git a/libyul/optimiser/Substitution.h b/libyul/optimiser/Substitution.h index 084edfcfb254..055e749f1df6 100644 --- a/libyul/optimiser/Substitution.h +++ b/libyul/optimiser/Substitution.h @@ -22,7 +22,6 @@ #pragma once #include -#include #include diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 629e8d149241..b3a1090dc57c 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index d9fbed92ddf3..09f6cdeb8170 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -22,7 +22,6 @@ #pragma once #include -#include #include #include diff --git a/libyul/optimiser/UnusedFunctionParameterPruner.cpp b/libyul/optimiser/UnusedFunctionParameterPruner.cpp index a6d826b79ea0..a13c5dfa0598 100644 --- a/libyul/optimiser/UnusedFunctionParameterPruner.cpp +++ b/libyul/optimiser/UnusedFunctionParameterPruner.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index 277d93002bc2..d9dd87449907 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -23,7 +23,6 @@ #include #include -#include #include #include diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp deleted file mode 100644 index 3cee65897f8b..000000000000 --- a/libyul/optimiser/VarNameCleaner.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - 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 -#include -#include -#include -#include -#include - -using namespace solidity::yul; -/* -VarNameCleaner::VarNameCleaner( - Block const& _ast, - Dialect const& _dialect, - std::set _namesToKeep -): - m_dialect{_dialect}, - m_namesToKeep{std::move(_namesToKeep)}, - m_translatedNames{} -{ - for (auto const& statement: _ast.statements) - if (std::holds_alternative(statement)) - m_namesToKeep.insert(std::get(statement).name); - m_usedNames = m_namesToKeep; -} - -void VarNameCleaner::operator()(FunctionDefinition& _funDef) -{ - yulAssert(!m_insideFunction, ""); - m_insideFunction = true; - - std::set globalUsedNames = std::move(m_usedNames); - m_usedNames = m_namesToKeep; - std::map globalTranslatedNames; - swap(globalTranslatedNames, m_translatedNames); - - renameVariables(_funDef.parameters); - renameVariables(_funDef.returnVariables); - ASTModifier::operator()(_funDef); - - swap(globalUsedNames, m_usedNames); - swap(globalTranslatedNames, m_translatedNames); - - m_insideFunction = false; -} - -void VarNameCleaner::operator()(VariableDeclaration& _varDecl) -{ - renameVariables(_varDecl.variables); - ASTModifier::operator()(_varDecl); -} - -void VarNameCleaner::renameVariables(std::vector& _variables) -{ - for (TypedName& typedName: _variables) - { - auto newName = findCleanName(typedName.name); - if (newName != typedName.name) - { - m_translatedNames[typedName.name] = newName; - typedName.name = newName; - } - m_usedNames.insert(typedName.name); - } -} - -void VarNameCleaner::operator()(Identifier& _identifier) -{ - auto name = m_translatedNames.find(_identifier.name); - if (name != m_translatedNames.end()) - _identifier.name = name->second; -} - -YulString VarNameCleaner::findCleanName(YulString const& _name) const -{ - auto newName = stripSuffix(_name); - if (!isUsedName(newName)) - return newName; - - // create new name with suffix (by finding a free identifier) - for (size_t i = 1; i < std::numeric_limits::max(); ++i) - { - YulString newNameSuffixed = YulString{newName.str() + "_" + std::to_string(i)}; - if (!isUsedName(newNameSuffixed)) - return newNameSuffixed; - } - yulAssert(false, "Exhausted by attempting to find an available suffix."); -} - -bool VarNameCleaner::isUsedName(YulString const& _name) const -{ - return isRestrictedIdentifier(m_dialect, _name) || m_usedNames.count(_name); -} - -YulString VarNameCleaner::stripSuffix(YulString const& _name) const -{ - static std::regex const suffixRegex("(_+[0-9]+)+$"); - - std::smatch suffixMatch; - if (regex_search(_name.str(), suffixMatch, suffixRegex)) - return {YulString{suffixMatch.prefix().str()}}; - return _name; -} -*/ diff --git a/libyul/optimiser/VarNameCleaner.h b/libyul/optimiser/VarNameCleaner.h deleted file mode 100644 index 658c770fd89f..000000000000 --- a/libyul/optimiser/VarNameCleaner.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - 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 -#include -#include -#include - -#include -#include -#include - -namespace solidity::yul -{ - -struct Dialect; - -/** - * Pass to normalize identifier suffixes. - * - * That is, for each function scope, nested suffixes get flattened and all suffixes - * renumbered by their base name. - * Function names are not modified. - * - * NOTE: This step destroys the promise of the Disambiguator and thus cannot - * be used in the main loop of the optimizer without running the disambiguator again. - * Because of that, it is not included in the step list of the Optimizer Suite. - * - * Prerequisites: Disambiguator, FunctionHoister, FunctionGrouper - */ - /* -class VarNameCleaner: public ASTModifier -{ -public: - static constexpr char const* name{"VarNameCleaner"}; - static void run(OptimiserStepContext& _context, Block& _ast) - { - VarNameCleaner{_ast, _context.dialect, _context.reservedIdentifiers}(_ast); - } - - using ASTModifier::operator(); - void operator()(VariableDeclaration& _varDecl) override; - void operator()(Identifier& _identifier) override; - void operator()(FunctionDefinition& _funDef) override; - -private: - VarNameCleaner( - Block const& _ast, - Dialect const& _dialect, - std::set _namesToKeep = {} - ); - - /// Tries to rename a list of variables. - void renameVariables(std::vector& _variables); - - /// @returns suffix-stripped name, if a suffix was detected, none otherwise. - YulString stripSuffix(YulString const& _name) const; - - /// Looks out for a "clean name" the given @p name could be trimmed down to. - /// @returns a trimmed down and "clean name" in case it found one, none otherwise. - YulString findCleanName(YulString const& name) const; - - /// Tests whether a given name was already used within this pass - /// or was set to be kept. - bool isUsedName(YulString const& _name) const; - - Dialect const& m_dialect; - - /// These names will not be modified. - std::set m_namesToKeep; - - /// Set of names that are in use. - std::set m_usedNames; - - /// Maps old to new names. - std::map m_translatedNames; - - /// Whether the traverse is inside a function definition. - /// Used to assert that a function definition cannot be inside another. - bool m_insideFunction = false; -}; -*/ -} diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 8941d42f5326..792e19b3fcdd 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -81,7 +81,7 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con }; handleObject("creation", *object); size_t deployedIndex = object->subIndexByName.at( - YulString(IRNames::deployedObject(compiler().contractDefinition(contractName))) + IRNames::deployedObject(compiler().contractDefinition(contractName)) ); handleObject("runtime", dynamic_cast(*object->subObjects[deployedIndex])); } diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 06e1933213b7..8ead88630f22 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include #include diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index 3b1faab0ad23..72399008c214 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -20,8 +20,6 @@ #include -#include - #include #include diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index 595aecdca3f4..76150cb62d24 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -33,8 +33,6 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) if (_size > 600) return 0; - YulStringRepository::reset(); - std::string input(reinterpret_cast(_data), _size); YulStack stack( langutil::EVMVersion(), diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index f0e79d146697..252958f7fb18 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -57,8 +57,6 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) })) return 0; - YulStringRepository::reset(); - YulStack stack( langutil::EVMVersion(), std::nullopt, diff --git a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp index 7553c81c0f44..92c3e33565c9 100644 --- a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp @@ -34,8 +34,6 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) if (_size > 600) return 0; - YulStringRepository::reset(); - std::string input(reinterpret_cast(_data), _size); YulStack stack( langutil::EVMVersion(), diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.h b/test/tools/yulInterpreter/EVMInstructionInterpreter.h index d3d221112991..1c1651fbf2dd 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.h +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.h @@ -38,7 +38,6 @@ enum class Instruction: uint8_t; namespace solidity::yul { -class YulString; struct BuiltinFunctionForEVM; } diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 52b7e9d345d2..5d5e5e64bd95 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 489f01e0ae15..8ca67814ba2e 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -143,7 +142,7 @@ std::variant, ErrorList> Program::parseObject(yul::YulNam // The other object references the nested one which makes analysis fail. Below we try to // extract just the nested one for that reason. This is just a heuristic. If there's no // subobject with such a suffix we fall back to accepting the whole object as is. - if (subObject != nullptr && subObject->name.str() == object->name.str() + "_deployed") + if (subObject != nullptr && subObject->name == object->name + "_deployed") { deployedObject = dynamic_cast(subObject.get()); if (deployedObject != nullptr) From e8c587eada1bc5c52a92d7959ed9ece04b794ed5 Mon Sep 17 00:00:00 2001 From: clonker Date: Thu, 4 Jul 2024 13:43:18 +0200 Subject: [PATCH 04/15] yul ast class --- libsolidity/analysis/ControlFlowBuilder.cpp | 4 +- libsolidity/analysis/PostTypeChecker.cpp | 4 +- libsolidity/analysis/ReferencesResolver.cpp | 4 +- libsolidity/analysis/SyntaxChecker.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 4 +- libsolidity/analysis/ViewPureChecker.cpp | 4 +- libsolidity/ast/AST.cpp | 8 +- libsolidity/ast/AST.h | 11 +- libsolidity/ast/ASTJsonExporter.cpp | 6 +- libsolidity/ast/ASTJsonImporter.cpp | 4 +- libsolidity/codegen/CompilerContext.cpp | 53 +-- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/codegen/ContractCompiler.cpp | 11 +- .../codegen/ir/IRGeneratorForStatements.cpp | 8 +- .../experimental/analysis/TypeInference.cpp | 4 +- .../codegen/IRGeneratorForStatements.cpp | 7 +- libsolidity/formal/SMTEncoder.cpp | 4 +- libsolidity/interface/CompilerStack.cpp | 5 +- libsolidity/lsp/RenameSymbol.cpp | 4 +- libsolidity/parsing/Parser.cpp | 11 +- libyul/AST.cpp | 20 ++ libyul/AST.h | 20 ++ libyul/ASTForward.h | 1 + libyul/AsmAnalysis.cpp | 6 +- libyul/AsmAnalysis.h | 2 +- libyul/AsmJsonImporter.cpp | 119 +++--- libyul/AsmJsonImporter.h | 40 +-- libyul/AsmParser.cpp | 123 ++++--- libyul/AsmParser.h | 36 +- libyul/CompilabilityChecker.cpp | 9 +- libyul/CompilabilityChecker.h | 2 +- libyul/Object.cpp | 11 +- libyul/Object.h | 5 +- libyul/ObjectParser.cpp | 12 +- libyul/ObjectParser.h | 10 +- libyul/Scope.cpp | 12 +- libyul/Scope.h | 7 +- libyul/ScopeFiller.cpp | 4 +- libyul/YulStack.cpp | 48 +-- libyul/YulStack.h | 14 +- libyul/backends/evm/AsmCodeGen.cpp | 6 +- libyul/backends/evm/AsmCodeGen.h | 3 +- libyul/backends/evm/EVMCodeTransform.cpp | 6 +- libyul/backends/evm/EVMCodeTransform.h | 9 +- libyul/backends/evm/EVMObjectCompiler.cpp | 16 +- libyul/backends/evm/EVMObjectCompiler.h | 6 +- libyul/optimiser/Semantics.cpp | 11 +- libyul/optimiser/Semantics.h | 7 +- libyul/optimiser/StackCompressor.cpp | 16 +- libyul/optimiser/StackLimitEvader.cpp | 15 +- libyul/optimiser/Suite.cpp | 24 +- libyul/optimiser/Suite.h | 1 - test/libsolidity/MemoryGuardTest.cpp | 8 +- test/libyul/Common.cpp | 23 +- test/libyul/Common.h | 7 +- test/libyul/CompilabilityChecker.cpp | 8 +- test/libyul/ControlFlowGraphTest.cpp | 9 +- test/libyul/ControlFlowGraphTest.h | 1 - test/libyul/ControlFlowSideEffectsTest.cpp | 11 +- test/libyul/EVMCodeTransformTest.cpp | 6 +- test/libyul/FunctionSideEffects.cpp | 9 +- test/libyul/Inliner.cpp | 6 +- test/libyul/KnowledgeBaseTest.cpp | 45 +-- test/libyul/Metrics.cpp | 4 +- test/libyul/ObjectParser.cpp | 3 +- test/libyul/Parser.cpp | 340 ++++++++---------- test/libyul/StackLayoutGeneratorTest.cpp | 10 +- test/libyul/StackLayoutGeneratorTest.h | 4 +- test/libyul/SyntaxTest.cpp | 6 +- test/libyul/SyntaxTest.h | 2 +- test/libyul/YulInterpreterTest.cpp | 6 +- test/libyul/YulInterpreterTest.h | 5 +- test/libyul/YulOptimizerTest.cpp | 9 +- test/libyul/YulOptimizerTest.h | 1 - test/libyul/YulOptimizerTestCommon.cpp | 337 +++++++++-------- test/libyul/YulOptimizerTestCommon.h | 10 +- test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp | 3 +- test/tools/ossfuzz/yulFuzzerCommon.cpp | 7 +- test/tools/ossfuzz/yulFuzzerCommon.h | 3 +- test/tools/yulInterpreter/Interpreter.h | 2 +- test/tools/yulopti.cpp | 37 +- test/tools/yulrun.cpp | 12 +- tools/yulPhaser/Program.cpp | 64 ++-- tools/yulPhaser/Program.h | 34 +- 84 files changed, 882 insertions(+), 931 deletions(-) diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index c280dcafb949..5ade03614e8b 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -451,7 +451,7 @@ bool ControlFlowBuilder::visit(InlineAssembly const& _inlineAssembly) solAssert(!!m_currentNode && !m_inlineAssembly, ""); m_inlineAssembly = &_inlineAssembly; - (*this)(_inlineAssembly.operations()); + (*this)(_inlineAssembly.operations().block()); m_inlineAssembly = nullptr; return false; @@ -582,7 +582,7 @@ void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall) solAssert(m_currentNode && m_inlineAssembly, ""); yul::ASTWalker::operator()(_functionCall); - if (auto const *builtinFunction = m_inlineAssembly->nameRepository().builtin(_functionCall.functionName.name)) + if (auto const *builtinFunction = m_inlineAssembly->operations().nameRepository().builtin(_functionCall.functionName.name)) { if (builtinFunction->data->controlFlowSideEffects.canTerminate) connect(m_currentNode, m_transactionReturnNode); diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index d832f77479b9..3361e443639e 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -507,8 +507,8 @@ class LValueChecker: public ASTConstVisitor if (m_willBeWrittenTo) return; - YulLValueChecker yulChecker{m_declaration->name(), _inlineAssembly.nameRepository()}; - yulChecker(_inlineAssembly.operations()); + YulLValueChecker yulChecker{m_declaration->name(), _inlineAssembly.operations().nameRepository()}; + yulChecker(_inlineAssembly.operations().block()); m_willBeWrittenTo = yulChecker.willBeWrittenTo(); } private: diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 184acfdf2772..49f688643b56 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -236,8 +236,8 @@ bool ReferencesResolver::visit(UsingForDirective const& _usingFor) bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) { m_yulAnnotation = &_inlineAssembly.annotation(); - m_yulNameRepository = &_inlineAssembly.nameRepository(); - (*this)(_inlineAssembly.operations()); + m_yulNameRepository = &_inlineAssembly.operations().nameRepository(); + (*this)(_inlineAssembly.operations().block()); m_yulNameRepository = nullptr; m_yulAnnotation = nullptr; diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 21966bae0def..335e8c3a864e 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -354,7 +354,7 @@ bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly) if (!m_useYulOptimizer) return false; - if (yul::MSizeFinder::containsMSize(_inlineAssembly.nameRepository(), _inlineAssembly.operations())) + if (yul::MSizeFinder::containsMSize(_inlineAssembly.operations())) m_errorReporter.syntaxError( 6553_error, _inlineAssembly.location(), diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 89605b9ba61f..6bf668c0fddd 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -944,10 +944,10 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) yul::AsmAnalyzer analyzer( *_inlineAssembly.annotation().analysisInfo, m_errorReporter, - _inlineAssembly.nameRepository(), + _inlineAssembly.operations().nameRepository(), identifierAccess ); - if (!analyzer.analyze(_inlineAssembly.operations())) + if (!analyzer.analyze(_inlineAssembly.operations().block())) solAssert(m_errorReporter.hasErrors()); _inlineAssembly.annotation().hasMemoryEffects = lvalueAccessToMemoryVariable || diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 8bb00b4962e1..ed9563e97d79 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -224,9 +224,9 @@ void ViewPureChecker::endVisit(Identifier const& _identifier) void ViewPureChecker::endVisit(InlineAssembly const& _inlineAssembly) { AssemblyViewPureChecker{ - _inlineAssembly.nameRepository(), + _inlineAssembly.operations().nameRepository(), [&](StateMutability _mutability, SourceLocation const& _location) { reportMutability(_mutability, _location); } - }(_inlineAssembly.operations()); + }(_inlineAssembly.operations().block()); } void ViewPureChecker::reportMutability( diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 0e5533e431c8..f20da0289471 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -1066,17 +1066,13 @@ InlineAssembly::InlineAssembly( int64_t _id, SourceLocation const& _location, ASTPointer const& _docString, - std::unique_ptr _yulNameRepository, ASTPointer>> _flags, - std::shared_ptr _operations + std::shared_ptr _operations ): Statement(_id, _location, _docString), - m_yulNameRepository(std::move(_yulNameRepository)), m_flags(std::move(_flags)), m_operations(std::move(_operations)) -{ - solAssert(m_yulNameRepository != nullptr); -} +{} InlineAssembly::~InlineAssembly() = default; diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 83c101f004c0..306afa916d4d 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -48,7 +48,7 @@ namespace solidity::yul { // Forward-declaration to -struct Block; +class AST; class YulNameRepository; } @@ -1567,24 +1567,21 @@ class InlineAssembly: public Statement int64_t _id, SourceLocation const& _location, ASTPointer const& _docString, - std::unique_ptr _yulNameRepository, ASTPointer>> _flags, - std::shared_ptr _operations + std::shared_ptr _operations ); ~InlineAssembly() override; void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; - yul::YulNameRepository& nameRepository() const { return *m_yulNameRepository; } - yul::Block const& operations() const { return *m_operations; } + yul::AST const& operations() const { return *m_operations; } ASTPointer>> const& flags() const { return m_flags; } InlineAssemblyAnnotation& annotation() const override; private: - std::unique_ptr mutable m_yulNameRepository; ASTPointer>> m_flags; - std::shared_ptr m_operations; + std::shared_ptr m_operations; }; /** diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 509d82200890..79242773671e 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -654,7 +654,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) for (auto const& it: _node.annotation().externalReferences) if (it.first) externalReferences.emplace_back(std::make_pair( - _node.nameRepository().labelOf(it.first->name), + _node.operations().nameRepository().labelOf(it.first->name), inlineAssemblyIdentifierToJson(it) )); @@ -665,9 +665,9 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) externalReferencesJson.emplace_back(std::move(it)); std::vector> attributes = { - std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()), _node.nameRepository())(_node.operations()))), + std::make_pair("AST", Json(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()), _node.operations().nameRepository())(_node.operations().block()))), std::make_pair("externalReferences", std::move(externalReferencesJson)), - std::make_pair("evmVersion", dynamic_cast(_node.nameRepository().dialect()).evmVersion().name()) + std::make_pair("evmVersion", dynamic_cast(_node.operations().nameRepository().dialect()).evmVersion().name()) }; if (_node.flags()) diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 0df3f0fd2f26..dda1773d4c78 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -733,12 +733,10 @@ ASTPointer ASTJsonImporter::createInlineAssembly(Json const& _no flags->emplace_back(std::make_shared(flag.get())); } } - auto repository = std::make_unique(dialect); - std::shared_ptr operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames, *repository).createBlock(member(_node, "AST"))); + auto operations = std::make_shared(yul::AsmJsonImporter(m_sourceNames, dialect).createAST(member(_node, "AST"))); return createASTNode( _node, nullOrASTString(_node, "documentation"), - std::move(repository), std::move(flags), operations ); diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index bdbe70369466..4be6202a86ce 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -48,6 +48,8 @@ #include #include +#include + #include // Change to "define" to output all intermediate code @@ -387,16 +389,19 @@ void CompilerContext::appendInlineAssembly( { unsigned startStackHeight = stackHeight(); yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); - yul::YulNameRepository nameRepository (dialect); - + auto nameRepository = std::make_unique(dialect); + + std::vector externallyUsedFunctionNames = _externallyUsedFunctions + | ranges::views::transform([&nameRepository](auto const& label) { return nameRepository->defineName(label); }) + | ranges::to_vector; + std::vector localVariableNames = _localVariables + | ranges::views::transform([&nameRepository](auto const& label) { return nameRepository->defineName(label); }) + | ranges::to_vector; std::set externallyUsedIdentifiers; - for (auto const& fun: _externallyUsedFunctions) - externallyUsedIdentifiers.insert(nameRepository.defineName(fun)); - for (auto const& var: _localVariables) - externallyUsedIdentifiers.insert(nameRepository.defineName(var)); + externallyUsedIdentifiers += externallyUsedFunctionNames + localVariableNames; yul::ExternalIdentifierAccess identifierAccess; - identifierAccess.resolve = [&]( + identifierAccess.resolve = [&localVariableNames]( yul::Identifier const& _identifier, yul::IdentifierContext, bool _insideFunction @@ -404,7 +409,7 @@ void CompilerContext::appendInlineAssembly( { if (_insideFunction) return false; - return util::contains(_localVariables, nameRepository.labelOf(_identifier.name)); + return util::contains(localVariableNames, _identifier.name); }; identifierAccess.generateCode = [&]( yul::Identifier const& _identifier, @@ -413,9 +418,9 @@ void CompilerContext::appendInlineAssembly( ) { solAssert(_context == yul::IdentifierContext::RValue || _context == yul::IdentifierContext::LValue, ""); - auto it = std::find(_localVariables.begin(), _localVariables.end(), nameRepository.labelOf(_identifier.name)); - solAssert(it != _localVariables.end(), ""); - auto stackDepth = static_cast(distance(it, _localVariables.end())); + auto it = std::find(localVariableNames.begin(), localVariableNames.end(), _identifier.name); + solAssert(it != localVariableNames.end(), ""); + auto stackDepth = static_cast(distance(it, localVariableNames.end())); size_t stackDiff = static_cast(_assembly.stackHeight()) - startStackHeight + stackDepth; if (_context == yul::IdentifierContext::LValue) stackDiff -= 1; @@ -440,9 +445,9 @@ void CompilerContext::appendInlineAssembly( std::optional locationOverride; if (!_system) locationOverride = m_asm->currentSourceLocation(); - std::shared_ptr parserResult = - yul::Parser(errorReporter, nameRepository, std::move(locationOverride)) - .parse(charStream); + std::shared_ptr parserResult = + yul::Parser(errorReporter, dialect, std::move(locationOverride)) + .parse(charStream, std::move(nameRepository)); #ifdef SOL_OUTPUT_ASM cout << yul::AsmPrinter(&dialect)(*parserResult) << endl; #endif @@ -470,9 +475,9 @@ void CompilerContext::appendInlineAssembly( analyzerResult = yul::AsmAnalyzer( analysisInfo, errorReporter, - nameRepository, + parserResult->nameRepository(), identifierAccess.resolve - ).analyze(*parserResult); + ).analyze(parserResult->block()); if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) reportError("Invalid assembly generated by code generator."); @@ -485,17 +490,17 @@ void CompilerContext::appendInlineAssembly( obj.analysisInfo = std::make_shared(analysisInfo); solAssert(!dialect.providesObjectAccess()); - optimizeYul(obj, dialect, nameRepository, _optimiserSettings, externallyUsedIdentifiers); + optimizeYul(obj, dialect, _optimiserSettings, externallyUsedIdentifiers); if (_system) { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - m_generatedYulUtilityCode = yul::AsmPrinter(nameRepository)(*obj.code); - std::string code = yul::AsmPrinter(nameRepository)(*obj.code); + std::string code = yul::AsmPrinter(parserResult->nameRepository())(obj.code->block()); + m_generatedYulUtilityCode = code; langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); - obj.code = yul::Parser(errorReporter, nameRepository).parse(charStream); - *obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(nameRepository, obj); + obj.code = yul::Parser(errorReporter, dialect).parse(charStream); + *obj.analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(obj); } analysisInfo = std::move(*obj.analysisInfo); @@ -522,7 +527,6 @@ void CompilerContext::appendInlineAssembly( analysisInfo, *m_asm, m_evmVersion, - nameRepository, identifierAccess.generateCode, _system, _optimiserSettings.optimizeStackAllocation @@ -533,16 +537,15 @@ void CompilerContext::appendInlineAssembly( } -void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, yul::YulNameRepository& _yulNameRepository, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) +void CompilerContext::optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSettings, std::set const& _externalIdentifiers) { #ifdef SOL_OUTPUT_ASM cout << yul::AsmPrinter(_yulNameRepository)(*_object.code) << endl; #endif bool const isCreation = runtimeContext() != nullptr; - yul::GasMeter meter(_yulNameRepository, _dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); + yul::GasMeter meter(_object.code->nameRepository(), _dialect, isCreation, _optimiserSettings.expectedExecutionsPerDeployment); yul::OptimiserSuite::run( - _yulNameRepository, &meter, _object, _optimiserSettings.optimizeStackAllocation, diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index bd8dab318fc0..c6972f92b83b 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -277,7 +277,7 @@ class CompilerContext /// Otherwise returns "revert(0, 0)". std::string revertReasonIfDebug(std::string const& _message = ""); - void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, yul::YulNameRepository& _yulNameRepository, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); + void optimizeYul(yul::Object& _object, yul::EVMDialect const& _dialect, OptimiserSettings const& _optimiserSetting, std::set const& _externalIdentifiers = {}); /// Appends arbitrary data to the end of the bytecode. void appendToAuxiliaryData(bytes const& _data) { m_asm->appendToAuxiliaryData(_data); } diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index ecb23b8092d0..c7dd7d098975 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -926,7 +926,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) } }; - yul::Block const* code = &_inlineAssembly.operations(); + yul::AST const* code = &_inlineAssembly.operations(); yul::AsmAnalysisInfo* analysisInfo = _inlineAssembly.annotation().analysisInfo.get(); // Only used in the scope below, but required to live outside to keep the @@ -939,14 +939,14 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) _inlineAssembly.annotation().externalReferences.empty() ) { - yul::EVMDialect const* dialect = dynamic_cast(&_inlineAssembly.nameRepository().dialect()); + yul::EVMDialect const* dialect = dynamic_cast(&code->nameRepository().dialect()); solAssert(dialect, ""); // Create a modifiable copy of the code and analysis - object.code = std::make_shared(yul::ASTCopier().translate(*code)); - object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(_inlineAssembly.nameRepository(), object)); + object.code = std::make_shared(*code); + object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(object)); - m_context.optimizeYul(object, *dialect, _inlineAssembly.nameRepository(), m_optimiserSettings); + m_context.optimizeYul(object, *dialect, m_optimiserSettings); code = object.code.get(); analysisInfo = object.analysisInfo.get(); @@ -957,7 +957,6 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) *analysisInfo, *m_context.assemblyPtr(), m_context.evmVersion(), - _inlineAssembly.nameRepository(), identifierAccessCodeGen, false, m_optimiserSettings.optimizeStackAllocation diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 85d3c2004553..9f9135055400 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -2250,14 +2250,16 @@ bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm) setLocation(_inlineAsm); if (*_inlineAsm.annotation().hasMemoryEffects && !_inlineAsm.annotation().markedMemorySafe) m_context.setMemoryUnsafeInlineAssemblySeen(); - CopyTranslate bodyCopier{_inlineAsm.nameRepository(), m_context, _inlineAsm.annotation().externalReferences}; + // make a copy of the name repository so that the "usr$" prefixed names can be defined on it + yul::YulNameRepository nameRepository = _inlineAsm.operations().nameRepository(); + CopyTranslate bodyCopier{nameRepository, m_context, _inlineAsm.annotation().externalReferences}; - yul::Statement modified = bodyCopier(_inlineAsm.operations()); + yul::Statement modified = bodyCopier(_inlineAsm.operations().block()); solAssert(std::holds_alternative(modified)); // Do not provide dialect so that we get the full type information. - appendCode() << yul::AsmPrinter(_inlineAsm.nameRepository())(std::get(modified)) << "\n"; + appendCode() << yul::AsmPrinter(nameRepository)(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/experimental/analysis/TypeInference.cpp b/libsolidity/experimental/analysis/TypeInference.cpp index 0b7c525a1843..6ea4977a68cf 100644 --- a/libsolidity/experimental/analysis/TypeInference.cpp +++ b/libsolidity/experimental/analysis/TypeInference.cpp @@ -299,10 +299,10 @@ bool TypeInference::visit(InlineAssembly const& _inlineAssembly) yul::AsmAnalyzer analyzer( *_inlineAssembly.annotation().analysisInfo, m_errorReporter, - _inlineAssembly.nameRepository(), + _inlineAssembly.operations().nameRepository(), identifierAccess ); - if (!analyzer.analyze(_inlineAssembly.operations())) + if (!analyzer.analyze(_inlineAssembly.operations().block())) solAssert(m_errorReporter.hasErrors()); return false; } diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index 863d04b13306..64cb101e8014 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -129,10 +129,11 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tupleExpression) bool IRGeneratorForStatements::visit(InlineAssembly const& _assembly) { - CopyTranslate bodyCopier{m_context, _assembly.nameRepository(), _assembly.annotation().externalReferences}; - yul::Statement modified = bodyCopier(_assembly.operations()); + yul::YulNameRepository nameRepository(_assembly.operations().nameRepository()); + CopyTranslate bodyCopier{m_context, nameRepository, _assembly.annotation().externalReferences}; + yul::Statement modified = bodyCopier(_assembly.operations().block()); solAssert(std::holds_alternative(modified)); - m_code << yul::AsmPrinter(_assembly.nameRepository())(std::get(modified)) << "\n"; + m_code << yul::AsmPrinter(nameRepository)(std::get(modified)) << "\n"; return false; } diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index f016785d7b38..f7d8d92d9c23 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -313,7 +313,7 @@ bool SMTEncoder::visit(InlineAssembly const& _inlineAsm) { AssignedExternalsCollector(InlineAssembly const& _inlineAsm): externalReferences(_inlineAsm.annotation().externalReferences) { - this->operator()(_inlineAsm.operations()); + this->operator()(_inlineAsm.operations().block()); } std::map const& externalReferences; @@ -330,7 +330,7 @@ bool SMTEncoder::visit(InlineAssembly const& _inlineAsm) } }; - yul::SideEffectsCollector sideEffectsCollector(_inlineAsm.nameRepository(), _inlineAsm.operations()); + yul::SideEffectsCollector sideEffectsCollector(_inlineAsm.operations()); if (sideEffectsCollector.invalidatesMemory()) resetMemoryVariables(); if (sideEffectsCollector.invalidatesStorage()) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 30ea615b8716..809073f8014f 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -836,10 +836,9 @@ Json CompilerStack::generatedSources(std::string const& _contractName, bool _run ErrorReporter errorReporter(errors); CharStream charStream(source, sourceName); yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); - YulNameRepository yulNameRepository(dialect); - std::shared_ptr parserResult = yul::Parser{errorReporter, yulNameRepository}.parse(charStream); + std::shared_ptr parserResult = yul::Parser{errorReporter, dialect}.parse(charStream); solAssert(parserResult, ""); - sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex, yulNameRepository}(*parserResult); + sources[0]["ast"] = yul::AsmJsonConverter{sourceIndex, parserResult->nameRepository()}(parserResult->block()); sources[0]["name"] = sourceName; sources[0]["id"] = sourceIndex; sources[0]["language"] = "Yul"; diff --git a/libsolidity/lsp/RenameSymbol.cpp b/libsolidity/lsp/RenameSymbol.cpp index 2a4a29f61870..d56316d066ad 100644 --- a/libsolidity/lsp/RenameSymbol.cpp +++ b/libsolidity/lsp/RenameSymbol.cpp @@ -283,7 +283,7 @@ void RenameSymbol::extractNameAndDeclaration(InlineAssembly const& _inlineAssemb if (location.containsOffset(_cursorBytePosition)) { m_declarationToRename = externalReference.declaration; - m_symbolName = _inlineAssembly.nameRepository().labelOf(identifier->name); + m_symbolName = _inlineAssembly.operations().nameRepository().labelOf(identifier->name); if (!externalReference.suffix.empty()) m_symbolName = m_symbolName.substr(0, m_symbolName.length() - externalReference.suffix.size() - 1); @@ -296,7 +296,7 @@ void RenameSymbol::Visitor::endVisit(InlineAssembly const& _node) { for (auto&& [identifier, externalReference]: _node.annotation().externalReferences) { - auto identifierName = _node.nameRepository().labelOf(identifier->name); + auto identifierName = _node.operations().nameRepository().labelOf(identifier->name); if (!externalReference.suffix.empty()) identifierName = identifierName.substr(0, identifierName.length() - externalReference.suffix.size() - 1); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 0e40c4fc9067..2a83a619b107 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1472,14 +1472,13 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con expectToken(Token::RParen); } - auto nameRepository = std::make_unique(dialect); - yul::Parser asmParser(m_errorReporter, *nameRepository); - std::shared_ptr block = asmParser.parseInline(m_scanner); - if (block == nullptr) + yul::Parser asmParser(m_errorReporter, dialect); + std::shared_ptr ast = asmParser.parseInline(m_scanner); + if (ast == nullptr) BOOST_THROW_EXCEPTION(FatalError()); - location.end = nativeLocationOf(*block).end; - return std::make_shared(nextID(), location, _docString, std::move(nameRepository), std::move(flags), block); + location.end = nativeLocationOf(ast->block()).end; + return std::make_shared(nextID(), location, _docString, std::move(flags), ast); } ASTPointer Parser::parseIfStatement(ASTPointer const& _docString) diff --git a/libyul/AST.cpp b/libyul/AST.cpp index 8c9f376415f9..b3d57c9b7d43 100644 --- a/libyul/AST.cpp +++ b/libyul/AST.cpp @@ -17,11 +17,31 @@ along with solidity. If not, see . // SPDX-License-Identifier: GPL-3.0 #include + +#include #include namespace solidity::yul { +AST::AST(std::unique_ptr _nameRepository, Block _block): + m_nameRepository(std::move(_nameRepository)), m_block(std::move(_block)) +{ + yulAssert(m_nameRepository != nullptr); +} + +AST::AST(solidity::yul::AST const& _rhs) +{ + *this = _rhs; +} + +AST& AST::operator=(AST const& _rhs) +{ + m_nameRepository = std::make_unique(*_rhs.m_nameRepository); + m_block = ASTCopier().translate(_rhs.m_block); + return *this; +} + LiteralValue::LiteralValue(std::string _builtinStringLiteralValue): m_numericValue(std::nullopt), m_stringValue(std::make_shared(std::move(_builtinStringLiteralValue))) diff --git a/libyul/AST.h b/libyul/AST.h index fb3723326635..f73ab45a90ea 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -101,6 +101,26 @@ struct Continue { langutil::DebugData::ConstPtr debugData; }; /// Leave statement (valid within function) struct Leave { langutil::DebugData::ConstPtr debugData; }; +class AST +{ +public: + AST(std::unique_ptr _nameRepository, Block _block); + AST(AST&&) = default; + AST& operator=(AST&& _rhs) = default; + AST(AST const& _rhs); + AST& operator=(AST const& _rhs); + ~AST() = default; + + Block const& block() const { return m_block; } + Block& block() { return m_block; } + YulNameRepository const& nameRepository() const { return *m_nameRepository; } + YulNameRepository& nameRepository() { return *m_nameRepository; } + +private: + std::unique_ptr m_nameRepository; + Block m_block; +}; + /// Extracts the IR source location from a Yul node. template inline langutil::SourceLocation nativeLocationOf(T const& _node) { diff --git a/libyul/ASTForward.h b/libyul/ASTForward.h index 129dffe9c105..8efdd6a45d78 100644 --- a/libyul/ASTForward.h +++ b/libyul/ASTForward.h @@ -47,6 +47,7 @@ struct Leave; struct ExpressionStatement; struct Block; struct Dialect; +class AST; struct TypedName; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 5eb2e7cddc34..9b26abe572e9 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -84,7 +84,7 @@ bool AsmAnalyzer::analyze(Block const& _block) return watcher.ok(); } -AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(YulNameRepository const& _yulNameRepository, Object const& _object) +AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Object const& _object) { ErrorList errorList; langutil::ErrorReporter errors(errorList); @@ -92,10 +92,10 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(YulNameRepository const& bool success = yul::AsmAnalyzer( analysisInfo, errors, - _yulNameRepository, + _object.code->nameRepository(), {}, _object.qualifiedDataNames() - ).analyze(*_object.code); + ).analyze(_object.code->block()); yulAssert(success && !errors.hasErrors(), "Invalid assembly/yul code."); return analysisInfo; } diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index a58a5a6c9e28..0c1b5a391669 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -77,7 +77,7 @@ class AsmAnalyzer /// Performs analysis on the outermost code of the given object and returns the analysis info. /// Asserts on failure. - static AsmAnalysisInfo analyzeStrictAssertCorrect(YulNameRepository const& _yulNameRepository, Object const& _object); + static AsmAnalysisInfo analyzeStrictAssertCorrect(Object const& _object); std::vector operator()(Literal const& _literal); std::vector operator()(Identifier const&); diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index e973406ee974..cd85515bc9ed 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -50,6 +50,13 @@ SourceLocation const AsmJsonImporter::createSourceLocation(Json const& _node) return solidity::langutil::parseSourceLocation(_node["src"].get(), m_sourceNames); } +AST AsmJsonImporter::createAST(solidity::Json const& _node) +{ + auto nameRepository = std::make_unique(m_dialect); + auto block = createBlock(_node, *nameRepository); + return {std::move(nameRepository), std::move(block)}; +} + template T AsmJsonImporter::createAsmNode(Json const& _node) { @@ -70,15 +77,15 @@ Json AsmJsonImporter::member(Json const& _node, std::string const& _name) return _node[_name]; } -TypedName AsmJsonImporter::createTypedName(Json const& _node) +TypedName AsmJsonImporter::createTypedName(Json const& _node, YulNameRepository& _nameRepository) { auto typedName = createAsmNode(_node); - typedName.type = m_yulNameRepository.nameOfType(member(_node, "type").get()); - typedName.name = m_yulNameRepository.defineName(member(_node, "name").get()); + typedName.type = _nameRepository.nameOfType(member(_node, "type").get()); + typedName.name = _nameRepository.defineName(member(_node, "name").get()); return typedName; } -Statement AsmJsonImporter::createStatement(Json const& _node) +Statement AsmJsonImporter::createStatement(Json const& _node, YulNameRepository& _nameRepository) { Json jsonNodeType = member(_node, "nodeType"); yulAssert(jsonNodeType.is_string(), "Expected \"nodeType\" to be of type string!"); @@ -88,19 +95,19 @@ Statement AsmJsonImporter::createStatement(Json const& _node) nodeType = nodeType.substr(3); if (nodeType == "ExpressionStatement") - return createExpressionStatement(_node); + return createExpressionStatement(_node, _nameRepository); else if (nodeType == "Assignment") - return createAssignment(_node); + return createAssignment(_node, _nameRepository); else if (nodeType == "VariableDeclaration") - return createVariableDeclaration(_node); + return createVariableDeclaration(_node, _nameRepository); else if (nodeType == "FunctionDefinition") - return createFunctionDefinition(_node); + return createFunctionDefinition(_node, _nameRepository); else if (nodeType == "If") - return createIf(_node); + return createIf(_node, _nameRepository); else if (nodeType == "Switch") - return createSwitch(_node); + return createSwitch(_node, _nameRepository); else if (nodeType == "ForLoop") - return createForLoop(_node); + return createForLoop(_node, _nameRepository); else if (nodeType == "Break") return createBreak(_node); else if (nodeType == "Continue") @@ -108,7 +115,7 @@ Statement AsmJsonImporter::createStatement(Json const& _node) else if (nodeType == "Leave") return createLeave(_node); else if (nodeType == "Block") - return createBlock(_node); + return createBlock(_node, _nameRepository); else yulAssert(false, "Invalid nodeType as statement"); @@ -116,7 +123,7 @@ Statement AsmJsonImporter::createStatement(Json const& _node) util::unreachable(); } -Expression AsmJsonImporter::createExpression(Json const& _node) +Expression AsmJsonImporter::createExpression(Json const& _node, YulNameRepository& _nameRepository) { Json jsonNodeType = member(_node, "nodeType"); yulAssert(jsonNodeType.is_string(), "Expected \"nodeType\" to be of type string!"); @@ -126,11 +133,11 @@ Expression AsmJsonImporter::createExpression(Json const& _node) nodeType = nodeType.substr(3); if (nodeType == "FunctionCall") - return createFunctionCall(_node); + return createFunctionCall(_node, _nameRepository); else if (nodeType == "Identifier") - return createIdentifier(_node); + return createIdentifier(_node, _nameRepository); else if (nodeType == "Literal") - return createLiteral(_node); + return createLiteral(_node, _nameRepository); else yulAssert(false, "Invalid nodeType as expression"); @@ -138,30 +145,30 @@ Expression AsmJsonImporter::createExpression(Json const& _node) util::unreachable(); } -std::vector AsmJsonImporter::createExpressionVector(Json const& _array) +std::vector AsmJsonImporter::createExpressionVector(Json const& _array, YulNameRepository& _nameRepository) { std::vector ret; for (auto& var: _array) - ret.emplace_back(createExpression(var)); + ret.emplace_back(createExpression(var, _nameRepository)); return ret; } -std::vector AsmJsonImporter::createStatementVector(Json const& _array) +std::vector AsmJsonImporter::createStatementVector(Json const& _array, YulNameRepository& _nameRepository) { std::vector ret; for (auto& var: _array) - ret.emplace_back(createStatement(var)); + ret.emplace_back(createStatement(var, _nameRepository)); return ret; } -Block AsmJsonImporter::createBlock(Json const& _node) +Block AsmJsonImporter::createBlock(Json const& _node, YulNameRepository& _nameRepository) { auto block = createAsmNode(_node); - block.statements = createStatementVector(_node["statements"]); + block.statements = createStatementVector(_node["statements"], _nameRepository); return block; } -Literal AsmJsonImporter::createLiteral(Json const& _node) +Literal AsmJsonImporter::createLiteral(Json const& _node, YulNameRepository& _nameRepository) { auto lit = createAsmNode(_node); std::string kind = member(_node, "kind").get(); @@ -172,7 +179,7 @@ Literal AsmJsonImporter::createLiteral(Json const& _node) value = util::asString(util::fromHex(member(_node, "hexValue").get())); else value = member(_node, "value").get(); - lit.type = m_yulNameRepository.nameOfType(member(_node, "type").get()); + lit.type = _nameRepository.nameOfType(member(_node, "type").get()); if (kind == "number") { langutil::CharStream charStream(value, ""); @@ -217,109 +224,109 @@ Leave AsmJsonImporter::createLeave(Json const& _node) return createAsmNode(_node); } -Identifier AsmJsonImporter::createIdentifier(Json const& _node) +Identifier AsmJsonImporter::createIdentifier(Json const& _node, YulNameRepository& _nameRepository) { auto identifier = createAsmNode(_node); - identifier.name = m_yulNameRepository.defineName(member(_node, "name").get()); + identifier.name = _nameRepository.defineName(member(_node, "name").get()); return identifier; } -Assignment AsmJsonImporter::createAssignment(Json const& _node) +Assignment AsmJsonImporter::createAssignment(Json const& _node, YulNameRepository& _nameRepository) { auto assignment = createAsmNode(_node); if (_node.contains("variableNames")) for (auto const& var: member(_node, "variableNames")) - assignment.variableNames.emplace_back(createIdentifier(var)); + assignment.variableNames.emplace_back(createIdentifier(var, _nameRepository)); - assignment.value = std::make_unique(createExpression(member(_node, "value"))); + assignment.value = std::make_unique(createExpression(member(_node, "value"), _nameRepository)); return assignment; } -FunctionCall AsmJsonImporter::createFunctionCall(Json const& _node) +FunctionCall AsmJsonImporter::createFunctionCall(Json const& _node, YulNameRepository& _nameRepository) { auto functionCall = createAsmNode(_node); for (auto const& var: member(_node, "arguments")) - functionCall.arguments.emplace_back(createExpression(var)); + functionCall.arguments.emplace_back(createExpression(var, _nameRepository)); - functionCall.functionName = createIdentifier(member(_node, "functionName")); + functionCall.functionName = createIdentifier(member(_node, "functionName"), _nameRepository); return functionCall; } -ExpressionStatement AsmJsonImporter::createExpressionStatement(Json const& _node) +ExpressionStatement AsmJsonImporter::createExpressionStatement(Json const& _node, YulNameRepository& _nameRepository) { auto statement = createAsmNode(_node); - statement.expression = createExpression(member(_node, "expression")); + statement.expression = createExpression(member(_node, "expression"), _nameRepository); return statement; } -VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json const& _node) +VariableDeclaration AsmJsonImporter::createVariableDeclaration(Json const& _node, YulNameRepository& _nameRepository) { auto varDec = createAsmNode(_node); for (auto const& var: member(_node, "variables")) - varDec.variables.emplace_back(createTypedName(var)); + varDec.variables.emplace_back(createTypedName(var, _nameRepository)); if (_node.contains("value")) - varDec.value = std::make_unique(createExpression(member(_node, "value"))); + varDec.value = std::make_unique(createExpression(member(_node, "value"), _nameRepository)); return varDec; } -FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json const& _node) +FunctionDefinition AsmJsonImporter::createFunctionDefinition(Json const& _node, YulNameRepository& _nameRepository) { auto funcDef = createAsmNode(_node); - funcDef.name = m_yulNameRepository.defineName(member(_node, "name").get()); + funcDef.name = _nameRepository.defineName(member(_node, "name").get()); if (_node.contains("parameters")) for (auto const& var: member(_node, "parameters")) - funcDef.parameters.emplace_back(createTypedName(var)); + funcDef.parameters.emplace_back(createTypedName(var, _nameRepository)); if (_node.contains("returnVariables")) for (auto const& var: member(_node, "returnVariables")) - funcDef.returnVariables.emplace_back(createTypedName(var)); + funcDef.returnVariables.emplace_back(createTypedName(var, _nameRepository)); - funcDef.body = createBlock(member(_node, "body")); + funcDef.body = createBlock(member(_node, "body"), _nameRepository); return funcDef; } -If AsmJsonImporter::createIf(Json const& _node) +If AsmJsonImporter::createIf(Json const& _node, YulNameRepository& _nameRepository) { auto ifStatement = createAsmNode(_node); - ifStatement.condition = std::make_unique(createExpression(member(_node, "condition"))); - ifStatement.body = createBlock(member(_node, "body")); + ifStatement.condition = std::make_unique(createExpression(member(_node, "condition"), _nameRepository)); + ifStatement.body = createBlock(member(_node, "body"), _nameRepository); return ifStatement; } -Case AsmJsonImporter::createCase(Json const& _node) +Case AsmJsonImporter::createCase(Json const& _node, YulNameRepository& _nameRepository) { auto caseStatement = createAsmNode(_node); auto const& value = member(_node, "value"); if (value.is_string()) yulAssert(value.get() == "default", "Expected default case"); else - caseStatement.value = std::make_unique(createLiteral(value)); - caseStatement.body = createBlock(member(_node, "body")); + caseStatement.value = std::make_unique(createLiteral(value, _nameRepository)); + caseStatement.body = createBlock(member(_node, "body"), _nameRepository); return caseStatement; } -Switch AsmJsonImporter::createSwitch(Json const& _node) +Switch AsmJsonImporter::createSwitch(Json const& _node, YulNameRepository& _nameRepository) { auto switchStatement = createAsmNode(_node); - switchStatement.expression = std::make_unique(createExpression(member(_node, "expression"))); + switchStatement.expression = std::make_unique(createExpression(member(_node, "expression"), _nameRepository)); for (auto const& var: member(_node, "cases")) - switchStatement.cases.emplace_back(createCase(var)); + switchStatement.cases.emplace_back(createCase(var, _nameRepository)); return switchStatement; } -ForLoop AsmJsonImporter::createForLoop(Json const& _node) +ForLoop AsmJsonImporter::createForLoop(Json const& _node, YulNameRepository& _nameRepository) { auto forLoop = createAsmNode(_node); - forLoop.pre = createBlock(member(_node, "pre")); - forLoop.condition = std::make_unique(createExpression(member(_node, "condition"))); - forLoop.post = createBlock(member(_node, "post")); - forLoop.body = createBlock(member(_node, "body")); + forLoop.pre = createBlock(member(_node, "pre"), _nameRepository); + forLoop.condition = std::make_unique(createExpression(member(_node, "condition"), _nameRepository)); + forLoop.post = createBlock(member(_node, "post"), _nameRepository); + forLoop.body = createBlock(member(_node, "body"), _nameRepository); return forLoop; } diff --git a/libyul/AsmJsonImporter.h b/libyul/AsmJsonImporter.h index d7bad0a0c2c2..01fa5af31292 100644 --- a/libyul/AsmJsonImporter.h +++ b/libyul/AsmJsonImporter.h @@ -39,11 +39,11 @@ namespace solidity::yul class AsmJsonImporter { public: - explicit AsmJsonImporter(std::vector> const& _sourceNames, YulNameRepository& _yulNameRepository): - m_yulNameRepository(_yulNameRepository), m_dialect(_yulNameRepository.dialect()), m_sourceNames(_sourceNames) + explicit AsmJsonImporter(std::vector> const& _sourceNames, Dialect const& _dialect): + m_dialect(_dialect), m_sourceNames(_sourceNames) {} - yul::Block createBlock(Json const& _node); + yul::AST createAST(Json const& node); private: langutil::SourceLocation const createSourceLocation(Json const& _node); template @@ -52,28 +52,28 @@ class AsmJsonImporter /// and throw an error if it does not exist Json member(Json const& _node, std::string const& _name); - yul::Statement createStatement(Json const& _node); - yul::Expression createExpression(Json const& _node); - std::vector createStatementVector(Json const& _array); - std::vector createExpressionVector(Json const& _array); + yul::Block createBlock(Json const& _node, YulNameRepository& _nameRepository); + yul::Statement createStatement(Json const& _node, YulNameRepository& _nameRepository); + yul::Expression createExpression(Json const& _node, YulNameRepository& _nameRepository); + std::vector createStatementVector(Json const& _array, YulNameRepository& _nameRepository); + std::vector createExpressionVector(Json const& _array, YulNameRepository& _nameRepository); - yul::TypedName createTypedName(Json const& _node); - yul::Literal createLiteral(Json const& _node); + yul::TypedName createTypedName(Json const& _node, YulNameRepository& _nameRepository); + yul::Literal createLiteral(Json const& _node, YulNameRepository& _nameRepository); yul::Leave createLeave(Json const& _node); - yul::Identifier createIdentifier(Json const& _node); - yul::Assignment createAssignment(Json const& _node); - yul::FunctionCall createFunctionCall(Json const& _node); - yul::ExpressionStatement createExpressionStatement(Json const& _node); - yul::VariableDeclaration createVariableDeclaration(Json const& _node); - yul::FunctionDefinition createFunctionDefinition(Json const& _node); - yul::If createIf(Json const& _node); - yul::Case createCase(Json const& _node); - yul::Switch createSwitch(Json const& _node); - yul::ForLoop createForLoop(Json const& _node); + yul::Identifier createIdentifier(Json const& _node, YulNameRepository& _nameRepository); + yul::Assignment createAssignment(Json const& _node, YulNameRepository& _nameRepository); + yul::FunctionCall createFunctionCall(Json const& _node, YulNameRepository& _nameRepository); + yul::ExpressionStatement createExpressionStatement(Json const& _node, YulNameRepository& _nameRepository); + yul::VariableDeclaration createVariableDeclaration(Json const& _node, YulNameRepository& _nameRepository); + yul::FunctionDefinition createFunctionDefinition(Json const& _node, YulNameRepository& _nameRepository); + yul::If createIf(Json const& _node, YulNameRepository& _nameRepository); + yul::Case createCase(Json const& _node, YulNameRepository& _nameRepository); + yul::Switch createSwitch(Json const& _node, YulNameRepository& _nameRepository); + yul::ForLoop createForLoop(Json const& _node, YulNameRepository& _nameRepository); yul::Break createBreak(Json const& _node); yul::Continue createContinue(Json const& _node); - YulNameRepository& m_yulNameRepository; Dialect const& m_dialect; std::vector> const& m_sourceNames; }; diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index b92ce7b9d942..fb2667cacca3 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -36,6 +36,7 @@ #include #include +#include using namespace std::string_literals; using namespace solidity; @@ -104,16 +105,19 @@ void Parser::updateLocationEndFrom( } } -std::unique_ptr Parser::parse(CharStream& _charStream) +std::unique_ptr Parser::parse(CharStream& _charStream, std::unique_ptr _nameRepository) { m_scanner = std::make_shared(_charStream); - std::unique_ptr block = parseInline(m_scanner); + std::unique_ptr ast = parseInline(m_scanner, std::move(_nameRepository)); expectToken(Token::EOS); - return block; + return ast; } -std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanner) +std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanner, std::unique_ptr _nameRepository) { + if (_nameRepository == nullptr) + _nameRepository = std::make_unique(m_dialect); + // todo assert that the input name repository dialect and m_dialect are compatible m_recursionDepth = 0; auto previousScannerKind = _scanner->scannerKind(); @@ -125,7 +129,8 @@ std::unique_ptr Parser::parseInline(std::shared_ptr const& _scan m_scanner = _scanner; if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments) fetchDebugDataFromComment(); - return std::make_unique(parseBlock()); + auto block = parseBlock(*_nameRepository); + return std::make_unique(std::move(_nameRepository), std::move(block)); } catch (FatalError const& error) { @@ -319,35 +324,35 @@ std::optional>> Parser::parseASTI return std::nullopt; } -Block Parser::parseBlock() +Block Parser::parseBlock(YulNameRepository& _nameRepository) { RecursionGuard recursionGuard(*this); Block block = createWithDebugData(); expectToken(Token::LBrace); while (currentToken() != Token::RBrace) - block.statements.emplace_back(parseStatement()); + block.statements.emplace_back(parseStatement(_nameRepository)); updateLocationEndFrom(block.debugData, currentLocation()); advance(); return block; } -Statement Parser::parseStatement() +Statement Parser::parseStatement(YulNameRepository& _nameRepository) { RecursionGuard recursionGuard(*this); switch (currentToken()) { case Token::Let: - return parseVariableDeclaration(); + return parseVariableDeclaration(_nameRepository); case Token::Function: - return parseFunctionDefinition(); + return parseFunctionDefinition(_nameRepository); case Token::LBrace: - return parseBlock(); + return parseBlock(_nameRepository); case Token::If: { If _if = createWithDebugData(); advance(); - _if.condition = std::make_unique(parseExpression()); - _if.body = parseBlock(); + _if.condition = std::make_unique(parseExpression(_nameRepository)); + _if.body = parseBlock(_nameRepository); updateLocationEndFrom(_if.debugData, nativeLocationOf(_if.body)); return Statement{std::move(_if)}; } @@ -355,11 +360,11 @@ Statement Parser::parseStatement() { Switch _switch = createWithDebugData(); advance(); - _switch.expression = std::make_unique(parseExpression()); + _switch.expression = std::make_unique(parseExpression(_nameRepository)); while (currentToken() == Token::Case) - _switch.cases.emplace_back(parseCase()); + _switch.cases.emplace_back(parseCase(_nameRepository)); if (currentToken() == Token::Default) - _switch.cases.emplace_back(parseCase()); + _switch.cases.emplace_back(parseCase(_nameRepository)); if (currentToken() == Token::Default) fatalParserError(6931_error, "Only one default case allowed."); else if (currentToken() == Token::Case) @@ -370,7 +375,7 @@ Statement Parser::parseStatement() return Statement{std::move(_switch)}; } case Token::For: - return parseForLoop(); + return parseForLoop(_nameRepository); case Token::Break: { Statement stmt{createWithDebugData()}; @@ -400,13 +405,13 @@ Statement Parser::parseStatement() // Options left: // Expression/FunctionCall // Assignment - std::variant elementary(parseLiteralOrIdentifier()); + std::variant elementary(parseLiteralOrIdentifier(_nameRepository)); switch (currentToken()) { case Token::LParen: { - Expression expr = parseCall(std::move(elementary)); + Expression expr = parseCall(std::move(elementary), _nameRepository); return ExpressionStatement{debugDataOf(expr), std::move(expr)}; } case Token::Comma: @@ -432,12 +437,12 @@ Statement Parser::parseStatement() auto const& identifier = std::get(elementary); - if (m_yulNameRepository.isBuiltinName(identifier.name)) + if (_nameRepository.isBuiltinName(identifier.name)) fatalParserError( 6272_error, fmt::format( "Cannot assign to builtin function \"{}\".", - m_yulNameRepository.labelOf(identifier.name) + _nameRepository.labelOf(identifier.name) ) ); @@ -448,12 +453,12 @@ Statement Parser::parseStatement() expectToken(Token::Comma); - elementary = parseLiteralOrIdentifier(); + elementary = parseLiteralOrIdentifier(_nameRepository); } expectToken(Token::AssemblyAssign); - assignment.value = std::make_unique(parseExpression()); + assignment.value = std::make_unique(parseExpression(_nameRepository)); updateLocationEndFrom(assignment.debugData, nativeLocationOf(*assignment.value)); return Statement{std::move(assignment)}; @@ -467,7 +472,7 @@ Statement Parser::parseStatement() return {}; } -Case Parser::parseCase() +Case Parser::parseCase(YulNameRepository& _nameRepository) { RecursionGuard recursionGuard(*this); Case _case = createWithDebugData(); @@ -476,19 +481,19 @@ Case Parser::parseCase() else if (currentToken() == Token::Case) { advance(); - std::variant literal = parseLiteralOrIdentifier(); + std::variant literal = parseLiteralOrIdentifier(_nameRepository); if (!std::holds_alternative(literal)) fatalParserError(4805_error, "Literal expected."); _case.value = std::make_unique(std::get(std::move(literal))); } else yulAssert(false, "Case or default case expected."); - _case.body = parseBlock(); + _case.body = parseBlock(_nameRepository); updateLocationEndFrom(_case.debugData, nativeLocationOf(_case.body)); return _case; } -ForLoop Parser::parseForLoop() +ForLoop Parser::parseForLoop(YulNameRepository& _nameRepository) { RecursionGuard recursionGuard(*this); @@ -497,13 +502,13 @@ ForLoop Parser::parseForLoop() ForLoop forLoop = createWithDebugData(); expectToken(Token::For); m_currentForLoopComponent = ForLoopComponent::ForLoopPre; - forLoop.pre = parseBlock(); + forLoop.pre = parseBlock(_nameRepository); m_currentForLoopComponent = ForLoopComponent::None; - forLoop.condition = std::make_unique(parseExpression()); + forLoop.condition = std::make_unique(parseExpression(_nameRepository)); m_currentForLoopComponent = ForLoopComponent::ForLoopPost; - forLoop.post = parseBlock(); + forLoop.post = parseBlock(_nameRepository); m_currentForLoopComponent = ForLoopComponent::ForLoopBody; - forLoop.body = parseBlock(); + forLoop.body = parseBlock(_nameRepository); updateLocationEndFrom(forLoop.debugData, nativeLocationOf(forLoop.body)); m_currentForLoopComponent = outerForLoopComponent; @@ -511,21 +516,21 @@ ForLoop Parser::parseForLoop() return forLoop; } -Expression Parser::parseExpression(bool _unlimitedLiteralArgument) +Expression Parser::parseExpression(YulNameRepository& _nameRepository, bool _unlimitedLiteralArgument) { RecursionGuard recursionGuard(*this); - std::variant operation = parseLiteralOrIdentifier(_unlimitedLiteralArgument); + std::variant operation = parseLiteralOrIdentifier(_nameRepository, _unlimitedLiteralArgument); return visit(GenericVisitor{ [&](Identifier& _identifier) -> Expression { if (currentToken() == Token::LParen) - return parseCall(std::move(operation)); - if (m_yulNameRepository.isBuiltinName(_identifier.name)) + return parseCall(std::move(operation), _nameRepository); + if (_nameRepository.isBuiltinName(_identifier.name)) fatalParserError( 7104_error, nativeLocationOf(_identifier), - fmt::format("Builtin function \"{}\" must be called.", m_yulNameRepository.labelOf(_identifier.name)) + fmt::format("Builtin function \"{}\" must be called.", _nameRepository.labelOf(_identifier.name)) ); return std::move(_identifier); }, @@ -536,14 +541,14 @@ Expression Parser::parseExpression(bool _unlimitedLiteralArgument) }, operation); } -std::variant Parser::parseLiteralOrIdentifier(bool _unlimitedLiteralArgument) +std::variant Parser::parseLiteralOrIdentifier(YulNameRepository& _nameRepository, bool _unlimitedLiteralArgument) { RecursionGuard recursionGuard(*this); switch (currentToken()) { case Token::Identifier: { - Identifier identifier{createDebugData(), m_yulNameRepository.defineName(currentLiteral())}; + Identifier identifier{createDebugData(), _nameRepository.defineName(currentLiteral())}; advance(); return identifier; } @@ -577,14 +582,14 @@ std::variant Parser::parseLiteralOrIdentifier(bool _unlimit createDebugData(), kind, valueOfLiteral(currentLiteral(), kind, _unlimitedLiteralArgument && kind == LiteralKind::String), - kind == LiteralKind::Boolean ? m_yulNameRepository.predefined().boolType : m_yulNameRepository.predefined().defaultType + kind == LiteralKind::Boolean ? _nameRepository.predefined().boolType : _nameRepository.predefined().defaultType }; advance(); if (currentToken() == Token::Colon) { expectToken(Token::Colon); updateLocationEndFrom(literal.debugData, currentLocation()); - literal.type = expectAsmIdentifier(); + literal.type = expectAsmIdentifier(_nameRepository); } return literal; @@ -598,14 +603,14 @@ std::variant Parser::parseLiteralOrIdentifier(bool _unlimit return {}; } -VariableDeclaration Parser::parseVariableDeclaration() +VariableDeclaration Parser::parseVariableDeclaration(YulNameRepository& _nameRepository) { RecursionGuard recursionGuard(*this); VariableDeclaration varDecl = createWithDebugData(); expectToken(Token::Let); while (true) { - varDecl.variables.emplace_back(parseTypedName()); + varDecl.variables.emplace_back(parseTypedName(_nameRepository)); if (currentToken() == Token::Comma) expectToken(Token::Comma); else @@ -614,7 +619,7 @@ VariableDeclaration Parser::parseVariableDeclaration() if (currentToken() == Token::AssemblyAssign) { expectToken(Token::AssemblyAssign); - varDecl.value = std::make_unique(parseExpression()); + varDecl.value = std::make_unique(parseExpression(_nameRepository)); updateLocationEndFrom(varDecl.debugData, nativeLocationOf(*varDecl.value)); } else @@ -623,7 +628,7 @@ VariableDeclaration Parser::parseVariableDeclaration() return varDecl; } -FunctionDefinition Parser::parseFunctionDefinition() +FunctionDefinition Parser::parseFunctionDefinition(YulNameRepository& _nameRepository) { RecursionGuard recursionGuard(*this); @@ -639,11 +644,11 @@ FunctionDefinition Parser::parseFunctionDefinition() FunctionDefinition funDef = createWithDebugData(); expectToken(Token::Function); - funDef.name = expectAsmIdentifier(); + funDef.name = expectAsmIdentifier(_nameRepository); expectToken(Token::LParen); while (currentToken() != Token::RParen) { - funDef.parameters.emplace_back(parseTypedName()); + funDef.parameters.emplace_back(parseTypedName(_nameRepository)); if (currentToken() == Token::RParen) break; expectToken(Token::Comma); @@ -654,7 +659,7 @@ FunctionDefinition Parser::parseFunctionDefinition() expectToken(Token::RightArrow); while (true) { - funDef.returnVariables.emplace_back(parseTypedName()); + funDef.returnVariables.emplace_back(parseTypedName(_nameRepository)); if (currentToken() == Token::LBrace) break; expectToken(Token::Comma); @@ -662,7 +667,7 @@ FunctionDefinition Parser::parseFunctionDefinition() } bool preInsideFunction = m_insideFunction; m_insideFunction = true; - funDef.body = parseBlock(); + funDef.body = parseBlock(_nameRepository); m_insideFunction = preInsideFunction; updateLocationEndFrom(funDef.debugData, nativeLocationOf(funDef.body)); @@ -670,7 +675,7 @@ FunctionDefinition Parser::parseFunctionDefinition() return funDef; } -FunctionCall Parser::parseCall(std::variant&& _initialOp) +FunctionCall Parser::parseCall(std::variant&& _initialOp, YulNameRepository& _nameRepository) { RecursionGuard recursionGuard(*this); @@ -680,7 +685,7 @@ FunctionCall Parser::parseCall(std::variant&& _initialOp) FunctionCall ret; ret.functionName = std::move(std::get(_initialOp)); ret.debugData = ret.functionName.debugData; - auto const isUnlimitedLiteralArgument = [f=m_yulNameRepository.builtin(ret.functionName.name)](size_t const index) { + auto const isUnlimitedLiteralArgument = [f=_nameRepository.builtin(ret.functionName.name)](size_t const index) { if (f && index < f->data->literalArguments.size()) return f->data->literalArgument(index).has_value(); return false; @@ -689,11 +694,11 @@ FunctionCall Parser::parseCall(std::variant&& _initialOp) expectToken(Token::LParen); if (currentToken() != Token::RParen) { - ret.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); + ret.arguments.emplace_back(parseExpression(_nameRepository, isUnlimitedLiteralArgument(argumentIndex++))); while (currentToken() != Token::RParen) { expectToken(Token::Comma); - ret.arguments.emplace_back(parseExpression(isUnlimitedLiteralArgument(argumentIndex++))); + ret.arguments.emplace_back(parseExpression(_nameRepository, isUnlimitedLiteralArgument(argumentIndex++))); } } updateLocationEndFrom(ret.debugData, currentLocation()); @@ -701,27 +706,27 @@ FunctionCall Parser::parseCall(std::variant&& _initialOp) return ret; } -TypedName Parser::parseTypedName() +TypedName Parser::parseTypedName(YulNameRepository& _nameRepository) { RecursionGuard recursionGuard(*this); TypedName typedName = createWithDebugData(); - typedName.name = expectAsmIdentifier(); + typedName.name = expectAsmIdentifier(_nameRepository); if (currentToken() == Token::Colon) { expectToken(Token::Colon); updateLocationEndFrom(typedName.debugData, currentLocation()); - typedName.type = expectAsmIdentifier(); + typedName.type = expectAsmIdentifier(_nameRepository); } else - typedName.type = m_yulNameRepository.predefined().defaultType; + typedName.type = _nameRepository.predefined().defaultType; return typedName; } -Type Parser::expectAsmIdentifier() +Type Parser::expectAsmIdentifier(YulNameRepository& _nameRepository) { - auto const name = m_yulNameRepository.defineName(currentLiteral()); - if (currentToken() == Token::Identifier && m_yulNameRepository.dialect().builtin(currentLiteral())) + auto const name = _nameRepository.defineName(currentLiteral()); + if (currentToken() == Token::Identifier && _nameRepository.dialect().builtin(currentLiteral())) fatalParserError( 5568_error, fmt::format( diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 5eca4041d1b9..62e33c9bb19e 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -55,11 +55,11 @@ class Parser: public langutil::ParserBase explicit Parser( langutil::ErrorReporter& _errorReporter, - YulNameRepository& _yulNameRepository, + Dialect const& _dialect, std::optional _locationOverride = {} ): ParserBase(_errorReporter), - m_yulNameRepository(_yulNameRepository), + m_dialect(_dialect), m_locationOverride{_locationOverride ? *_locationOverride : langutil::SourceLocation{}}, m_useSourceLocationFrom{ _locationOverride ? @@ -72,11 +72,11 @@ class Parser: public langutil::ParserBase /// from the comments (via @src and other tags). explicit Parser( langutil::ErrorReporter& _errorReporter, - YulNameRepository& _yulNameRepository, + Dialect const& _dialect, std::optional>> _sourceNames ): ParserBase(_errorReporter), - m_yulNameRepository(_yulNameRepository), + m_dialect(_dialect), m_sourceNames{std::move(_sourceNames)}, m_useSourceLocationFrom{ m_sourceNames.has_value() ? @@ -87,12 +87,12 @@ class Parser: public langutil::ParserBase /// Parses an inline assembly block starting with `{` and ending with `}`. /// @returns an empty shared pointer on error. - std::unique_ptr parseInline(std::shared_ptr const& _scanner); + std::unique_ptr parseInline(std::shared_ptr const& _scanner, std::unique_ptr _nameRepository = nullptr); /// Parses an assembly block starting with `{` and ending with `}` /// and expects end of input after the '}'. /// @returns an empty shared pointer on error. - std::unique_ptr parse(langutil::CharStream& _charStream); + std::unique_ptr parse(langutil::CharStream& _charStream, std::unique_ptr _nameRepository = nullptr); protected: langutil::SourceLocation currentLocation() const override @@ -133,20 +133,20 @@ class Parser: public langutil::ParserBase return r; } - Block parseBlock(); - Statement parseStatement(); - Case parseCase(); - ForLoop parseForLoop(); + Block parseBlock(YulNameRepository& _nameRepository); + Statement parseStatement(YulNameRepository& _nameRepository); + Case parseCase(YulNameRepository& _nameRepository); + ForLoop parseForLoop(YulNameRepository& _nameRepository); /// Parses a functional expression that has to push exactly one stack element - Expression parseExpression(bool _unlimitedLiteralArgument = false); + Expression parseExpression(YulNameRepository& _nameRepository, bool _unlimitedLiteralArgument = false); /// Parses an elementary operation, i.e. a literal, identifier, instruction or /// builtin function call (only the name). - std::variant parseLiteralOrIdentifier(bool _unlimitedLiteralArgument = false); - VariableDeclaration parseVariableDeclaration(); - FunctionDefinition parseFunctionDefinition(); - FunctionCall parseCall(std::variant&& _initialOp); - TypedName parseTypedName(); - Type expectAsmIdentifier(); + std::variant parseLiteralOrIdentifier(YulNameRepository& _nameRepository, bool _unlimitedLiteralArgument = false); + VariableDeclaration parseVariableDeclaration(YulNameRepository& _nameRepository); + FunctionDefinition parseFunctionDefinition(YulNameRepository& _nameRepository); + FunctionCall parseCall(std::variant&& _initialOp, YulNameRepository& _nameRepository); + TypedName parseTypedName(YulNameRepository& _nameRepository); + Type expectAsmIdentifier(YulNameRepository& _nameRepository); /// Reports an error if we are currently not inside the body part of a for loop. void checkBreakContinuePosition(std::string const& _which); @@ -154,7 +154,7 @@ class Parser: public langutil::ParserBase static bool isValidNumberLiteral(std::string const& _literal); private: - YulNameRepository& m_yulNameRepository; + Dialect const& m_dialect; std::optional>> m_sourceNames; langutil::SourceLocation m_locationOverride; diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 49a96f15b427..1a715f9cfee3 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -31,17 +31,15 @@ using namespace solidity::yul; using namespace solidity::util; CompilabilityChecker::CompilabilityChecker( - YulNameRepository const& _yulNameRepository, Object const& _object, bool _optimizeStackAllocation ) { - if (auto const* evmDialect = dynamic_cast(&_yulNameRepository.dialect())) + if (auto const* evmDialect = dynamic_cast(&_object.code->nameRepository().dialect())) { NoOutputEVMDialect noOutputDialect(*evmDialect); - yul::AsmAnalysisInfo analysisInfo = - yul::AsmAnalyzer::analyzeStrictAssertCorrect(_yulNameRepository, _object); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_object); BuiltinContext builtinContext; builtinContext.currentObject = &_object; @@ -54,12 +52,11 @@ CompilabilityChecker::CompilabilityChecker( assembly, analysisInfo, *_object.code, - _yulNameRepository, noOutputDialect, builtinContext, _optimizeStackAllocation ); - transform(*_object.code); + transform(_object.code->block()); for (StackTooDeepError const& error: transform.stackErrors()) { diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index 782021dd4303..0c88232fe021 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -44,7 +44,7 @@ namespace solidity::yul */ struct CompilabilityChecker { - CompilabilityChecker(YulNameRepository const& _yulNameRepository, Object const& _object, bool _optimizeStackAllocation); + CompilabilityChecker(Object const& _object, bool _optimizeStackAllocation); std::map> unreachableVariables; std::map stackDeficit; }; diff --git a/libyul/Object.cpp b/libyul/Object.cpp index bdc9a97b7880..92819537b66c 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -38,13 +38,12 @@ using namespace solidity::langutil; using namespace solidity::util; using namespace solidity::yul; -std::string Data::toString(YulNameRepository const&, AsmPrinter::Mode, DebugInfoSelection const&, CharStreamProvider const*) const +std::string Data::toString(AsmPrinter::Mode, DebugInfoSelection const&, CharStreamProvider const*) const { return "data \"" + name + "\" hex\"" + util::toHex(data) + "\""; } std::string Object::toString( - YulNameRepository const& _yulNameRepository, AsmPrinter::Mode const _printingMode, DebugInfoSelection const& _debugInfoSelection, CharStreamProvider const* _soliditySourceProvider @@ -64,15 +63,15 @@ std::string Object::toString( "\n"; std::string inner = "code " + AsmPrinter( - _yulNameRepository, + code->nameRepository(), _printingMode, debugData->sourceNames, _debugInfoSelection, _soliditySourceProvider - )(*code); + )(code->block()); for (auto const& obj: subObjects) - inner += "\n" + obj->toString(_yulNameRepository, _printingMode, _debugInfoSelection, _soliditySourceProvider); + inner += "\n" + obj->toString(_printingMode, _debugInfoSelection, _soliditySourceProvider); return useSrcComment + "object \"" + name + "\" {\n" + indent(inner) + "\n}"; } @@ -90,7 +89,7 @@ Json Object::toJson(YulNameRepository const& _yulNameRepository) const yulAssert(code, "No code"); Json codeJson; - codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */, _yulNameRepository)(*code); + codeJson["block"] = AsmJsonConverter(0 /* sourceIndex */, code->nameRepository())(code->block()); Json subObjectsJson = Json::array(); for (std::shared_ptr const& subObject: subObjects) diff --git a/libyul/Object.h b/libyul/Object.h index 83780b38bd39..1b9af84fd678 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -55,7 +55,6 @@ struct ObjectNode /// Can be empty since .yul files can also just contain code, without explicitly placing it in an object. std::string name; virtual std::string toString( - YulNameRepository const& _yulNameRepository, AsmPrinter::Mode printingMode, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider @@ -73,7 +72,6 @@ struct Data: public ObjectNode bytes data; std::string toString( - YulNameRepository const& _yulNameRepository, AsmPrinter::Mode printingMode, langutil::DebugInfoSelection const& _debugInfoSelection, langutil::CharStreamProvider const* _soliditySourceProvider @@ -96,7 +94,6 @@ struct Object: public ObjectNode public: /// @returns a (parseable) string representation. std::string toString( - YulNameRepository const& _yulNameRepository, AsmPrinter::Mode printingMode = AsmPrinter::Mode::FullTypeInfo, langutil::DebugInfoSelection const& _debugInfoSelection = langutil::DebugInfoSelection::Default(), langutil::CharStreamProvider const* _soliditySourceProvider = nullptr @@ -123,7 +120,7 @@ struct Object: public ObjectNode /// sub id for object if it is subobject of another object, max value if it is not subobject size_t subId = std::numeric_limits::max(); - std::shared_ptr code; + std::shared_ptr code; std::vector> subObjects; std::map> subIndexByName; std::shared_ptr analysisInfo; diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 798568a18bdd..58240799e54c 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -106,7 +106,7 @@ std::shared_ptr ObjectParser::parseObject(Object* _containingObject) return ret; } -std::shared_ptr ObjectParser::parseCode(std::optional _sourceNames) +std::shared_ptr ObjectParser::parseCode(std::optional _sourceNames) { if (currentToken() != Token::Identifier || currentLiteral() != "code") fatalParserError(4846_error, "Expected keyword \"code\"."); @@ -169,12 +169,12 @@ std::optional ObjectParser::tryParseSourceNameMapping() const return std::nullopt; } -std::shared_ptr ObjectParser::parseBlock(std::optional _sourceNames) +std::shared_ptr ObjectParser::parseBlock(std::optional _sourceNames) { - Parser parser(m_errorReporter, m_yulNameRepository, std::move(_sourceNames)); - std::shared_ptr block = parser.parseInline(m_scanner); - yulAssert(block || m_errorReporter.hasErrors(), "Invalid block but no error!"); - return block; + Parser parser(m_errorReporter, m_dialect, std::move(_sourceNames)); + auto ast = parser.parseInline(m_scanner); + yulAssert(ast || m_errorReporter.hasErrors(), "Invalid block but no error!"); + return ast; } void ObjectParser::parseData(Object& _containingObject) diff --git a/libyul/ObjectParser.h b/libyul/ObjectParser.h index f06f0b5850d8..1d7756f5ae71 100644 --- a/libyul/ObjectParser.h +++ b/libyul/ObjectParser.h @@ -45,8 +45,8 @@ namespace solidity::yul class ObjectParser: public langutil::ParserBase { public: - explicit ObjectParser(langutil::ErrorReporter& _errorReporter, YulNameRepository& _yulNameRepository): - ParserBase(_errorReporter), m_yulNameRepository(_yulNameRepository) {} + explicit ObjectParser(langutil::ErrorReporter& _errorReporter, Dialect const& _dialect): + ParserBase(_errorReporter), m_dialect(_dialect) {} /// Parses a Yul object. /// Falls back to code-only parsing if the source starts with `{`. @@ -57,15 +57,15 @@ class ObjectParser: public langutil::ParserBase private: std::optional tryParseSourceNameMapping() const; std::shared_ptr parseObject(Object* _containingObject = nullptr); - std::shared_ptr parseCode(std::optional _sourceNames); - std::shared_ptr parseBlock(std::optional _sourceNames); + std::shared_ptr parseCode(std::optional _sourceNames); + std::shared_ptr parseBlock(std::optional _sourceNames); void parseData(Object& _containingObject); /// Tries to parse a name that is non-empty and unique inside the containing object. std::string parseUniqueName(Object const* _containingObject); void addNamedSubObject(Object& _container, std::string_view _name, std::shared_ptr _subObject); - YulNameRepository& m_yulNameRepository; + Dialect const& m_dialect; }; } diff --git a/libyul/Scope.cpp b/libyul/Scope.cpp index a84ce7d42d35..5443437b7768 100644 --- a/libyul/Scope.cpp +++ b/libyul/Scope.cpp @@ -25,9 +25,9 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; -bool Scope::registerVariable(YulName const _name, YulType const& _type, YulNameRepository const& _nameRepository) +bool Scope::registerVariable(YulName const _name, YulType const& _type) { - if (exists(_name, _nameRepository)) + if (exists(_name)) return false; Variable variable; variable.type = _type; @@ -37,9 +37,9 @@ bool Scope::registerVariable(YulName const _name, YulType const& _type, YulNameR return true; } -bool Scope::registerFunction(YulName const _name, std::vector _arguments, std::vector _returns, YulNameRepository const& _nameRepository) +bool Scope::registerFunction(YulName const _name, std::vector _arguments, std::vector _returns) { - if (exists(_name, _nameRepository)) + if (exists(_name)) return false; identifiers[_name] = Function{std::move(_arguments), std::move(_returns), _name}; identifierLabels.emplace(_name); @@ -66,12 +66,12 @@ Scope::Identifier* Scope::lookup(YulName _name) return nullptr; } -bool Scope::exists(YulName const _name, YulNameRepository const& _nameRepository) const +bool Scope::exists(YulName const _name) const { if (identifierLabels.count(_name)) return true; else if (superScope) - return superScope->exists(_name, _nameRepository); + return superScope->exists(_name); else return false; } diff --git a/libyul/Scope.h b/libyul/Scope.h index ff0e8254be9e..244d0d3ff217 100644 --- a/libyul/Scope.h +++ b/libyul/Scope.h @@ -51,12 +51,11 @@ struct Scope using Identifier = std::variant; - bool registerVariable(YulName _name, YulType const& _type, YulNameRepository const& _nameRepository); + bool registerVariable(YulName _name, YulType const& _type); bool registerFunction( YulName _name, std::vector _arguments, - std::vector _returns, - YulNameRepository const& _nameRepository + std::vector _returns ); /// Looks up the identifier in this or super scopes and returns a valid pointer if found @@ -81,7 +80,7 @@ struct Scope } /// @returns true if the name exists in this scope or in super scopes (also searches /// across function and assembly boundaries). - bool exists(YulName _name, YulNameRepository const& _nameRepository) const; + bool exists(YulName _name) const; /// @returns the number of variables directly registered inside the scope. size_t numberOfVariables() const; diff --git a/libyul/ScopeFiller.cpp b/libyul/ScopeFiller.cpp index 4d530094da3b..63dddfcab433 100644 --- a/libyul/ScopeFiller.cpp +++ b/libyul/ScopeFiller.cpp @@ -136,7 +136,7 @@ bool ScopeFiller::operator()(Block const& _block) bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const& _location, Scope& _scope) { - if (!_scope.registerVariable(_name.name, _name.type, m_yulNameRegistry)) + if (!_scope.registerVariable(_name.name, _name.type)) { //@TODO secondary location m_errorReporter.declarationError( @@ -157,7 +157,7 @@ bool ScopeFiller::registerFunction(FunctionDefinition const& _funDef) std::vector returns; for (auto const& returnVariable: _funDef.returnVariables) returns.emplace_back(returnVariable.type); - if (!m_currentScope->registerFunction(_funDef.name, std::move(parameters), std::move(returns), m_yulNameRegistry)) + if (!m_currentScope->registerFunction(_funDef.name, std::move(parameters), std::move(returns))) { //@TODO secondary location m_errorReporter.declarationError( diff --git a/libyul/YulStack.cpp b/libyul/YulStack.cpp index 71a0de2232bb..975425fe0e54 100644 --- a/libyul/YulStack.cpp +++ b/libyul/YulStack.cpp @@ -62,20 +62,6 @@ EVMDialect const& languageToDialect(YulStack::Language _language, EVMVersion _ve } -YulStack::YulStack( - langutil::EVMVersion _evmVersion, - std::optional _eofVersion, - solidity::yul::YulStack::Language _language, - solidity::frontend::OptimiserSettings _optimiserSettings, - langutil::DebugInfoSelection const& _debugInfoSelection -): - m_yulNameRepository(std::make_shared(languageToDialect(_language, _evmVersion))), - m_evmVersion(_evmVersion), - m_eofVersion(_eofVersion), - m_optimiserSettings(std::move(_optimiserSettings)), - m_debugInfoSelection(_debugInfoSelection), - m_errorReporter(m_errors) -{} CharStream const& YulStack::charStream(std::string const& _sourceName) const { @@ -91,7 +77,7 @@ bool YulStack::parse(std::string const& _sourceName, std::string const& _source) { m_charStream = std::make_unique(_source, _sourceName); std::shared_ptr scanner = std::make_shared(*m_charStream); - m_parserResult = ObjectParser(m_errorReporter, *yulNameRepository()).parse(scanner, false); + m_parserResult = ObjectParser(m_errorReporter, languageToDialect(m_language, m_evmVersion)).parse(scanner, false); } catch (UnimplementedFeatureError const& _error) { @@ -128,7 +114,7 @@ void YulStack::optimize() { if ( !m_optimiserSettings.runYulOptimiser && - yul::MSizeFinder::containsMSize(*yulNameRepository(), *m_parserResult) + yul::MSizeFinder::containsMSize(*m_parserResult) ) return; @@ -158,7 +144,7 @@ bool YulStack::analyzeParsed(Object& _object) AsmAnalyzer analyzer( *_object.analysisInfo, m_errorReporter, - *yulNameRepository(), + _object.code->nameRepository(), {}, _object.qualifiedDataNames() ); @@ -166,7 +152,7 @@ bool YulStack::analyzeParsed(Object& _object) bool success = false; try { - success = analyzer.analyze(*_object.code); + success = analyzer.analyze(_object.code->block()); for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) if (!analyzeParsed(*subObject)) @@ -186,17 +172,19 @@ bool YulStack::analyzeParsed(Object& _object) void YulStack::compileEVM(AbstractAssembly& _assembly, bool _optimize) { - auto const* evmDialect = dynamic_cast(&yulNameRepository()->dialect()); - yulAssert(evmDialect); - EVMObjectCompiler::compile(*m_parserResult, _assembly, *yulNameRepository(), *evmDialect, _optimize, m_eofVersion); + EVMObjectCompiler::compile( + *m_parserResult, + _assembly, + languageToDialect(m_language, m_evmVersion), + _optimize, + m_eofVersion + ); } void YulStack::optimize(Object& _object, bool _isCreation) { yulAssert(_object.code, ""); yulAssert(_object.analysisInfo, ""); - auto const* evmDialect = dynamic_cast(&yulNameRepository()->dialect()); - yulAssert(evmDialect); for (auto& subNode: _object.subObjects) if (auto subObject = dynamic_cast(subNode.get())) { @@ -205,7 +193,7 @@ void YulStack::optimize(Object& _object, bool _isCreation) } std::unique_ptr meter; - meter = std::make_unique(*yulNameRepository(), *evmDialect, _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment); + meter = std::make_unique(_object.code->nameRepository(), languageToDialect(m_language, m_evmVersion), _isCreation, m_optimiserSettings.expectedExecutionsPerDeployment); auto [optimizeStackAllocation, yulOptimiserSteps, yulOptimiserCleanupSteps] = [&]() -> std::tuple { @@ -233,7 +221,6 @@ void YulStack::optimize(Object& _object, bool _isCreation) }(); OptimiserSuite::run( - *yulNameRepository(), meter.get(), _object, // Defaults are the minimum necessary to avoid running into "Stack too deep" constantly. @@ -318,7 +305,7 @@ YulStack::assembleEVMWithDeployed(std::optional _deployName) // it with the minimal steps required to avoid "stack too deep". bool optimize = m_optimiserSettings.optimizeStackAllocation || ( !m_optimiserSettings.runYulOptimiser && - !yul::MSizeFinder::containsMSize(*yulNameRepository(), *m_parserResult) + !yul::MSizeFinder::containsMSize(*m_parserResult) ); try { @@ -365,7 +352,7 @@ std::string YulStack::print( yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); - return m_parserResult->toString(*yulNameRepository(), AsmPrinter::Mode::FullTypeInfo, m_debugInfoSelection, _soliditySourceProvider) + "\n"; + return m_parserResult->toString(AsmPrinter::Mode::FullTypeInfo, m_debugInfoSelection, _soliditySourceProvider) + "\n"; } Json YulStack::astJson() const @@ -373,7 +360,7 @@ Json YulStack::astJson() const yulAssert(m_stackState >= Parsed); yulAssert(m_parserResult, ""); yulAssert(m_parserResult->code, ""); - return m_parserResult->toJson(*yulNameRepository()); + return m_parserResult->toJson(m_parserResult->code->nameRepository()); } std::shared_ptr YulStack::parserResult() const @@ -389,8 +376,3 @@ void YulStack::reportUnimplementedFeatureError(UnimplementedFeatureError const& solAssert(_error.comment(), "Unimplemented feature errors must include a message for the user"); m_errorReporter.unimplementedFeatureError(1920_error, _error.sourceLocation(), *_error.comment()); } - -std::shared_ptr const YulStack::yulNameRepository() const -{ - return m_yulNameRepository; -} diff --git a/libyul/YulStack.h b/libyul/YulStack.h index cc8b34e617c8..4422cc284c41 100644 --- a/libyul/YulStack.h +++ b/libyul/YulStack.h @@ -90,7 +90,14 @@ class YulStack: public langutil::CharStreamProvider Language _language, solidity::frontend::OptimiserSettings _optimiserSettings, langutil::DebugInfoSelection const& _debugInfoSelection - ); + ): + m_language(_language), + m_evmVersion(_evmVersion), + m_eofVersion(_eofVersion), + m_optimiserSettings(std::move(_optimiserSettings)), + m_debugInfoSelection(_debugInfoSelection), + m_errorReporter(m_errors) + {} /// @returns the char stream used during parsing langutil::CharStream const& charStream(std::string const& _sourceName) const override; @@ -134,8 +141,6 @@ class YulStack: public langutil::CharStreamProvider /// Return the parsed and analyzed object. std::shared_ptr parserResult() const; - std::shared_ptr const yulNameRepository() const; - private: bool parse(std::string const& _sourceName, std::string const& _source); bool analyzeParsed(); @@ -147,8 +152,7 @@ class YulStack: public langutil::CharStreamProvider void reportUnimplementedFeatureError(langutil::UnimplementedFeatureError const& _error); - std::shared_ptr m_yulNameRepository; - + Language m_language = Language::Assembly; langutil::EVMVersion m_evmVersion; std::optional m_eofVersion; solidity::frontend::OptimiserSettings m_optimiserSettings; diff --git a/libyul/backends/evm/AsmCodeGen.cpp b/libyul/backends/evm/AsmCodeGen.cpp index 1a1edb711282..a90c61a64886 100644 --- a/libyul/backends/evm/AsmCodeGen.cpp +++ b/libyul/backends/evm/AsmCodeGen.cpp @@ -34,11 +34,10 @@ using namespace solidity::util; using namespace solidity::langutil; void CodeGenerator::assemble( - Block const& _parsedData, + AST const& _parsedData, AsmAnalysisInfo& _analysisInfo, evmasm::Assembly& _assembly, langutil::EVMVersion _evmVersion, - YulNameRepository const& _yulNameRepository, ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, bool _useNamedLabelsForFunctions, bool _optimizeStackAllocation @@ -50,7 +49,6 @@ void CodeGenerator::assemble( assemblyAdapter, _analysisInfo, _parsedData, - _yulNameRepository, EVMDialect::strictAssemblyForEVM(_evmVersion), builtinContext, _optimizeStackAllocation, @@ -59,7 +57,7 @@ void CodeGenerator::assemble( CodeTransform::UseNamedLabels::YesAndForceUnique : CodeTransform::UseNamedLabels::Never ); - transform(_parsedData); + transform(_parsedData.block()); if (!transform.stackErrors().empty()) assertThrow( false, diff --git a/libyul/backends/evm/AsmCodeGen.h b/libyul/backends/evm/AsmCodeGen.h index 13cfe48c8315..060068e9f595 100644 --- a/libyul/backends/evm/AsmCodeGen.h +++ b/libyul/backends/evm/AsmCodeGen.h @@ -40,11 +40,10 @@ class CodeGenerator public: /// Performs code generation and appends generated to _assembly. static void assemble( - Block const& _parsedData, + AST const& _parsedData, AsmAnalysisInfo& _analysisInfo, evmasm::Assembly& _assembly, langutil::EVMVersion _evmVersion, - YulNameRepository const& _yulNameRepository, ExternalIdentifierAccess::CodeGenerator _identifierAccess = {}, bool _useNamedLabelsForFunctions = false, bool _optimizeStackAllocation = false diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 8d2b2915af15..e23b68ec9141 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -50,8 +50,8 @@ CodeTransform::CodeTransform( AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, Block const& _block, + YulNameRepository const& _nameRepository, bool _allowStackOpt, - YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, BuiltinContext& _builtinContext, ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, @@ -62,7 +62,7 @@ CodeTransform::CodeTransform( ): m_assembly(_assembly), m_info(_analysisInfo), - m_yulNameRepository(_yulNameRepository), + m_yulNameRepository(_nameRepository), m_dialect(_dialect), m_builtinContext(_builtinContext), m_allowStackOpt(_allowStackOpt), @@ -387,8 +387,8 @@ void CodeTransform::operator()(FunctionDefinition const& _function) m_assembly, m_info, _function.body, - m_allowStackOpt, m_yulNameRepository, + m_allowStackOpt, m_dialect, m_builtinContext, m_identifierAccessCodeGen, diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index fcdedb05c5cd..212249f57e57 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -77,8 +77,7 @@ class CodeTransform CodeTransform( AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, - Block const& _block, - YulNameRepository const& _yulNameRepository, + AST const& _ast, EVMDialect const& _dialect, BuiltinContext& _builtinContext, bool _allowStackOpt = false, @@ -87,9 +86,9 @@ class CodeTransform ): CodeTransform( _assembly, _analysisInfo, - _block, + _ast.block(), + _ast.nameRepository(), _allowStackOpt, - _yulNameRepository, _dialect, _builtinContext, _identifierAccessCodeGen, @@ -110,8 +109,8 @@ class CodeTransform AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, Block const& _block, + YulNameRepository const& _nameRepository, bool _allowStackOpt, - YulNameRepository const& _yulNameRepository, EVMDialect const& _dialect, BuiltinContext& _builtinContext, ExternalIdentifierAccess::CodeGenerator _identifierAccessCodeGen, diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index c403bebf5680..bc323bfc084d 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -37,13 +37,12 @@ using namespace solidity::yul; void EVMObjectCompiler::compile( Object& _object, AbstractAssembly& _assembly, - YulNameRepository& _yulNameRepository, EVMDialect const& _dialect, bool _optimize, std::optional _eofVersion ) { - EVMObjectCompiler compiler(_assembly, _yulNameRepository, _dialect, _eofVersion); + EVMObjectCompiler compiler(_assembly, _dialect, _eofVersion); compiler.run(_object, _optimize); } @@ -60,7 +59,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) auto subAssemblyAndID = m_assembly.createSubAssembly(isCreation, subObject->name); context.subIDs[subObject->name] = subAssemblyAndID.second; subObject->subId = subAssemblyAndID.second; - compile(*subObject, *subAssemblyAndID.first, m_yulNameRepository, m_dialect, _optimize, m_eofVersion); + compile(*subObject, *subAssemblyAndID.first, m_dialect, _optimize, m_eofVersion); } else { @@ -84,16 +83,16 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) auto stackErrors = OptimizedEVMCodeTransform::run( m_assembly, *_object.analysisInfo, - *_object.code, - m_yulNameRepository, + _object.code->block(), + _object.code->nameRepository(), context, OptimizedEVMCodeTransform::UseNamedLabels::ForFirstFunctionOfEachName ); if (!stackErrors.empty()) { std::vector memoryGuardCalls = FunctionCallFinder::run( - *_object.code, - m_yulNameRepository.predefined().memoryguard + _object.code->block(), + _object.code->nameRepository().predefined().memoryguard ); auto stackError = stackErrors.front(); std::string msg = stackError.comment() ? *stackError.comment() : ""; @@ -115,14 +114,13 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) m_assembly, *_object.analysisInfo, *_object.code, - m_yulNameRepository, m_dialect, context, _optimize, {}, CodeTransform::UseNamedLabels::ForFirstFunctionOfEachName }; - transform(*_object.code); + transform(_object.code->block()); if (!transform.stackErrors().empty()) BOOST_THROW_EXCEPTION(transform.stackErrors().front()); } diff --git a/libyul/backends/evm/EVMObjectCompiler.h b/libyul/backends/evm/EVMObjectCompiler.h index 3c9fabbbfa79..fba600c4f2a9 100644 --- a/libyul/backends/evm/EVMObjectCompiler.h +++ b/libyul/backends/evm/EVMObjectCompiler.h @@ -37,20 +37,18 @@ class EVMObjectCompiler static void compile( Object& _object, AbstractAssembly& _assembly, - YulNameRepository& _yulNameRepository, EVMDialect const& _dialect, bool _optimize, std::optional _eofVersion ); private: - EVMObjectCompiler(AbstractAssembly& _assembly, YulNameRepository& _yulNameRepository, EVMDialect const& _dialect, std::optional _eofVersion): - m_assembly(_assembly), m_yulNameRepository(_yulNameRepository), m_dialect(_dialect), m_eofVersion(_eofVersion) + EVMObjectCompiler(AbstractAssembly& _assembly, EVMDialect const& _dialect, std::optional _eofVersion): + m_assembly(_assembly), m_dialect(_dialect), m_eofVersion(_eofVersion) {} void run(Object& _object, bool _optimize); AbstractAssembly& m_assembly; - YulNameRepository& m_yulNameRepository; EVMDialect const& m_dialect; std::optional m_eofVersion; }; diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index f204d593a457..48ee2f5a2f5c 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -93,19 +93,24 @@ bool MSizeFinder::containsMSize(YulNameRepository const& _yulNameRepository, Blo return finder.m_msizeFound; } -bool MSizeFinder::containsMSize(YulNameRepository const& _yulNameRepository, Object const& _object) +bool MSizeFinder::containsMSize(Object const& _object) { - if (containsMSize(_yulNameRepository, *_object.code)) + if (containsMSize(_object.code->nameRepository(), _object.code->block())) return true; for (std::shared_ptr const& node: _object.subObjects) if (auto const* object = dynamic_cast(node.get())) - if (containsMSize(_yulNameRepository, *object)) + if (containsMSize(*object)) return true; return false; } +bool MSizeFinder::containsMSize(AST const& _ast) +{ + return containsMSize(_ast.nameRepository(), _ast.block()); +} + void MSizeFinder::operator()(FunctionCall const& _functionCall) { ASTWalker::operator()(_functionCall); diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index a7e2649da9ff..2392858b45d8 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -60,6 +60,10 @@ class SideEffectsCollector: public ASTWalker ForLoop const& _ast, std::map const* _functionSideEffects = nullptr ); + SideEffectsCollector( + AST const& _ast, + std::map const* _functionSideEffects = nullptr + ) : SideEffectsCollector(_ast.nameRepository(), _ast.block(), _functionSideEffects) {} using ASTWalker::operator(); void operator()(FunctionCall const& _functionCall) override; @@ -149,7 +153,8 @@ class MSizeFinder: public ASTWalker { public: static bool containsMSize(YulNameRepository const& _yulNameRepository, Block const& _ast); - static bool containsMSize(YulNameRepository const& _yulNameRepository, Object const& _object); + static bool containsMSize(Object const& _object); + static bool containsMSize(AST const& _ast); using ASTWalker::operator(); void operator()(FunctionCall const& _funCall) override; diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index a38522672a0c..49d4bb1adf04 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -244,7 +244,7 @@ bool StackCompressor::run( { yulAssert( _object.code && - _object.code->statements.size() > 0 && std::holds_alternative(_object.code->statements.at(0)), + _object.code->block().statements.size() > 0 && std::holds_alternative(_object.code->block().statements.at(0)), "Need to run the function grouper before the stack compressor." ); bool usesOptimizedCodeGenerator = false; @@ -253,15 +253,15 @@ bool StackCompressor::run( _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - bool allowMSizeOptimization = !MSizeFinder::containsMSize(_yulNameRepository, *_object.code); - _yulNameRepository.generateLabels(*_object.code); + bool allowMSizeOptimization = !MSizeFinder::containsMSize(*_object.code); + _yulNameRepository.generateLabels(_object.code->block()); if (usesOptimizedCodeGenerator) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_yulNameRepository, _object); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _yulNameRepository, *_object.code); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_object); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _yulNameRepository, _object.code->block()); eliminateVariablesOptimizedCodegen( _yulNameRepository, - *_object.code, + _object.code->block(), StackLayoutGenerator::reportStackTooDeep(*cfg), allowMSizeOptimization ); @@ -270,10 +270,10 @@ bool StackCompressor::run( { for (size_t iterations = 0; iterations < _maxIterations; iterations++) { - std::map stackSurplus = CompilabilityChecker(_yulNameRepository, _object, _optimizeStackAllocation).stackDeficit; + std::map stackSurplus = CompilabilityChecker(_object, _optimizeStackAllocation).stackDeficit; if (stackSurplus.empty()) return true; - eliminateVariables(_yulNameRepository, *_object.code, stackSurplus, allowMSizeOptimization); + eliminateVariables(_yulNameRepository, _object.code->block(), stackSurplus, allowMSizeOptimization); } } return false; diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index 1b69d932821d..e4a9ebd234f6 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -128,13 +128,12 @@ void StackLimitEvader::run( ); if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_context.yulNameRepository, _object); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _context.yulNameRepository, *_object.code); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_object); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _context.yulNameRepository, _object.code->block()); run(_context, _object, StackLayoutGenerator::reportStackTooDeep(*cfg)); } else run(_context, _object, CompilabilityChecker{ - _context.yulNameRepository, _object, true }.unreachableVariables); @@ -174,7 +173,7 @@ void StackLimitEvader::run( ); std::vector memoryGuardCalls = FunctionCallFinder::run( - *_object.code, + _object.code->block(), _context.yulNameRepository.predefined().memoryguard ); // Do not optimise, if no ``memoryguard`` call is found. @@ -189,23 +188,23 @@ void StackLimitEvader::run( if (reservedMemory != literalArgumentValue(*memoryGuardCall)) return; - CallGraph callGraph = CallGraphGenerator::callGraph(*_object.code); + CallGraph callGraph = CallGraphGenerator::callGraph(_object.code->block()); // We cannot move variables in recursive functions to fixed memory offsets. for (YulName function: callGraph.recursiveFunctions()) if (_unreachableVariables.count(function)) return; - std::map functionDefinitions = allFunctionDefinitions(*_object.code); + std::map functionDefinitions = allFunctionDefinitions(_object.code->block()); MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls, functionDefinitions}; uint64_t requiredSlots = memoryOffsetAllocator.run(); yulAssert(requiredSlots < (uint64_t(1) << 32) - 1, ""); - StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, *_object.code); + StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, _object.code->block()); reservedMemory += 32 * requiredSlots; - for (FunctionCall* memoryGuardCall: FunctionCallFinder::run(*_object.code, _context.yulNameRepository.predefined().memoryguard)) + for (FunctionCall* memoryGuardCall: FunctionCallFinder::run(_object.code->block(), _context.yulNameRepository.predefined().memoryguard)) { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index b3a1090dc57c..2c4e8eee790a 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -132,7 +132,6 @@ void outputPerformanceMetrics(map const& _metrics) void OptimiserSuite::run( - YulNameRepository& _yulNameRepository, GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, @@ -142,7 +141,8 @@ void OptimiserSuite::run( std::set const& _externallyUsedIdentifiers ) { - EVMDialect const* evmDialect = dynamic_cast(&_yulNameRepository.dialect()); + auto const& dialect = _object.code->nameRepository().dialect(); + EVMDialect const* evmDialect = dynamic_cast(&dialect); bool usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect && @@ -150,14 +150,14 @@ void OptimiserSuite::run( evmDialect->providesObjectAccess(); std::set reservedIdentifiers = _externallyUsedIdentifiers; - *_object.code = std::get(Disambiguator( - _yulNameRepository, + _object.code->block() = std::get(Disambiguator( + _object.code->nameRepository(), *_object.analysisInfo, reservedIdentifiers - )(*_object.code)); - Block& ast = *_object.code; + )(_object.code->block())); + Block& ast = _object.code->block(); - OptimiserStepContext context{_yulNameRepository.dialect(), _yulNameRepository, reservedIdentifiers, _expectedExecutionsPerDeployment}; + OptimiserStepContext context{dialect, _object.code->nameRepository(), reservedIdentifiers, _expectedExecutionsPerDeployment}; OptimiserSuite suite(context, Debug::None); @@ -176,7 +176,7 @@ void OptimiserSuite::run( // message once we perform code generation. if (!usesOptimizedCodeGenerator) StackCompressor::run( - _yulNameRepository, + _object.code->nameRepository(), _object, _optimizeStackAllocation, stackCompressorMaxIterations @@ -192,11 +192,11 @@ void OptimiserSuite::run( if (evmDialect) { yulAssert(_meter, ""); - ConstantOptimiser{_yulNameRepository, *evmDialect, *_meter}(ast); + ConstantOptimiser{_object.code->nameRepository(), *evmDialect, *_meter}(ast); if (usesOptimizedCodeGenerator) { StackCompressor::run( - _yulNameRepository, + _object.code->nameRepository(), _object, _optimizeStackAllocation, stackCompressorMaxIterations @@ -211,8 +211,8 @@ void OptimiserSuite::run( #ifdef PROFILE_OPTIMIZER_STEPS outputPerformanceMetrics(suite.m_durationPerStepInMicroseconds); #endif - _yulNameRepository.generateLabels(*_object.code); - *_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_yulNameRepository, _object); + _object.code->nameRepository().generateLabels(_object.code->block()); + *_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_object); } namespace diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 09f6cdeb8170..1b4e3488c16c 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -60,7 +60,6 @@ class OptimiserSuite /// The value nullopt for `_expectedExecutionsPerDeployment` represents creation code. static void run( - YulNameRepository& _yulNameRepository, GasMeter const* _meter, Object& _object, bool _optimizeStackAllocation, diff --git a/test/libsolidity/MemoryGuardTest.cpp b/test/libsolidity/MemoryGuardTest.cpp index 792e19b3fcdd..13db5e5ab344 100644 --- a/test/libsolidity/MemoryGuardTest.cpp +++ b/test/libsolidity/MemoryGuardTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -59,10 +60,9 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con for (std::string contractName: compiler().contractNames()) { ErrorList errors; - YulNameRepository repository (EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion())); auto [object, analysisInfo] = yul::test::parse( compiler().yulIR(contractName), - repository, + EVMDialect::strictAssemblyForEVMObjects(CommonOptions::get().evmVersion()), errors ); @@ -75,8 +75,8 @@ TestCase::TestResult MemoryGuardTest::run(std::ostream& _stream, std::string con auto handleObject = [&](std::string const& _kind, Object const& _object) { m_obtainedResult += contractName + "(" + _kind + ") " + (FunctionCallFinder::run( - *_object.code, - repository.predefined().memoryguard + _object.code->block(), + _object.code->nameRepository().predefined().memoryguard ).empty() ? "false" : "true") + "\n"; }; handleObject("creation", *object); diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 0387bdf323d3..f22d5873cc5d 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -42,7 +42,7 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::langutil; -std::tuple, std::shared_ptr, std::shared_ptr> yul::test::parse(std::string const& _source, bool _yul) +std::tuple, std::shared_ptr> yul::test::parse(std::string const& _source, bool _yul) { YulStack stack( solidity::test::CommonOptions::get().evmVersion(), @@ -55,43 +55,44 @@ std::tuple, std::shared_ptr, std::shared ); if (!stack.parseAndAnalyze("", _source) || !stack.errors().empty()) BOOST_FAIL("Invalid source."); - return std::make_tuple(stack.parserResult()->code, stack.parserResult()->analysisInfo, stack.yulNameRepository()); + return std::make_tuple(stack.parserResult()->code, stack.parserResult()->analysisInfo); } std::pair, std::shared_ptr> yul::test::parse( std::string const& _source, - YulNameRepository& _yulNameRepository, + Dialect const& _dialect, ErrorList& _errors ) { ErrorReporter errorReporter(_errors); CharStream stream(_source, ""); std::shared_ptr scanner = std::make_shared(stream); - std::shared_ptr parserResult = yul::ObjectParser(errorReporter, _yulNameRepository).parse(scanner, false); + std::shared_ptr parserResult = yul::ObjectParser(errorReporter, _dialect).parse(scanner, false); if (!parserResult) return {}; if (!parserResult->code || errorReporter.hasErrors()) return {}; std::shared_ptr analysisInfo = std::make_shared(); - AsmAnalyzer analyzer(*analysisInfo, errorReporter, _yulNameRepository, {}, parserResult->qualifiedDataNames()); + AsmAnalyzer analyzer(*analysisInfo, errorReporter, parserResult->code->nameRepository(), {}, parserResult->qualifiedDataNames()); // TODO this should be done recursively. - if (!analyzer.analyze(*parserResult->code) || errorReporter.hasErrors()) + if (!analyzer.analyze(parserResult->code->block()) || errorReporter.hasErrors()) return {}; return {std::move(parserResult), std::move(analysisInfo)}; } -std::tuple> yul::test::disambiguate(std::string const& _source, bool _yul) +std::shared_ptr yul::test::disambiguate(std::string const& _source, bool _yul) { auto result = parse(_source, _yul); - auto const& [code, analysisInfo, nameRepository] = result; - return std::make_tuple(std::get(Disambiguator(*nameRepository, *analysisInfo, {})(*code)), nameRepository); + auto const& [code, analysisInfo] = result; + Disambiguator(code->nameRepository(), *analysisInfo, {})(code->block()); + return code; } std::string yul::test::format(std::string const& _source, bool _yul) { auto result = parse(_source, _yul); - auto const& [code, analysisInfo, nameRepository] = result; - return yul::AsmPrinter(*nameRepository)(*code); + auto const& [code, analysisInfo] = result; + return yul::AsmPrinter(code->nameRepository())(code->block()); } namespace diff --git a/test/libyul/Common.h b/test/libyul/Common.h index fa663fb2930a..b11b8c1d0dcf 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -39,6 +39,7 @@ struct AsmAnalysisInfo; struct Block; struct Object; struct Dialect; +class AST; class YulStack; class YulNameRepository; } @@ -46,13 +47,13 @@ class YulNameRepository; namespace solidity::yul::test { -std::tuple, std::shared_ptr, std::shared_ptr> +std::tuple, std::shared_ptr> parse(std::string const& _source, bool _yul = true); std::pair, std::shared_ptr> -parse(std::string const& _source, YulNameRepository& _yulNameRepository, langutil::ErrorList& _errors); +parse(std::string const& _source, Dialect const& _dialect, langutil::ErrorList& _errors); -std::tuple> disambiguate(std::string const& _source, bool _yul = true); +std::shared_ptr disambiguate(std::string const& _source, bool _yul = true); std::string format(std::string const& _source, bool _yul = true); solidity::yul::Dialect const& dialect(std::string const& _name, langutil::EVMVersion _evmVersion); diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 9c1d17f2eda1..c90474b00140 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -22,6 +22,7 @@ #include #include +#include #include @@ -32,15 +33,14 @@ namespace { std::string check(std::string const& _input) { - std::shared_ptr nameRepository; Object obj; - std::tie(obj.code, obj.analysisInfo, nameRepository) = yul::test::parse(_input, false); + std::tie(obj.code, obj.analysisInfo) = yul::test::parse(_input, false); BOOST_REQUIRE(obj.code); - auto functions = CompilabilityChecker(*nameRepository, obj, true).stackDeficit; + auto functions = CompilabilityChecker(obj, true).stackDeficit; // recast into map string -> int s.t. order is predictable std::map labelledFunctions; for(const auto& [k, v] : functions) - labelledFunctions[std::string(nameRepository->labelOf(k))] = v; + labelledFunctions[std::string(obj.code->nameRepository().labelOf(k))] = v; std::string out; for (auto const& function: labelledFunctions) out += function.first + ": " + std::to_string(function.second) + " "; diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index 10f7a051da0d..7423df366110 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -46,7 +46,6 @@ ControlFlowGraphTest::ControlFlowGraphTest(std::string const& _filename): m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); - m_yulNameRepository = std::make_unique(*m_dialect); m_expectation = m_reader.simpleExpectations(); } @@ -199,7 +198,7 @@ class ControlFlowGraphPrinter TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_yulNameRepository, errors); + auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); if (!object || !analysisInfo || Error::containsErrors(errors)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; @@ -208,11 +207,11 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_yulNameRepository, *object->code); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, object->code->nameRepository(), object->code->block()); - m_yulNameRepository->generateLabels(*object->code); + object->code->nameRepository().generateLabels(object->code->block()); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - ControlFlowGraphPrinter printer{output, *m_yulNameRepository}; + ControlFlowGraphPrinter printer{output, object->code->nameRepository()}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/ControlFlowGraphTest.h b/test/libyul/ControlFlowGraphTest.h index 265e8d9d38c2..823bc58694ba 100644 --- a/test/libyul/ControlFlowGraphTest.h +++ b/test/libyul/ControlFlowGraphTest.h @@ -39,7 +39,6 @@ class ControlFlowGraphTest: public solidity::frontend::test::TestCase TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: Dialect const* m_dialect = nullptr; - std::unique_ptr m_yulNameRepository; }; } } diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index d4631249bdc2..9d302965db6d 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -57,20 +57,19 @@ ControlFlowSideEffectsTest::ControlFlowSideEffectsTest(std::string const& _filen TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - std::shared_ptr nameRepository; Object obj; - std::tie(obj.code, obj.analysisInfo, nameRepository) = yul::test::parse(m_source, false); + std::tie(obj.code, obj.analysisInfo) = yul::test::parse(m_source, false); if (!obj.code) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); ControlFlowSideEffectsCollector sideEffects( - *nameRepository, - *obj.code + obj.code->nameRepository(), + obj.code->block() ); m_obtainedResult.clear(); - forEach(*obj.code, [&](FunctionDefinition const& _fun) { + forEach(obj.code->block(), [&](FunctionDefinition const& _fun) { std::string effectStr = toString(sideEffects.functionSideEffects().at(&_fun)); - m_obtainedResult += std::string(nameRepository->labelOf(_fun.name)) + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; + m_obtainedResult += std::string(obj.code->nameRepository().labelOf(_fun.name)) + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; }); return checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/EVMCodeTransformTest.cpp b/test/libyul/EVMCodeTransformTest.cpp index 487464097cf1..be9e6c83493b 100644 --- a/test/libyul/EVMCodeTransformTest.cpp +++ b/test/libyul/EVMCodeTransformTest.cpp @@ -21,9 +21,10 @@ #include -#include #include #include +#include +#include #include @@ -72,8 +73,7 @@ TestCase::TestResult EVMCodeTransformTest::run(std::ostream& _stream, std::strin EVMObjectCompiler::compile( *stack.parserResult(), adapter, - *stack.yulNameRepository(), - dynamic_cast(stack.yulNameRepository()->dialect()), + dynamic_cast(stack.parserResult()->code->nameRepository().dialect()), m_stackOpt, std::nullopt ); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 2eba3e46614f..6d58d7eae6a2 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -82,20 +82,19 @@ FunctionSideEffects::FunctionSideEffects(std::string const& _filename): TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) { - std::shared_ptr nameRepository; Object obj; - std::tie(obj.code, obj.analysisInfo, nameRepository) = yul::test::parse(m_source, false); + std::tie(obj.code, obj.analysisInfo) = yul::test::parse(m_source, false); if (!obj.code) BOOST_THROW_EXCEPTION(std::runtime_error("Parsing input failed.")); std::map functionSideEffects = SideEffectsPropagator::sideEffects( - *nameRepository, - CallGraphGenerator::callGraph(*obj.code) + obj.code->nameRepository(), + CallGraphGenerator::callGraph(obj.code->block()) ); std::map functionSideEffectsStr; for (auto const& fun: functionSideEffects) - functionSideEffectsStr[nameRepository->labelOf(fun.first)] = toString(fun.second); + functionSideEffectsStr[obj.code->nameRepository().labelOf(fun.first)] = toString(fun.second); m_obtainedResult.clear(); for (auto const& fun: functionSideEffectsStr) diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp index d884efdca4fc..6a5f7318a840 100644 --- a/test/libyul/Inliner.cpp +++ b/test/libyul/Inliner.cpp @@ -42,14 +42,14 @@ namespace { std::string inlinableFunctions(std::string const& _source) { - auto [ast, repository] = disambiguate(_source); + auto ast = disambiguate(_source); InlinableExpressionFunctionFinder funFinder; - funFinder(ast); + funFinder(ast->block()); std::vector functionNames; for (auto const& f: funFinder.inlinableFunctions()) - functionNames.emplace_back(repository->baseLabelOf(f.first)); + functionNames.emplace_back(ast->nameRepository().baseLabelOf(f.first)); std::sort(functionNames.begin(), functionNames.end()); return boost::algorithm::join(functionNames, ","); } diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index b825e6a4f4a0..7b2d686a3c21 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -44,22 +44,21 @@ class KnowledgeBaseTest { ErrorList errorList; std::shared_ptr analysisInfo; - std::tie(m_object, analysisInfo) = yul::test::parse(_source, m_yulNameRepository, errorList); + std::tie(m_object, analysisInfo) = yul::test::parse(_source, m_dialect, errorList); BOOST_REQUIRE(m_object && errorList.empty() && m_object->code); std::set reserved{}; - OptimiserStepContext context{m_yulNameRepository.dialect(), m_yulNameRepository, reserved, 0}; - CommonSubexpressionEliminator::run(context, *m_object->code); + OptimiserStepContext context{m_object->code->nameRepository().dialect(), m_object->code->nameRepository(), reserved, 0}; + CommonSubexpressionEliminator::run(context, m_object->code->block()); - m_ssaValues(*m_object->code); + m_ssaValues(m_object->code->block()); for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; - return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }, m_yulNameRepository); + return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }, m_object->code->nameRepository()); } EVMDialect m_dialect{EVMVersion{}, true}; - YulNameRepository m_yulNameRepository {m_dialect}; std::shared_ptr m_object; SSAValueTracker m_ssaValues; std::map m_values; @@ -77,15 +76,16 @@ BOOST_AUTO_TEST_CASE(basic) let d := mul(b, 0) let e := sub(a, b) })"); + auto const& nameRepository = m_object->code->nameRepository(); - BOOST_CHECK(!kb.knownToBeDifferent(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("b"))); + BOOST_CHECK(!kb.knownToBeDifferent(nameRepository.nameOfLabel("a"), nameRepository.nameOfLabel("b"))); // This only works if the variable names are the same. // It assumes that SSA+CSE+Simplifier actually replaces the variables. - BOOST_CHECK(!kb.valueIfKnownConstant(m_yulNameRepository.nameOfLabel("a"))); - BOOST_CHECK(kb.valueIfKnownConstant(m_yulNameRepository.nameOfLabel("zero")) == u256(0)); - BOOST_CHECK(kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("b")) == u256(0)); - BOOST_CHECK(kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("c")) == u256(0)); - BOOST_CHECK(kb.valueIfKnownConstant(m_yulNameRepository.nameOfLabel("e")) == u256(0)); + BOOST_CHECK(!kb.valueIfKnownConstant(nameRepository.nameOfLabel("a"))); + BOOST_CHECK(kb.valueIfKnownConstant(nameRepository.nameOfLabel("zero")) == u256(0)); + BOOST_CHECK(kb.differenceIfKnownConstant(nameRepository.nameOfLabel("a"), nameRepository.nameOfLabel("b")) == u256(0)); + BOOST_CHECK(kb.differenceIfKnownConstant(nameRepository.nameOfLabel("a"), nameRepository.nameOfLabel("c")) == u256(0)); + BOOST_CHECK(kb.valueIfKnownConstant(nameRepository.nameOfLabel("e")) == u256(0)); } BOOST_AUTO_TEST_CASE(difference) @@ -97,31 +97,32 @@ BOOST_AUTO_TEST_CASE(difference) let d := add(12, c) let e := sub(c, 12) })"); + auto const& nameRepository = m_object->code->nameRepository(); BOOST_CHECK( - kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("c"), m_yulNameRepository.nameOfLabel("b")) == + kb.differenceIfKnownConstant(nameRepository.nameOfLabel("c"), nameRepository.nameOfLabel("b")) == u256(20) ); BOOST_CHECK( - kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("c")) == + kb.differenceIfKnownConstant(nameRepository.nameOfLabel("b"), nameRepository.nameOfLabel("c")) == u256(-20) ); - BOOST_CHECK(!kb.knownToBeDifferentByAtLeast32(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("c"))); - BOOST_CHECK(kb.knownToBeDifferentByAtLeast32(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("d"))); - BOOST_CHECK(kb.knownToBeDifferentByAtLeast32(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("b"))); - BOOST_CHECK(kb.knownToBeDifferentByAtLeast32(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("a"))); + BOOST_CHECK(!kb.knownToBeDifferentByAtLeast32(nameRepository.nameOfLabel("b"), nameRepository.nameOfLabel("c"))); + BOOST_CHECK(kb.knownToBeDifferentByAtLeast32(nameRepository.nameOfLabel("b"), nameRepository.nameOfLabel("d"))); + BOOST_CHECK(kb.knownToBeDifferentByAtLeast32(nameRepository.nameOfLabel("a"), nameRepository.nameOfLabel("b"))); + BOOST_CHECK(kb.knownToBeDifferentByAtLeast32(nameRepository.nameOfLabel("b"), nameRepository.nameOfLabel("a"))); BOOST_CHECK( - kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("e"), m_yulNameRepository.nameOfLabel("a")) == u256(208) + kb.differenceIfKnownConstant(nameRepository.nameOfLabel("e"), nameRepository.nameOfLabel("a")) == u256(208) ); BOOST_CHECK( - kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("e"), m_yulNameRepository.nameOfLabel("b")) == u256(8) + kb.differenceIfKnownConstant(nameRepository.nameOfLabel("e"), nameRepository.nameOfLabel("b")) == u256(8) ); BOOST_CHECK( - kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("a"), m_yulNameRepository.nameOfLabel("e")) == u256(-208) + kb.differenceIfKnownConstant(nameRepository.nameOfLabel("a"), nameRepository.nameOfLabel("e")) == u256(-208) ); BOOST_CHECK( - kb.differenceIfKnownConstant(m_yulNameRepository.nameOfLabel("b"), m_yulNameRepository.nameOfLabel("e")) == u256(-8) + kb.differenceIfKnownConstant(nameRepository.nameOfLabel("b"), nameRepository.nameOfLabel("e")) == u256(-8) ); } diff --git a/test/libyul/Metrics.cpp b/test/libyul/Metrics.cpp index 4d710123692f..2f3e8ccc8cfb 100644 --- a/test/libyul/Metrics.cpp +++ b/test/libyul/Metrics.cpp @@ -37,9 +37,9 @@ namespace size_t codeSize(std::string const& _source, CodeWeights const _weights = {}) { - std::shared_ptr ast = std::get<0>(parse(_source, false)); + std::shared_ptr ast = std::get<0>(parse(_source, false)); BOOST_REQUIRE(ast); - return CodeSize::codeSize(*ast, _weights); + return CodeSize::codeSize(ast->block(), _weights); } } diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp index 9d616d294fbb..b23e530601da 100644 --- a/test/libyul/ObjectParser.cpp +++ b/test/libyul/ObjectParser.cpp @@ -113,8 +113,7 @@ std::tuple, ErrorList> tryGetSourceLocationMapping( ErrorList errors; ErrorReporter reporter(errors); Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(EVMVersion::berlin()); - YulNameRepository repository (dialect); - ObjectParser objectParser{reporter, repository}; + ObjectParser objectParser{reporter, dialect}; CharStream stream(std::move(source), ""); auto object = objectParser.parse(std::make_shared(stream), false); BOOST_REQUIRE(object && object->debugData); diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 6cf52b22cd6a..46d752fd6845 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -55,7 +55,7 @@ namespace solidity::yul::test namespace { -std::shared_ptr parse(std::string const& _source, YulNameRepository& _yulNameRepository, ErrorReporter& errorReporter) +std::shared_ptr parse(std::string const& _source, Dialect const& _dialect, ErrorReporter& errorReporter) { auto stream = CharStream(_source, ""); std::map> indicesToSourceNames; @@ -64,7 +64,7 @@ std::shared_ptr parse(std::string const& _source, YulNameRepository& _yul auto parserResult = yul::Parser( errorReporter, - _yulNameRepository, + _dialect, std::move(indicesToSourceNames) ).parse(stream); if (parserResult) @@ -73,18 +73,18 @@ std::shared_ptr parse(std::string const& _source, YulNameRepository& _yul if (yul::AsmAnalyzer( analysisInfo, errorReporter, - _yulNameRepository - ).analyze(*parserResult)) + parserResult->nameRepository() + ).analyze(parserResult->block())) return parserResult; } return {}; } -std::optional parseAndReturnFirstError(std::string const& _source, YulNameRepository& _yulNameRepository, bool _allowWarningsAndInfos = true) +std::optional parseAndReturnFirstError(std::string const& _source, Dialect const& _dialect, bool _allowWarningsAndInfos = true) { ErrorList errors; ErrorReporter errorReporter(errors); - if (!parse(_source, _yulNameRepository, errorReporter)) + if (!parse(_source, _dialect, errorReporter)) { BOOST_REQUIRE(!errors.empty()); BOOST_CHECK_EQUAL(errors.size(), 1); @@ -107,14 +107,12 @@ std::optional parseAndReturnFirstError(std::string const& _source, YulNam bool successParse(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarningsAndInfos = true) { - YulNameRepository repository (_dialect); - return !parseAndReturnFirstError(_source, repository, _allowWarningsAndInfos); + return !parseAndReturnFirstError(_source, _dialect, _allowWarningsAndInfos); } Error expectError(std::string const& _source, Dialect const& _dialect = Dialect::yulDeprecated(), bool _allowWarningsAndInfos = false) { - YulNameRepository repository (_dialect); - auto error = parseAndReturnFirstError(_source, repository, _allowWarningsAndInfos); + auto error = parseAndReturnFirstError(_source, _dialect, _allowWarningsAndInfos); BOOST_REQUIRE(error); return *error; } @@ -166,24 +164,23 @@ BOOST_AUTO_TEST_CASE(builtins_analysis) BOOST_AUTO_TEST_CASE(default_types_set) { - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); ErrorList errorList; ErrorReporter reporter(errorList); - std::shared_ptr result = parse( + std::shared_ptr result = parse( "{" "let x:bool := true:bool " "let z:bool := true " "let y := add(1, 2) " "switch y case 0 {} default {} " "}", - repository, + EVMDialectTyped::instance(EVMVersion{}), reporter ); BOOST_REQUIRE(!!result && errorList.size() == 0); // By default, all types are printed. // This tests that the default types are properly assigned. - BOOST_CHECK_EQUAL(AsmPrinter{repository}(*result), + BOOST_CHECK_EQUAL(AsmPrinter{result->nameRepository()}(result->block()), "{\n" " let x:bool := true:bool\n" " let z:bool := true:bool\n" @@ -195,7 +192,7 @@ BOOST_AUTO_TEST_CASE(default_types_set) ); // got to declare the string representation outside the check due to macro weirdness - std::string stringRepr = AsmPrinter{repository, AsmPrinter::Mode::OmitDefaultType}(*result); + std::string stringRepr = AsmPrinter{result->nameRepository(), AsmPrinter::Mode::OmitDefaultType}(result->block()); BOOST_CHECK_EQUAL(stringRepr, "{\n" " let x:bool := true\n" @@ -222,10 +219,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_empty_block) auto const sourceText = "/// @src 0:234:543\n" "{}\n"; - YulNameRepository repository (EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + auto result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 234, 543); } BOOST_AUTO_TEST_CASE(customSourceLocations_block_with_children) @@ -240,15 +236,14 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_with_children) "let z:bool := true\n" "let y := add(1, 2)\n" "}\n"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); - BOOST_REQUIRE_EQUAL(3, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 234, 543); - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source0", 123, 432); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 234, 543); + BOOST_REQUIRE_EQUAL(3, result->block().statements.size()); + CHECK_LOCATION(originLocationOf(result->block().statements.at(0)), "source0", 234, 543); + CHECK_LOCATION(originLocationOf(result->block().statements.at(1)), "source0", 123, 432); // [2] is inherited source location - CHECK_LOCATION(originLocationOf(result->statements.at(2)), "source0", 123, 432); + CHECK_LOCATION(originLocationOf(result->block().statements.at(2)), "source0", 123, 432); } BOOST_AUTO_TEST_CASE(customSourceLocations_block_different_sources) @@ -263,15 +258,14 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_different_sources) "let z:bool := true\n" "let y := add(1, 2)\n" "}\n"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); - BOOST_REQUIRE_EQUAL(3, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 234, 543); - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source1", 123, 432); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 234, 543); + BOOST_REQUIRE_EQUAL(3, result->block().statements.size()); + CHECK_LOCATION(originLocationOf(result->block().statements.at(0)), "source0", 234, 543); + CHECK_LOCATION(originLocationOf(result->block().statements.at(1)), "source1", 123, 432); // [2] is inherited source location - CHECK_LOCATION(originLocationOf(result->statements.at(2)), "source1", 123, 432); + CHECK_LOCATION(originLocationOf(result->block().statements.at(2)), "source1", 123, 432); } BOOST_AUTO_TEST_CASE(customSourceLocations_block_nested) @@ -285,12 +279,11 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_nested) "/// @src 0:343:434\n" "switch y case 0 {} default {}\n" "}\n"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); - BOOST_REQUIRE_EQUAL(2, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source0", 343, 434); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 234, 543); + BOOST_REQUIRE_EQUAL(2, result->block().statements.size()); + CHECK_LOCATION(originLocationOf(result->block().statements.at(1)), "source0", 343, 434); } BOOST_AUTO_TEST_CASE(customSourceLocations_block_switch_case) @@ -309,14 +302,13 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_block_switch_case) " let z := add(3, 4)\n" "}\n" "}\n"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 234, 543); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 234, 543); - BOOST_REQUIRE_EQUAL(2, result->statements.size()); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); - auto const& switchStmt = std::get(result->statements.at(1)); + BOOST_REQUIRE_EQUAL(2, result->block().statements.size()); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(1))); + auto const& switchStmt = std::get(result->block().statements.at(1)); CHECK_LOCATION(switchStmt.debugData->originLocation, "source0", 343, 434); BOOST_REQUIRE_EQUAL(1, switchStmt.cases.size()); @@ -341,23 +333,22 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_inherit_into_outer_scope) "let z:bool := true\n" "let y := add(1, 2)\n" "}\n"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 1, 100); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 1, 100); - BOOST_REQUIRE_EQUAL(3, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 1, 100); + BOOST_REQUIRE_EQUAL(3, result->block().statements.size()); + CHECK_LOCATION(originLocationOf(result->block().statements.at(0)), "source0", 1, 100); // First child element must be a block itself with one statement. - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - BOOST_REQUIRE_EQUAL(std::get(result->statements.at(0)).statements.size(), 1); - CHECK_LOCATION(originLocationOf(std::get(result->statements.at(0)).statements.at(0)), "source0", 123, 432); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + BOOST_REQUIRE_EQUAL(std::get(result->block().statements.at(0)).statements.size(), 1); + CHECK_LOCATION(originLocationOf(std::get(result->block().statements.at(0)).statements.at(0)), "source0", 123, 432); // The next two elements have an inherited source location from the prior inner scope. - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source0", 123, 432); - CHECK_LOCATION(originLocationOf(result->statements.at(2)), "source0", 123, 432); + CHECK_LOCATION(originLocationOf(result->block().statements.at(1)), "source0", 123, 432); + CHECK_LOCATION(originLocationOf(result->block().statements.at(2)), "source0", 123, 432); } BOOST_AUTO_TEST_CASE(customSourceLocations_assign_empty) @@ -372,12 +363,11 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_assign_empty) "/// @src 1:1:10\n" "a := true:bool\n" "}\n"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // should still parse - BOOST_REQUIRE_EQUAL(2, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 123, 432); - CHECK_LOCATION(originLocationOf(result->statements.at(1)), "source1", 1, 10); + BOOST_REQUIRE_EQUAL(2, result->block().statements.size()); + CHECK_LOCATION(originLocationOf(result->block().statements.at(0)), "source0", 123, 432); + CHECK_LOCATION(originLocationOf(result->block().statements.at(1)), "source1", 1, 10); } BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_source_index) @@ -393,8 +383,7 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_source_index) "let b:bool := true:bool\n" "\n" "}\n"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); // should still parse BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -413,14 +402,13 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_1) "/// @src 0:234:2026\n" ":= true:bool\n" "}\n"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(1, result->statements.size()); - CHECK_LOCATION(originLocationOf(result->statements.at(0)), "source0", 123, 432); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE_EQUAL(1, result->block().statements.size()); + CHECK_LOCATION(originLocationOf(result->block().statements.at(0)), "source0", 123, 432); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->block().statements.at(0)); CHECK_LOCATION(originLocationOf(*varDecl.value), "source0", 234, 2026); } @@ -436,15 +424,14 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_2) 2) } )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(1, result->statements.size()); - CHECK_LOCATION(result->debugData->originLocation, "source0", 0, 5); + BOOST_REQUIRE_EQUAL(1, result->block().statements.size()); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 0, 5); // `let x := add(1, ` - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->block().statements.at(0)); CHECK_LOCATION(varDecl.debugData->originLocation, "source0", 0, 5); BOOST_REQUIRE(!!varDecl.value); BOOST_REQUIRE(std::holds_alternative(*varDecl.value)); @@ -470,25 +457,24 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_mixed_locations_3) mstore(1, 2) // FunctionCall } )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(2, result->statements.size()); - CHECK_LOCATION(result->debugData->originLocation, "source1", 23, 45); + BOOST_REQUIRE_EQUAL(2, result->block().statements.size()); + CHECK_LOCATION(result->block().debugData->originLocation, "source1", 23, 45); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - Block const& innerBlock = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + Block const& innerBlock = std::get(result->block().statements.at(0)); CHECK_LOCATION(innerBlock.debugData->originLocation, "source1", 23, 45); BOOST_REQUIRE_EQUAL(1, innerBlock.statements.size()); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(1))); ExpressionStatement const& sstoreStmt = std::get(innerBlock.statements.at(0)); BOOST_REQUIRE(std::holds_alternative(sstoreStmt.expression)); FunctionCall const& sstoreCall = std::get(sstoreStmt.expression); CHECK_LOCATION(sstoreCall.debugData->originLocation, "source1", 23, 45); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); - ExpressionStatement mstoreStmt = std::get(result->statements.at(1)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(1))); + ExpressionStatement mstoreStmt = std::get(result->block().statements.at(1)); BOOST_REQUIRE(std::holds_alternative(mstoreStmt.expression)); FunctionCall const& mstoreCall = std::get(mstoreStmt.expression); CHECK_LOCATION(mstoreCall.debugData->originLocation, "source0", 420, 680); @@ -506,14 +492,13 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_comments_after_valid) let a:bool := true } )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(1, result->statements.size()); - CHECK_LOCATION(result->debugData->originLocation, "source1", 23, 45); + BOOST_REQUIRE_EQUAL(1, result->block().statements.size()); + CHECK_LOCATION(result->block().debugData->originLocation, "source1", 23, 45); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->block().statements.at(0)); CHECK_LOCATION(varDecl.debugData->originLocation, "source0", 420, 680); } @@ -525,13 +510,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_suffix) /// @src 0:420:680foo {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 8387_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_prefix) @@ -542,10 +526,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_prefix) /// abc@src 0:111:222 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_unspecified) @@ -556,10 +539,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_unspecified) /// @src -1:-1:-1 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_non_integer) @@ -570,13 +552,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_non_integer) /// @src a:b:c {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 8387_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_bad_integer) @@ -587,13 +568,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_bad_integer) /// @src 111111111111111111111:222222222222222222222:333333333333333333333 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 6367_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_ensure_last_match) @@ -608,11 +588,10 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_ensure_last_match) let x:bool := true } )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->block().statements.at(0)); // Ensure the latest @src per documentation-comment is used (0:30:40). CHECK_LOCATION(varDecl.debugData->originLocation, "source0", 30, 40); @@ -626,13 +605,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_no_whitespace) /// @src 0:111:222@src 1:333:444 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 8387_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_space) @@ -643,10 +621,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_separated_with_single_s /// @src 0:111:222 @src 1:333:444 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source1", 333, 444); + CHECK_LOCATION(result->block().debugData->originLocation, "source1", 333, 444); } BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace) @@ -654,10 +631,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_leading_trailing_whitespace) ErrorList errorList; ErrorReporter reporter(errorList); auto const sourceText = "/// @src 0:111:222 \n{}"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc) @@ -671,11 +647,10 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_reference_original_sloc) let x:bool := true } )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varDecl = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + VariableDeclaration const& varDecl = std::get(result->block().statements.at(0)); // -1 points to original source code, which in this case is `"source0"` (which is also CHECK_LOCATION(varDecl.debugData->originLocation, "", 10, 20); @@ -693,17 +668,16 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets) let y := /** @src 1:96:165 "contract D {..." */ 128 } )~~~"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(result->statements.size(), 2); + BOOST_REQUIRE_EQUAL(result->block().statements.size(), 2); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varX = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + VariableDeclaration const& varX = std::get(result->block().statements.at(0)); CHECK_LOCATION(varX.debugData->originLocation, "source0", 149, 156); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); - VariableDeclaration const& varY = std::get(result->statements.at(1)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(1))); + VariableDeclaration const& varY = std::get(result->block().statements.at(1)); BOOST_REQUIRE(!!varY.value); BOOST_REQUIRE(std::holds_alternative(*varY.value)); Literal const& literal128 = std::get(*varY.value); @@ -718,10 +692,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_empty_snippet) /// @src 0:111:222 "" {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_before_snippet) @@ -732,13 +705,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_befo /// @src 0:111:222"abc" def {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 8387_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_after_snippet) @@ -749,10 +721,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_no_whitespace_afte /// @src 0:111:222 "abc"def {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whitespace) @@ -763,10 +734,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_no_whites /// @src 0:111:222 "abc"@src 1:333:444 "abc" {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source1", 333, 444); + CHECK_LOCATION(result->block().debugData->originLocation, "source1", 333, 444); } BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_unterminated_quote) @@ -777,13 +747,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_locations_with_snippets_untermina /// @src 0:111:222 " abc @src 1:333:444 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 1544_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) @@ -795,13 +764,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote) /// {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 1544_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) @@ -812,12 +780,11 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_two_snippets_with_hex_comment) /// @src 0:111:222 hex"abc"@src 1:333:444 "abc" {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); // the second source location is not parsed as such, as the hex string isn't interpreted as snippet but // as the beginning of the tail in AsmParser - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) @@ -828,10 +795,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_invalid_escapes) /// @src 0:111:222 "\n\\x\x\w\uö\xy\z\y\fq" {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source0", 111, 222); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 111, 222); } BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces_and_escapes) @@ -843,10 +809,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_single_quote_snippet_with_whitespaces /// @src 1 : 222 : 333 '\x33\u1234\t\n' {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - CHECK_LOCATION(result->debugData->originLocation, "source1", 222, 333); + CHECK_LOCATION(result->block().debugData->originLocation, "source1", 222, 333); } BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_are_ignored, boost::unit_test::data::make({"0x ", "/** unterminated comment", "1_23_4"}), invalid) @@ -858,10 +823,9 @@ BOOST_DATA_TEST_CASE(customSourceLocations_scanner_errors_outside_string_lits_ar /// @src 1:222:333 {{}} )", invalid); - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.empty()); - CHECK_LOCATION(result->debugData->originLocation, "source1", 222, 333); + CHECK_LOCATION(result->block().debugData->originLocation, "source1", 222, 333); } BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) @@ -876,10 +840,9 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multi_line_source_loc) /// " @src 0:333:444 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.empty()); - CHECK_LOCATION(result->debugData->originLocation, "source0", 333, 444); + CHECK_LOCATION(result->block().debugData->originLocation, "source0", 333, 444); } BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locations) @@ -894,17 +857,16 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locati let y := /** @src 1:96:165 "function f() internal { \"\/** @src 0:6:7 *\/\"; }" */ 128 } )~~~"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(result->statements.size(), 2); + BOOST_REQUIRE_EQUAL(result->block().statements.size(), 2); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varX = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + VariableDeclaration const& varX = std::get(result->block().statements.at(0)); CHECK_LOCATION(varX.debugData->originLocation, "source0", 149, 156); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(1))); - VariableDeclaration const& varY = std::get(result->statements.at(1)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(1))); + VariableDeclaration const& varY = std::get(result->block().statements.at(1)); BOOST_REQUIRE(!!varY.value); BOOST_REQUIRE(std::holds_alternative(*varY.value)); Literal const& literal128 = std::get(*varY.value); @@ -923,14 +885,13 @@ BOOST_AUTO_TEST_CASE(astid) mstore(1, 2) } )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); - BOOST_CHECK(result->debugData->astID == int64_t(7)); - auto const& funDef = std::get(result->statements.at(0)); + BOOST_CHECK(result->block().debugData->astID == int64_t(7)); + auto const& funDef = std::get(result->block().statements.at(0)); BOOST_CHECK(funDef.debugData->astID == int64_t(2)); BOOST_CHECK(funDef.parameters.at(0).debugData->astID == std::nullopt); - BOOST_CHECK(debugDataOf(result->statements.at(1))->astID == std::nullopt); + BOOST_CHECK(debugDataOf(result->block().statements.at(1))->astID == std::nullopt); } BOOST_AUTO_TEST_CASE(astid_reset) @@ -945,14 +906,13 @@ BOOST_AUTO_TEST_CASE(astid_reset) mstore(1, 2) } )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); - BOOST_CHECK(result->debugData->astID == int64_t(7)); - auto const& funDef = std::get(result->statements.at(0)); + BOOST_CHECK(result->block().debugData->astID == int64_t(7)); + auto const& funDef = std::get(result->block().statements.at(0)); BOOST_CHECK(funDef.debugData->astID == int64_t(2)); BOOST_CHECK(funDef.parameters.at(0).debugData->astID == std::nullopt); - BOOST_CHECK(debugDataOf(result->statements.at(1))->astID == std::nullopt); + BOOST_CHECK(debugDataOf(result->block().statements.at(1))->astID == std::nullopt); } BOOST_AUTO_TEST_CASE(astid_multi) @@ -963,10 +923,9 @@ BOOST_AUTO_TEST_CASE(astid_multi) /// @src -1:-1:-1 @ast-id 7 @src 1:1:1 @ast-id 8 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); - BOOST_CHECK(result->debugData->astID == int64_t(8)); + BOOST_CHECK(result->block().debugData->astID == int64_t(8)); } BOOST_AUTO_TEST_CASE(astid_invalid) @@ -977,13 +936,12 @@ BOOST_AUTO_TEST_CASE(astid_invalid) /// @src -1:-1:-1 @ast-id abc @src 1:1:1 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); BOOST_TEST(errorList[0]->errorId() == 1749_error); - CHECK_LOCATION(result->debugData->originLocation, "", -1, -1); + CHECK_LOCATION(result->block().debugData->originLocation, "", -1, -1); } BOOST_AUTO_TEST_CASE(astid_too_large) @@ -994,8 +952,7 @@ BOOST_AUTO_TEST_CASE(astid_too_large) /// @ast-id 9223372036854775808 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -1010,8 +967,7 @@ BOOST_AUTO_TEST_CASE(astid_way_too_large) /// @ast-id 999999999999999999999999999999999999999 {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -1026,8 +982,7 @@ BOOST_AUTO_TEST_CASE(astid_not_fully_numeric) /// @ast-id 9x {} )"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result); BOOST_REQUIRE(errorList.size() == 1); BOOST_TEST(errorList[0]->type() == Error::Type::SyntaxError); @@ -1048,13 +1003,12 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line) "\n" " let x := 123\n" "}\n"; - YulNameRepository repository(EVMDialectTyped::instance(EVMVersion{})); - std::shared_ptr result = parse(sourceText, repository, reporter); + std::shared_ptr result = parse(sourceText, EVMDialectTyped::instance(EVMVersion{}), reporter); BOOST_REQUIRE(!!result && errorList.size() == 0); - BOOST_REQUIRE_EQUAL(result->statements.size(), 1); + BOOST_REQUIRE_EQUAL(result->block().statements.size(), 1); - BOOST_REQUIRE(std::holds_alternative(result->statements.at(0))); - VariableDeclaration const& varX = std::get(result->statements.at(0)); + BOOST_REQUIRE(std::holds_alternative(result->block().statements.at(0))); + VariableDeclaration const& varX = std::get(result->block().statements.at(0)); CHECK_LOCATION(varX.debugData->originLocation, "source1", 4, 5); } diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 34d541f78de2..02847dfdebe9 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -49,7 +49,7 @@ StackLayoutGeneratorTest::StackLayoutGeneratorTest(std::string const& _filename) { m_source = m_reader.source(); auto dialectName = m_reader.stringSetting("dialect", "evm"); - m_yulNameRepository = std::make_unique(dialect(dialectName, solidity::test::CommonOptions::get().evmVersion())); + m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); m_expectation = m_reader.simpleExpectations(); } @@ -216,7 +216,7 @@ class StackLayoutPrinter TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted) { ErrorList errors; - auto [object, analysisInfo] = parse(m_source, *m_yulNameRepository, errors); + auto [object, analysisInfo] = parse(m_source, *m_dialect, errors); if (!object || !analysisInfo || Error::containsErrors(errors)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; @@ -225,12 +225,12 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, *m_yulNameRepository, *object->code); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, object->code->nameRepository(), object->code->block()); StackLayout stackLayout = StackLayoutGenerator::run(*cfg); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - StackLayoutPrinter printer{output, stackLayout, *m_yulNameRepository}; - m_yulNameRepository->generateLabels(*object->code); // todo need more? + StackLayoutPrinter printer{output, stackLayout, object->code->nameRepository()}; + object->code->nameRepository().generateLabels(object->code->block()); // todo need more? printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/StackLayoutGeneratorTest.h b/test/libyul/StackLayoutGeneratorTest.h index a6cb9573188e..9f570045f78e 100644 --- a/test/libyul/StackLayoutGeneratorTest.h +++ b/test/libyul/StackLayoutGeneratorTest.h @@ -22,7 +22,7 @@ namespace solidity::yul { -class YulNameRepository; +struct Dialect; namespace test { @@ -37,7 +37,7 @@ class StackLayoutGeneratorTest: public solidity::frontend::test::TestCase explicit StackLayoutGeneratorTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; private: - std::unique_ptr m_yulNameRepository; + Dialect const* m_dialect = nullptr; }; } } diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index 31ee98b9b5c2..0bf196dc912f 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -45,9 +45,9 @@ void SyntaxTest::parseAndAnalyze() std::string const& source = m_sources.sources.begin()->second; ErrorList errorList{}; - soltestAssert(m_yulNameRepository, ""); + soltestAssert(m_dialect); // Silently ignoring the results. - yul::test::parse(source, *m_yulNameRepository, errorList); + yul::test::parse(source, *m_dialect, errorList); for (auto const& error: errorList) { int locationStart = -1; @@ -75,5 +75,5 @@ SyntaxTest::SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVe CommonSyntaxTest(_filename, _evmVersion) { std::string dialectName = m_reader.stringSetting("dialect", "evmTyped"); - m_yulNameRepository = std::make_unique(dialect(dialectName, solidity::test::CommonOptions::get().evmVersion())); + m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); } diff --git a/test/libyul/SyntaxTest.h b/test/libyul/SyntaxTest.h index 453729941cdb..4f5e62ffec7f 100644 --- a/test/libyul/SyntaxTest.h +++ b/test/libyul/SyntaxTest.h @@ -39,7 +39,7 @@ class SyntaxTest: public solidity::test::CommonSyntaxTest void parseAndAnalyze() override; private: - std::unique_ptr m_yulNameRepository; + Dialect const* m_dialect; }; } diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index cc5c61356431..65f49dbb8117 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -72,7 +73,6 @@ bool YulInterpreterTest::parse(std::ostream& _stream, std::string const& _linePr solidity::frontend::OptimiserSettings::none(), DebugInfoSelection::All() ); - m_yulNameRepository = stack.yulNameRepository(); if (stack.parseAndAnalyze("", m_source)) { m_ast = stack.parserResult()->code; @@ -98,8 +98,8 @@ std::string YulInterpreterTest::interpret() { Interpreter::run( state, - *m_yulNameRepository, - *m_ast, + m_ast->nameRepository(), + m_ast->block(), /*disableExternalCalls=*/ !m_simulateExternalCallsToSelf, /*disableMemoryTracing=*/ false ); diff --git a/test/libyul/YulInterpreterTest.h b/test/libyul/YulInterpreterTest.h index 63b746ec19e7..2c7e916e43b1 100644 --- a/test/libyul/YulInterpreterTest.h +++ b/test/libyul/YulInterpreterTest.h @@ -23,7 +23,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; -struct Block; +class AST; class YulNameRepository; } @@ -46,9 +46,8 @@ class YulInterpreterTest: public solidity::frontend::test::EVMVersionRestrictedT bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); std::string interpret(); - std::shared_ptr m_ast; + std::shared_ptr m_ast; std::shared_ptr m_analysisInfo; - std::shared_ptr m_yulNameRepository; bool m_simulateExternalCallsToSelf = false; }; diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index aab5715a5a4e..93b3b05316f9 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -56,8 +57,6 @@ YulOptimizerTest::YulOptimizerTest(std::string const& _filename): auto dialectName = m_reader.stringSetting("dialect", "evm"); m_dialect = &dialect(dialectName, solidity::test::CommonOptions::get().evmVersion()); - m_yulNameRepository = std::make_unique(*m_dialect); - m_expectation = m_reader.simpleExpectations(); } @@ -70,7 +69,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co soltestAssert(m_dialect, "Dialect not set."); m_object->analysisInfo = m_analysisInfo; - YulOptimizerTestCommon tester(m_object, *m_yulNameRepository); + YulOptimizerTestCommon tester(m_object); tester.setStep(m_optimizerStep); if (!tester.runStep()) @@ -79,7 +78,7 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co return TestResult::FatalError; } - auto const printed = (m_object->subObjects.empty() ? AsmPrinter{ *m_yulNameRepository, AsmPrinter::Mode::OmitDefaultType }(*m_object->code) : m_object->toString(*m_yulNameRepository)); + auto const printed = (m_object->subObjects.empty() ? AsmPrinter{ m_object->code->nameRepository(), AsmPrinter::Mode::OmitDefaultType }(m_object->code->block()) : m_object->toString()); // Re-parse new code for compilability if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printed))) @@ -106,7 +105,7 @@ std::pair, std::shared_ptr> YulOptimize soltestAssert(m_dialect, ""); std::shared_ptr object; std::shared_ptr analysisInfo; - std::tie(object, analysisInfo) = yul::test::parse(_source, *m_yulNameRepository, errors); + std::tie(object, analysisInfo) = yul::test::parse(_source, *m_dialect, errors); if (!object || !analysisInfo || Error::containsErrors(errors)) { AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << std::endl; diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 91642c182e1a..25d9a7c9e74f 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -56,7 +56,6 @@ class YulOptimizerTest: public solidity::frontend::test::EVMVersionRestrictedTes std::string m_optimizerStep; Dialect const* m_dialect = nullptr; - std::unique_ptr m_yulNameRepository; std::shared_ptr m_object; std::shared_ptr m_analysisInfo; diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 8ead88630f22..f37ad7a5b1b4 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -73,18 +73,13 @@ using namespace solidity::yul::test; using namespace solidity::frontend; YulOptimizerTestCommon::YulOptimizerTestCommon( - std::shared_ptr _obj, - YulNameRepository& _yulNameRepository -): m_yulNameRepository(_yulNameRepository) + std::shared_ptr _obj +): m_yulNameRepository(_obj->code->nameRepository()), m_object(_obj), m_ast(m_object->code->block()), m_analysisInfo(m_object->analysisInfo) { - m_object = _obj; - m_ast = m_object->code; - m_analysisInfo = m_object->analysisInfo; - m_namedSteps = { {"disambiguator", [&]() { disambiguate(); - m_context->yulNameRepository.generateLabels(*m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"nameDisplacer", [&]() { disambiguate(); @@ -95,281 +90,280 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( m_yulNameRepository.defineName("illegal5") }, m_yulNameRepository - }(*m_ast); - m_context->yulNameRepository.generateLabels(*m_ast, {"illegal1", "illegal2", "illegal3", "illegal4", "illegal5"}); + }(m_ast); + m_context->yulNameRepository.generateLabels(m_ast, {"illegal1", "illegal2", "illegal3", "illegal4", "illegal5"}); }}, {"blockFlattener", [&]() { disambiguate(); - FunctionGrouper::run(*m_context, *m_ast); - BlockFlattener::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionGrouper::run(*m_context, m_ast); + BlockFlattener::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"constantOptimiser", [&]() { GasMeter meter(m_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), false, 200); - ConstantOptimiser{_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), meter}(*m_ast); + ConstantOptimiser{m_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), meter}(m_ast); }}, - {"varDeclInitializer", [&]() { VarDeclInitializer::run(*m_context, *m_ast); }}, + {"varDeclInitializer", [&]() { VarDeclInitializer::run(*m_context, m_ast); }}, {"varNameCleaner", [&]() { disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - FunctionGrouper::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionHoister::run(*m_context, m_ast); + FunctionGrouper::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"forLoopConditionIntoBody", [&]() { disambiguate(); - ForLoopConditionIntoBody::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopConditionIntoBody::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"forLoopInitRewriter", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"commonSubexpressionEliminator", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + CommonSubexpressionEliminator::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"conditionalUnsimplifier", [&]() { disambiguate(); - ConditionalUnsimplifier::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ConditionalUnsimplifier::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"conditionalSimplifier", [&]() { disambiguate(); - ConditionalSimplifier::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ConditionalSimplifier::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"expressionSplitter", [&]() { - ExpressionSplitter::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ExpressionSplitter::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"expressionJoiner", [&]() { disambiguate(); - ExpressionJoiner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ExpressionJoiner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"splitJoin", [&]() { disambiguate(); - ExpressionSplitter::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ExpressionSplitter::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"functionGrouper", [&]() { disambiguate(); - FunctionGrouper::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionGrouper::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"functionHoister", [&]() { disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionHoister::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"functionSpecializer", [&]() { disambiguate(); - FunctionHoister::run(*m_context, *m_object->code); - FunctionSpecializer::run(*m_context, *m_object->code); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionHoister::run(*m_context, m_ast); + FunctionSpecializer::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"expressionInliner", [&]() { disambiguate(); - ExpressionInliner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ExpressionInliner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"fullInliner", [&]() { disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - FunctionGrouper::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - FullInliner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionHoister::run(*m_context, m_ast); + FunctionGrouper::run(*m_context, m_ast); + ExpressionSplitter::run(*m_context, m_ast); + FullInliner::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"fullInlinerWithoutSplitter", [&]() { disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - FunctionGrouper::run(*m_context, *m_ast); - FullInliner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionHoister::run(*m_context, m_ast); + FunctionGrouper::run(*m_context, m_ast); + FullInliner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"rematerialiser", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - Rematerialiser::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + Rematerialiser::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"expressionSimplifier", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); - UnusedPruner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + ExpressionSplitter::run(*m_context, m_ast); + CommonSubexpressionEliminator::run(*m_context, m_ast); + ExpressionSimplifier::run(*m_context, m_ast); + ExpressionSimplifier::run(*m_context, m_ast); + ExpressionSimplifier::run(*m_context, m_ast); + UnusedPruner::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"fullSimplify", [&]() { disambiguate(); - FunctionGrouper::run(*m_context, *m_ast); - BlockFlattener::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); - UnusedPruner::run(*m_context, *m_ast); - CircularReferencesPruner::run(*m_context, *m_ast); - DeadCodeEliminator::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionGrouper::run(*m_context, m_ast); + BlockFlattener::run(*m_context, m_ast); + ExpressionSplitter::run(*m_context, m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + CommonSubexpressionEliminator::run(*m_context, m_ast); + ExpressionSimplifier::run(*m_context, m_ast); + UnusedPruner::run(*m_context, m_ast); + CircularReferencesPruner::run(*m_context, m_ast); + DeadCodeEliminator::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"unusedFunctionParameterPruner", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_object->code); - LiteralRematerialiser::run(*m_context, *m_object->code); - UnusedFunctionParameterPruner::run(*m_context, *m_object->code); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + LiteralRematerialiser::run(*m_context, m_ast); + UnusedFunctionParameterPruner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"unusedPruner", [&]() { disambiguate(); - UnusedPruner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + UnusedPruner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"circularReferencesPruner", [&]() { disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - CircularReferencesPruner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionHoister::run(*m_context, m_ast); + CircularReferencesPruner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"deadCodeEliminator", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - DeadCodeEliminator::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + DeadCodeEliminator::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"ssaTransform", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - SSATransform::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + SSATransform::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"unusedAssignEliminator", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - UnusedAssignEliminator::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + UnusedAssignEliminator::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"unusedStoreEliminator", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - SSATransform::run(*m_context, *m_ast); - UnusedStoreEliminator::run(*m_context, *m_ast); - SSAReverser::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + ExpressionSplitter::run(*m_context, m_ast); + SSATransform::run(*m_context, m_ast); + UnusedStoreEliminator::run(*m_context, m_ast); + SSAReverser::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"equalStoreEliminator", [&]() { disambiguate(); - FunctionHoister::run(*m_context, *m_ast); - ForLoopInitRewriter::run(*m_context, *m_ast); - EqualStoreEliminator::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + FunctionHoister::run(*m_context, m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + EqualStoreEliminator::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"ssaPlusCleanup", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - SSATransform::run(*m_context, *m_ast); - UnusedAssignEliminator::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + SSATransform::run(*m_context, m_ast); + UnusedAssignEliminator::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"loadResolver", [&]() { disambiguate(); - FunctionGrouper::run(*m_context, *m_ast); - BlockFlattener::run(*m_context, *m_ast); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - ExpressionSplitter::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); - ExpressionSimplifier::run(*m_context, *m_ast); + FunctionGrouper::run(*m_context, m_ast); + BlockFlattener::run(*m_context, m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + ExpressionSplitter::run(*m_context, m_ast); + CommonSubexpressionEliminator::run(*m_context, m_ast); + ExpressionSimplifier::run(*m_context, m_ast); - LoadResolver::run(*m_context, *m_ast); + LoadResolver::run(*m_context, m_ast); - UnusedPruner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - ExpressionJoiner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + UnusedPruner::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + ExpressionJoiner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"loopInvariantCodeMotion", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - LoopInvariantCodeMotion::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + LoopInvariantCodeMotion::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"controlFlowSimplifier", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - ControlFlowSimplifier::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + ControlFlowSimplifier::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"structuralSimplifier", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - LiteralRematerialiser::run(*m_context, *m_ast); - StructuralSimplifier::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + LiteralRematerialiser::run(*m_context, m_ast); + StructuralSimplifier::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"equivalentFunctionCombiner", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - EquivalentFunctionCombiner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + EquivalentFunctionCombiner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"ssaReverser", [&]() { disambiguate(); - SSAReverser::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + SSAReverser::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"ssaAndBack", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); // apply SSA - SSATransform::run(*m_context, *m_ast); - UnusedAssignEliminator::run(*m_context, *m_ast); + SSATransform::run(*m_context, m_ast); + UnusedAssignEliminator::run(*m_context, m_ast); // reverse SSA - SSAReverser::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - CommonSubexpressionEliminator::run(*m_context, *m_ast); - UnusedPruner::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + SSAReverser::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + CommonSubexpressionEliminator::run(*m_context, m_ast); + UnusedPruner::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"stackCompressor", [&]() { disambiguate(); - ForLoopInitRewriter::run(*m_context, *m_ast); - FunctionHoister::run(*m_context, *m_ast); - FunctionGrouper::run(*m_context, *m_ast); + ForLoopInitRewriter::run(*m_context, m_ast); + FunctionHoister::run(*m_context, m_ast); + FunctionGrouper::run(*m_context, m_ast); size_t maxIterations = 16; StackCompressor::run(m_yulNameRepository, *m_object, true, maxIterations); - BlockFlattener::run(*m_context, *m_ast); - m_context->yulNameRepository.generateLabels(*m_ast); + BlockFlattener::run(*m_context, m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"fullSuite", [&]() { GasMeter meter(m_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), false, 200); OptimiserSuite::run( - m_yulNameRepository, &meter, *m_object, true, @@ -377,17 +371,16 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( frontend::OptimiserSettings::DefaultYulOptimiserCleanupSteps, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment ); - m_context->yulNameRepository.generateLabels(*m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"stackLimitEvader", [&]() { disambiguate(); - m_context->yulNameRepository.generateLabels(*m_ast); + m_context->yulNameRepository.generateLabels(m_ast); StackLimitEvader::run(*m_context, *m_object, CompilabilityChecker{ - m_yulNameRepository, *m_object, true }.unreachableVariables); - m_context->yulNameRepository.generateLabels(*m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }}, {"fakeStackLimitEvader", [&]() { disambiguate(); @@ -429,9 +422,9 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( YulNameRepository const& m_yulNameRepository; }; FakeUnreachableGenerator fakeUnreachableGenerator (m_yulNameRepository); - fakeUnreachableGenerator(*m_ast); + fakeUnreachableGenerator(m_ast); StackLimitEvader::run(*m_context, *m_object, fakeUnreachableGenerator.fakeUnreachables); - m_context->yulNameRepository.generateLabels(*m_ast); + m_context->yulNameRepository.generateLabels(m_ast); }} }; } @@ -482,14 +475,14 @@ std::string YulOptimizerTestCommon::randomOptimiserStep(unsigned _seed) yulAssert(false, "Optimiser step selection failed."); } -std::shared_ptr YulOptimizerTestCommon::run() +Block* YulOptimizerTestCommon::run() { - return runStep() ? m_ast : nullptr; + return runStep() ? &m_ast : nullptr; } void YulOptimizerTestCommon::disambiguate() { - *m_object->code = std::get(Disambiguator(m_yulNameRepository, *m_analysisInfo)(*m_object->code)); + m_object->code->block() = std::get(Disambiguator(m_yulNameRepository, *m_analysisInfo)(m_object->code->block())); m_analysisInfo.reset(); updateContext(); } diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index 72399008c214..3f3616503727 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -27,6 +27,7 @@ namespace solidity::yul { struct AsmAnalysisInfo; struct Object; +class AST; } namespace solidity::yul::test @@ -34,16 +35,13 @@ namespace solidity::yul::test class YulOptimizerTestCommon { public: - explicit YulOptimizerTestCommon( - std::shared_ptr _obj, - YulNameRepository& _yulNameRepository - ); + explicit YulOptimizerTestCommon(std::shared_ptr _obj); /// Sets optimiser step to be run to @param /// _optimiserStep. void setStep(std::string const& _optimizerStep); /// Runs chosen optimiser step returning pointer /// to yul AST Block post optimisation. - std::shared_ptr run(); + Block* run(); /// Runs chosen optimiser step returning true if /// successful, false otherwise. bool runStep(); @@ -62,7 +60,7 @@ class YulOptimizerTestCommon std::unique_ptr m_context; std::shared_ptr m_object; - std::shared_ptr m_ast; + Block& m_ast; std::shared_ptr m_analysisInfo; std::map> m_namedSteps; }; diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index 252958f7fb18..2ef4939d3bce 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -87,7 +88,6 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret( os1, stack.parserResult()->code, - *stack.yulNameRepository(), /*disableMemoryTracing=*/true ); if (yulFuzzerUtil::resourceLimitsExceeded(termReason)) @@ -97,7 +97,6 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) termReason = yulFuzzerUtil::interpret( os2, stack.parserResult()->code, - *stack.yulNameRepository(), /*disableMemoryTracing=*/true ); diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp index d40bd30a65e6..1325e22739b5 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.cpp +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -17,14 +17,15 @@ // SPDX-License-Identifier: GPL-3.0 #include +#include + using namespace solidity; using namespace solidity::yul; using namespace solidity::yul::test::yul_fuzzer; yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( std::ostream& _os, - std::shared_ptr _ast, - YulNameRepository const& _yulNameRepository, + std::shared_ptr _ast, bool _disableMemoryTracing, bool _outputStorageOnly, size_t _maxSteps, @@ -52,7 +53,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( TerminationReason reason = TerminationReason::None; try { - Interpreter::run(state, _yulNameRepository, *_ast, true, _disableMemoryTracing); + Interpreter::run(state, _ast->nameRepository(), _ast->block(), true, _disableMemoryTracing); } catch (StepLimitReached const&) { diff --git a/test/tools/ossfuzz/yulFuzzerCommon.h b/test/tools/ossfuzz/yulFuzzerCommon.h index 63af29b84102..d43a42a455c0 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.h +++ b/test/tools/ossfuzz/yulFuzzerCommon.h @@ -40,8 +40,7 @@ struct yulFuzzerUtil /// eliminator. static TerminationReason interpret( std::ostream& _os, - std::shared_ptr _ast, - YulNameRepository const& _yulNameRepository, + std::shared_ptr _ast, bool _disableMemoryTracing = false, bool _outputStorageOnly = false, size_t _maxSteps = maxSteps, diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h index b37d026952d0..9ab8c986924d 100644 --- a/test/tools/yulInterpreter/Interpreter.h +++ b/test/tools/yulInterpreter/Interpreter.h @@ -163,7 +163,7 @@ class Interpreter: public ASTWalker static void run( InterpreterState& _state, YulNameRepository const& _yulNameRepository, - Block const& _ast, + Block const& _ast, // todo AST? bool _disableExternalCalls, bool _disableMemoryTracing ); diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 5d5e5e64bd95..bb2952caf944 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -91,7 +91,7 @@ class YulOpti CharStream _charStream(_input, ""); try { - m_ast = yul::Parser(errorReporter, m_yulNameRepository).parse(_charStream); + m_ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); if (!m_ast || !errorReporter.errors().empty()) { std::cerr << "Error parsing source." << std::endl; @@ -102,9 +102,9 @@ class YulOpti AsmAnalyzer analyzer( *m_analysisInfo, errorReporter, - m_yulNameRepository + m_ast->nameRepository() ); - if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) + if (!analyzer.analyze(m_ast->block()) || !errorReporter.errors().empty()) { std::cerr << "Error analyzing source." << std::endl; printErrors(_charStream, errors); @@ -170,7 +170,7 @@ class YulOpti void disambiguate() { - *m_ast = std::get(Disambiguator(m_yulNameRepository, *m_analysisInfo)(*m_ast)); + m_ast->block() = std::get(Disambiguator(m_ast->nameRepository(), *m_analysisInfo)(m_ast->block())); m_analysisInfo.reset(); } @@ -178,8 +178,9 @@ class YulOpti { parse(_source); disambiguate(); - OptimiserSuite{m_context}.runSequence(_steps, *m_ast); - std::cout << AsmPrinter{m_yulNameRepository}(*m_ast) << std::endl; + OptimiserStepContext context {m_dialect, m_ast->nameRepository(), m_reservedIdentifiers, solidity::frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment}; + OptimiserSuite{context}.runSequence(_steps, m_ast->block()); + std::cout << AsmPrinter{m_ast->nameRepository()}(m_ast->block()) << std::endl; } void runInteractive(std::string _source, bool _disambiguated = false) @@ -218,17 +219,17 @@ class YulOpti { Object obj; obj.code = m_ast; - StackCompressor::run(m_yulNameRepository, obj, true, 16); + StackCompressor::run(m_ast->nameRepository(), obj, true, 16); break; } default: - OptimiserSuite{m_context}.runSequence( - std::string_view(&option, 1), - *m_ast - ); + { + OptimiserStepContext context {m_dialect, m_ast->nameRepository(), m_reservedIdentifiers, solidity::frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment}; + OptimiserSuite{context}.runSequence(std::string_view(&option, 1), m_ast->block()); + } } - m_yulNameRepository.generateLabels(*m_ast); - _source = AsmPrinter{m_yulNameRepository}(*m_ast); + m_ast->nameRepository().generateLabels(m_ast->block()); + _source = AsmPrinter{m_ast->nameRepository()}(m_ast->block()); } catch (...) { @@ -241,16 +242,10 @@ class YulOpti } private: - std::shared_ptr m_ast; - YulNameRepository m_yulNameRepository {EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; + std::shared_ptr m_ast; + Dialect const& m_dialect {EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; std::unique_ptr m_analysisInfo; std::set const m_reservedIdentifiers = {}; - OptimiserStepContext m_context{ - m_yulNameRepository.dialect(), - m_yulNameRepository, - m_reservedIdentifiers, - solidity::frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment - }; }; int main(int argc, char** argv) diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index df82f483b198..e35a5b26d21c 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -54,7 +54,7 @@ namespace po = boost::program_options; namespace { -std::pair, std::shared_ptr> parse(std::string const& _source) +std::pair, std::shared_ptr> parse(std::string const& _source) { YulStack stack( langutil::EVMVersion(), @@ -77,7 +77,7 @@ std::pair, std::shared_ptr> parse(std::s void interpret(std::string const& _source, bool _inspect, bool _disableExternalCalls) { - std::shared_ptr ast; + std::shared_ptr ast; std::shared_ptr analysisInfo; tie(ast, analysisInfo) = parse(_source); if (!ast || !analysisInfo) @@ -87,14 +87,12 @@ void interpret(std::string const& _source, bool _inspect, bool _disableExternalC state.maxTraceSize = 10000; try { - Dialect const& dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{})); - YulNameRepository repository (dialect); - + YulNameRepository& repository = ast->nameRepository(); if (_inspect) - InspectedInterpreter::run(std::make_shared(_source, state, repository), state, repository, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); + InspectedInterpreter::run(std::make_shared(_source, state, repository), state, repository, ast->block(), _disableExternalCalls, /*disableMemoryTracing=*/false); else - Interpreter::run(state, repository, *ast, _disableExternalCalls, /*disableMemoryTracing=*/false); + Interpreter::run(state, repository, ast->block(), _disableExternalCalls, /*disableMemoryTracing=*/false); } catch (InterpreterTerminatedGeneric const&) { diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 8ca67814ba2e..6a2aa4c324a8 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -58,8 +58,8 @@ std::ostream& operator<<(std::ostream& _stream, Program const& _program); } Program::Program(Program const& program): - m_ast(std::make_unique(std::get(ASTCopier{}(*program.m_ast)))), - m_yulNameRepository(std::make_unique(*program.m_yulNameRepository)) + m_ast(std::make_unique(*program.m_ast)), + m_dialect(program.m_dialect) { } @@ -67,26 +67,23 @@ std::variant Program::load(CharStream& _sourceCode) { // ASSUMPTION: parseSource() rewinds the stream on its own Dialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{}); - auto nameRepository = std::make_unique(dialect); - std::variant, ErrorList> astOrErrors = parseObject(*nameRepository, _sourceCode); + std::variant, ErrorList> astOrErrors = parseObject(dialect, _sourceCode); if (std::holds_alternative(astOrErrors)) return std::get(astOrErrors); std::variant, ErrorList> analysisInfoOrErrors = analyzeAST( - *nameRepository, - *std::get>(astOrErrors) + *std::get>(astOrErrors) ); if (std::holds_alternative(analysisInfoOrErrors)) return std::get(analysisInfoOrErrors); auto ast = disambiguateAST( - *nameRepository, - *std::get>(astOrErrors), + *std::get>(astOrErrors), *std::get>(analysisInfoOrErrors) ); Program program( - std::move(nameRepository), + dialect, std::move(ast) ); program.optimise({ @@ -94,40 +91,41 @@ std::variant Program::load(CharStream& _sourceCode) FunctionGrouper::name, ForLoopInitRewriter::name, }); - program.m_yulNameRepository->generateLabels(*program.m_ast); + program.m_ast->nameRepository().generateLabels(program.m_ast->block()); return program; } void Program::optimise(std::vector const& _optimisationSteps) { - m_ast = applyOptimisationSteps(*m_yulNameRepository, std::move(m_ast), _optimisationSteps); + m_ast = applyOptimisationSteps(std::move(m_ast), _optimisationSteps); } std::ostream& phaser::operator<<(std::ostream& _stream, Program const& _program) { - _program.m_yulNameRepository->generateLabels(*_program.m_ast); - return _stream << AsmPrinter(*_program.m_yulNameRepository)(*_program.m_ast); + YulNameRepository nameRepository (_program.m_ast->nameRepository()); + nameRepository.generateLabels(_program.m_ast->block()); + return _stream << AsmPrinter(nameRepository)(_program.m_ast->block()); } std::string Program::toJson() const { - Json serializedAst = AsmJsonConverter(0, *m_yulNameRepository)(*m_ast); + Json serializedAst = AsmJsonConverter(0, nameRepository())(m_ast->block()); return jsonPrettyPrint(removeNullMembers(std::move(serializedAst))); } yul::YulNameRepository const& Program::nameRepository() const { - return *m_yulNameRepository; + return m_ast->nameRepository(); } -std::variant, ErrorList> Program::parseObject(yul::YulNameRepository& _yulNameRepository, CharStream _source) +std::variant, ErrorList> Program::parseObject(yul::Dialect const& _dialect, CharStream _source) { ErrorList errors; ErrorReporter errorReporter(errors); auto scanner = std::make_shared(_source); - ObjectParser parser(errorReporter, _yulNameRepository); + ObjectParser parser(errorReporter, _dialect); std::shared_ptr object = parser.parse(scanner, false); if (object == nullptr || !errorReporter.errors().empty()) // NOTE: It's possible to get errors even if the returned object is non-null. @@ -156,19 +154,19 @@ std::variant, ErrorList> Program::parseObject(yul::YulNam // The public API of the class does not provide access to the smart pointer so it won't be hard // to switch to shared_ptr if the copying turns out to be an issue (though it would be better // to refactor ObjectParser and Object to use unique_ptr instead). - auto astCopy = std::make_unique(std::get(ASTCopier{}(*selectedObject->code))); + auto astCopy = std::make_unique(*selectedObject->code); - return std::variant, ErrorList>(std::move(astCopy)); + return std::variant, ErrorList>(std::move(astCopy)); } -std::variant, ErrorList> Program::analyzeAST(yul::YulNameRepository const& _yulNameRepository, Block const& _ast) +std::variant, ErrorList> Program::analyzeAST(AST const& _ast) { ErrorList errors; ErrorReporter errorReporter(errors); auto analysisInfo = std::make_unique(); - AsmAnalyzer analyzer(*analysisInfo, errorReporter, _yulNameRepository); + AsmAnalyzer analyzer(*analysisInfo, errorReporter, _ast.nameRepository()); - bool analysisSuccessful = analyzer.analyze(_ast); + bool analysisSuccessful = analyzer.analyze(_ast.block()); if (!analysisSuccessful) return errors; @@ -176,21 +174,21 @@ std::variant, ErrorList> Program::analyzeAST(yu return std::variant, ErrorList>(std::move(analysisInfo)); } -std::unique_ptr Program::disambiguateAST( - yul::YulNameRepository& _yulNameRepository, - Block const& _ast, +std::unique_ptr Program::disambiguateAST( + AST const& _ast, AsmAnalysisInfo const& _analysisInfo ) { + auto nameRepository = std::make_unique(_ast.nameRepository()); std::set const externallyUsedIdentifiers = {}; - Disambiguator disambiguator(_yulNameRepository, _analysisInfo, externallyUsedIdentifiers); + Disambiguator disambiguator(*nameRepository, _analysisInfo, externallyUsedIdentifiers); - return std::make_unique(std::get(disambiguator(_ast))); + auto block = std::get(disambiguator(_ast.block())); + return std::make_unique(std::move(nameRepository), std::move(block)); } -std::unique_ptr Program::applyOptimisationSteps( - yul::YulNameRepository& _yulNameRepository, - std::unique_ptr _ast, +std::unique_ptr Program::applyOptimisationSteps( + std::unique_ptr _ast, std::vector const& _optimisationSteps ) { @@ -198,14 +196,14 @@ std::unique_ptr Program::applyOptimisationSteps( // think it would be useful in this tool. Other tools (like yulopti) have it empty too. std::set const externallyUsedIdentifiers = {}; OptimiserStepContext context{ - _yulNameRepository.dialect(), - _yulNameRepository, + _ast->nameRepository().dialect(), + _ast->nameRepository(), externallyUsedIdentifiers, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }; for (std::string const& step: _optimisationSteps) - OptimiserSuite::allSteps().at(step)->run(context, *_ast); + OptimiserSuite::allSteps().at(step)->run(context, _ast->block()); return _ast; } diff --git a/tools/yulPhaser/Program.h b/tools/yulPhaser/Program.h index b0d6e8a13abe..e4f3aef902f7 100644 --- a/tools/yulPhaser/Program.h +++ b/tools/yulPhaser/Program.h @@ -65,7 +65,7 @@ class Program Program(Program const& program); Program(Program&& program): m_ast(std::move(program.m_ast)), - m_yulNameRepository(std::move(program.m_yulNameRepository)) + m_dialect(program.m_dialect) {} Program operator=(Program const& program) = delete; Program operator=(Program&& program) = delete; @@ -73,8 +73,8 @@ class Program static std::variant load(langutil::CharStream& _sourceCode); void optimise(std::vector const& _optimisationSteps); - size_t codeSize(yul::CodeWeights const& _weights) const { return computeCodeSize(*m_ast, _weights); } - yul::Block const& ast() const { return *m_ast; } + size_t codeSize(yul::CodeWeights const& _weights) const { return computeCodeSize(m_ast->block(), _weights); } + yul::Block const& ast() const { return m_ast->block(); } friend std::ostream& operator<<(std::ostream& _stream, Program const& _program); std::string toJson() const; @@ -83,35 +83,31 @@ class Program private: Program( - std::unique_ptr _yulNameRepository, - std::unique_ptr _ast + yul::Dialect const& _dialect, + std::unique_ptr _ast ): m_ast(std::move(_ast)), - m_yulNameRepository(std::move(_yulNameRepository)) + m_dialect(_dialect) {} - static std::variant, langutil::ErrorList> parseObject( - yul::YulNameRepository& _yulNameRepository, - langutil::CharStream _source + static std::variant, langutil::ErrorList> parseObject( + yul::Dialect const& _dialect, langutil::CharStream _source ); static std::variant, langutil::ErrorList> analyzeAST( - yul::YulNameRepository const& _yulNameRepository, - yul::Block const& _ast + yul::AST const& _ast ); - static std::unique_ptr disambiguateAST( - yul::YulNameRepository& _yulNameRepository, - yul::Block const& _ast, + static std::unique_ptr disambiguateAST( + yul::AST const& _ast, yul::AsmAnalysisInfo const& _analysisInfo ); - static std::unique_ptr applyOptimisationSteps( - yul::YulNameRepository& _yulNameRepository, - std::unique_ptr _ast, + static std::unique_ptr applyOptimisationSteps( + std::unique_ptr _ast, std::vector const& _optimisationSteps ); static size_t computeCodeSize(yul::Block const& _ast, yul::CodeWeights const& _weights); - std::unique_ptr m_ast; - std::unique_ptr m_yulNameRepository; + std::unique_ptr m_ast; + yul::Dialect const& m_dialect; }; } From 0d9746447fda8b77dbfb2d44e21e91141c474f9b Mon Sep 17 00:00:00 2001 From: clonker Date: Tue, 9 Jul 2024 14:36:38 +0200 Subject: [PATCH 05/15] rebase --- libsolidity/analysis/PostTypeChecker.cpp | 2 +- libsolidity/analysis/ReferencesResolver.cpp | 10 ++--- libsolidity/ast/ASTJsonExporter.cpp | 2 +- .../codegen/ir/IRGeneratorForStatements.cpp | 2 +- .../codegen/IRGeneratorForStatements.cpp | 2 +- libsolidity/lsp/RenameSymbol.cpp | 4 +- libyul/AsmAnalysis.cpp | 42 +++++++++---------- libyul/AsmJsonConverter.cpp | 10 ++--- libyul/AsmParser.cpp | 4 +- libyul/AsmPrinter.cpp | 8 ++-- libyul/ScopeFiller.cpp | 4 +- libyul/YulName.cpp | 7 ++++ libyul/YulName.h | 16 +++---- libyul/backends/evm/EVMCodeTransform.cpp | 6 +-- libyul/backends/evm/EVMDialect.cpp | 7 ---- .../evm/OptimizedEVMCodeTransform.cpp | 8 ++-- libyul/backends/evm/StackHelpers.h | 6 +-- test/libyul/CompilabilityChecker.cpp | 2 +- test/libyul/ControlFlowGraphTest.cpp | 14 +++---- test/libyul/ControlFlowSideEffectsTest.cpp | 2 +- test/libyul/FunctionSideEffects.cpp | 2 +- test/libyul/StackLayoutGeneratorTest.cpp | 14 +++---- test/libyul/YulName.cpp | 10 ++--- test/tools/yulInterpreter/Inspector.cpp | 4 +- test/yulPhaser/Program.cpp | 4 +- 25 files changed, 93 insertions(+), 99 deletions(-) diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index 3361e443639e..2c5dbf5c50f3 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -473,7 +473,7 @@ class YulLValueChecker : public solidity::yul::ASTWalker if (ranges::any_of( _assignment.variableNames, - [&](auto const& yulIdentifier) { return m_yulNameRepository.labelOf(yulIdentifier.name) == m_identifierName; } + [&](auto const& yulIdentifier) { return m_yulNameRepository.requiredLabelOf(yulIdentifier.name) == m_identifierName; } )) m_willBeWrittenTo = true; } diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 49f688643b56..913df20be2cb 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -274,11 +274,11 @@ void ReferencesResolver::operator()(yul::FunctionDefinition const& _function) { solAssert(m_yulNameRepository != nullptr); solAssert(nativeLocationOf(_function) == originLocationOf(_function), ""); - validateYulIdentifierName(m_yulNameRepository->labelOf(_function.name), nativeLocationOf(_function)); + validateYulIdentifierName(m_yulNameRepository->requiredLabelOf(_function.name), nativeLocationOf(_function)); for (yul::TypedName const& varName: _function.parameters + _function.returnVariables) { solAssert(nativeLocationOf(varName) == originLocationOf(varName), ""); - validateYulIdentifierName(m_yulNameRepository->labelOf(varName.name), nativeLocationOf(varName)); + validateYulIdentifierName(m_yulNameRepository->requiredLabelOf(varName.name), nativeLocationOf(varName)); } bool wasInsideFunction = m_yulInsideFunction; @@ -291,7 +291,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier) { solAssert(m_yulNameRepository != nullptr); solAssert(nativeLocationOf(_identifier) == originLocationOf(_identifier), ""); - auto const identifierLabel = m_yulNameRepository->labelOf(_identifier.name); + auto const identifierLabel = m_yulNameRepository->requiredLabelOf(_identifier.name); if (m_resolver.experimentalSolidity()) { std::vector splitName; @@ -399,10 +399,10 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl) for (auto const& identifier: _varDecl.variables) { solAssert(nativeLocationOf(identifier) == originLocationOf(identifier), ""); - validateYulIdentifierName(m_yulNameRepository->labelOf(identifier.name), nativeLocationOf(identifier)); + validateYulIdentifierName(m_yulNameRepository->requiredLabelOf(identifier.name), nativeLocationOf(identifier)); if ( - auto declarations = m_resolver.nameFromCurrentScope(std::string(m_yulNameRepository->labelOf(identifier.name))); + auto declarations = m_resolver.nameFromCurrentScope(std::string(m_yulNameRepository->requiredLabelOf(identifier.name))); !declarations.empty() ) { diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 79242773671e..8740b375fa6f 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -654,7 +654,7 @@ bool ASTJsonExporter::visit(InlineAssembly const& _node) for (auto const& it: _node.annotation().externalReferences) if (it.first) externalReferences.emplace_back(std::make_pair( - _node.operations().nameRepository().labelOf(it.first->name), + _node.operations().nameRepository().requiredLabelOf(it.first->name), inlineAssemblyIdentifierToJson(it) )); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 9f9135055400..b56f1f8ef784 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -87,7 +87,7 @@ struct CopyTranslate: public yul::ASTCopier if (m_yulNameRepository.isBuiltinName(_name)) return _name; else - return m_yulNameRepository.defineName("usr$" + std::string(m_yulNameRepository.labelOf(_name))); + return m_yulNameRepository.defineName("usr$" + std::string(m_yulNameRepository.requiredLabelOf(_name))); } yul::Identifier translate(yul::Identifier const& _identifier) override diff --git a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp index 64cb101e8014..a40e0e58bea4 100644 --- a/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp +++ b/libsolidity/experimental/codegen/IRGeneratorForStatements.cpp @@ -75,7 +75,7 @@ struct CopyTranslate: public yul::ASTCopier if (m_yulNameRepository.isBuiltinName(_name)) return _name; else - return m_yulNameRepository.defineName("usr$" + std::string(m_yulNameRepository.labelOf(_name))); + return m_yulNameRepository.defineName("usr$" + std::string(m_yulNameRepository.requiredLabelOf(_name))); } yul::Identifier translate(yul::Identifier const& _identifier) override diff --git a/libsolidity/lsp/RenameSymbol.cpp b/libsolidity/lsp/RenameSymbol.cpp index d56316d066ad..4e968d6feb5d 100644 --- a/libsolidity/lsp/RenameSymbol.cpp +++ b/libsolidity/lsp/RenameSymbol.cpp @@ -283,7 +283,7 @@ void RenameSymbol::extractNameAndDeclaration(InlineAssembly const& _inlineAssemb if (location.containsOffset(_cursorBytePosition)) { m_declarationToRename = externalReference.declaration; - m_symbolName = _inlineAssembly.operations().nameRepository().labelOf(identifier->name); + m_symbolName = _inlineAssembly.operations().nameRepository().requiredLabelOf(identifier->name); if (!externalReference.suffix.empty()) m_symbolName = m_symbolName.substr(0, m_symbolName.length() - externalReference.suffix.size() - 1); @@ -296,7 +296,7 @@ void RenameSymbol::Visitor::endVisit(InlineAssembly const& _node) { for (auto&& [identifier, externalReference]: _node.annotation().externalReferences) { - auto identifierName = _node.operations().nameRepository().labelOf(identifier->name); + auto identifierName = _node.operations().nameRepository().requiredLabelOf(identifier->name); if (!externalReference.suffix.empty()) identifierName = identifierName.substr(0, identifierName.length() - externalReference.suffix.size() - 1); diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 9b26abe572e9..8c17f6cebf3b 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -126,7 +126,7 @@ std::vector AsmAnalyzer::operator()(Literal const& _literal) nativeLocationOf(_literal), fmt::format( R"(Invalid type "{}" for literal "{}".)", - m_yulNameRepository.labelOf(_literal.type), + m_yulNameRepository.requiredLabelOf(_literal.type), formatLiteral(_literal, false) ) ); @@ -151,7 +151,7 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) nativeLocationOf(_identifier), fmt::format( "Variable {} used before it was declared.", - m_yulNameRepository.labelOf(_identifier.name) + m_yulNameRepository.requiredLabelOf(_identifier.name) ) ); type = _var.type; @@ -161,7 +161,7 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) m_errorReporter.typeError( 6041_error, nativeLocationOf(_identifier), - fmt::format("Function {} used without being called.", m_yulNameRepository.labelOf(_identifier.name)) + fmt::format("Function {} used without being called.", m_yulNameRepository.requiredLabelOf(_identifier.name)) ); } })) @@ -186,7 +186,7 @@ std::vector AsmAnalyzer::operator()(Identifier const& _identifier) m_errorReporter.declarationError( 8198_error, nativeLocationOf(_identifier), - fmt::format("Identifier \"{}\" not found.", m_yulNameRepository.labelOf(_identifier.name)) + fmt::format("Identifier \"{}\" not found.", m_yulNameRepository.requiredLabelOf(_identifier.name)) ); } @@ -224,7 +224,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment) nativeLocationOf(_assignment), fmt::format( "Variable {} occurs multiple times on the left-hand side of the assignment.", - m_yulNameRepository.labelOf(_variableName.name) + m_yulNameRepository.requiredLabelOf(_variableName.name) ) ); @@ -236,7 +236,7 @@ void AsmAnalyzer::operator()(Assignment const& _assignment) nativeLocationOf(_assignment), fmt::format( "Variable count for assignment to \"{}\" does not match number of values ({} vs. {})", - joinHumanReadable(applyMap(_assignment.variableNames, [this](auto const& _identifier){ return m_yulNameRepository.labelOf(_identifier.name); })), + joinHumanReadable(applyMap(_assignment.variableNames, [this](auto const& _identifier){ return m_yulNameRepository.requiredLabelOf(_identifier.name); })), numVariables, types.size() ) @@ -273,7 +273,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) nativeLocationOf(_varDecl), fmt::format( "Variable count mismatch for declaration of \"{}\": {} variables and {} values.", - joinHumanReadable(applyMap(_varDecl.variables, [this](auto const& _identifier){ return m_yulNameRepository.labelOf(_identifier.name); })), + joinHumanReadable(applyMap(_varDecl.variables, [this](auto const& _identifier){ return m_yulNameRepository.requiredLabelOf(_identifier.name); })), numVariables, types.size() ) @@ -291,8 +291,8 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) nativeLocationOf(variable), fmt::format( R"(Assigning value of type "{}" to variable of type "{}".)", - m_yulNameRepository.labelOf(givenType), - m_yulNameRepository.labelOf(variable.type) + m_yulNameRepository.requiredLabelOf(givenType), + m_yulNameRepository.requiredLabelOf(variable.type) ) ); } @@ -395,7 +395,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) m_errorReporter.declarationError( 4619_error, nativeLocationOf(_funCall.functionName), - fmt::format("Function \"{}\" not found.", m_yulNameRepository.labelOf(_funCall.functionName.name)) + fmt::format("Function \"{}\" not found.", m_yulNameRepository.requiredLabelOf(_funCall.functionName.name)) ); yulAssert(!watcher.ok(), "Expected a reported error."); } @@ -406,7 +406,7 @@ std::vector AsmAnalyzer::operator()(FunctionCall const& _funCall) nativeLocationOf(_funCall.functionName), fmt::format( "Function \"{}\" expects {} arguments but got {}.", - m_yulNameRepository.labelOf(_funCall.functionName.name), + m_yulNameRepository.requiredLabelOf(_funCall.functionName.name), parameterTypes->size(), _funCall.arguments.size() ) @@ -597,8 +597,8 @@ void AsmAnalyzer::expectBoolExpression(Expression const& _expr) nativeLocationOf(_expr), fmt::format( R"(Expected a value of boolean type "{}" but got "{}")", - m_yulNameRepository.labelOf(m_yulNameRepository.predefined().boolType), - m_yulNameRepository.labelOf(type) + m_yulNameRepository.requiredLabelOf(m_yulNameRepository.predefined().boolType), + m_yulNameRepository.requiredLabelOf(type) ) ); } @@ -625,7 +625,7 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, Type _valueType) m_errorReporter.declarationError( 1133_error, nativeLocationOf(_variable), - fmt::format("Variable {} used before it was declared.", m_yulNameRepository.labelOf(_variable.name)) + fmt::format("Variable {} used before it was declared.", m_yulNameRepository.requiredLabelOf(_variable.name)) ); else variableType = &std::get(*var).type; @@ -650,8 +650,8 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, Type _valueType) nativeLocationOf(_variable), fmt::format( R"(Assigning a value of type "{}" to a variable of type "{}".)", - m_yulNameRepository.labelOf(_valueType), - m_yulNameRepository.labelOf(*variableType) + m_yulNameRepository.requiredLabelOf(_valueType), + m_yulNameRepository.requiredLabelOf(*variableType) ) ); @@ -668,7 +668,7 @@ Scope& AsmAnalyzer::scope(Block const* _block) void AsmAnalyzer::expectValidIdentifier(YulName _identifier, SourceLocation const& _location) { - auto const label = m_yulNameRepository.labelOf(_identifier); + auto const label = m_yulNameRepository.requiredLabelOf(_identifier); // NOTE: the leading dot case is handled by the parser not allowing it. if (boost::ends_with(label, ".")) m_errorReporter.syntaxError( @@ -698,7 +698,7 @@ void AsmAnalyzer::expectValidType(Type _type, SourceLocation const& _location) m_errorReporter.typeError( 5473_error, _location, - fmt::format("\"{}\" is not a valid type (user defined types are not yet supported).", m_yulNameRepository.labelOf(_type)) + fmt::format("\"{}\" is not a valid type (user defined types are not yet supported).", m_yulNameRepository.requiredLabelOf(_type)) ); } @@ -710,8 +710,8 @@ void AsmAnalyzer::expectType(Type _expectedType, Type _givenType, SourceLocation _location, fmt::format( R"(Expected a value of type "{}" but got "{}".)", - m_yulNameRepository.labelOf(_expectedType), - m_yulNameRepository.labelOf(_givenType) + m_yulNameRepository.requiredLabelOf(_expectedType), + m_yulNameRepository.requiredLabelOf(_givenType) ) ); } @@ -806,5 +806,5 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio bool AsmAnalyzer::validateInstructions(FunctionCall const& _functionCall) { - return validateInstructions(m_yulNameRepository.labelOf(_functionCall.functionName.name), nativeLocationOf(_functionCall.functionName)); + return validateInstructions(m_yulNameRepository.requiredLabelOf(_functionCall.functionName.name), nativeLocationOf(_functionCall.functionName)); } diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index 69b6803920d5..51e7e281d55d 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -45,8 +45,8 @@ Json AsmJsonConverter::operator()(TypedName const& _node) const { yulAssert(YulNameRepository::emptyName() != _node.name, "Invalid variable name."); Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulTypedName"); - ret["name"] = m_yulNameRepository.labelOf(_node.name); - ret["type"] = m_yulNameRepository.labelOf(_node.type); + ret["name"] = m_yulNameRepository.requiredLabelOf(_node.name); + ret["type"] = m_yulNameRepository.requiredLabelOf(_node.type); return ret; } @@ -67,7 +67,7 @@ Json AsmJsonConverter::operator()(Literal const& _node) const ret["hexValue"] = util::toHex(util::asBytes(formatLiteral(_node))); break; } - ret["type"] = m_yulNameRepository.labelOf(_node.type); + ret["type"] = m_yulNameRepository.requiredLabelOf(_node.type); { auto const formattedLiteral = formatLiteral(_node); if (util::validateUTF8(formattedLiteral)) @@ -80,7 +80,7 @@ Json AsmJsonConverter::operator()(Identifier const& _node) const { yulAssert(YulNameRepository::emptyName() != _node.name, "Invalid identifier"); Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulIdentifier"); - ret["name"] = m_yulNameRepository.labelOf(_node.name); + ret["name"] = m_yulNameRepository.requiredLabelOf(_node.name); return ret; } @@ -122,7 +122,7 @@ Json AsmJsonConverter::operator()(FunctionDefinition const& _node) const { yulAssert(YulNameRepository::emptyName() != _node.name, "Invalid function name."); Json ret = createAstNode(originLocationOf(_node), nativeLocationOf(_node), "YulFunctionDefinition"); - ret["name"] = m_yulNameRepository.labelOf(_node.name); + ret["name"] = m_yulNameRepository.requiredLabelOf(_node.name); for (auto const& var: _node.parameters) ret["parameters"].emplace_back((*this)(var)); for (auto const& var: _node.returnVariables) diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index fb2667cacca3..feee5aac299a 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -442,7 +442,7 @@ Statement Parser::parseStatement(YulNameRepository& _nameRepository) 6272_error, fmt::format( "Cannot assign to builtin function \"{}\".", - _nameRepository.labelOf(identifier.name) + _nameRepository.requiredLabelOf(identifier.name) ) ); @@ -530,7 +530,7 @@ Expression Parser::parseExpression(YulNameRepository& _nameRepository, bool _unl fatalParserError( 7104_error, nativeLocationOf(_identifier), - fmt::format("Builtin function \"{}\" must be called.", _nameRepository.labelOf(_identifier.name)) + fmt::format("Builtin function \"{}\" must be called.", _nameRepository.requiredLabelOf(_identifier.name)) ); return std::move(_identifier); }, diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index a7f335080c60..547e306f82e9 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -66,7 +66,7 @@ std::string AsmPrinter::operator()(Literal const& _literal) std::string AsmPrinter::operator()(Identifier const& _identifier) { yulAssert(_identifier.name != YulNameRepository::emptyName(), "Invalid identifier."); - return formatDebugData(_identifier) + std::string(m_nameRepository.labelOf(_identifier.name)); + return formatDebugData(_identifier) + std::string(m_nameRepository.requiredLabelOf(_identifier.name)); } std::string AsmPrinter::operator()(ExpressionStatement const& _statement) @@ -112,7 +112,7 @@ std::string AsmPrinter::operator()(FunctionDefinition const& _functionDefinition yulAssert(_functionDefinition.name != YulNameRepository::emptyName(), "Invalid function name."); std::string out = formatDebugData(_functionDefinition); - out += "function " + std::string(m_nameRepository.labelOf(_functionDefinition.name)) + "("; + out += "function " + std::string(m_nameRepository.requiredLabelOf(_functionDefinition.name)) + "("; out += boost::algorithm::join( _functionDefinition.parameters | ranges::views::transform( [this](TypedName argument) { return formatTypedName(argument); } @@ -240,7 +240,7 @@ std::string AsmPrinter::operator()(Block const& _block) std::string AsmPrinter::formatTypedName(TypedName const& _variable) { yulAssert(_variable.name != YulNameRepository::emptyName(), "Invalid variable name."); - return formatDebugData(_variable) + std::string(m_nameRepository.labelOf(_variable.name)) + appendTypeName(_variable.type); + return formatDebugData(_variable) + std::string(m_nameRepository.requiredLabelOf(_variable.name)) + appendTypeName(_variable.type); } std::string AsmPrinter::appendTypeName(Type _type, bool const _isBoolLiteral) const @@ -256,7 +256,7 @@ std::string AsmPrinter::appendTypeName(Type _type, bool const _isBoolLiteral) co if (_type == YulNameRepository::emptyName()) return {}; else - return fmt::format(":{}", m_nameRepository.labelOf(_type)); + return fmt::format(":{}", m_nameRepository.requiredLabelOf(_type)); } std::string AsmPrinter::formatSourceLocation( diff --git a/libyul/ScopeFiller.cpp b/libyul/ScopeFiller.cpp index 63dddfcab433..155a138f6b20 100644 --- a/libyul/ScopeFiller.cpp +++ b/libyul/ScopeFiller.cpp @@ -142,7 +142,7 @@ bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const& m_errorReporter.declarationError( 1395_error, _location, - fmt::format("Variable name {} already taken in this scope.", m_yulNameRegistry.labelOf(_name.name)) + fmt::format("Variable name {} already taken in this scope.", m_yulNameRegistry.requiredLabelOf(_name.name)) ); return false; } @@ -163,7 +163,7 @@ bool ScopeFiller::registerFunction(FunctionDefinition const& _funDef) m_errorReporter.declarationError( 6052_error, nativeLocationOf(_funDef), - fmt::format("Function name {} already taken in this scope.", m_yulNameRegistry.labelOf(_funDef.name)) + fmt::format("Function name {} already taken in this scope.", m_yulNameRegistry.requiredLabelOf(_funDef.name)) ); return false; } diff --git a/libyul/YulName.cpp b/libyul/YulName.cpp index 32bf777e3ddb..03f5187c1170 100644 --- a/libyul/YulName.cpp +++ b/libyul/YulName.cpp @@ -163,6 +163,13 @@ std::optional YulNameRepository::labelOf(YulName const _name) return std::nullopt; } +std::string_view YulNameRepository::requiredLabelOf(YulName const _name) const +{ + auto const label = labelOf(_name); + yulAssert(label.has_value(), "YulName currently has no defined label in the YulNameRepository."); + return label.value(); +} + YulNameRepository::YulName YulNameRepository::baseNameOf(YulName _name) const { yulAssert(nameWithinBounds(_name), "YulName exceeds repository size, probably stems from another instance."); diff --git a/libyul/YulName.h b/libyul/YulName.h index d83123d5506a..1fd5ac92f0cb 100644 --- a/libyul/YulName.h +++ b/libyul/YulName.h @@ -102,6 +102,10 @@ class YulNameRepository /// generated with ``generateLabels``, or it is a builtin. std::optional labelOf(YulName _name) const; + /// If it can be assumed that the label was already generated, this function will yield it (or fail with an + /// assertion error). + std::string_view requiredLabelOf(YulName _name) const; + /// Yields the name that the provided name was based on - or the name itself, if the name was directly "defined". YulName baseNameOf(YulName _name) const; @@ -157,16 +161,6 @@ class YulNameRepository void generateLabels(Block const& _ast, std::set const& _illegal = {}); private: - bool nameWithinBounds(YulName const _name) const { return _name < m_index; } - - size_t indexOfType(YulName _type) const; - BuiltinFunction convertBuiltinFunction(YulName _name, yul::BuiltinFunction const& _builtin) const; - BuiltinFunction const* fetchTypedPredefinedFunction(YulName _type, std::vector> const& _functions) const; - - Dialect const& m_dialect; - std::vector> m_dialectTypes; - std::map m_builtinFunctions; - struct PredefinedBuiltinFunctions { std::vector> discardFunctions; @@ -186,8 +180,8 @@ class YulNameRepository size_t endBuiltins {}; }; enum class YulNameState { DERIVED, DEFINED }; - bool nameWithinBounds(YulName const _name) const { return _name < m_index; } + bool nameWithinBounds(YulName const _name) const { return _name < m_index; } size_t indexOfType(YulName _type) const; BuiltinFunction convertBuiltinFunction(YulName _name, yul::BuiltinFunction const& _builtin) const; BuiltinFunction const* fetchTypedPredefinedFunction(YulName _type, std::vector> const& _functions) const; diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index e23b68ec9141..bb85a4fb9f93 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -465,7 +465,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) static_cast(stackLayout.size()) - 17, fmt::format( "The function {} has {} parameters or return variables too many to fit the stack size.", - m_yulNameRepository.labelOf(_function.name), stackLayout.size() - 17 + m_yulNameRepository.requiredLabelOf(_function.name), stackLayout.size() - 17 ) ); stackError(std::move(error), m_assembly.stackHeight() - static_cast(_function.parameters.size())); @@ -605,7 +605,7 @@ void CodeTransform::createFunctionEntryID(FunctionDefinition const& _function) !nameAlreadySeen ) ? m_assembly.namedLabel( - std::string(m_yulNameRepository.labelOf(_function.name)), + std::string(m_yulNameRepository.requiredLabelOf(_function.name)), _function.parameters.size(), _function.returnVariables.size(), astID @@ -787,7 +787,7 @@ size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulName _v heightDiff - limit, fmt::format( "Variable {} is {} slot(s) too deep inside the stack. {}", - m_yulNameRepository.labelOf(_varName), heightDiff - limit, stackTooDeepString + m_yulNameRepository.requiredLabelOf(_varName), heightDiff - limit, stackTooDeepString ) ); m_assembly.markAsInvalid(); diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 7aca938fa872..82680acc2c57 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -476,13 +476,6 @@ std::set EVMDialect::builtinNames() const { return { keys.begin(), keys.end() }; } -std::set EVMDialect::builtinNames() const { - static std::array verbatim {YulString("verbatim")}; - auto const keys = ranges::views::concat(ranges::views::keys(m_functions), verbatim) - | ranges::views::transform([](auto const& name) { return name.str(); }); - return { keys.begin(), keys.end() }; -} - EVMDialectTyped::EVMDialectTyped(langutil::EVMVersion _evmVersion, bool _objectAccess): EVMDialect(_evmVersion, _objectAccess) { diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index a9726ffbf1e8..651fb226489c 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -197,7 +197,7 @@ OptimizedEVMCodeTransform::OptimizedEVMCodeTransform( bool useNamedLabel = _useNamedLabelsForFunctions != UseNamedLabels::Never && !nameAlreadySeen; functionLabels[&functionInfo] = useNamedLabel ? m_assembly.namedLabel( - std::string(_yulNameRepository.labelOf(function->name)), + std::string(_yulNameRepository.requiredLabelOf(function->name)), function->arguments.size(), function->returns.size(), functionInfo.debugData ? functionInfo.debugData->astID : std::nullopt @@ -270,8 +270,8 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr YulName varNameDeep = slotVariableName(deepSlot); YulName varNameTop = slotVariableName(m_stack.back()); std::string msg = - "Cannot swap " + (varNameDeep == YulNameRepository::emptyName() ? "Slot " + stackSlotToString(deepSlot, m_yulNameRepository) : "Variable " + std::string(m_yulNameRepository.labelOf(varNameDeep))) + - " with " + (varNameTop == YulNameRepository::emptyName() ? "Slot " + stackSlotToString(m_stack.back(), m_yulNameRepository) : "Variable " + std::string(m_yulNameRepository.labelOf(varNameTop))) + + "Cannot swap " + (varNameDeep == YulNameRepository::emptyName() ? "Slot " + stackSlotToString(deepSlot, m_yulNameRepository) : "Variable " + std::string(m_yulNameRepository.requiredLabelOf(varNameDeep))) + + " with " + (varNameTop == YulNameRepository::emptyName() ? "Slot " + stackSlotToString(m_stack.back(), m_yulNameRepository) : "Variable " + std::string(m_yulNameRepository.requiredLabelOf(varNameTop))) + ": too deep in the stack by " + std::to_string(deficit) + " slots in " + stackToString(m_stack, m_yulNameRepository); m_stackErrors.emplace_back(StackTooDeepError( m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulNameRepository::emptyName(), @@ -300,7 +300,7 @@ void OptimizedEVMCodeTransform::createStackLayout(langutil::DebugData::ConstPtr int deficit = static_cast(*depth - 15); YulName varName = slotVariableName(_slot); std::string msg = - (varName == YulNameRepository::emptyName() ? "Slot " + stackSlotToString(_slot, m_yulNameRepository) : "Variable " + std::string(m_yulNameRepository.labelOf(varName))) + (varName == YulNameRepository::emptyName() ? "Slot " + stackSlotToString(_slot, m_yulNameRepository) : "Variable " + std::string(m_yulNameRepository.requiredLabelOf(varName))) + " is " + std::to_string(*depth - 15) + " too deep in the stack " + stackToString(m_stack, m_yulNameRepository); m_stackErrors.emplace_back(StackTooDeepError( m_currentFunctionInfo ? m_currentFunctionInfo->function.name : YulNameRepository::emptyName(), diff --git a/libyul/backends/evm/StackHelpers.h b/libyul/backends/evm/StackHelpers.h index 4644511c9488..a0a6387abbf7 100644 --- a/libyul/backends/evm/StackHelpers.h +++ b/libyul/backends/evm/StackHelpers.h @@ -36,11 +36,11 @@ namespace solidity::yul inline std::string stackSlotToString(StackSlot const& _slot, YulNameRepository const& _yulNameRepository) { return std::visit(util::GenericVisitor{ - [&_yulNameRepository](FunctionCallReturnLabelSlot const& _ret) -> std::string { return fmt::format("RET[{}]", _yulNameRepository.labelOf(_ret.call.get().functionName.name)); }, + [&_yulNameRepository](FunctionCallReturnLabelSlot const& _ret) -> std::string { return fmt::format("RET[{}]", _yulNameRepository.requiredLabelOf(_ret.call.get().functionName.name)); }, [](FunctionReturnLabelSlot const&) -> std::string { return "RET"; }, - [&_yulNameRepository](VariableSlot const& _var) { return std::string(_yulNameRepository.labelOf(_var.variable.get().name)); }, + [&_yulNameRepository](VariableSlot const& _var) { return std::string(_yulNameRepository.requiredLabelOf(_var.variable.get().name)); }, [](LiteralSlot const& _lit) { return toCompactHexWithPrefix(_lit.value); }, - [&_yulNameRepository](TemporarySlot const& _tmp) -> std::string { return fmt::format("TMP[{}, {}]", _yulNameRepository.labelOf(_tmp.call.get().functionName.name), _tmp.index); }, + [&_yulNameRepository](TemporarySlot const& _tmp) -> std::string { return fmt::format("TMP[{}, {}]", _yulNameRepository.requiredLabelOf(_tmp.call.get().functionName.name), _tmp.index); }, [](JunkSlot const&) -> std::string { return "JUNK"; } }, _slot); } diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index c90474b00140..6052fa81fe16 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -40,7 +40,7 @@ std::string check(std::string const& _input) // recast into map string -> int s.t. order is predictable std::map labelledFunctions; for(const auto& [k, v] : functions) - labelledFunctions[std::string(obj.code->nameRepository().labelOf(k))] = v; + labelledFunctions[std::string(obj.code->nameRepository().requiredLabelOf(k))] = v; std::string out; for (auto const& function: labelledFunctions) out += function.first + ": " + std::to_string(function.second) + " "; diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index 7423df366110..af80800ab9c6 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -53,7 +53,7 @@ namespace { static std::string variableSlotToString(VariableSlot const& _slot, YulNameRepository const& _yulNameRepository) { - return std::string{_yulNameRepository.labelOf(_slot.variable.get().name)}; + return std::string{_yulNameRepository.requiredLabelOf(_slot.variable.get().name)}; } } @@ -83,8 +83,8 @@ class ControlFlowGraphPrinter CFG::FunctionInfo const& _info ) { - m_stream << "FunctionEntry_" << m_yulNameRepository.labelOf(_info.function.name) << "_" << getBlockId(*_info.entry) << " [label=\""; - m_stream << "function " << m_yulNameRepository.labelOf(_info.function.name) << "("; + m_stream << "FunctionEntry_" << m_yulNameRepository.requiredLabelOf(_info.function.name) << "_" << getBlockId(*_info.entry) << " [label=\""; + m_stream << "function " << m_yulNameRepository.requiredLabelOf(_info.function.name) << "("; m_stream << joinHumanReadable(_info.parameters | ranges::views::transform([&](auto const& var) { return variableSlotToString(var, m_yulNameRepository); })); m_stream << ")"; if (!_info.returnVariables.empty()) @@ -93,7 +93,7 @@ class ControlFlowGraphPrinter m_stream << joinHumanReadable(_info.returnVariables | ranges::views::transform([&](auto const& var) { return variableSlotToString(var, m_yulNameRepository); })); } m_stream << "\"];\n"; - m_stream << "FunctionEntry_" << m_yulNameRepository.labelOf(_info.function.name) << "_" << getBlockId(*_info.entry) << " -> Block" << getBlockId(*_info.entry) << ";\n"; + m_stream << "FunctionEntry_" << m_yulNameRepository.requiredLabelOf(_info.function.name) << "_" << getBlockId(*_info.entry) << " -> Block" << getBlockId(*_info.entry) << ";\n"; (*this)(*_info.entry, false); } @@ -126,10 +126,10 @@ class ControlFlowGraphPrinter { std::visit(util::GenericVisitor{ [&](CFG::FunctionCall const& _call) { - m_stream << m_yulNameRepository.labelOf(_call.function.get().name) << ": "; + m_stream << m_yulNameRepository.requiredLabelOf(_call.function.get().name) << ": "; }, [&](CFG::BuiltinCall const& _call) { - m_stream << m_yulNameRepository.labelOf(_call.functionCall.get().functionName.name) << ": "; + m_stream << m_yulNameRepository.requiredLabelOf(_call.functionCall.get().functionName.name) << ": "; }, [&](CFG::Assignment const& _assignment) { @@ -169,7 +169,7 @@ class ControlFlowGraphPrinter }, [&](CFG::BasicBlock::FunctionReturn const& _return) { - m_stream << "Block" << getBlockId(_block) << "Exit [label=\"FunctionReturn[" << m_yulNameRepository.labelOf(_return.info->function.name) << "]\"];\n"; + m_stream << "Block" << getBlockId(_block) << "Exit [label=\"FunctionReturn[" << m_yulNameRepository.requiredLabelOf(_return.info->function.name) << "]\"];\n"; m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; }, [&](CFG::BasicBlock::Terminated const&) diff --git a/test/libyul/ControlFlowSideEffectsTest.cpp b/test/libyul/ControlFlowSideEffectsTest.cpp index 9d302965db6d..ff69a56eba8b 100644 --- a/test/libyul/ControlFlowSideEffectsTest.cpp +++ b/test/libyul/ControlFlowSideEffectsTest.cpp @@ -69,7 +69,7 @@ TestCase::TestResult ControlFlowSideEffectsTest::run(std::ostream& _stream, std: m_obtainedResult.clear(); forEach(obj.code->block(), [&](FunctionDefinition const& _fun) { std::string effectStr = toString(sideEffects.functionSideEffects().at(&_fun)); - m_obtainedResult += std::string(obj.code->nameRepository().labelOf(_fun.name)) + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; + m_obtainedResult += std::string(obj.code->nameRepository().requiredLabelOf(_fun.name)) + (effectStr.empty() ? ":" : ": " + effectStr) + "\n"; }); return checkResult(_stream, _linePrefix, _formatted); diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index 6d58d7eae6a2..ee0713e0851a 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -94,7 +94,7 @@ TestCase::TestResult FunctionSideEffects::run(std::ostream& _stream, std::string std::map functionSideEffectsStr; for (auto const& fun: functionSideEffects) - functionSideEffectsStr[obj.code->nameRepository().labelOf(fun.first)] = toString(fun.second); + functionSideEffectsStr[obj.code->nameRepository().requiredLabelOf(fun.first)] = toString(fun.second); m_obtainedResult.clear(); for (auto const& fun: functionSideEffectsStr) diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 02847dfdebe9..053ac3601ae0 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -57,7 +57,7 @@ namespace { static std::string variableSlotToString(VariableSlot const& _slot, YulNameRepository const& _yulNameRepository) { - return std::string(_yulNameRepository.labelOf(_slot.variable.get().name)); + return std::string(_yulNameRepository.requiredLabelOf(_slot.variable.get().name)); } } @@ -87,8 +87,8 @@ class StackLayoutPrinter CFG::FunctionInfo const& _info ) { - m_stream << "FunctionEntry_" << m_yulNameRepository.labelOf(_info.function.name) << " [label=\""; - m_stream << "function " << m_yulNameRepository.labelOf(_info.function.name) << "("; + m_stream << "FunctionEntry_" << m_yulNameRepository.requiredLabelOf(_info.function.name) << " [label=\""; + m_stream << "function " << m_yulNameRepository.requiredLabelOf(_info.function.name) << "("; m_stream << joinHumanReadable(_info.parameters | ranges::views::transform([&](auto const& var) { return variableSlotToString(var, m_yulNameRepository); })); m_stream << ")"; if (!_info.returnVariables.empty()) @@ -100,7 +100,7 @@ class StackLayoutPrinter Stack functionEntryStack = {FunctionReturnLabelSlot{_info.function}}; functionEntryStack += _info.parameters | ranges::views::reverse; m_stream << stackToString(functionEntryStack, m_yulNameRepository) << "\"];\n"; - m_stream << "FunctionEntry_" << m_yulNameRepository.labelOf(_info.function.name) << " -> Block" << getBlockId(*_info.entry) << ";\n"; + m_stream << "FunctionEntry_" << m_yulNameRepository.requiredLabelOf(_info.function.name) << " -> Block" << getBlockId(*_info.entry) << ";\n"; (*this)(*_info.entry, false); } @@ -137,10 +137,10 @@ class StackLayoutPrinter m_stream << stackToString(m_stackLayout.operationEntryLayout.at(&operation), m_yulNameRepository) << "\\l\\\n"; std::visit(util::GenericVisitor{ [&](CFG::FunctionCall const& _call) { - m_stream << m_yulNameRepository.labelOf(_call.function.get().name); + m_stream << m_yulNameRepository.requiredLabelOf(_call.function.get().name); }, [&](CFG::BuiltinCall const& _call) { - m_stream << m_yulNameRepository.labelOf(_call.functionCall.get().functionName.name); + m_stream << m_yulNameRepository.requiredLabelOf(_call.functionCall.get().functionName.name); }, [&](CFG::Assignment const& _assignment) { @@ -186,7 +186,7 @@ class StackLayoutPrinter }, [&](CFG::BasicBlock::FunctionReturn const& _return) { - m_stream << "Block" << getBlockId(_block) << "Exit [label=\"FunctionReturn[" << m_yulNameRepository.labelOf(_return.info->function.name) << "]\"];\n"; + m_stream << "Block" << getBlockId(_block) << "Exit [label=\"FunctionReturn[" << m_yulNameRepository.requiredLabelOf(_return.info->function.name) << "]\"];\n"; m_stream << "Block" << getBlockId(_block) << " -> Block" << getBlockId(_block) << "Exit;\n"; }, [&](CFG::BasicBlock::Terminated const&) diff --git a/test/libyul/YulName.cpp b/test/libyul/YulName.cpp index 6c7238799853..8d3c9539e0de 100644 --- a/test/libyul/YulName.cpp +++ b/test/libyul/YulName.cpp @@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(repository_with_evm_dialect) auto const extractEVMFunction = [](auto const* function) { return function ? function->data : nullptr; }; auto const type = YulNameRepository::emptyName(); - YulString typeLabel(std::string(nameRepository.labelOf(type).value())); + std::string typeLabel(nameRepository.labelOf(type).value()); BOOST_CHECK(extractEVMFunction(nameRepository.discardFunction(type)) == dialect.discardFunction(typeLabel)); BOOST_CHECK(extractEVMFunction(nameRepository.equalityFunction(type)) == dialect.equalityFunction(typeLabel));; BOOST_CHECK(extractEVMFunction(nameRepository.booleanNegationFunction()) == dialect.booleanNegationFunction()); @@ -114,7 +114,7 @@ BOOST_AUTO_TEST_CASE(repository_with_evm_dialect) BOOST_CHECK(extractEVMFunction(nameRepository.memoryLoadFunction(type)) == dialect.memoryLoadFunction(typeLabel)); BOOST_CHECK(extractEVMFunction(nameRepository.storageStoreFunction(type)) == dialect.storageStoreFunction(typeLabel)); BOOST_CHECK(extractEVMFunction(nameRepository.storageLoadFunction(type)) == dialect.storageLoadFunction(typeLabel)); - BOOST_CHECK(nameRepository.labelOf(nameRepository.hashFunction(type)) == dialect.hashFunction(typeLabel).str()); + BOOST_CHECK(nameRepository.labelOf(nameRepository.hashFunction(type)) == dialect.hashFunction(typeLabel)); } BOOST_AUTO_TEST_CASE(repository_with_typed_evm_dialect) @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(repository_with_typed_evm_dialect) for (auto const type : {wordType, boolType}) { - YulString typeLabel(std::string(nameRepository.labelOf(type).value())); + std::string typeLabel(nameRepository.labelOf(type).value()); BOOST_CHECK(extractEVMFunction(nameRepository.discardFunction(type)) == dialect.discardFunction(typeLabel)); BOOST_CHECK(extractEVMFunction(nameRepository.equalityFunction(type)) == dialect.equalityFunction(typeLabel)); BOOST_CHECK(extractEVMFunction(nameRepository.booleanNegationFunction()) == dialect.booleanNegationFunction()); @@ -143,7 +143,7 @@ BOOST_AUTO_TEST_CASE(repository_with_typed_evm_dialect) BOOST_CHECK(extractEVMFunction(nameRepository.memoryLoadFunction(type)) == dialect.memoryLoadFunction(typeLabel)); BOOST_CHECK(extractEVMFunction(nameRepository.storageStoreFunction(type)) == dialect.storageStoreFunction(typeLabel)); BOOST_CHECK(extractEVMFunction(nameRepository.storageLoadFunction(type)) == dialect.storageLoadFunction(typeLabel)); - BOOST_CHECK(nameRepository.labelOf(nameRepository.hashFunction(type)) == dialect.hashFunction(typeLabel).str()); + BOOST_CHECK(nameRepository.labelOf(nameRepository.hashFunction(type)) == dialect.hashFunction(typeLabel)); } } @@ -156,7 +156,7 @@ BOOST_AUTO_TEST_CASE(verbatim_functions) BOOST_CHECK(nameRepository.isBuiltinName(verbatimName)); BOOST_CHECK(nameRepository.isDerivedName(verbatimName)); BOOST_CHECK(nameRepository.baseNameOf(verbatimName) == nameRepository.predefined().verbatim); - BOOST_CHECK(nameRepository.builtin(verbatimName)->data == dialect.builtin(YulString{"verbatim_5i_3o"})); + BOOST_CHECK(nameRepository.builtin(verbatimName)->data == dialect.builtin("verbatim_5i_3o")); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/tools/yulInterpreter/Inspector.cpp b/test/tools/yulInterpreter/Inspector.cpp index f9d8bcf1d1e4..823c236d1c4c 100644 --- a/test/tools/yulInterpreter/Inspector.cpp +++ b/test/tools/yulInterpreter/Inspector.cpp @@ -99,7 +99,7 @@ Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std else if (input == "variables" || input == "v") { for (auto &&[yulName, val]: _variables) - printVariable(m_yulNameRepository.labelOf(yulName), val); + printVariable(m_yulNameRepository.requiredLabelOf(yulName), val); std::cout << std::endl; } else if ( @@ -119,7 +119,7 @@ Inspector::NodeAction Inspector::queryUser(langutil::DebugData const& _data, std bool found = false; for (auto &&[yulName, val]: _variables) { - auto const yulStr = m_yulNameRepository.labelOf(yulName); + auto const yulStr = m_yulNameRepository.requiredLabelOf(yulName); if (yulStr == varname) { printVariable(yulStr, val); diff --git a/test/yulPhaser/Program.cpp b/test/yulPhaser/Program.cpp index 97813949b122..f3424a4749e5 100644 --- a/test/yulPhaser/Program.cpp +++ b/test/yulPhaser/Program.cpp @@ -122,8 +122,8 @@ BOOST_AUTO_TEST_CASE(load_should_disambiguate) VariableDeclaration const& declaration2 = get(innerBlock2.statements[0]); BOOST_TEST(declaration1.variables[0].name != declaration2.variables[0].name); - BOOST_TEST(program.nameRepository().labelOf(declaration1.variables[0].name) == "x"); - BOOST_TEST(program.nameRepository().labelOf(declaration2.variables[0].name) != "x"); + BOOST_TEST(program.nameRepository().requiredLabelOf(declaration1.variables[0].name) == "x"); + BOOST_TEST(program.nameRepository().requiredLabelOf(declaration2.variables[0].name) != "x"); } BOOST_AUTO_TEST_CASE(load_should_do_function_grouping_and_hoisting) From e8fbe2b5be24b0f725d806da2db655cabf5340bd Mon Sep 17 00:00:00 2001 From: clonker Date: Tue, 9 Jul 2024 17:19:54 +0200 Subject: [PATCH 06/15] yul optimizer suite operates on a copy of the ast --- libsolidity/codegen/CompilerContext.cpp | 8 +++--- libsolidity/codegen/ContractCompiler.cpp | 2 +- libyul/AST.cpp | 16 ++--------- libyul/AST.h | 12 ++++---- libyul/AsmAnalysis.cpp | 14 +++++++-- libyul/AsmAnalysis.h | 5 ++++ libyul/AsmJsonImporter.cpp | 4 +-- libyul/AsmParser.cpp | 10 +++---- libyul/AsmParser.h | 4 +-- libyul/Object.h | 4 +-- libyul/optimiser/StackCompressor.cpp | 31 +++++++++++--------- libyul/optimiser/StackCompressor.h | 5 ++-- libyul/optimiser/StackLimitEvader.cpp | 36 +++++++++++++----------- libyul/optimiser/StackLimitEvader.h | 7 +++-- libyul/optimiser/Suite.cpp | 22 ++++++++------- test/libyul/YulOptimizerTestCommon.cpp | 8 +++--- tools/yulPhaser/Program.cpp | 11 ++++---- 17 files changed, 104 insertions(+), 95 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 4be6202a86ce..446ed61aae92 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -389,13 +389,13 @@ void CompilerContext::appendInlineAssembly( { unsigned startStackHeight = stackHeight(); yul::EVMDialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(m_evmVersion); - auto nameRepository = std::make_unique(dialect); + yul::YulNameRepository nameRepository(dialect); std::vector externallyUsedFunctionNames = _externallyUsedFunctions - | ranges::views::transform([&nameRepository](auto const& label) { return nameRepository->defineName(label); }) + | ranges::views::transform([&nameRepository](auto const& label) { return nameRepository.defineName(label); }) | ranges::to_vector; std::vector localVariableNames = _localVariables - | ranges::views::transform([&nameRepository](auto const& label) { return nameRepository->defineName(label); }) + | ranges::views::transform([&nameRepository](auto const& label) { return nameRepository.defineName(label); }) | ranges::to_vector; std::set externallyUsedIdentifiers; externallyUsedIdentifiers += externallyUsedFunctionNames + localVariableNames; @@ -496,7 +496,7 @@ void CompilerContext::appendInlineAssembly( { // Store as generated sources, but first re-parse to update the source references. solAssert(m_generatedYulUtilityCode.empty(), ""); - std::string code = yul::AsmPrinter(parserResult->nameRepository())(obj.code->block()); + std::string code = yul::AsmPrinter(obj.code->nameRepository())(obj.code->block()); m_generatedYulUtilityCode = code; langutil::CharStream charStream(m_generatedYulUtilityCode, _sourceName); obj.code = yul::Parser(errorReporter, dialect).parse(charStream); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index c7dd7d098975..324a66db16f9 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -943,7 +943,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) solAssert(dialect, ""); // Create a modifiable copy of the code and analysis - object.code = std::make_shared(*code); + object.code = std::make_shared(yul::YulNameRepository(code->nameRepository()), std::get(yul::ASTCopier{}(code->block()))); object.analysisInfo = std::make_shared(yul::AsmAnalyzer::analyzeStrictAssertCorrect(object)); m_context.optimizeYul(object, *dialect, m_optimiserSettings); diff --git a/libyul/AST.cpp b/libyul/AST.cpp index b3d57c9b7d43..d56c1cf54bce 100644 --- a/libyul/AST.cpp +++ b/libyul/AST.cpp @@ -24,22 +24,10 @@ along with solidity. If not, see . namespace solidity::yul { -AST::AST(std::unique_ptr _nameRepository, Block _block): +AST::AST(YulNameRepository _nameRepository, Block _block): m_nameRepository(std::move(_nameRepository)), m_block(std::move(_block)) { - yulAssert(m_nameRepository != nullptr); -} - -AST::AST(solidity::yul::AST const& _rhs) -{ - *this = _rhs; -} - -AST& AST::operator=(AST const& _rhs) -{ - m_nameRepository = std::make_unique(*_rhs.m_nameRepository); - m_block = ASTCopier().translate(_rhs.m_block); - return *this; + m_nameRepository.generateLabels(m_block); } LiteralValue::LiteralValue(std::string _builtinStringLiteralValue): diff --git a/libyul/AST.h b/libyul/AST.h index f73ab45a90ea..33f1b3b17b97 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -104,20 +104,20 @@ struct Leave { langutil::DebugData::ConstPtr debugData; }; class AST { public: - AST(std::unique_ptr _nameRepository, Block _block); + AST(YulNameRepository _nameRepository, Block _block); AST(AST&&) = default; AST& operator=(AST&& _rhs) = default; - AST(AST const& _rhs); - AST& operator=(AST const& _rhs); + AST(AST const& _rhs) = default; + AST& operator=(AST const& _rhs) = default; ~AST() = default; Block const& block() const { return m_block; } Block& block() { return m_block; } - YulNameRepository const& nameRepository() const { return *m_nameRepository; } - YulNameRepository& nameRepository() { return *m_nameRepository; } + YulNameRepository const& nameRepository() const { return m_nameRepository; } + YulNameRepository& nameRepository() { return m_nameRepository; } private: - std::unique_ptr m_nameRepository; + YulNameRepository m_nameRepository; Block m_block; }; diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 8c17f6cebf3b..3d5d8df7a32c 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -85,6 +85,14 @@ bool AsmAnalyzer::analyze(Block const& _block) } AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Object const& _object) +{ + return analyzeStrictAssertCorrect(_object.code->nameRepository(), _object.code->block(), _object.qualifiedDataNames()); +} + +AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect( + YulNameRepository const& _nameRepository, + Block const& _block, + std::set const& _qualifiedDataNames) { ErrorList errorList; langutil::ErrorReporter errors(errorList); @@ -92,10 +100,10 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Object const& _object) bool success = yul::AsmAnalyzer( analysisInfo, errors, - _object.code->nameRepository(), + _nameRepository, {}, - _object.qualifiedDataNames() - ).analyze(_object.code->block()); + _qualifiedDataNames + ).analyze(_block); yulAssert(success && !errors.hasErrors(), "Invalid assembly/yul code."); return analysisInfo; } diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 0c1b5a391669..b93b2a9418fa 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -78,6 +78,11 @@ class AsmAnalyzer /// Performs analysis on the outermost code of the given object and returns the analysis info. /// Asserts on failure. static AsmAnalysisInfo analyzeStrictAssertCorrect(Object const& _object); + static AsmAnalysisInfo analyzeStrictAssertCorrect( + YulNameRepository const& _nameRepository, + Block const& _block, + std::set const& _qualifiedDataNames + ); std::vector operator()(Literal const& _literal); std::vector operator()(Identifier const&); diff --git a/libyul/AsmJsonImporter.cpp b/libyul/AsmJsonImporter.cpp index cd85515bc9ed..47ba89bb27c4 100644 --- a/libyul/AsmJsonImporter.cpp +++ b/libyul/AsmJsonImporter.cpp @@ -52,8 +52,8 @@ SourceLocation const AsmJsonImporter::createSourceLocation(Json const& _node) AST AsmJsonImporter::createAST(solidity::Json const& _node) { - auto nameRepository = std::make_unique(m_dialect); - auto block = createBlock(_node, *nameRepository); + YulNameRepository nameRepository(m_dialect); + auto block = createBlock(_node, nameRepository); return {std::move(nameRepository), std::move(block)}; } diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index feee5aac299a..1157963ed78d 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -105,7 +105,7 @@ void Parser::updateLocationEndFrom( } } -std::unique_ptr Parser::parse(CharStream& _charStream, std::unique_ptr _nameRepository) +std::unique_ptr Parser::parse(CharStream& _charStream, std::optional _nameRepository) { m_scanner = std::make_shared(_charStream); std::unique_ptr ast = parseInline(m_scanner, std::move(_nameRepository)); @@ -113,10 +113,10 @@ std::unique_ptr Parser::parse(CharStream& _charStream, std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanner, std::unique_ptr _nameRepository) +std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanner, std::optional _nameRepository) { - if (_nameRepository == nullptr) - _nameRepository = std::make_unique(m_dialect); + if (!_nameRepository.has_value()) + _nameRepository = YulNameRepository(m_dialect); // todo assert that the input name repository dialect and m_dialect are compatible m_recursionDepth = 0; @@ -130,7 +130,7 @@ std::unique_ptr Parser::parseInline(std::shared_ptr const& _scanne if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments) fetchDebugDataFromComment(); auto block = parseBlock(*_nameRepository); - return std::make_unique(std::move(_nameRepository), std::move(block)); + return std::make_unique(std::move(*_nameRepository), std::move(block)); } catch (FatalError const& error) { diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 62e33c9bb19e..64d7e368f4d2 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -87,12 +87,12 @@ class Parser: public langutil::ParserBase /// Parses an inline assembly block starting with `{` and ending with `}`. /// @returns an empty shared pointer on error. - std::unique_ptr parseInline(std::shared_ptr const& _scanner, std::unique_ptr _nameRepository = nullptr); + std::unique_ptr parseInline(std::shared_ptr const& _scanner, std::optional _nameRepository = std::nullopt); /// Parses an assembly block starting with `{` and ending with `}` /// and expects end of input after the '}'. /// @returns an empty shared pointer on error. - std::unique_ptr parse(langutil::CharStream& _charStream, std::unique_ptr _nameRepository = nullptr); + std::unique_ptr parse(langutil::CharStream& _charStream, std::optional _nameRepository = std::nullopt); protected: langutil::SourceLocation currentLocation() const override diff --git a/libyul/Object.h b/libyul/Object.h index 1b9af84fd678..94ceaf82f853 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -42,8 +42,6 @@ struct AsmAnalysisInfo; using SourceNameMap = std::map>; -struct Object; - /** * Generic base class for both Yul objects and Yul data. */ @@ -89,7 +87,7 @@ struct ObjectDebugData /** * Yul code and data object container. */ -struct Object: public ObjectNode +class Object: public ObjectNode { public: /// @returns a (parseable) string representation. diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 49d4bb1adf04..a6f41e16b071 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -236,44 +236,49 @@ void eliminateVariablesOptimizedCodegen( } bool StackCompressor::run( - YulNameRepository& _yulNameRepository, - Object& _object, + YulNameRepository& _nameRepository, + Block& _block, + Object const& _object, bool _optimizeStackAllocation, size_t _maxIterations ) { yulAssert( - _object.code && - _object.code->block().statements.size() > 0 && std::holds_alternative(_object.code->block().statements.at(0)), + !_block.statements.empty() && std::holds_alternative(_block.statements.at(0)), "Need to run the function grouper before the stack compressor." ); bool usesOptimizedCodeGenerator = false; - if (auto evmDialect = dynamic_cast(&_yulNameRepository.dialect())) + if (auto evmDialect = dynamic_cast(&_nameRepository.dialect())) usesOptimizedCodeGenerator = _optimizeStackAllocation && evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); - bool allowMSizeOptimization = !MSizeFinder::containsMSize(*_object.code); - _yulNameRepository.generateLabels(_object.code->block()); + bool allowMSizeOptimization = !MSizeFinder::containsMSize(_nameRepository, _block); + _nameRepository.generateLabels(_block); if (usesOptimizedCodeGenerator) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_object); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _yulNameRepository, _object.code->block()); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_nameRepository, _block, _object.qualifiedDataNames()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _nameRepository, _block); eliminateVariablesOptimizedCodegen( - _yulNameRepository, - _object.code->block(), + _nameRepository, + _block, StackLayoutGenerator::reportStackTooDeep(*cfg), allowMSizeOptimization ); } else { + Object object(_object); for (size_t iterations = 0; iterations < _maxIterations; iterations++) { - std::map stackSurplus = CompilabilityChecker(_object, _optimizeStackAllocation).stackDeficit; + // todo... + object.code = std::make_shared(std::move(_nameRepository), std::move(_block)); + std::map stackSurplus = CompilabilityChecker(object, _optimizeStackAllocation).stackDeficit; + _nameRepository = std::move(object.code->nameRepository()); + _block = std::move(object.code->block()); if (stackSurplus.empty()) return true; - eliminateVariables(_yulNameRepository, _object.code->block(), stackSurplus, allowMSizeOptimization); + eliminateVariables(_nameRepository, _block, stackSurplus, allowMSizeOptimization); } } return false; diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index deb327bce6be..90f1a6771b6d 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -47,8 +47,9 @@ class StackCompressor /// Try to remove local variables until the AST is compilable. /// @returns true if it was successful. static bool run( - YulNameRepository& _yulNameRepository, - Object& _object, + YulNameRepository& _nameRepository, + Block& _block, + Object const& _object, bool _optimizeStackAllocation, size_t _maxIterations ); diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index e4a9ebd234f6..cdab2c798664 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -15,6 +15,7 @@ along with solidity. If not, see . */ +#include #include #include #include @@ -118,7 +119,8 @@ u256 literalArgumentValue(FunctionCall const& _call) void StackLimitEvader::run( OptimiserStepContext& _context, - Object& _object + Block& _block, + Object const& _object ) { auto const* evmDialect = dynamic_cast(&_context.dialect); @@ -128,21 +130,22 @@ void StackLimitEvader::run( ); if (evmDialect && evmDialect->evmVersion().canOverchargeGasForCall()) { - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_object); - std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _context.yulNameRepository, _object.code->block()); - run(_context, _object, StackLayoutGenerator::reportStackTooDeep(*cfg)); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_context.yulNameRepository, _block, _object.qualifiedDataNames()); + std::unique_ptr cfg = ControlFlowGraphBuilder::build(analysisInfo, _context.yulNameRepository, _block); + run(_context, _block, StackLayoutGenerator::reportStackTooDeep(*cfg)); } else - run(_context, _object, CompilabilityChecker{ - _object, - true - }.unreachableVariables); + { + Object object(_object); + object.code = std::make_shared(_context.yulNameRepository, std::get(ASTCopier{}(_block))); + run(_context, _block, CompilabilityChecker{object, true}.unreachableVariables); + } } void StackLimitEvader::run( OptimiserStepContext& _context, - Object& _object, + Block& _block, std::map> const& _stackTooDeepErrors ) { @@ -156,16 +159,15 @@ void StackLimitEvader::run( if (!util::contains(unreachables, variable)) unreachables.emplace_back(variable); } - run(_context, _object, unreachableVariables); + run(_context, _block, unreachableVariables); } void StackLimitEvader::run( OptimiserStepContext& _context, - Object& _object, + Block& _block, std::map> const& _unreachableVariables ) { - yulAssert(_object.code, ""); auto const* evmDialect = dynamic_cast(&_context.dialect); yulAssert( evmDialect && evmDialect->providesObjectAccess(), @@ -173,7 +175,7 @@ void StackLimitEvader::run( ); std::vector memoryGuardCalls = FunctionCallFinder::run( - _object.code->block(), + _block, _context.yulNameRepository.predefined().memoryguard ); // Do not optimise, if no ``memoryguard`` call is found. @@ -188,23 +190,23 @@ void StackLimitEvader::run( if (reservedMemory != literalArgumentValue(*memoryGuardCall)) return; - CallGraph callGraph = CallGraphGenerator::callGraph(_object.code->block()); + CallGraph callGraph = CallGraphGenerator::callGraph(_block); // We cannot move variables in recursive functions to fixed memory offsets. for (YulName function: callGraph.recursiveFunctions()) if (_unreachableVariables.count(function)) return; - std::map functionDefinitions = allFunctionDefinitions(_object.code->block()); + std::map functionDefinitions = allFunctionDefinitions(_block); MemoryOffsetAllocator memoryOffsetAllocator{_unreachableVariables, callGraph.functionCalls, functionDefinitions}; uint64_t requiredSlots = memoryOffsetAllocator.run(); yulAssert(requiredSlots < (uint64_t(1) << 32) - 1, ""); - StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, _object.code->block()); + StackToMemoryMover::run(_context, reservedMemory, memoryOffsetAllocator.slotAllocations, requiredSlots, _block); reservedMemory += 32 * requiredSlots; - for (FunctionCall* memoryGuardCall: FunctionCallFinder::run(_object.code->block(), _context.yulNameRepository.predefined().memoryguard)) + for (FunctionCall* memoryGuardCall: FunctionCallFinder::run(_block, _context.yulNameRepository.predefined().memoryguard)) { Literal* literal = std::get_if(&memoryGuardCall->arguments.front()); yulAssert(literal && literal->kind == LiteralKind::Number, ""); diff --git a/libyul/optimiser/StackLimitEvader.h b/libyul/optimiser/StackLimitEvader.h index 0411f05735bc..8e65c7f22bec 100644 --- a/libyul/optimiser/StackLimitEvader.h +++ b/libyul/optimiser/StackLimitEvader.h @@ -59,7 +59,7 @@ class StackLimitEvader /// are contained in a recursive function. static void run( OptimiserStepContext& _context, - Object& _object, + Block& _block, std::map> const& _unreachableVariables ); /// @a _stackTooDeepErrors can be determined by the StackLayoutGenerator. @@ -69,7 +69,7 @@ class StackLimitEvader /// are contained in a recursive function. static void run( OptimiserStepContext& _context, - Object& _object, + Block& _block, std::map> const& _stackTooDeepErrors ); /// Determines stack too deep errors using the appropriate code generation backend. @@ -79,7 +79,8 @@ class StackLimitEvader /// are contained in a recursive function. static void run( OptimiserStepContext& _context, - Object& _object + Block& _block, + Object const& _object ); }; diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 2c4e8eee790a..d4831b3de3c9 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -150,14 +150,14 @@ void OptimiserSuite::run( evmDialect->providesObjectAccess(); std::set reservedIdentifiers = _externallyUsedIdentifiers; - _object.code->block() = std::get(Disambiguator( - _object.code->nameRepository(), + YulNameRepository nameRepository (_object.code->nameRepository()); + auto ast = std::get(Disambiguator( + nameRepository, *_object.analysisInfo, reservedIdentifiers )(_object.code->block())); - Block& ast = _object.code->block(); - OptimiserStepContext context{dialect, _object.code->nameRepository(), reservedIdentifiers, _expectedExecutionsPerDeployment}; + OptimiserStepContext context{dialect, nameRepository, reservedIdentifiers, _expectedExecutionsPerDeployment}; OptimiserSuite suite(context, Debug::None); @@ -176,7 +176,8 @@ void OptimiserSuite::run( // message once we perform code generation. if (!usesOptimizedCodeGenerator) StackCompressor::run( - _object.code->nameRepository(), + nameRepository, + ast, _object, _optimizeStackAllocation, stackCompressorMaxIterations @@ -192,26 +193,27 @@ void OptimiserSuite::run( if (evmDialect) { yulAssert(_meter, ""); - ConstantOptimiser{_object.code->nameRepository(), *evmDialect, *_meter}(ast); + ConstantOptimiser{nameRepository, *evmDialect, *_meter}(ast); if (usesOptimizedCodeGenerator) { StackCompressor::run( - _object.code->nameRepository(), + nameRepository, + ast, _object, _optimizeStackAllocation, stackCompressorMaxIterations ); if (evmDialect->providesObjectAccess()) - StackLimitEvader::run(suite.m_context, _object); + StackLimitEvader::run(suite.m_context, ast, _object); } else if (evmDialect->providesObjectAccess() && _optimizeStackAllocation) - StackLimitEvader::run(suite.m_context, _object); + StackLimitEvader::run(suite.m_context, ast, _object); } #ifdef PROFILE_OPTIMIZER_STEPS outputPerformanceMetrics(suite.m_durationPerStepInMicroseconds); #endif - _object.code->nameRepository().generateLabels(_object.code->block()); + _object.code = std::make_shared(std::move(nameRepository), std::move(ast)); *_object.analysisInfo = AsmAnalyzer::analyzeStrictAssertCorrect(_object); } diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index f37ad7a5b1b4..22bf2eff5c86 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -357,7 +357,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( FunctionHoister::run(*m_context, m_ast); FunctionGrouper::run(*m_context, m_ast); size_t maxIterations = 16; - StackCompressor::run(m_yulNameRepository, *m_object, true, maxIterations); + StackCompressor::run(m_yulNameRepository, m_ast, *m_object, true, maxIterations); BlockFlattener::run(*m_context, m_ast); m_context->yulNameRepository.generateLabels(m_ast); }}, @@ -371,12 +371,12 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( frontend::OptimiserSettings::DefaultYulOptimiserCleanupSteps, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment ); - m_context->yulNameRepository.generateLabels(m_ast); + m_object->code->nameRepository().generateLabels(m_object->code->block()); }}, {"stackLimitEvader", [&]() { disambiguate(); m_context->yulNameRepository.generateLabels(m_ast); - StackLimitEvader::run(*m_context, *m_object, CompilabilityChecker{ + StackLimitEvader::run(*m_context, m_ast, CompilabilityChecker{ *m_object, true }.unreachableVariables); @@ -423,7 +423,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( }; FakeUnreachableGenerator fakeUnreachableGenerator (m_yulNameRepository); fakeUnreachableGenerator(m_ast); - StackLimitEvader::run(*m_context, *m_object, fakeUnreachableGenerator.fakeUnreachables); + StackLimitEvader::run(*m_context, m_ast, fakeUnreachableGenerator.fakeUnreachables); m_context->yulNameRepository.generateLabels(m_ast); }} }; diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 6a2aa4c324a8..cdf11e6f26e9 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -58,7 +58,7 @@ std::ostream& operator<<(std::ostream& _stream, Program const& _program); } Program::Program(Program const& program): - m_ast(std::make_unique(*program.m_ast)), + m_ast(std::make_unique(program.m_ast->nameRepository(), std::get(ASTCopier{}(program.m_ast->block())))), m_dialect(program.m_dialect) { } @@ -154,9 +154,8 @@ std::variant, ErrorList> Program::parseObject(yul::Dialect // The public API of the class does not provide access to the smart pointer so it won't be hard // to switch to shared_ptr if the copying turns out to be an issue (though it would be better // to refactor ObjectParser and Object to use unique_ptr instead). - auto astCopy = std::make_unique(*selectedObject->code); - - return std::variant, ErrorList>(std::move(astCopy)); + auto astCopy = std::make_unique(selectedObject->code->nameRepository(), std::get(ASTCopier{}(selectedObject->code->block()))); + return {std::move(astCopy)}; } std::variant, ErrorList> Program::analyzeAST(AST const& _ast) @@ -179,9 +178,9 @@ std::unique_ptr Program::disambiguateAST( AsmAnalysisInfo const& _analysisInfo ) { - auto nameRepository = std::make_unique(_ast.nameRepository()); + YulNameRepository nameRepository(_ast.nameRepository()); std::set const externallyUsedIdentifiers = {}; - Disambiguator disambiguator(*nameRepository, _analysisInfo, externallyUsedIdentifiers); + Disambiguator disambiguator(nameRepository, _analysisInfo, externallyUsedIdentifiers); auto block = std::get(disambiguator(_ast.block())); return std::make_unique(std::move(nameRepository), std::move(block)); From 9a89463930f4c76dedb6d986703253bdcd20dffe Mon Sep 17 00:00:00 2001 From: clonker Date: Tue, 9 Jul 2024 17:32:45 +0200 Subject: [PATCH 07/15] yul optimizer suite operates on a copy of the ast --- test/tools/yulopti.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index bb2952caf944..3c6923d9ed75 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -219,7 +219,7 @@ class YulOpti { Object obj; obj.code = m_ast; - StackCompressor::run(m_ast->nameRepository(), obj, true, 16); + StackCompressor::run(m_ast->nameRepository(), m_ast->block(), obj, true, 16); break; } default: From 5ac2df55d6159b22b6a89a781cdb7819976c2140 Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 10 Jul 2024 08:46:55 +0200 Subject: [PATCH 08/15] avoid an ast copy --- libyul/CompilabilityChecker.cpp | 22 +++++++++++++++++----- libyul/CompilabilityChecker.h | 7 ++++++- libyul/Object.h | 2 +- libyul/backends/evm/AsmCodeGen.cpp | 3 ++- libyul/backends/evm/EVMCodeTransform.cpp | 4 ++-- libyul/backends/evm/EVMCodeTransform.h | 9 +++++---- libyul/backends/evm/EVMObjectCompiler.cpp | 3 ++- libyul/optimiser/StackCompressor.cpp | 7 +------ libyul/optimiser/StackLimitEvader.cpp | 4 +--- 9 files changed, 37 insertions(+), 24 deletions(-) diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 1a715f9cfee3..b27ec50141a7 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -32,14 +32,25 @@ using namespace solidity::util; CompilabilityChecker::CompilabilityChecker( Object const& _object, - bool _optimizeStackAllocation + bool _optimizeStackAllocation, + YulNameRepository const* _nameRepository, + Block const* _block ) { - if (auto const* evmDialect = dynamic_cast(&_object.code->nameRepository().dialect())) + yulAssert(_object.code || (_nameRepository && _block)); + if (!_nameRepository) + _nameRepository = &_object.code->nameRepository(); + if (auto const* evmDialect = dynamic_cast(&_nameRepository->dialect())) { + if (!_block) + _block = &_object.code->block(); NoOutputEVMDialect noOutputDialect(*evmDialect); - yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_object); + yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect( + *_nameRepository, + *_block, + _object.qualifiedDataNames() + ); BuiltinContext builtinContext; builtinContext.currentObject = &_object; @@ -51,12 +62,13 @@ CompilabilityChecker::CompilabilityChecker( CodeTransform transform( assembly, analysisInfo, - *_object.code, + *_nameRepository, + *_block, noOutputDialect, builtinContext, _optimizeStackAllocation ); - transform(_object.code->block()); + transform(*_block); for (StackTooDeepError const& error: transform.stackErrors()) { diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index 0c88232fe021..ab33ba7b670f 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -44,7 +44,12 @@ namespace solidity::yul */ struct CompilabilityChecker { - CompilabilityChecker(Object const& _object, bool _optimizeStackAllocation); + CompilabilityChecker( + Object const& _object, + bool _optimizeStackAllocation, + YulNameRepository const* _nameRepositoryOverride = nullptr, + Block const* _blockOverride = nullptr + ); std::map> unreachableVariables; std::map stackDeficit; }; diff --git a/libyul/Object.h b/libyul/Object.h index 94ceaf82f853..ac51ee37636f 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -87,7 +87,7 @@ struct ObjectDebugData /** * Yul code and data object container. */ -class Object: public ObjectNode +struct Object: public ObjectNode { public: /// @returns a (parseable) string representation. diff --git a/libyul/backends/evm/AsmCodeGen.cpp b/libyul/backends/evm/AsmCodeGen.cpp index a90c61a64886..d130ea377c72 100644 --- a/libyul/backends/evm/AsmCodeGen.cpp +++ b/libyul/backends/evm/AsmCodeGen.cpp @@ -48,7 +48,8 @@ void CodeGenerator::assemble( CodeTransform transform( assemblyAdapter, _analysisInfo, - _parsedData, + _parsedData.nameRepository(), + _parsedData.block(), EVMDialect::strictAssemblyForEVM(_evmVersion), builtinContext, _optimizeStackAllocation, diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index bb85a4fb9f93..1790f30cb1d4 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -49,8 +49,8 @@ using namespace solidity::util; CodeTransform::CodeTransform( AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, - Block const& _block, YulNameRepository const& _nameRepository, + Block const& _block, bool _allowStackOpt, EVMDialect const& _dialect, BuiltinContext& _builtinContext, @@ -386,8 +386,8 @@ void CodeTransform::operator()(FunctionDefinition const& _function) CodeTransform subTransform( m_assembly, m_info, - _function.body, m_yulNameRepository, + _function.body, m_allowStackOpt, m_dialect, m_builtinContext, diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index 212249f57e57..2666075a0ade 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -77,7 +77,8 @@ class CodeTransform CodeTransform( AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, - AST const& _ast, + YulNameRepository const& _nameRepository, + Block const& _block, EVMDialect const& _dialect, BuiltinContext& _builtinContext, bool _allowStackOpt = false, @@ -86,8 +87,8 @@ class CodeTransform ): CodeTransform( _assembly, _analysisInfo, - _ast.block(), - _ast.nameRepository(), + _nameRepository, + _block, _allowStackOpt, _dialect, _builtinContext, @@ -108,8 +109,8 @@ class CodeTransform CodeTransform( AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, - Block const& _block, YulNameRepository const& _nameRepository, + Block const& _block, bool _allowStackOpt, EVMDialect const& _dialect, BuiltinContext& _builtinContext, diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index bc323bfc084d..983d826a8dc3 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -113,7 +113,8 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) CodeTransform transform{ m_assembly, *_object.analysisInfo, - *_object.code, + _object.code->nameRepository(), + _object.code->block(), m_dialect, context, _optimize, diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index a6f41e16b071..62cb00d82011 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -268,14 +268,9 @@ bool StackCompressor::run( } else { - Object object(_object); for (size_t iterations = 0; iterations < _maxIterations; iterations++) { - // todo... - object.code = std::make_shared(std::move(_nameRepository), std::move(_block)); - std::map stackSurplus = CompilabilityChecker(object, _optimizeStackAllocation).stackDeficit; - _nameRepository = std::move(object.code->nameRepository()); - _block = std::move(object.code->block()); + std::map stackSurplus = CompilabilityChecker(_object, _optimizeStackAllocation, &_nameRepository, &_block).stackDeficit; if (stackSurplus.empty()) return true; eliminateVariables(_nameRepository, _block, stackSurplus, allowMSizeOptimization); diff --git a/libyul/optimiser/StackLimitEvader.cpp b/libyul/optimiser/StackLimitEvader.cpp index cdab2c798664..97df73fde745 100644 --- a/libyul/optimiser/StackLimitEvader.cpp +++ b/libyul/optimiser/StackLimitEvader.cpp @@ -136,9 +136,7 @@ void StackLimitEvader::run( } else { - Object object(_object); - object.code = std::make_shared(_context.yulNameRepository, std::get(ASTCopier{}(_block))); - run(_context, _block, CompilabilityChecker{object, true}.unreachableVariables); + run(_context, _block, CompilabilityChecker{_object, true, &_context.yulNameRepository, &_block}.unreachableVariables); } } From c1002bcb4dea53a14123514e07d1c6e2563e328e Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 10 Jul 2024 10:17:37 +0200 Subject: [PATCH 09/15] Function call finder with const result --- libyul/optimiser/FunctionCallFinder.cpp | 39 +++++++++++++++++++------ libyul/optimiser/FunctionCallFinder.h | 9 ++---- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/libyul/optimiser/FunctionCallFinder.cpp b/libyul/optimiser/FunctionCallFinder.cpp index 45f23503629f..cb7089fd57a8 100644 --- a/libyul/optimiser/FunctionCallFinder.cpp +++ b/libyul/optimiser/FunctionCallFinder.cpp @@ -21,18 +21,39 @@ using namespace solidity; using namespace solidity::yul; -std::vector FunctionCallFinder::run(Block& _block, YulName _functionName) +namespace +{ +template +class FunctionCallFinderBase: Base { - FunctionCallFinder functionCallFinder(_functionName); - functionCallFinder(_block); - return functionCallFinder.m_calls; +public: + using MaybeConstBlock = std::conditional_t, Block const, Block>; + static std::vector run(MaybeConstBlock& _block, YulName _functionName) + { + FunctionCallFinderBase functionCallFinder(_functionName); + functionCallFinder(_block); + return functionCallFinder.m_calls; + } +private: + explicit FunctionCallFinderBase(YulName _functionName): m_functionName(_functionName) {} + using Base::operator(); + void operator()(ResultType& _functionCall) override + { + Base::operator()(_functionCall); + if (_functionCall.functionName.name == m_functionName) + m_calls.emplace_back(&_functionCall); + } + YulName m_functionName; + std::vector m_calls; +}; } -FunctionCallFinder::FunctionCallFinder(YulName _functionName): m_functionName(_functionName) {} +std::vector FunctionCallFinder::run(Block& _block, YulName _functionName) +{ + return FunctionCallFinderBase::run(_block, _functionName); +} -void FunctionCallFinder::operator()(FunctionCall& _functionCall) +std::vector FunctionCallFinder::run(Block const& _block, YulName _functionName) { - ASTModifier::operator()(_functionCall); - if (_functionCall.functionName.name == m_functionName) - m_calls.emplace_back(&_functionCall); + return FunctionCallFinderBase::run(_block, _functionName); } diff --git a/libyul/optimiser/FunctionCallFinder.h b/libyul/optimiser/FunctionCallFinder.h index fd6367019a64..844fc4e9c1b4 100644 --- a/libyul/optimiser/FunctionCallFinder.h +++ b/libyul/optimiser/FunctionCallFinder.h @@ -32,16 +32,11 @@ namespace solidity::yul * * Prerequisite: Disambiguator */ -class FunctionCallFinder: ASTModifier +class FunctionCallFinder { public: static std::vector run(Block& _block, YulName _functionName); -private: - FunctionCallFinder(YulName _functionName); - using ASTModifier::operator(); - void operator()(FunctionCall& _functionCall) override; - YulName m_functionName; - std::vector m_calls; + static std::vector run(Block const& _block, YulName _functionName); }; } From 675a4ebdc357a4c30bc049fd587bc4de0d1a75f9 Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 10 Jul 2024 11:41:32 +0200 Subject: [PATCH 10/15] immutable block in ast --- libyul/AST.h | 1 - libyul/backends/evm/EVMObjectCompiler.cpp | 2 +- libyul/optimiser/StackCompressor.cpp | 20 +- libyul/optimiser/StackCompressor.h | 11 +- test/libyul/KnowledgeBaseTest.cpp | 13 +- test/libyul/YulOptimizerTest.cpp | 3 +- test/libyul/YulOptimizerTestCommon.cpp | 622 +++++++++++----------- test/libyul/YulOptimizerTestCommon.h | 13 +- test/tools/yulopti.cpp | 43 +- tools/yulPhaser/Program.cpp | 10 +- 10 files changed, 397 insertions(+), 341 deletions(-) diff --git a/libyul/AST.h b/libyul/AST.h index 33f1b3b17b97..3d5148f8a6ea 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -112,7 +112,6 @@ class AST ~AST() = default; Block const& block() const { return m_block; } - Block& block() { return m_block; } YulNameRepository const& nameRepository() const { return m_nameRepository; } YulNameRepository& nameRepository() { return m_nameRepository; } diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 983d826a8dc3..e5056765a7a7 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -90,7 +90,7 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) ); if (!stackErrors.empty()) { - std::vector memoryGuardCalls = FunctionCallFinder::run( + std::vector memoryGuardCalls = FunctionCallFinder::run( _object.code->block(), _object.code->nameRepository().predefined().memoryguard ); diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 62cb00d82011..5e7cdf92a824 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -235,18 +236,31 @@ void eliminateVariablesOptimizedCodegen( } +bool StackCompressor::run( + Object& _object, + bool _optimizeStackAllocation, + size_t _maxIterations) +{ + yulAssert(_object.code); + YulNameRepository nameRepository(_object.code->nameRepository()); + auto block = std::get(ASTCopier{}(_object.code->block())); + auto result = run(nameRepository, block, _object, _optimizeStackAllocation, _maxIterations); + _object.code = std::make_shared(std::move(nameRepository), std::move(block)); + return result; +} + bool StackCompressor::run( YulNameRepository& _nameRepository, Block& _block, Object const& _object, bool _optimizeStackAllocation, - size_t _maxIterations -) + size_t _maxIterations) { yulAssert( - !_block.statements.empty() && std::holds_alternative(_block.statements.at(0)), + !_object.code->block().statements.empty() && std::holds_alternative(_object.code->block().statements.at(0)), "Need to run the function grouper before the stack compressor." ); + bool usesOptimizedCodeGenerator = false; if (auto evmDialect = dynamic_cast(&_nameRepository.dialect())) usesOptimizedCodeGenerator = diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index 90f1a6771b6d..58ea81a64ea2 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -44,7 +44,16 @@ struct FunctionDefinition; class StackCompressor { public: - /// Try to remove local variables until the AST is compilable. + /// Try to remove local variables until the AST is compilable. Modifies the object's AST. + /// @returns true if it was successful. + static bool run( + Object& _object, + bool _optimizeStackAllocation, + size_t _maxIterations + ); + + /// Try to remove local variables until the AST is compilable. Operates on provided name repository and block, + /// disregards the AST contained in object. /// @returns true if it was successful. static bool run( YulNameRepository& _nameRepository, diff --git a/test/libyul/KnowledgeBaseTest.cpp b/test/libyul/KnowledgeBaseTest.cpp index 7b2d686a3c21..586a250c3260 100644 --- a/test/libyul/KnowledgeBaseTest.cpp +++ b/test/libyul/KnowledgeBaseTest.cpp @@ -23,13 +23,12 @@ #include #include +#include #include #include #include #include -#include - #include using namespace solidity::langutil; @@ -47,14 +46,18 @@ class KnowledgeBaseTest std::tie(m_object, analysisInfo) = yul::test::parse(_source, m_dialect, errorList); BOOST_REQUIRE(m_object && errorList.empty() && m_object->code); + YulNameRepository nameRepository(m_object->code->nameRepository()); + auto block = std::get(yul::ASTCopier{}(m_object->code->block())); std::set reserved{}; - OptimiserStepContext context{m_object->code->nameRepository().dialect(), m_object->code->nameRepository(), reserved, 0}; - CommonSubexpressionEliminator::run(context, m_object->code->block()); + OptimiserStepContext context{nameRepository.dialect(), nameRepository, reserved, 0}; + CommonSubexpressionEliminator::run(context, block); - m_ssaValues(m_object->code->block()); + m_ssaValues(block); for (auto const& [name, expression]: m_ssaValues.values()) m_values[name].value = expression; + m_object->code = std::make_shared(std::move(nameRepository), std::move(block)); + return KnowledgeBase([this](YulName _var) { return util::valueOrNullptr(m_values, _var); }, m_object->code->nameRepository()); } diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 93b3b05316f9..4ee50b4cc0d7 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -77,8 +77,9 @@ TestCase::TestResult YulOptimizerTest::run(std::ostream& _stream, std::string co AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << std::endl; return TestResult::FatalError; } + auto result = tester.resultObject(); - auto const printed = (m_object->subObjects.empty() ? AsmPrinter{ m_object->code->nameRepository(), AsmPrinter::Mode::OmitDefaultType }(m_object->code->block()) : m_object->toString()); + auto const printed = (result->subObjects.empty() ? AsmPrinter{ result->code->nameRepository(), AsmPrinter::Mode::OmitDefaultType }(result->code->block()) : result->toString()); // Re-parse new code for compilability if (!std::get<0>(parse(_stream, _linePrefix, _formatted, printed))) diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index 22bf2eff5c86..e98989747a2e 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -74,295 +74,304 @@ using namespace solidity::frontend; YulOptimizerTestCommon::YulOptimizerTestCommon( std::shared_ptr _obj -): m_yulNameRepository(_obj->code->nameRepository()), m_object(_obj), m_ast(m_object->code->block()), m_analysisInfo(m_object->analysisInfo) +): m_object(_obj), m_resultObject(std::make_shared()), m_analysisInfo(m_object->analysisInfo) { + *m_resultObject = *m_object; m_namedSteps = { - {"disambiguator", [&]() { - disambiguate(); - m_context->yulNameRepository.generateLabels(m_ast); + {"disambiguator", [&](YulNameRepository& _nameRepository) { + return disambiguate(_nameRepository); }}, - {"nameDisplacer", [&]() { - disambiguate(); + {"nameDisplacer", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); NameDisplacer{ { - m_yulNameRepository.defineName("illegal1"), m_yulNameRepository.defineName("illegal2"), - m_yulNameRepository.defineName("illegal3"), m_yulNameRepository.defineName("illegal4"), - m_yulNameRepository.defineName("illegal5") + _nameRepository.defineName("illegal1"), _nameRepository.defineName("illegal2"), + _nameRepository.defineName("illegal3"), _nameRepository.defineName("illegal4"), + _nameRepository.defineName("illegal5") }, - m_yulNameRepository - }(m_ast); - m_context->yulNameRepository.generateLabels(m_ast, {"illegal1", "illegal2", "illegal3", "illegal4", "illegal5"}); - }}, - {"blockFlattener", [&]() { - disambiguate(); - FunctionGrouper::run(*m_context, m_ast); - BlockFlattener::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"constantOptimiser", [&]() { - GasMeter meter(m_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), false, 200); - ConstantOptimiser{m_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), meter}(m_ast); - }}, - {"varDeclInitializer", [&]() { VarDeclInitializer::run(*m_context, m_ast); }}, - {"varNameCleaner", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, m_ast); - FunctionGrouper::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"forLoopConditionIntoBody", [&]() { - disambiguate(); - ForLoopConditionIntoBody::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"forLoopInitRewriter", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"commonSubexpressionEliminator", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - CommonSubexpressionEliminator::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"conditionalUnsimplifier", [&]() { - disambiguate(); - ConditionalUnsimplifier::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"conditionalSimplifier", [&]() { - disambiguate(); - ConditionalSimplifier::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"expressionSplitter", [&]() { - ExpressionSplitter::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"expressionJoiner", [&]() { - disambiguate(); - ExpressionJoiner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"splitJoin", [&]() { - disambiguate(); - ExpressionSplitter::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"functionGrouper", [&]() { - disambiguate(); - FunctionGrouper::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"functionHoister", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"functionSpecializer", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, m_ast); - FunctionSpecializer::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"expressionInliner", [&]() { - disambiguate(); - ExpressionInliner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"fullInliner", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, m_ast); - FunctionGrouper::run(*m_context, m_ast); - ExpressionSplitter::run(*m_context, m_ast); - FullInliner::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"fullInlinerWithoutSplitter", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, m_ast); - FunctionGrouper::run(*m_context, m_ast); - FullInliner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"rematerialiser", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - Rematerialiser::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"expressionSimplifier", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - ExpressionSplitter::run(*m_context, m_ast); - CommonSubexpressionEliminator::run(*m_context, m_ast); - ExpressionSimplifier::run(*m_context, m_ast); - ExpressionSimplifier::run(*m_context, m_ast); - ExpressionSimplifier::run(*m_context, m_ast); - UnusedPruner::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"fullSimplify", [&]() { - disambiguate(); - FunctionGrouper::run(*m_context, m_ast); - BlockFlattener::run(*m_context, m_ast); - ExpressionSplitter::run(*m_context, m_ast); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - CommonSubexpressionEliminator::run(*m_context, m_ast); - ExpressionSimplifier::run(*m_context, m_ast); - UnusedPruner::run(*m_context, m_ast); - CircularReferencesPruner::run(*m_context, m_ast); - DeadCodeEliminator::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"unusedFunctionParameterPruner", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - LiteralRematerialiser::run(*m_context, m_ast); - UnusedFunctionParameterPruner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"unusedPruner", [&]() { - disambiguate(); - UnusedPruner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"circularReferencesPruner", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, m_ast); - CircularReferencesPruner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"deadCodeEliminator", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - DeadCodeEliminator::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"ssaTransform", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - SSATransform::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"unusedAssignEliminator", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - UnusedAssignEliminator::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"unusedStoreEliminator", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - ExpressionSplitter::run(*m_context, m_ast); - SSATransform::run(*m_context, m_ast); - UnusedStoreEliminator::run(*m_context, m_ast); - SSAReverser::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"equalStoreEliminator", [&]() { - disambiguate(); - FunctionHoister::run(*m_context, m_ast); - ForLoopInitRewriter::run(*m_context, m_ast); - EqualStoreEliminator::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"ssaPlusCleanup", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - SSATransform::run(*m_context, m_ast); - UnusedAssignEliminator::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"loadResolver", [&]() { - disambiguate(); - FunctionGrouper::run(*m_context, m_ast); - BlockFlattener::run(*m_context, m_ast); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - ExpressionSplitter::run(*m_context, m_ast); - CommonSubexpressionEliminator::run(*m_context, m_ast); - ExpressionSimplifier::run(*m_context, m_ast); + _nameRepository + }(block); + m_context->yulNameRepository.generateLabels(block, {"illegal1", "illegal2", "illegal3", "illegal4", "illegal5"}); + return block; + }}, + {"blockFlattener", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionGrouper::run(*m_context, block); + BlockFlattener::run(*m_context, block); + return block; + }}, + {"constantOptimiser", [&](YulNameRepository& _nameRepository) { + auto block = std::get(ASTCopier{}(m_object->code->block())); + GasMeter meter(_nameRepository, dynamic_cast(_nameRepository.dialect()), false, 200); + ConstantOptimiser{_nameRepository, dynamic_cast(_nameRepository.dialect()), meter}(block); + return block; + }}, + {"varDeclInitializer", [&](YulNameRepository&) { + auto block = std::get(ASTCopier{}(m_object->code->block())); + VarDeclInitializer::run(*m_context, block); + return block; + }}, + {"varNameCleaner", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionHoister::run(*m_context, block); + FunctionGrouper::run(*m_context, block); + return block; + }}, + {"forLoopConditionIntoBody", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopConditionIntoBody::run(*m_context, block); + return block; + }}, + {"forLoopInitRewriter", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + return block; + }}, + {"commonSubexpressionEliminator", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + return block; + }}, + {"conditionalUnsimplifier", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ConditionalUnsimplifier::run(*m_context, block); + return block; + }}, + {"conditionalSimplifier", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ConditionalSimplifier::run(*m_context, block); + return block; + }}, + {"expressionSplitter", [&](YulNameRepository&) { + auto block = std::get(ASTCopier{}(m_object->code->block())); + ExpressionSplitter::run(*m_context, block); + return block; + }}, + {"expressionJoiner", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ExpressionJoiner::run(*m_context, block); + return block; + }}, + {"splitJoin", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ExpressionSplitter::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; + }}, + {"functionGrouper", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionGrouper::run(*m_context, block); + return block; + }}, + {"functionHoister", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionHoister::run(*m_context, block); + return block; + }}, + {"functionSpecializer", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionHoister::run(*m_context, block); + FunctionSpecializer::run(*m_context, block); + return block; + }}, + {"expressionInliner", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ExpressionInliner::run(*m_context, block); + return block; + }}, + {"fullInliner", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionHoister::run(*m_context, block); + FunctionGrouper::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + FullInliner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; + }}, + {"fullInlinerWithoutSplitter", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionHoister::run(*m_context, block); + FunctionGrouper::run(*m_context, block); + FullInliner::run(*m_context, block); + return block; + }}, + {"rematerialiser", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + Rematerialiser::run(*m_context, block); + return block; + }}, + {"expressionSimplifier", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); + UnusedPruner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; + }}, + {"fullSimplify", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionGrouper::run(*m_context, block); + BlockFlattener::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); + UnusedPruner::run(*m_context, block); + CircularReferencesPruner::run(*m_context, block); + DeadCodeEliminator::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; + }}, + {"unusedFunctionParameterPruner", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + LiteralRematerialiser::run(*m_context, block); + UnusedFunctionParameterPruner::run(*m_context, block); + return block; + }}, + {"unusedPruner", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + UnusedPruner::run(*m_context, block); + return block; + }}, + {"circularReferencesPruner", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionHoister::run(*m_context, block); + CircularReferencesPruner::run(*m_context, block); + return block; + }}, + {"deadCodeEliminator", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + DeadCodeEliminator::run(*m_context, block); + return block; + }}, + {"ssaTransform", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + SSATransform::run(*m_context, block); + return block; + }}, + {"unusedAssignEliminator", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + UnusedAssignEliminator::run(*m_context, block); + return block; + }}, + {"unusedStoreEliminator", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + SSATransform::run(*m_context, block); + UnusedStoreEliminator::run(*m_context, block); + SSAReverser::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; + }}, + {"equalStoreEliminator", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionHoister::run(*m_context, block); + ForLoopInitRewriter::run(*m_context, block); + EqualStoreEliminator::run(*m_context, block); + return block; + }}, + {"ssaPlusCleanup", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + SSATransform::run(*m_context, block); + UnusedAssignEliminator::run(*m_context, block); + return block; + }}, + {"loadResolver", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + FunctionGrouper::run(*m_context, block); + BlockFlattener::run(*m_context, block); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + ExpressionSplitter::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + ExpressionSimplifier::run(*m_context, block); - LoadResolver::run(*m_context, m_ast); + LoadResolver::run(*m_context, block); - UnusedPruner::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - ExpressionJoiner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"loopInvariantCodeMotion", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - LoopInvariantCodeMotion::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"controlFlowSimplifier", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - ControlFlowSimplifier::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"structuralSimplifier", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - LiteralRematerialiser::run(*m_context, m_ast); - StructuralSimplifier::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"equivalentFunctionCombiner", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - EquivalentFunctionCombiner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"ssaReverser", [&]() { - disambiguate(); - SSAReverser::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"ssaAndBack", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); + UnusedPruner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + ExpressionJoiner::run(*m_context, block); + return block; + }}, + {"loopInvariantCodeMotion", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + LoopInvariantCodeMotion::run(*m_context, block); + return block; + }}, + {"controlFlowSimplifier", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + ControlFlowSimplifier::run(*m_context, block); + return block; + }}, + {"structuralSimplifier", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + LiteralRematerialiser::run(*m_context, block); + StructuralSimplifier::run(*m_context, block); + return block; + }}, + {"equivalentFunctionCombiner", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + EquivalentFunctionCombiner::run(*m_context, block); + return block; + }}, + {"ssaReverser", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + SSAReverser::run(*m_context, block); + m_context->yulNameRepository.generateLabels(block); + return block; + }}, + {"ssaAndBack", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); // apply SSA - SSATransform::run(*m_context, m_ast); - UnusedAssignEliminator::run(*m_context, m_ast); + SSATransform::run(*m_context, block); + UnusedAssignEliminator::run(*m_context, block); // reverse SSA - SSAReverser::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - CommonSubexpressionEliminator::run(*m_context, m_ast); - UnusedPruner::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); - }}, - {"stackCompressor", [&]() { - disambiguate(); - ForLoopInitRewriter::run(*m_context, m_ast); - FunctionHoister::run(*m_context, m_ast); - FunctionGrouper::run(*m_context, m_ast); + SSAReverser::run(*m_context, block); + FunctionHoister::run(*m_context, block); + CommonSubexpressionEliminator::run(*m_context, block); + UnusedPruner::run(*m_context, block); + return block; + }}, + {"stackCompressor", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + ForLoopInitRewriter::run(*m_context, block); + FunctionHoister::run(*m_context, block); + FunctionGrouper::run(*m_context, block); size_t maxIterations = 16; - StackCompressor::run(m_yulNameRepository, m_ast, *m_object, true, maxIterations); - BlockFlattener::run(*m_context, m_ast); - m_context->yulNameRepository.generateLabels(m_ast); + StackCompressor::run(_nameRepository, block, *m_object, true, maxIterations); + BlockFlattener::run(*m_context, block); + return block; }}, - {"fullSuite", [&]() { - GasMeter meter(m_yulNameRepository, dynamic_cast(m_yulNameRepository.dialect()), false, 200); + {"fullSuite", [&](YulNameRepository& _nameRepository) { + GasMeter meter(m_object->code->nameRepository(), dynamic_cast(m_object->code->nameRepository().dialect()), false, 200); OptimiserSuite::run( &meter, *m_object, @@ -371,19 +380,22 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( frontend::OptimiserSettings::DefaultYulOptimiserCleanupSteps, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment ); - m_object->code->nameRepository().generateLabels(m_object->code->block()); + _nameRepository = YulNameRepository(m_object->code->nameRepository()); + return std::get(ASTCopier{}(m_object->code->block())); }}, - {"stackLimitEvader", [&]() { - disambiguate(); - m_context->yulNameRepository.generateLabels(m_ast); - StackLimitEvader::run(*m_context, m_ast, CompilabilityChecker{ + {"stackLimitEvader", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); + m_context->yulNameRepository.generateLabels(block); + StackLimitEvader::run(*m_context, block, CompilabilityChecker{ *m_object, - true + true, + &_nameRepository, + &block }.unreachableVariables); - m_context->yulNameRepository.generateLabels(m_ast); + return block; }}, - {"fakeStackLimitEvader", [&]() { - disambiguate(); + {"fakeStackLimitEvader", [&](YulNameRepository& _nameRepository) { + auto block = disambiguate(_nameRepository); // Mark all variables with a name starting with "$" for escalation to memory. struct FakeUnreachableGenerator: ASTWalker { @@ -421,10 +433,10 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( YulName m_currentFunction = YulNameRepository::emptyName(); YulNameRepository const& m_yulNameRepository; }; - FakeUnreachableGenerator fakeUnreachableGenerator (m_yulNameRepository); - fakeUnreachableGenerator(m_ast); - StackLimitEvader::run(*m_context, m_ast, fakeUnreachableGenerator.fakeUnreachables); - m_context->yulNameRepository.generateLabels(m_ast); + FakeUnreachableGenerator fakeUnreachableGenerator (_nameRepository); + fakeUnreachableGenerator(block); + StackLimitEvader::run(*m_context, block, fakeUnreachableGenerator.fakeUnreachables); + return block; }} }; } @@ -436,10 +448,14 @@ void YulOptimizerTestCommon::setStep(std::string const& _optimizerStep) bool YulOptimizerTestCommon::runStep() { - updateContext(); + YulNameRepository nameRepository(m_object->code->nameRepository()); + updateContext(nameRepository); if (m_namedSteps.count(m_optimizerStep)) - m_namedSteps[m_optimizerStep](); + { + auto block = m_namedSteps[m_optimizerStep](nameRepository); + m_resultObject->code = std::make_shared(std::move(nameRepository), std::move(block)); + } else return false; @@ -475,25 +491,31 @@ std::string YulOptimizerTestCommon::randomOptimiserStep(unsigned _seed) yulAssert(false, "Optimiser step selection failed."); } -Block* YulOptimizerTestCommon::run() +Block const* YulOptimizerTestCommon::run() { - return runStep() ? &m_ast : nullptr; + return runStep() ? &m_resultObject->code->block() : nullptr; } -void YulOptimizerTestCommon::disambiguate() +Block YulOptimizerTestCommon::disambiguate(YulNameRepository& _nameRepository) { - m_object->code->block() = std::get(Disambiguator(m_yulNameRepository, *m_analysisInfo)(m_object->code->block())); + auto block = std::get(Disambiguator(_nameRepository, *m_analysisInfo)(m_object->code->block())); m_analysisInfo.reset(); - updateContext(); + updateContext(_nameRepository); + return block; } -void YulOptimizerTestCommon::updateContext() +void YulOptimizerTestCommon::updateContext(YulNameRepository& _nameRepository) { static std::set nothingReserved {}; m_context = std::make_unique(OptimiserStepContext{ - m_yulNameRepository.dialect(), - m_yulNameRepository, + _nameRepository.dialect(), + _nameRepository, nothingReserved, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }); } + +std::shared_ptr YulOptimizerTestCommon::resultObject() const +{ + return m_resultObject; +} diff --git a/test/libyul/YulOptimizerTestCommon.h b/test/libyul/YulOptimizerTestCommon.h index 3f3616503727..ecbfb2a67c37 100644 --- a/test/libyul/YulOptimizerTestCommon.h +++ b/test/libyul/YulOptimizerTestCommon.h @@ -41,7 +41,7 @@ class YulOptimizerTestCommon void setStep(std::string const& _optimizerStep); /// Runs chosen optimiser step returning pointer /// to yul AST Block post optimisation. - Block* run(); + Block const* run(); /// Runs chosen optimiser step returning true if /// successful, false otherwise. bool runStep(); @@ -50,19 +50,20 @@ class YulOptimizerTestCommon /// @param _seed is an unsigned integer that /// seeds the random selection. std::string randomOptimiserStep(unsigned _seed); + /// the resulting object after performing optimization steps + std::shared_ptr resultObject() const; private: - void disambiguate(); - void updateContext(); + Block disambiguate(YulNameRepository& _nameRepository); + void updateContext(YulNameRepository& _nameRepository); std::string m_optimizerStep; - YulNameRepository& m_yulNameRepository; std::unique_ptr m_context; std::shared_ptr m_object; - Block& m_ast; + std::shared_ptr m_resultObject; std::shared_ptr m_analysisInfo; - std::map> m_namedSteps; + std::map> m_namedSteps; }; } diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 3c6923d9ed75..281374b2427f 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -57,9 +57,7 @@ #include #include -#include #include -#include #include #include @@ -91,20 +89,22 @@ class YulOpti CharStream _charStream(_input, ""); try { - m_ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); - if (!m_ast || !errorReporter.errors().empty()) + auto ast = yul::Parser(errorReporter, m_dialect).parse(_charStream); + if (!m_block || !errorReporter.errors().empty()) { std::cerr << "Error parsing source." << std::endl; printErrors(_charStream, errors); throw std::runtime_error("Could not parse source."); } + m_nameRepository = std::make_shared(ast->nameRepository()); + m_block = std::make_shared(std::get(ASTCopier{}(ast->block()))); m_analysisInfo = std::make_unique(); AsmAnalyzer analyzer( *m_analysisInfo, errorReporter, - m_ast->nameRepository() + *m_nameRepository ); - if (!analyzer.analyze(m_ast->block()) || !errorReporter.errors().empty()) + if (!analyzer.analyze(*m_block) || !errorReporter.errors().empty()) { std::cerr << "Error analyzing source." << std::endl; printErrors(_charStream, errors); @@ -170,7 +170,7 @@ class YulOpti void disambiguate() { - m_ast->block() = std::get(Disambiguator(m_ast->nameRepository(), *m_analysisInfo)(m_ast->block())); + *m_block = std::get(Disambiguator(*m_nameRepository, *m_analysisInfo)(*m_block)); m_analysisInfo.reset(); } @@ -178,9 +178,8 @@ class YulOpti { parse(_source); disambiguate(); - OptimiserStepContext context {m_dialect, m_ast->nameRepository(), m_reservedIdentifiers, solidity::frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment}; - OptimiserSuite{context}.runSequence(_steps, m_ast->block()); - std::cout << AsmPrinter{m_ast->nameRepository()}(m_ast->block()) << std::endl; + OptimiserSuite{m_context}.runSequence(_steps, *m_block); + std::cout << AsmPrinter{*m_nameRepository}(*m_block) << std::endl; } void runInteractive(std::string _source, bool _disambiguated = false) @@ -218,18 +217,17 @@ class YulOpti case ';': { Object obj; - obj.code = m_ast; - StackCompressor::run(m_ast->nameRepository(), m_ast->block(), obj, true, 16); + StackCompressor::run(*m_nameRepository, *m_block, obj, true, 16); break; } default: - { - OptimiserStepContext context {m_dialect, m_ast->nameRepository(), m_reservedIdentifiers, solidity::frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment}; - OptimiserSuite{context}.runSequence(std::string_view(&option, 1), m_ast->block()); - } + OptimiserSuite{m_context}.runSequence( + std::string_view(&option, 1), + *m_block + ); } - m_ast->nameRepository().generateLabels(m_ast->block()); - _source = AsmPrinter{m_ast->nameRepository()}(m_ast->block()); + m_nameRepository->generateLabels(*m_block); + _source = AsmPrinter{*m_nameRepository}(*m_block); } catch (...) { @@ -242,10 +240,17 @@ class YulOpti } private: - std::shared_ptr m_ast; + std::shared_ptr m_block; + std::shared_ptr m_nameRepository; Dialect const& m_dialect {EVMDialect::strictAssemblyForEVMObjects(EVMVersion{})}; std::unique_ptr m_analysisInfo; std::set const m_reservedIdentifiers = {}; + OptimiserStepContext m_context{ + m_dialect, + *m_nameRepository, + m_reservedIdentifiers, + solidity::frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment + }; }; int main(int argc, char** argv) diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index cdf11e6f26e9..696bae07a7fc 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -194,17 +194,19 @@ std::unique_ptr Program::applyOptimisationSteps( // An empty set of reserved identifiers. It could be a constructor parameter but I don't // think it would be useful in this tool. Other tools (like yulopti) have it empty too. std::set const externallyUsedIdentifiers = {}; + YulNameRepository nameRepository (_ast->nameRepository()); OptimiserStepContext context{ - _ast->nameRepository().dialect(), - _ast->nameRepository(), + nameRepository.dialect(), + nameRepository, externallyUsedIdentifiers, frontend::OptimiserSettings::standard().expectedExecutionsPerDeployment }; + auto block = std::get(ASTCopier{}(_ast->block())); for (std::string const& step: _optimisationSteps) - OptimiserSuite::allSteps().at(step)->run(context, _ast->block()); + OptimiserSuite::allSteps().at(step)->run(context, block); - return _ast; + return std::make_unique(std::move(nameRepository), std::move(block)); } size_t Program::computeCodeSize(Block const& _ast, CodeWeights const& _weights) From e50d8f12e252517b6f3fb70433438aa191da76ba Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 10 Jul 2024 11:42:41 +0200 Subject: [PATCH 11/15] f --- libyul/optimiser/StackCompressor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 5e7cdf92a824..2ebeabeecad1 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -257,7 +257,7 @@ bool StackCompressor::run( size_t _maxIterations) { yulAssert( - !_object.code->block().statements.empty() && std::holds_alternative(_object.code->block().statements.at(0)), + !_block.statements.empty() && std::holds_alternative(_block.statements.at(0)), "Need to run the function grouper before the stack compressor." ); From 709861fd8c2f6b9b619029ca3e967faa22bf5b41 Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 10 Jul 2024 13:47:43 +0200 Subject: [PATCH 12/15] f --- libyul/AST.h | 1 - libyul/backends/evm/ControlFlowGraph.h | 2 ++ .../backends/evm/ControlFlowGraphBuilder.cpp | 23 +++++++++---------- libyul/backends/evm/ControlFlowGraphBuilder.h | 6 ++--- test/libyul/Common.cpp | 5 ++-- test/libyul/ControlFlowGraphTest.cpp | 4 +--- test/libyul/StackLayoutGeneratorTest.cpp | 3 +-- test/tools/yulrun.cpp | 6 ++--- tools/yulPhaser/Program.cpp | 1 - 9 files changed, 22 insertions(+), 29 deletions(-) diff --git a/libyul/AST.h b/libyul/AST.h index 3d5148f8a6ea..af389438b684 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -113,7 +113,6 @@ class AST Block const& block() const { return m_block; } YulNameRepository const& nameRepository() const { return m_nameRepository; } - YulNameRepository& nameRepository() { return m_nameRepository; } private: YulNameRepository m_nameRepository; diff --git a/libyul/backends/evm/ControlFlowGraph.h b/libyul/backends/evm/ControlFlowGraph.h index 980787c52297..8bef32d3c0ff 100644 --- a/libyul/backends/evm/ControlFlowGraph.h +++ b/libyul/backends/evm/ControlFlowGraph.h @@ -237,6 +237,8 @@ struct CFG /// Ghost calls are used for the equality comparisons of the switch condition ghost variable with /// the switch case literals when transforming the control flow of a switch to a sequence of conditional jumps. std::list ghostCalls; + /// Name repository that holds yul names for added artificial nodes. + std::unique_ptr nameRepository; BasicBlock& makeBlock(langutil::DebugData::ConstPtr _debugData) { diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.cpp b/libyul/backends/evm/ControlFlowGraphBuilder.cpp index 087c0e84dbd2..ed90831edfac 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.cpp +++ b/libyul/backends/evm/ControlFlowGraphBuilder.cpp @@ -207,15 +207,16 @@ void markNeedsCleanStack(CFG& _cfg) std::unique_ptr ControlFlowGraphBuilder::build( AsmAnalysisInfo const& _analysisInfo, - YulNameRepository& _yulNameRepository, + YulNameRepository const& _yulNameRepository, Block const& _block ) { auto result = std::make_unique(); result->entry = &result->makeBlock(debugDataOf(_block)); + result->nameRepository = std::make_unique(_yulNameRepository); - ControlFlowSideEffectsCollector sideEffects(_yulNameRepository, _block); - ControlFlowGraphBuilder builder(*result, _analysisInfo, sideEffects.functionSideEffects(), _yulNameRepository); + ControlFlowSideEffectsCollector sideEffects(*result->nameRepository, _block); + ControlFlowGraphBuilder builder(*result, _analysisInfo, sideEffects.functionSideEffects()); builder.m_currentBlock = result->entry; builder(_block); @@ -233,13 +234,11 @@ std::unique_ptr ControlFlowGraphBuilder::build( ControlFlowGraphBuilder::ControlFlowGraphBuilder( CFG& _graph, AsmAnalysisInfo const& _analysisInfo, - std::map const& _functionSideEffects, - YulNameRepository& _yulNameRepository + std::map const& _functionSideEffects ): m_graph(_graph), m_info(_analysisInfo), - m_functionSideEffects(_functionSideEffects), - m_yulNameRepository(_yulNameRepository) + m_functionSideEffects(_functionSideEffects) { } @@ -335,7 +334,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) yulAssert(m_currentBlock, ""); langutil::DebugData::ConstPtr preSwitchDebugData = debugDataOf(_switch); - auto const ghostVariableName = m_yulNameRepository.addGhost(); + auto const ghostVariableName = m_graph.nameRepository->addGhost(); auto& ghostVar = m_graph.ghostVariables.emplace_back(Scope::Variable{YulNameRepository::emptyName(), ghostVariableName}); // Artificially generate: @@ -348,7 +347,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) CFG::Assignment{_switch.debugData, {ghostVarSlot}} }); - auto const* equalityBuiltin = m_yulNameRepository.equalityFunction({}); + auto const* equalityBuiltin = m_graph.nameRepository->equalityFunction({}); yulAssert(equalityBuiltin, ""); // Artificially generate: @@ -356,7 +355,7 @@ void ControlFlowGraphBuilder::operator()(Switch const& _switch) auto makeValueCompare = [&](Case const& _case) { yul::FunctionCall const& ghostCall = m_graph.ghostCalls.emplace_back(yul::FunctionCall{ debugDataOf(_case), - yul::Identifier{{}, m_yulNameRepository.predefined().eq}, + yul::Identifier{{}, m_graph.nameRepository->predefined().eq}, {*_case.value, Identifier{{}, ghostVariableName}} }); CFG::Operation& operation = m_currentBlock->operations.emplace_back(CFG::Operation{ @@ -467,7 +466,7 @@ void ControlFlowGraphBuilder::operator()(FunctionDefinition const& _function) CFG::FunctionInfo& functionInfo = m_graph.functionInfo.at(&function); - ControlFlowGraphBuilder builder{m_graph, m_info, m_functionSideEffects, m_yulNameRepository}; + ControlFlowGraphBuilder builder{m_graph, m_info, m_functionSideEffects}; builder.m_currentFunction = &functionInfo; builder.m_currentBlock = functionInfo.entry; builder(_function.body); @@ -515,7 +514,7 @@ Stack const& ControlFlowGraphBuilder::visitFunctionCall(FunctionCall const& _cal Stack const* output = nullptr; bool canContinue = true; - if (auto const* builtin = m_yulNameRepository.builtin(_call.functionName.name)) + if (auto const* builtin = m_graph.nameRepository->builtin(_call.functionName.name)) { Stack inputs; for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse) diff --git a/libyul/backends/evm/ControlFlowGraphBuilder.h b/libyul/backends/evm/ControlFlowGraphBuilder.h index dba1aa3423cb..b70ad41f47f9 100644 --- a/libyul/backends/evm/ControlFlowGraphBuilder.h +++ b/libyul/backends/evm/ControlFlowGraphBuilder.h @@ -31,7 +31,7 @@ class ControlFlowGraphBuilder public: ControlFlowGraphBuilder(ControlFlowGraphBuilder const&) = delete; ControlFlowGraphBuilder& operator=(ControlFlowGraphBuilder const&) = delete; - static std::unique_ptr build(AsmAnalysisInfo const& _analysisInfo, YulNameRepository& _yulNameRepository, Block const& _block); + static std::unique_ptr build(AsmAnalysisInfo const& _analysisInfo, YulNameRepository const& _yulNameRepository, Block const& _block); StackSlot operator()(Expression const& _literal); StackSlot operator()(Literal const& _literal); @@ -56,8 +56,7 @@ class ControlFlowGraphBuilder ControlFlowGraphBuilder( CFG& _graph, AsmAnalysisInfo const& _analysisInfo, - std::map const& _functionSideEffects, - YulNameRepository& _yulNameRepository + std::map const& _functionSideEffects ); void registerFunction(FunctionDefinition const& _function); Stack const& visitFunctionCall(FunctionCall const&); @@ -80,7 +79,6 @@ class ControlFlowGraphBuilder CFG& m_graph; AsmAnalysisInfo const& m_info; std::map const& m_functionSideEffects; - YulNameRepository& m_yulNameRepository; CFG::BasicBlock* m_currentBlock = nullptr; Scope* m_scope = nullptr; struct ForLoopInfo diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index f22d5873cc5d..ff5b2c614faa 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -84,8 +84,9 @@ std::shared_ptr yul::test::disambiguate(std::string const& _source, bool _y { auto result = parse(_source, _yul); auto const& [code, analysisInfo] = result; - Disambiguator(code->nameRepository(), *analysisInfo, {})(code->block()); - return code; + YulNameRepository nameRepository(code->nameRepository()); + auto block = std::get(Disambiguator(nameRepository, *analysisInfo, {})(code->block())); + return std::make_shared(std::move(nameRepository), std::move(block)); } std::string yul::test::format(std::string const& _source, bool _yul) diff --git a/test/libyul/ControlFlowGraphTest.cpp b/test/libyul/ControlFlowGraphTest.cpp index af80800ab9c6..a5336af60e73 100644 --- a/test/libyul/ControlFlowGraphTest.cpp +++ b/test/libyul/ControlFlowGraphTest.cpp @@ -206,12 +206,10 @@ TestCase::TestResult ControlFlowGraphTest::run(std::ostream& _stream, std::strin } std::ostringstream output; - std::unique_ptr cfg = ControlFlowGraphBuilder::build(*analysisInfo, object->code->nameRepository(), object->code->block()); - object->code->nameRepository().generateLabels(object->code->block()); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - ControlFlowGraphPrinter printer{output, object->code->nameRepository()}; + ControlFlowGraphPrinter printer{output, *cfg->nameRepository}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/libyul/StackLayoutGeneratorTest.cpp b/test/libyul/StackLayoutGeneratorTest.cpp index 053ac3601ae0..570c60266d98 100644 --- a/test/libyul/StackLayoutGeneratorTest.cpp +++ b/test/libyul/StackLayoutGeneratorTest.cpp @@ -229,8 +229,7 @@ TestCase::TestResult StackLayoutGeneratorTest::run(std::ostream& _stream, std::s StackLayout stackLayout = StackLayoutGenerator::run(*cfg); output << "digraph CFG {\nnodesep=0.7;\nnode[shape=box];\n\n"; - StackLayoutPrinter printer{output, stackLayout, object->code->nameRepository()}; - object->code->nameRepository().generateLabels(object->code->block()); // todo need more? + StackLayoutPrinter printer{output, stackLayout, *cfg->nameRepository}; printer(*cfg->entry); for (auto function: cfg->functions) printer(cfg->functionInfo.at(function)); diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index e35a5b26d21c..effee21e4834 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -87,12 +87,10 @@ void interpret(std::string const& _source, bool _inspect, bool _disableExternalC state.maxTraceSize = 10000; try { - YulNameRepository& repository = ast->nameRepository(); if (_inspect) - InspectedInterpreter::run(std::make_shared(_source, state, repository), state, repository, ast->block(), _disableExternalCalls, /*disableMemoryTracing=*/false); - + InspectedInterpreter::run(std::make_shared(_source, state, ast->nameRepository()), state, ast->nameRepository(), ast->block(), _disableExternalCalls, /*disableMemoryTracing=*/false); else - Interpreter::run(state, repository, ast->block(), _disableExternalCalls, /*disableMemoryTracing=*/false); + Interpreter::run(state, ast->nameRepository(), ast->block(), _disableExternalCalls, /*disableMemoryTracing=*/false); } catch (InterpreterTerminatedGeneric const&) { diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 696bae07a7fc..f0705ede7476 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -91,7 +91,6 @@ std::variant Program::load(CharStream& _sourceCode) FunctionGrouper::name, ForLoopInitRewriter::name, }); - program.m_ast->nameRepository().generateLabels(program.m_ast->block()); return program; } From 7394b2350c5bbb3e11245af65117023bcfb65b96 Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 10 Jul 2024 13:53:33 +0200 Subject: [PATCH 13/15] immutable ast --- libyul/backends/evm/OptimizedEVMCodeTransform.cpp | 2 +- libyul/backends/evm/OptimizedEVMCodeTransform.h | 2 +- libyul/optimiser/StackCompressor.cpp | 3 +-- libyul/optimiser/StackCompressor.h | 2 +- libyul/optimiser/Suite.cpp | 12 +++++------- test/tools/yulopti.cpp | 1 + 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp index 651fb226489c..8d5aeff96c4c 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.cpp +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.cpp @@ -43,7 +43,7 @@ std::vector OptimizedEVMCodeTransform::run( AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, Block const& _block, - YulNameRepository& _yulNameRepository, + YulNameRepository const& _yulNameRepository, BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions ) diff --git a/libyul/backends/evm/OptimizedEVMCodeTransform.h b/libyul/backends/evm/OptimizedEVMCodeTransform.h index d3632af3abec..c5f1615a26a5 100644 --- a/libyul/backends/evm/OptimizedEVMCodeTransform.h +++ b/libyul/backends/evm/OptimizedEVMCodeTransform.h @@ -51,7 +51,7 @@ class OptimizedEVMCodeTransform AbstractAssembly& _assembly, AsmAnalysisInfo& _analysisInfo, Block const& _block, - YulNameRepository& _yulNameRepository, + YulNameRepository const& _yulNameRepository, BuiltinContext& _builtinContext, UseNamedLabels _useNamedLabelsForFunctions ); diff --git a/libyul/optimiser/StackCompressor.cpp b/libyul/optimiser/StackCompressor.cpp index 2ebeabeecad1..62158a497942 100644 --- a/libyul/optimiser/StackCompressor.cpp +++ b/libyul/optimiser/StackCompressor.cpp @@ -250,7 +250,7 @@ bool StackCompressor::run( } bool StackCompressor::run( - YulNameRepository& _nameRepository, + YulNameRepository const& _nameRepository, Block& _block, Object const& _object, bool _optimizeStackAllocation, @@ -268,7 +268,6 @@ bool StackCompressor::run( evmDialect->evmVersion().canOverchargeGasForCall() && evmDialect->providesObjectAccess(); bool allowMSizeOptimization = !MSizeFinder::containsMSize(_nameRepository, _block); - _nameRepository.generateLabels(_block); if (usesOptimizedCodeGenerator) { yul::AsmAnalysisInfo analysisInfo = yul::AsmAnalyzer::analyzeStrictAssertCorrect(_nameRepository, _block, _object.qualifiedDataNames()); diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index 58ea81a64ea2..771eb82bb05c 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -56,7 +56,7 @@ class StackCompressor /// disregards the AST contained in object. /// @returns true if it was successful. static bool run( - YulNameRepository& _nameRepository, + YulNameRepository const& _nameRepository, Block& _block, Object const& _object, bool _optimizeStackAllocation, diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index d4831b3de3c9..046aba7cc347 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -175,13 +175,10 @@ void OptimiserSuite::run( // We ignore the return value because we will get a much better error // message once we perform code generation. if (!usesOptimizedCodeGenerator) - StackCompressor::run( - nameRepository, - ast, - _object, - _optimizeStackAllocation, - stackCompressorMaxIterations - ); + { + nameRepository.generateLabels(ast); + StackCompressor::run(nameRepository, ast, _object, _optimizeStackAllocation, stackCompressorMaxIterations); + } // Run the user-supplied clean up sequence suite.runSequence(_optimisationCleanupSequence, ast); @@ -196,6 +193,7 @@ void OptimiserSuite::run( ConstantOptimiser{nameRepository, *evmDialect, *_meter}(ast); if (usesOptimizedCodeGenerator) { + nameRepository.generateLabels(ast); StackCompressor::run( nameRepository, ast, diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 281374b2427f..410885b26783 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -216,6 +216,7 @@ class YulOpti break; case ';': { + m_nameRepository->generateLabels(*m_block); Object obj; StackCompressor::run(*m_nameRepository, *m_block, obj, true, 16); break; From b2cce39258c48ef07df581d7343e26819aed184a Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 10 Jul 2024 13:55:55 +0200 Subject: [PATCH 14/15] immutable ast --- libyul/AST.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libyul/AST.h b/libyul/AST.h index af389438b684..12df5b3c7dcd 100644 --- a/libyul/AST.h +++ b/libyul/AST.h @@ -105,11 +105,6 @@ class AST { public: AST(YulNameRepository _nameRepository, Block _block); - AST(AST&&) = default; - AST& operator=(AST&& _rhs) = default; - AST(AST const& _rhs) = default; - AST& operator=(AST const& _rhs) = default; - ~AST() = default; Block const& block() const { return m_block; } YulNameRepository const& nameRepository() const { return m_nameRepository; } From 1cb984dcb03f8e94fe8ff6f133b6535a1f9583a2 Mon Sep 17 00:00:00 2001 From: clonker Date: Wed, 10 Jul 2024 14:00:33 +0200 Subject: [PATCH 15/15] immutable ast --- test/libyul/YulOptimizerTestCommon.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/libyul/YulOptimizerTestCommon.cpp b/test/libyul/YulOptimizerTestCommon.cpp index e98989747a2e..b0cf1d319693 100644 --- a/test/libyul/YulOptimizerTestCommon.cpp +++ b/test/libyul/YulOptimizerTestCommon.cpp @@ -366,6 +366,7 @@ YulOptimizerTestCommon::YulOptimizerTestCommon( FunctionHoister::run(*m_context, block); FunctionGrouper::run(*m_context, block); size_t maxIterations = 16; + _nameRepository.generateLabels(block); StackCompressor::run(_nameRepository, block, *m_object, true, maxIterations); BlockFlattener::run(*m_context, block); return block;