mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #11348 from ethereum/div32ceil
Introduce ceil division helper function.
This commit is contained in:
commit
4c7b61d8f6
@ -541,6 +541,18 @@ string YulUtilFunctions::roundUpFunction()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string YulUtilFunctions::divide32CeilFunction()
|
||||||
|
{
|
||||||
|
return m_functionCollector.createFunction(
|
||||||
|
"divide_by_32_ceil",
|
||||||
|
[&](vector<string>& _args, vector<string>& _ret) {
|
||||||
|
_args = {"value"};
|
||||||
|
_ret = {"result"};
|
||||||
|
return "result := div(add(value, 31), 32)";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
string YulUtilFunctions::overflowCheckedIntAddFunction(IntegerType const& _type)
|
string YulUtilFunctions::overflowCheckedIntAddFunction(IntegerType const& _type)
|
||||||
{
|
{
|
||||||
string functionName = "checked_add_" + _type.identifier();
|
string functionName = "checked_add_" + _type.identifier();
|
||||||
@ -1257,14 +1269,14 @@ string YulUtilFunctions::cleanUpDynamicByteArrayEndSlotsFunction(ArrayType const
|
|||||||
return Whiskers(R"(
|
return Whiskers(R"(
|
||||||
if gt(len, 31) {
|
if gt(len, 31) {
|
||||||
let dataArea := <dataLocation>(array)
|
let dataArea := <dataLocation>(array)
|
||||||
let deleteStart := add(dataArea, div(<roundUp>(startIndex), 32))
|
let deleteStart := add(dataArea, <div32Ceil>(startIndex))
|
||||||
// If we are clearing array to be short byte array, we want to clear only data starting from array data area.
|
// If we are clearing array to be short byte array, we want to clear only data starting from array data area.
|
||||||
if lt(startIndex, 32) { deleteStart := dataArea }
|
if lt(startIndex, 32) { deleteStart := dataArea }
|
||||||
<clearStorageRange>(deleteStart, add(dataArea, div(add(len, 31), 32)))
|
<clearStorageRange>(deleteStart, add(dataArea, <div32Ceil>(len)))
|
||||||
}
|
}
|
||||||
)")
|
)")
|
||||||
("dataLocation", arrayDataAreaFunction(_type))
|
("dataLocation", arrayDataAreaFunction(_type))
|
||||||
("roundUp", roundUpFunction())
|
("div32Ceil", divide32CeilFunction())
|
||||||
("clearStorageRange", clearStorageRangeFunction(*_type.baseType()))
|
("clearStorageRange", clearStorageRangeFunction(*_type.baseType()))
|
||||||
.render();
|
.render();
|
||||||
});
|
});
|
||||||
@ -1279,13 +1291,13 @@ string YulUtilFunctions::decreaseByteArraySizeFunction(ArrayType const& _type)
|
|||||||
switch lt(newLen, 32)
|
switch lt(newLen, 32)
|
||||||
case 0 {
|
case 0 {
|
||||||
let arrayDataStart := <dataPosition>(array)
|
let arrayDataStart := <dataPosition>(array)
|
||||||
let deleteStart := add(arrayDataStart, div(add(newLen, 31), 32))
|
let deleteStart := add(arrayDataStart, <div32Ceil>(newLen))
|
||||||
|
|
||||||
// we have to partially clear last slot that is still used
|
// we have to partially clear last slot that is still used
|
||||||
let offset := and(newLen, 0x1f)
|
let offset := and(newLen, 0x1f)
|
||||||
if offset { <partialClearStorageSlot>(sub(deleteStart, 1), offset) }
|
if offset { <partialClearStorageSlot>(sub(deleteStart, 1), offset) }
|
||||||
|
|
||||||
<clearStorageRange>(deleteStart, add(arrayDataStart, div(add(oldLen, 31), 32)))
|
<clearStorageRange>(deleteStart, add(arrayDataStart, <div32Ceil>(oldLen)))
|
||||||
|
|
||||||
sstore(array, or(mul(2, newLen), 1))
|
sstore(array, or(mul(2, newLen), 1))
|
||||||
}
|
}
|
||||||
@ -1294,7 +1306,7 @@ string YulUtilFunctions::decreaseByteArraySizeFunction(ArrayType const& _type)
|
|||||||
case 1 {
|
case 1 {
|
||||||
let arrayDataStart := <dataPosition>(array)
|
let arrayDataStart := <dataPosition>(array)
|
||||||
// clear whole old array, as we are transforming to short bytes array
|
// clear whole old array, as we are transforming to short bytes array
|
||||||
<clearStorageRange>(add(arrayDataStart, 1), add(arrayDataStart, div(add(oldLen, 31), 32)))
|
<clearStorageRange>(add(arrayDataStart, 1), add(arrayDataStart, <div32Ceil>(oldLen)))
|
||||||
<transitLongToShort>(array, newLen)
|
<transitLongToShort>(array, newLen)
|
||||||
}
|
}
|
||||||
default {
|
default {
|
||||||
@ -1307,6 +1319,7 @@ string YulUtilFunctions::decreaseByteArraySizeFunction(ArrayType const& _type)
|
|||||||
("partialClearStorageSlot", partialClearStorageSlotFunction())
|
("partialClearStorageSlot", partialClearStorageSlotFunction())
|
||||||
("clearStorageRange", clearStorageRangeFunction(*_type.baseType()))
|
("clearStorageRange", clearStorageRangeFunction(*_type.baseType()))
|
||||||
("transitLongToShort", byteArrayTransitLongToShortFunction(_type))
|
("transitLongToShort", byteArrayTransitLongToShortFunction(_type))
|
||||||
|
("div32Ceil", divide32CeilFunction())
|
||||||
("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction())
|
("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction())
|
||||||
.render();
|
.render();
|
||||||
});
|
});
|
||||||
|
@ -126,9 +126,16 @@ public:
|
|||||||
|
|
||||||
/// @returns the name of a function that rounds its input to the next multiple
|
/// @returns the name of a function that rounds its input to the next multiple
|
||||||
/// of 32 or the input if it is a multiple of 32.
|
/// of 32 or the input if it is a multiple of 32.
|
||||||
|
/// Ignores overflow.
|
||||||
/// signature: (value) -> result
|
/// signature: (value) -> result
|
||||||
std::string roundUpFunction();
|
std::string roundUpFunction();
|
||||||
|
|
||||||
|
/// @returns the name of a function that divides by 32 and rounds up during the division.
|
||||||
|
/// In other words, on input x it returns the smallest y such that y * 32 >= x.
|
||||||
|
/// Ignores overflow.
|
||||||
|
/// signature: (x) -> y
|
||||||
|
std::string divide32CeilFunction();
|
||||||
|
|
||||||
/// signature: (x, y) -> sum
|
/// signature: (x, y) -> sum
|
||||||
std::string overflowCheckedIntAddFunction(IntegerType const& _type);
|
std::string overflowCheckedIntAddFunction(IntegerType const& _type);
|
||||||
/// signature: (x, y) -> sum
|
/// signature: (x, y) -> sum
|
||||||
|
Loading…
Reference in New Issue
Block a user