mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8408 from ethereum/utilFunctionsFromOldCodegen
Allow using YulUtilFunctions from old codegen
This commit is contained in:
commit
27a4670ad8
@ -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 <functionName>(headStart <valueParams>) -> 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());
|
||||
@ -240,13 +240,6 @@ string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||
});
|
||||
}
|
||||
|
||||
pair<string, set<string>> ABIFunctions::requestedFunctions()
|
||||
{
|
||||
std::set<string> empty;
|
||||
swap(empty, m_externallyUsedFunctions);
|
||||
return make_pair(m_functionCollector->requestedFunctions(), std::move(empty));
|
||||
}
|
||||
|
||||
string ABIFunctions::EncodingOptions::toFunctionNameSuffix() const
|
||||
{
|
||||
string suffix;
|
||||
@ -1502,13 +1495,6 @@ string ABIFunctions::createFunction(string const& _name, function<string ()> con
|
||||
return m_functionCollector->createFunction(_name, _creator);
|
||||
}
|
||||
|
||||
string ABIFunctions::createExternallyUsedFunction(string const& _name, function<string ()> const& _creator)
|
||||
{
|
||||
string name = createFunction(_name, _creator);
|
||||
m_externallyUsedFunctions.insert(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
size_t ABIFunctions::headSize(TypePointers const& _targetTypes)
|
||||
{
|
||||
size_t headSize = 0;
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace solidity::frontend
|
||||
@ -104,12 +103,6 @@ public:
|
||||
/// stack slot, it takes exactly that number of values.
|
||||
std::string tupleDecoder(TypePointers const& _types, bool _fromMemory = false);
|
||||
|
||||
/// @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<std::string, std::set<std::string>> requestedFunctions();
|
||||
|
||||
private:
|
||||
struct EncodingOptions
|
||||
{
|
||||
@ -239,11 +232,6 @@ private:
|
||||
/// cases.
|
||||
std::string createFunction(std::string const& _name, std::function<std::string()> 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<std::string()> const& _creator);
|
||||
|
||||
/// @returns the size of the static part of the encoding of the given types.
|
||||
static size_t headSize(TypePointers const& _targetTypes);
|
||||
|
||||
@ -260,7 +248,6 @@ private:
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
RevertStrings const m_revertStrings;
|
||||
std::shared_ptr<MultiUseYulFunctionCollector> m_functionCollector;
|
||||
std::set<std::string> m_externallyUsedFunctions;
|
||||
YulUtilFunctions m_utils;
|
||||
};
|
||||
|
||||
|
@ -94,6 +94,20 @@ void CompilerContext::callLowLevelFunction(
|
||||
*this << retTag.tag();
|
||||
}
|
||||
|
||||
void CompilerContext::callYulFunction(
|
||||
string const& _name,
|
||||
unsigned _inArgs,
|
||||
unsigned _outArgs
|
||||
)
|
||||
{
|
||||
m_externallyUsedYulFunctions.insert(_name);
|
||||
auto const retTag = pushNewTag();
|
||||
CompilerUtils(*this).moveIntoStack(_inArgs);
|
||||
appendJumpTo(namedTag(_name));
|
||||
adjustStackOffset(int(_outArgs) - 1 - _inArgs);
|
||||
*this << retTag.tag();
|
||||
}
|
||||
|
||||
evmasm::AssemblyItem CompilerContext::lowLevelFunctionTag(
|
||||
string const& _name,
|
||||
unsigned _inArgs,
|
||||
@ -133,6 +147,13 @@ void CompilerContext::appendMissingLowLevelFunctions()
|
||||
}
|
||||
}
|
||||
|
||||
pair<string, set<string>> CompilerContext::requestedYulFunctions()
|
||||
{
|
||||
set<string> empty;
|
||||
swap(empty, m_externallyUsedYulFunctions);
|
||||
return make_pair(m_yulFunctionCollector->requestedFunctions(), std::move(empty));
|
||||
}
|
||||
|
||||
void CompilerContext::addVariable(
|
||||
VariableDeclaration const& _declaration,
|
||||
unsigned _offsetToCurrent
|
||||
|
@ -65,7 +65,8 @@ public:
|
||||
m_evmVersion(_evmVersion),
|
||||
m_revertStrings(_revertStrings),
|
||||
m_runtimeContext(_runtimeContext),
|
||||
m_abiFunctions(m_evmVersion, m_revertStrings)
|
||||
m_abiFunctions(m_evmVersion, m_revertStrings, m_yulFunctionCollector),
|
||||
m_yulUtilFunctions(m_evmVersion, m_revertStrings, m_yulFunctionCollector)
|
||||
{
|
||||
if (m_runtimeContext)
|
||||
m_runtimeSub = size_t(m_asm->newSub(m_runtimeContext->m_asm).data());
|
||||
@ -131,6 +132,14 @@ public:
|
||||
unsigned _outArgs,
|
||||
std::function<void(CompilerContext&)> const& _generator
|
||||
);
|
||||
|
||||
/// Appends a call to a yul function and registers the function as externally used.
|
||||
void callYulFunction(
|
||||
std::string const& _name,
|
||||
unsigned _inArgs,
|
||||
unsigned _outArgs
|
||||
);
|
||||
|
||||
/// Returns the tag of the named low-level function and inserts the generator into the
|
||||
/// list of low-level-functions to be generated, unless it already exists.
|
||||
/// Note that the generator should not assume that objects are still alive when it is called,
|
||||
@ -144,6 +153,12 @@ public:
|
||||
/// Generates the code for missing low-level functions, i.e. calls the generators passed above.
|
||||
void appendMissingLowLevelFunctions();
|
||||
ABIFunctions& abiFunctions() { return m_abiFunctions; }
|
||||
YulUtilFunctions& utilFunctions() { return m_yulUtilFunctions; }
|
||||
/// @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<std::string, std::set<std::string>> 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).
|
||||
@ -355,8 +370,14 @@ private:
|
||||
size_t m_runtimeSub = -1;
|
||||
/// An index of low-level function labels by name.
|
||||
std::map<std::string, evmasm::AssemblyItem> m_lowLevelFunctions;
|
||||
/// Collector for yul functions.
|
||||
std::shared_ptr<MultiUseYulFunctionCollector> m_yulFunctionCollector = std::make_shared<MultiUseYulFunctionCollector>();
|
||||
/// Set of externally used yul functions.
|
||||
std::set<std::string> m_externallyUsedYulFunctions;
|
||||
/// Container for ABI functions to be generated.
|
||||
ABIFunctions m_abiFunctions;
|
||||
/// Container for Yul Util functions to be generated.
|
||||
YulUtilFunctions m_yulUtilFunctions;
|
||||
/// The queue of low-level functions to generate.
|
||||
std::queue<std::tuple<std::string, unsigned, unsigned, std::function<void(CompilerContext&)>>> m_lowLevelFunctionGenerationQueue;
|
||||
};
|
||||
|
@ -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.callYulFunction(encoderName, sizeOnStack(_givenTypes) + 1, 1);
|
||||
}
|
||||
|
||||
void CompilerUtils::abiDecodeV2(TypePointers const& _parameterTypes, bool _fromMemory)
|
||||
{
|
||||
// stack: <source_offset> <length> [stack top]
|
||||
auto ret = m_context.pushNewTag();
|
||||
moveIntoStack(2);
|
||||
// stack: <return tag> <source_offset> <length> [stack top]
|
||||
m_context << Instruction::DUP2 << Instruction::ADD;
|
||||
m_context << Instruction::SWAP1;
|
||||
// stack: <return tag> <end> <start>
|
||||
// stack: <end> <start>
|
||||
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.callYulFunction(decoderName, 2, sizeOnStack(_parameterTypes));
|
||||
}
|
||||
|
||||
void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type)
|
||||
|
@ -1267,12 +1267,12 @@ void ContractCompiler::appendMissingFunctions()
|
||||
solAssert(m_context.nextFunctionToCompile() != function, "Compiled the wrong function?");
|
||||
}
|
||||
m_context.appendMissingLowLevelFunctions();
|
||||
auto abiFunctions = m_context.abiFunctions().requestedFunctions();
|
||||
if (!abiFunctions.first.empty())
|
||||
auto [yulFunctions, externallyUsedYulFunctions] = m_context.requestedYulFunctions();
|
||||
if (!yulFunctions.empty())
|
||||
m_context.appendInlineAssembly(
|
||||
"{" + move(abiFunctions.first) + "}",
|
||||
"{" + move(yulFunctions) + "}",
|
||||
{},
|
||||
abiFunctions.second,
|
||||
externallyUsedYulFunctions,
|
||||
true,
|
||||
m_optimiserSettings
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user