mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add packed encoder V2.
This commit is contained in:
parent
1b9d30f05f
commit
a08f4f43fa
@ -107,6 +107,74 @@ string ABIFunctions::tupleEncoder(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string ABIFunctions::tupleEncoderPacked(
|
||||||
|
TypePointers const& _givenTypes,
|
||||||
|
TypePointers const& _targetTypes
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EncodingOptions options;
|
||||||
|
options.encodeAsLibraryTypes = false;
|
||||||
|
options.encodeFunctionFromStack = true;
|
||||||
|
options.padded = false;
|
||||||
|
options.dynamicInplace = true;
|
||||||
|
|
||||||
|
string functionName = string("abi_encode_tuple_packed_");
|
||||||
|
for (auto const& t: _givenTypes)
|
||||||
|
functionName += t->identifier() + "_";
|
||||||
|
functionName += "_to_";
|
||||||
|
for (auto const& t: _targetTypes)
|
||||||
|
functionName += t->identifier() + "_";
|
||||||
|
functionName += options.toFunctionNameSuffix();
|
||||||
|
|
||||||
|
return createExternallyUsedFunction(functionName, [&]() {
|
||||||
|
solAssert(!_givenTypes.empty(), "");
|
||||||
|
|
||||||
|
// Note that the values are in reverse due to the difference in calling semantics.
|
||||||
|
Whiskers templ(R"(
|
||||||
|
function <functionName>(pos <valueParams>) -> end {
|
||||||
|
<encodeElements>
|
||||||
|
end := pos
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
templ("functionName", functionName);
|
||||||
|
string valueParams;
|
||||||
|
string encodeElements;
|
||||||
|
size_t stackPos = 0;
|
||||||
|
for (size_t i = 0; i < _givenTypes.size(); ++i)
|
||||||
|
{
|
||||||
|
solAssert(_givenTypes[i], "");
|
||||||
|
solAssert(_targetTypes[i], "");
|
||||||
|
size_t sizeOnStack = _givenTypes[i]->sizeOnStack();
|
||||||
|
string valueNames = "";
|
||||||
|
for (size_t j = 0; j < sizeOnStack; j++)
|
||||||
|
{
|
||||||
|
valueNames += "value" + to_string(stackPos) + ", ";
|
||||||
|
valueParams = ", value" + to_string(stackPos) + valueParams;
|
||||||
|
stackPos++;
|
||||||
|
}
|
||||||
|
bool dynamic = _targetTypes[i]->isDynamicallyEncoded();
|
||||||
|
Whiskers elementTempl(
|
||||||
|
dynamic ?
|
||||||
|
string(R"(
|
||||||
|
pos := <abiEncode>(<values> pos)
|
||||||
|
)") :
|
||||||
|
string(R"(
|
||||||
|
<abiEncode>(<values> pos)
|
||||||
|
pos := add(pos, <calldataEncodedSize>)
|
||||||
|
)")
|
||||||
|
);
|
||||||
|
elementTempl("values", valueNames);
|
||||||
|
if (!dynamic)
|
||||||
|
elementTempl("calldataEncodedSize", to_string(_targetTypes[i]->calldataEncodedSize(false)));
|
||||||
|
elementTempl("abiEncode", abiEncodingFunction(*_givenTypes[i], *_targetTypes[i], options));
|
||||||
|
encodeElements += elementTempl.render();
|
||||||
|
}
|
||||||
|
templ("valueParams", valueParams);
|
||||||
|
templ("encodeElements", encodeElements);
|
||||||
|
|
||||||
|
return templ.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
string ABIFunctions::tupleDecoder(TypePointers const& _types, bool _fromMemory)
|
||||||
{
|
{
|
||||||
string functionName = string("abi_decode_tuple_");
|
string functionName = string("abi_decode_tuple_");
|
||||||
|
@ -60,16 +60,26 @@ public:
|
|||||||
/// The values represent stack slots. If a type occupies more or less than one
|
/// The values represent stack slots. If a type occupies more or less than one
|
||||||
/// stack slot, it takes exactly that number of values.
|
/// stack slot, it takes exactly that number of values.
|
||||||
/// Returns a pointer to the end of the area written in memory.
|
/// Returns a pointer to the end of the area written in memory.
|
||||||
/// Does not allocate memory (does not change the memory head pointer), but writes
|
/// Does not allocate memory (does not change the free memory pointer), but writes
|
||||||
/// to memory starting at $headStart and an unrestricted amount after that.
|
/// to memory starting at $headStart and an unrestricted amount after that.
|
||||||
/// Assigns the end of encoded memory either to $value0 or (if that is not present)
|
|
||||||
/// to $headStart.
|
|
||||||
std::string tupleEncoder(
|
std::string tupleEncoder(
|
||||||
TypePointers const& _givenTypes,
|
TypePointers const& _givenTypes,
|
||||||
TypePointers const& _targetTypes,
|
TypePointers const& _targetTypes,
|
||||||
bool _encodeAsLibraryTypes = false
|
bool _encodeAsLibraryTypes = false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// @returns name of an assembly function to encode values of @a _givenTypes
|
||||||
|
/// with packed encoding into memory, converting the types to @a _targetTypes on the fly.
|
||||||
|
/// Parameters are: <memPos> <value_n> ... <value_1>, i.e.
|
||||||
|
/// the layout on the stack is <value_1> ... <value_n> <memPos> with
|
||||||
|
/// the top of the stack on the right.
|
||||||
|
/// The values represent stack slots. If a type occupies more or less than one
|
||||||
|
/// stack slot, it takes exactly that number of values.
|
||||||
|
/// Returns a pointer to the end of the area written in memory.
|
||||||
|
/// Does not allocate memory (does not change the free memory pointer), but writes
|
||||||
|
/// to memory starting at memPos and an unrestricted amount after that.
|
||||||
|
std::string tupleEncoderPacked(TypePointers const& _givenTypes, TypePointers const& _targetTypes);
|
||||||
|
|
||||||
/// @returns name of an assembly function to ABI-decode values of @a _types
|
/// @returns name of an assembly function to ABI-decode values of @a _types
|
||||||
/// into memory. If @a _fromMemory is true, decodes from memory instead of
|
/// into memory. If @a _fromMemory is true, decodes from memory instead of
|
||||||
/// from calldata.
|
/// from calldata.
|
||||||
|
@ -348,11 +348,15 @@ void CompilerUtils::encodeToMemory(
|
|||||||
|
|
||||||
if (_givenTypes.empty())
|
if (_givenTypes.empty())
|
||||||
return;
|
return;
|
||||||
else if (_padToWordBoundaries && !_copyDynamicDataInPlace && encoderV2)
|
if (encoderV2)
|
||||||
{
|
{
|
||||||
// Use the new Yul-based encoding function
|
// Use the new Yul-based encoding function
|
||||||
|
solAssert(
|
||||||
|
_padToWordBoundaries != _copyDynamicDataInPlace,
|
||||||
|
"Non-padded and in-place encoding can only be combined."
|
||||||
|
);
|
||||||
auto stackHeightBefore = m_context.stackHeight();
|
auto stackHeightBefore = m_context.stackHeight();
|
||||||
abiEncodeV2(_givenTypes, targetTypes, _encodeAsLibraryTypes);
|
abiEncodeV2(_givenTypes, targetTypes, _encodeAsLibraryTypes, _padToWordBoundaries);
|
||||||
solAssert(stackHeightBefore - m_context.stackHeight() == sizeOnStack(_givenTypes), "");
|
solAssert(stackHeightBefore - m_context.stackHeight() == sizeOnStack(_givenTypes), "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -466,15 +470,22 @@ void CompilerUtils::encodeToMemory(
|
|||||||
void CompilerUtils::abiEncodeV2(
|
void CompilerUtils::abiEncodeV2(
|
||||||
TypePointers const& _givenTypes,
|
TypePointers const& _givenTypes,
|
||||||
TypePointers const& _targetTypes,
|
TypePointers const& _targetTypes,
|
||||||
bool _encodeAsLibraryTypes
|
bool _encodeAsLibraryTypes,
|
||||||
|
bool _padToWordBoundaries
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
if (!_padToWordBoundaries)
|
||||||
|
solAssert(!_encodeAsLibraryTypes, "Library calls cannot be packed.");
|
||||||
|
|
||||||
// stack: <$value0> <$value1> ... <$value(n-1)> <$headStart>
|
// stack: <$value0> <$value1> ... <$value(n-1)> <$headStart>
|
||||||
|
|
||||||
auto ret = m_context.pushNewTag();
|
auto ret = m_context.pushNewTag();
|
||||||
moveIntoStack(sizeOnStack(_givenTypes) + 1);
|
moveIntoStack(sizeOnStack(_givenTypes) + 1);
|
||||||
|
|
||||||
string encoderName = m_context.abiFunctions().tupleEncoder(_givenTypes, _targetTypes, _encodeAsLibraryTypes);
|
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.appendJumpTo(m_context.namedTag(encoderName));
|
||||||
m_context.adjustStackOffset(-int(sizeOnStack(_givenTypes)) - 1);
|
m_context.adjustStackOffset(-int(sizeOnStack(_givenTypes)) - 1);
|
||||||
m_context << ret.tag();
|
m_context << ret.tag();
|
||||||
|
@ -159,7 +159,8 @@ public:
|
|||||||
void abiEncodeV2(
|
void abiEncodeV2(
|
||||||
TypePointers const& _givenTypes,
|
TypePointers const& _givenTypes,
|
||||||
TypePointers const& _targetTypes,
|
TypePointers const& _targetTypes,
|
||||||
bool _encodeAsLibraryTypes = false
|
bool _encodeAsLibraryTypes = false,
|
||||||
|
bool _padToWordBoundaries = true
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Decodes data from ABI encoding into internal encoding. If @a _fromMemory is set to true,
|
/// Decodes data from ABI encoding into internal encoding. If @a _fromMemory is set to true,
|
||||||
|
Loading…
Reference in New Issue
Block a user