mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[Sol->Yul] Implementing array resizing for packed array types.
This commit is contained in:
parent
b34465c5ef
commit
aa23ebc8e6
@ -873,6 +873,12 @@ std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type)
|
||||
let arrayDataStart := <dataPosition>(array)
|
||||
let deleteStart := add(arrayDataStart, newSlotCount)
|
||||
let deleteEnd := add(arrayDataStart, oldSlotCount)
|
||||
<?packed>
|
||||
// if we are dealing with packed array and offset is greater than zero
|
||||
// we have to partially clear last slot that is still used, so decreasing start by one
|
||||
let offset := mul(mod(newLen, <itemsPerSlot>), <storageBytes>)
|
||||
if gt(offset, 0) { <partialClearStorageSlot>(sub(deleteStart, 1), offset) }
|
||||
</packed>
|
||||
<clearStorageRange>(deleteStart, deleteEnd)
|
||||
}
|
||||
})")
|
||||
@ -883,6 +889,10 @@ std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type)
|
||||
("dataPosition", arrayDataAreaFunction(_type))
|
||||
("clearStorageRange", clearStorageRangeFunction(*_type.baseType()))
|
||||
("maxArrayLength", (u256(1) << 64).str())
|
||||
("packed", _type.baseType()->storageBytes() <= 16)
|
||||
("itemsPerSlot", to_string(32 / _type.baseType()->storageBytes()))
|
||||
("storageBytes", to_string(_type.baseType()->storageBytes()))
|
||||
("partialClearStorageSlot", partialClearStorageSlotFunction())
|
||||
.render();
|
||||
});
|
||||
}
|
||||
@ -1060,11 +1070,29 @@ string YulUtilFunctions::storageArrayPushZeroFunction(ArrayType const& _type)
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::partialClearStorageSlotFunction()
|
||||
{
|
||||
string functionName = "partial_clear_storage_slot";
|
||||
return m_functionCollector.createFunction(functionName, [&]() {
|
||||
return Whiskers(R"(
|
||||
function <functionName>(slot, offset) {
|
||||
let mask := <shr>(mul(8, sub(32, offset)), <ones>)
|
||||
sstore(slot, and(mask, sload(slot)))
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("ones", formatNumber((bigint(1) << 256) - 1))
|
||||
("shr", shiftRightFunctionDynamic())
|
||||
.render();
|
||||
});
|
||||
}
|
||||
|
||||
string YulUtilFunctions::clearStorageRangeFunction(Type const& _type)
|
||||
{
|
||||
string functionName = "clear_storage_range_" + _type.identifier();
|
||||
if (_type.storageBytes() < 32)
|
||||
solAssert(_type.isValueType(), "");
|
||||
|
||||
solAssert(_type.storageBytes() >= 32, "Expected smaller value for storage bytes");
|
||||
string functionName = "clear_storage_range_" + _type.identifier();
|
||||
|
||||
return m_functionCollector.createFunction(functionName, [&]() {
|
||||
return Whiskers(R"(
|
||||
@ -1076,7 +1104,7 @@ string YulUtilFunctions::clearStorageRangeFunction(Type const& _type)
|
||||
}
|
||||
)")
|
||||
("functionName", functionName)
|
||||
("setToZero", storageSetToZeroFunction(_type))
|
||||
("setToZero", storageSetToZeroFunction(_type.storageBytes() < 32 ? *TypeProvider::uint256() : _type))
|
||||
("increment", _type.storageSize().str())
|
||||
.render();
|
||||
});
|
||||
|
@ -422,6 +422,11 @@ private:
|
||||
/// @returns a function that reads a reference type from storage to memory (performing a deep copy).
|
||||
std::string readFromStorageReferenceType(Type const& _type);
|
||||
|
||||
/// @returns the name of a function that will clear given storage slot
|
||||
/// starting with given offset until the end of the slot
|
||||
/// signature: (slot, offset)
|
||||
std::string partialClearStorageSlotFunction();
|
||||
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
RevertStrings m_revertStrings;
|
||||
MultiUseYulFunctionCollector& m_functionCollector;
|
||||
|
Loading…
Reference in New Issue
Block a user