Extract storing length to its own function.

This commit is contained in:
chriseth 2019-02-06 12:26:54 +01:00
parent d3820aa833
commit 49f8fa4cfe
2 changed files with 36 additions and 13 deletions

View File

@ -621,12 +621,12 @@ string ABIFunctions::abiEncodingFunctionCalldataArray(
Whiskers templ(R"(
// <readableTypeNameFrom> -> <readableTypeNameTo>
function <functionName>(start, length, pos) -> end {
<storeLength> // might update pos
pos := <storeLength>(pos, length)
<copyFun>(start, pos, length)
end := add(pos, <roundUpFun>(length))
}
)");
templ("storeLength", _to.isDynamicallySized() ? "mstore(pos, length) pos := add(pos, 0x20)" : "");
templ("storeLength", arrayStoreLengthForEncodingFunction(toArrayType));
templ("functionName", functionName);
templ("readableTypeNameFrom", _from.toString(true));
templ("readableTypeNameTo", _to.toString(true));
@ -665,7 +665,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
// <readableTypeNameFrom> -> <readableTypeNameTo>
function <functionName>(value, pos) <return> {
let length := <lengthFun>(value)
<storeLength> // might update pos
pos := <storeLength>(pos, length)
let headStart := pos
let tail := add(pos, mul(length, 0x20))
let srcPtr := <dataAreaFun>(value)
@ -684,7 +684,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
// <readableTypeNameFrom> -> <readableTypeNameTo>
function <functionName>(value, pos) <return> {
let length := <lengthFun>(value)
<storeLength> // might update pos
pos := <storeLength>(pos, length)
let srcPtr := <dataAreaFun>(value)
for { let i := 0 } lt(i, length) { i := add(i, 1) }
{
@ -702,10 +702,7 @@ string ABIFunctions::abiEncodingFunctionSimpleArray(
templ("return", dynamic ? " -> end " : "");
templ("assignEnd", dynamic ? "end := pos" : "");
templ("lengthFun", arrayLengthFunction(_from));
if (_to.isDynamicallySized())
templ("storeLength", "mstore(pos, length) pos := add(pos, 0x20)");
else
templ("storeLength", "");
templ("storeLength", arrayStoreLengthForEncodingFunction(_to));
templ("dataAreaFun", arrayDataAreaFunction(_from));
templ("elementEncodedSize", toCompactHexWithPrefix(_to.baseType()->calldataEncodedSize()));
@ -828,7 +825,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
// <readableTypeNameFrom> -> <readableTypeNameTo>
function <functionName>(value, pos) <return> {
let length := <lengthFun>(value)
<storeLength> // might update pos
pos := <storeLength>(pos, length)
let originalPos := pos
let srcPtr := <dataArea>(value)
for { let i := 0 } lt(i, length) { i := add(i, <itemsPerSlot>) }
@ -851,10 +848,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
templ("return", dynamic ? " -> end " : "");
templ("assignEnd", dynamic ? "end := pos" : "");
templ("lengthFun", arrayLengthFunction(_from));
if (_to.isDynamicallySized())
templ("storeLength", "mstore(pos, length) pos := add(pos, 0x20)");
else
templ("storeLength", "");
templ("storeLength", arrayStoreLengthForEncodingFunction(_to));
templ("dataArea", arrayDataAreaFunction(_from));
templ("itemsPerSlot", to_string(itemsPerSlot));
string elementEncodedSize = toCompactHexWithPrefix(_to.baseType()->calldataEncodedSize());
@ -1686,6 +1680,30 @@ string ABIFunctions::nextArrayElementFunction(ArrayType const& _type)
});
}
string ABIFunctions::arrayStoreLengthForEncodingFunction(ArrayType const& _type)
{
string functionName = "array_storeLengthForEncoding_" + _type.identifier();
return createFunction(functionName, [&]() {
if (_type.isDynamicallySized())
return Whiskers(R"(
function <functionName>(pos, length) -> updated_pos {
mstore(pos, length)
updated_pos := add(pos, 0x20)
}
)")
("functionName", functionName)
.render();
else
return Whiskers(R"(
function <functionName>(pos, length) -> updated_pos {
updated_pos := pos
}
)")
("functionName", functionName)
.render();
});
}
string ABIFunctions::allocationFunction()
{
string functionName = "allocateMemory";

View File

@ -231,6 +231,11 @@ private:
/// Only works for memory arrays and storage arrays that store one item per slot.
std::string nextArrayElementFunction(ArrayType const& _type);
/// @returns the name of a function used during encoding that stores the length
/// if the array is dynamically sized. It returns the new encoding position.
/// If the array is not dynamically sized, does nothing and just returns the position again.
std::string arrayStoreLengthForEncodingFunction(ArrayType const& _type);
/// @returns the name of a function that allocates memory.
/// Modifies the "free memory pointer"
/// Arguments: size