mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9905 from ethereum/deleteArrayPackedSol2Yul
[Sol->Yul] Implementing deleting of storage array of types that are packed in storage
This commit is contained in:
commit
e5771efdf8
@ -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;
|
||||
|
@ -0,0 +1,18 @@
|
||||
contract C {
|
||||
uint120[] data;
|
||||
|
||||
function f() public returns (uint120, uint120, uint120) {
|
||||
data.push(123);
|
||||
data.push(234);
|
||||
data.push(345);
|
||||
delete data;
|
||||
assembly {
|
||||
sstore(data.slot, 3)
|
||||
}
|
||||
return (data[0], data[1], data[2]);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// f() -> 0, 0, 0
|
Loading…
Reference in New Issue
Block a user