diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index b69f47346..b6d690898 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -55,7 +55,7 @@ string ABIFunctions::tupleEncoder( functionName += t->identifier() + "_"; functionName += options.toFunctionNameSuffix(); - return createExternallyUsedFunction(functionName, [&]() { + return createFunction(functionName, [&]() { // Note that the values are in reverse due to the difference in calling semantics. Whiskers templ(R"( function (headStart ) -> tail { @@ -121,7 +121,7 @@ string ABIFunctions::tupleEncoderPacked( functionName += t->identifier() + "_"; functionName += options.toFunctionNameSuffix(); - return createExternallyUsedFunction(functionName, [&]() { + return createFunction(functionName, [&]() { solAssert(!_givenTypes.empty(), ""); // Note that the values are in reverse due to the difference in calling semantics. @@ -173,7 +173,7 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory) if (_fromMemory) functionName += "_fromMemory"; - return createExternallyUsedFunction(functionName, [&]() { + return createFunction(functionName, [&]() { TypePointers decodingTypes; for (auto const& t: _types) decodingTypes.emplace_back(t->decodingType()); @@ -1495,11 +1495,6 @@ string ABIFunctions::createFunction(string const& _name, function con return m_functionCollector->createFunction(_name, _creator); } -string ABIFunctions::createExternallyUsedFunction(string const& _name, function const& _creator) -{ - return m_functionCollector->createExternallyUsedFunction(_name, _creator); -} - size_t ABIFunctions::headSize(TypePointers const& _targetTypes) { size_t headSize = 0; diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index 74bfdf7fa..1099e3593 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -31,7 +31,6 @@ #include #include -#include #include namespace solidity::frontend @@ -233,11 +232,6 @@ private: /// cases. std::string createFunction(std::string const& _name, std::function const& _creator); - /// Helper function that uses @a _creator to create a function and add it to - /// @a m_requestedFunctions if it has not been created yet and returns @a _name in both - /// cases. Also adds it to the list of externally used functions. - std::string createExternallyUsedFunction(std::string const& _name, std::function const& _creator); - /// @returns the size of the static part of the encoding of the given types. static size_t headSize(TypePointers const& _targetTypes); diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index f65ccae52..ee12b9b3e 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -100,7 +100,7 @@ void CompilerContext::callYulUtilFunction( unsigned _outArgs ) { - m_functionCollector->markAsExternallyUsed(_name); + m_externallyUsedFunctions.insert(_name); auto retTag = pushNewTag(); CompilerUtils(*this).moveIntoStack(_inArgs); appendJumpTo(namedTag(_name)); @@ -147,6 +147,13 @@ void CompilerContext::appendMissingLowLevelFunctions() } } +pair> CompilerContext::requestedYulFunctions() +{ + set empty; + swap(empty, m_externallyUsedFunctions); + return make_pair(m_functionCollector->requestedFunctions(), std::move(empty)); +} + void CompilerContext::addVariable( VariableDeclaration const& _declaration, unsigned _offsetToCurrent diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index d9393e23a..6d554da82 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -154,10 +154,11 @@ public: void appendMissingLowLevelFunctions(); ABIFunctions& abiFunctions() { return m_abiFunctions; } YulUtilFunctions& utilFunctions() { return m_yulUtilFunctions; } - std::pair> requestedYulFunctions() - { - return m_functionCollector->requestedFunctions(); - } + /// @returns concatenation of all generated functions and a set of the + /// externally used functions. + /// Clears the internal list, i.e. calling it again will result in an + /// empty return value. + std::pair> requestedYulFunctions(); ModifierDefinition const& resolveVirtualFunctionModifier(ModifierDefinition const& _modifier) const; /// Returns the distance of the given local variable from the bottom of the stack (of the current function). @@ -371,6 +372,8 @@ private: std::map m_lowLevelFunctions; // Collector for yul functions. std::shared_ptr m_functionCollector = std::make_shared(); + /// Set of externally used yul functions. + std::set m_externallyUsedFunctions; /// Container for ABI functions to be generated. ABIFunctions m_abiFunctions; /// Container for Yul Util functions to be generated. diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 4c75081ff..a0d38eae5 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -595,31 +595,21 @@ void CompilerUtils::abiEncodeV2( // stack: <$value0> <$value1> ... <$value(n-1)> <$headStart> - auto ret = m_context.pushNewTag(); - moveIntoStack(sizeOnStack(_givenTypes) + 1); - string encoderName = _padToWordBoundaries ? m_context.abiFunctions().tupleEncoder(_givenTypes, _targetTypes, _encodeAsLibraryTypes) : m_context.abiFunctions().tupleEncoderPacked(_givenTypes, _targetTypes); - m_context.appendJumpTo(m_context.namedTag(encoderName)); - m_context.adjustStackOffset(-int(sizeOnStack(_givenTypes)) - 1); - m_context << ret.tag(); + m_context.callYulUtilFunction(encoderName, sizeOnStack(_givenTypes) + 1, 1); } void CompilerUtils::abiDecodeV2(TypePointers const& _parameterTypes, bool _fromMemory) { // stack: [stack top] - auto ret = m_context.pushNewTag(); - moveIntoStack(2); - // stack: [stack top] m_context << Instruction::DUP2 << Instruction::ADD; m_context << Instruction::SWAP1; - // stack: + // stack: string decoderName = m_context.abiFunctions().tupleDecoder(_parameterTypes, _fromMemory); - m_context.appendJumpTo(m_context.namedTag(decoderName)); - m_context.adjustStackOffset(int(sizeOnStack(_parameterTypes)) - 3); - m_context << ret.tag(); + m_context.callYulUtilFunction(decoderName, 2, sizeOnStack(_parameterTypes)); } void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type) diff --git a/libsolidity/codegen/MultiUseYulFunctionCollector.cpp b/libsolidity/codegen/MultiUseYulFunctionCollector.cpp index 8af292eda..2be3d29ae 100644 --- a/libsolidity/codegen/MultiUseYulFunctionCollector.cpp +++ b/libsolidity/codegen/MultiUseYulFunctionCollector.cpp @@ -30,15 +30,13 @@ using namespace std; using namespace solidity; using namespace solidity::frontend; -pair> MultiUseYulFunctionCollector::requestedFunctions() +string MultiUseYulFunctionCollector::requestedFunctions() { string result; for (auto const& f: m_requestedFunctions) result += f.second; m_requestedFunctions.clear(); - std::set empty; - swap(empty, m_externallyUsedFunctions); - return make_pair(result, std::move(empty)); + return result; } string MultiUseYulFunctionCollector::createFunction(string const& _name, function const& _creator) @@ -52,9 +50,3 @@ string MultiUseYulFunctionCollector::createFunction(string const& _name, functio } return _name; } - -string MultiUseYulFunctionCollector::createExternallyUsedFunction(string const& _name, function const& _creator) -{ - m_externallyUsedFunctions.insert(_name); - return createFunction(_name, _creator); -} diff --git a/libsolidity/codegen/MultiUseYulFunctionCollector.h b/libsolidity/codegen/MultiUseYulFunctionCollector.h index a1c733274..d839a31be 100644 --- a/libsolidity/codegen/MultiUseYulFunctionCollector.h +++ b/libsolidity/codegen/MultiUseYulFunctionCollector.h @@ -23,7 +23,6 @@ #include #include -#include #include namespace solidity::frontend @@ -41,28 +40,14 @@ public: /// cases. std::string createFunction(std::string const& _name, std::function const& _creator); - /// Helper function that uses @a _creator to create a function and add it to - /// @a m_requestedFunctions if it has not been created yet and returns @a _name in both - /// cases. - std::string createExternallyUsedFunction(std::string const& _name, std::function const& _creator); - - /// Manually mark a function as externally used. - void markAsExternallyUsed(std::string const& _name) - { - m_externallyUsedFunctions.insert(_name); - } - - /// @returns concatenation of all generated functions and a set of the - /// externally used functions. + /// @returns concatenation of all generated functions. /// Clears the internal list, i.e. calling it again will result in an /// empty return value. - std::pair> requestedFunctions(); + std::string requestedFunctions(); private: /// Map from function name to code for a multi-use function. std::map m_requestedFunctions; - // Set of externally used functions. - std::set m_externallyUsedFunctions; }; } diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 0f2ffaf35..9c2d8807c 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -107,7 +107,7 @@ string IRGenerator::generate(ContractDefinition const& _contract) for (auto const* contract: _contract.annotation().linearizedBaseContracts) for (auto const* fun: contract->definedFunctions()) generateFunction(*fun); - t("functions", m_context.functionCollector()->requestedFunctions().first); + t("functions", m_context.functionCollector()->requestedFunctions()); resetContext(_contract); m_context.setInheritanceHierarchy(_contract.annotation().linearizedBaseContracts); @@ -116,7 +116,7 @@ string IRGenerator::generate(ContractDefinition const& _contract) for (auto const* contract: _contract.annotation().linearizedBaseContracts) for (auto const* fun: contract->definedFunctions()) generateFunction(*fun); - t("runtimeFunctions", m_context.functionCollector()->requestedFunctions().first); + t("runtimeFunctions", m_context.functionCollector()->requestedFunctions()); return t.render(); } @@ -383,7 +383,7 @@ string IRGenerator::memoryInit() void IRGenerator::resetContext(ContractDefinition const& _contract) { solAssert( - m_context.functionCollector()->requestedFunctions().first.empty(), + m_context.functionCollector()->requestedFunctions().empty(), "Reset context while it still had functions." ); m_context = IRGenerationContext(m_evmVersion, m_context.revertStrings(), m_optimiserSettings);