Skip to content

Commit 170526b

Browse files
committed
wip
1 parent 763afc3 commit 170526b

File tree

4 files changed

+53
-26
lines changed

4 files changed

+53
-26
lines changed

Diff for: libsolidity/codegen/ArrayUtils.cpp

+18-12
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,9 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
290290
_context << Instruction::POP << Instruction::SWAP1 << Instruction::POP;
291291
// stack: target_ref target_data_end target_data_pos_updated
292292
if (targetBaseType->storageBytes() < 32)
293-
utils.clearStorageLoop(TypeProvider::uint256(), false); // TODO: check the boolean
293+
utils.clearStorageLoopAssumingNoOverflow(TypeProvider::uint256());
294294
else
295-
utils.clearStorageLoop(targetBaseType, false); // TODO: check the boolean
295+
utils.clearStorageLoopAssumingNoOverflow(targetBaseType);
296296
_context << Instruction::POP;
297297
}
298298
);
@@ -590,9 +590,10 @@ void ArrayUtils::clearArray(ArrayType const& _typeIn) const
590590
ArrayUtils(_context).convertLengthToSize(_type);
591591
_context << Instruction::ADD << Instruction::SWAP1;
592592
if (_type.baseType()->storageBytes() < 32)
593-
ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256(), !_type.isDynamicallySized()); // TODO: check boolean
593+
// wraps around cleaning for static arrays
594+
ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256(), !_type.isDynamicallySized());
594595
else
595-
ArrayUtils(_context).clearStorageLoop(_type.baseType(), !_type.isDynamicallySized()); // TODO: check boolean
596+
ArrayUtils(_context).clearStorageLoop(_type.baseType(), !_type.isDynamicallySized());
596597
_context << Instruction::POP;
597598
}
598599
solAssert(_context.stackHeight() == stackHeightStart - 2, "");
@@ -631,9 +632,9 @@ void ArrayUtils::clearDynamicArray(ArrayType const& _type) const
631632
<< Instruction::SWAP1;
632633
// stack: data_pos_end data_pos
633634
if (_type.storageStride() < 32)
634-
clearStorageLoop(TypeProvider::uint256(), false); // TODO: check boolean
635+
clearStorageLoopAssumingNoOverflow(TypeProvider::uint256());
635636
else
636-
clearStorageLoop(_type.baseType(), false); // TODO: check boolean
637+
clearStorageLoopAssumingNoOverflow(_type.baseType());
637638
// cleanup
638639
m_context << endTag;
639640
m_context << Instruction::POP;
@@ -738,7 +739,7 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
738739
ArrayUtils(_context).convertLengthToSize(_type);
739740
_context << Instruction::DUP2 << Instruction::ADD << Instruction::SWAP1;
740741
// stack: ref new_length current_length first_word data_location_end data_location
741-
ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256(), false);
742+
ArrayUtils(_context).clearStorageLoopAssumingNoOverflow(TypeProvider::uint256());
742743
_context << Instruction::POP;
743744
// stack: ref new_length current_length first_word
744745
solAssert(_context.stackHeight() - stackHeightStart == 4 - 2, "3");
@@ -777,9 +778,9 @@ void ArrayUtils::resizeDynamicArray(ArrayType const& _typeIn) const
777778
_context << Instruction::SWAP2 << Instruction::ADD;
778779
// stack: ref new_length delete_end delete_start
779780
if (_type.storageStride() < 32)
780-
ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256(), false);
781+
ArrayUtils(_context).clearStorageLoopAssumingNoOverflow(TypeProvider::uint256());
781782
else
782-
ArrayUtils(_context).clearStorageLoop(_type.baseType(), false);
783+
ArrayUtils(_context).clearStorageLoopAssumingNoOverflow(_type.baseType());
783784

784785
_context << resizeEnd;
785786
// cleanup
@@ -921,14 +922,19 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
921922
}
922923
}
923924

924-
void ArrayUtils::clearStorageLoop(Type const* _type, bool _assumeEndAfterStart) const
925+
void ArrayUtils::clearStorageLoopAssumingNoOverflow(Type const* _type) const
926+
{
927+
clearStorageLoop(_type, false);
928+
}
929+
930+
void ArrayUtils::clearStorageLoop(Type const* _type, bool _canOverflow) const
925931
{
926932
solAssert(_type->storageBytes() >= 32, "");
927933
m_context.callLowLevelFunction(
928934
"$clearStorageLoop_" + _type->identifier(),
929935
2,
930936
1,
931-
[_type, _assumeEndAfterStart](CompilerContext& _context)
937+
[_type, _canOverflow](CompilerContext& _context)
932938
{
933939
unsigned stackHeightStart = _context.stackHeight();
934940
if (_type->category() == Type::Category::Mapping)
@@ -944,7 +950,7 @@ void ArrayUtils::clearStorageLoop(Type const* _type, bool _assumeEndAfterStart)
944950
_context <<
945951
Instruction::DUP1 <<
946952
Instruction::DUP3;
947-
if (_assumeEndAfterStart)
953+
if (_canOverflow)
948954
_context << Instruction::EQ;
949955
else
950956
_context << Instruction::GT << Instruction::ISZERO;

Diff for: libsolidity/codegen/ArrayUtils.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,8 @@ class ArrayUtils
7676
/// Stack pre: reference
7777
/// Stack post:
7878
void popStorageArrayElement(ArrayType const& _type) const;
79-
/// Appends a loop that clears a sequence of storage slots of the given type (excluding end).
80-
/// Stack pre: end_ref start_ref
81-
/// Stack post: end_ref
82-
void clearStorageLoop(Type const* _type, bool _assumeEndAfterStart) const;
79+
/// Calls clearStorageLoop assuming no overflow occurs.
80+
void clearStorageLoopAssumingNoOverflow(Type const* _type) const;
8381
/// Converts length to size (number of storage slots or calldata/memory bytes).
8482
/// if @a _pad then add padding to multiples of 32 bytes for calldata/memory.
8583
/// Stack pre: length
@@ -108,6 +106,11 @@ class ArrayUtils
108106
void accessCallDataArrayElement(ArrayType const& _arrayType, bool _doBoundsCheck = true) const;
109107

110108
private:
109+
/// Appends a loop that clears a sequence of storage slots of the given type (excluding end).
110+
/// @param _canOverflow whether the storage is treated as circular when clearing.
111+
/// Stack pre: end_ref start_ref
112+
/// Stack post: end_ref
113+
void clearStorageLoop(Type const* _type, bool _canOverflow) const;
111114
/// Adds the given number of bytes to a storage byte offset counter and also increments
112115
/// the storage offset if adding this number again would increase the counter over 32.
113116
/// @param byteOffsetPosition the stack offset of the storage byte offset

Diff for: libsolidity/codegen/YulUtilFunctions.cpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,7 @@ std::string YulUtilFunctions::cleanUpStorageArrayEndFunction(ArrayType const& _t
14311431
)")
14321432
("convertToSize", arrayConvertLengthToSize(_type))
14331433
("dataPosition", arrayDataAreaFunction(_type))
1434-
("clearStorageRange", clearStorageRangeFunction(*_type.baseType(), false))
1434+
("clearStorageRange", clearStorageRangeFunctionAssumingNoOverflow(*_type.baseType()))
14351435
("packed", _type.baseType()->storageBytes() <= 16)
14361436
("itemsPerSlot", std::to_string(32 / _type.baseType()->storageBytes()))
14371437
("storageBytes", std::to_string(_type.baseType()->storageBytes()))
@@ -1483,7 +1483,7 @@ std::string YulUtilFunctions::cleanUpDynamicByteArrayEndSlotsFunction(ArrayType
14831483
)")
14841484
("dataLocation", arrayDataAreaFunction(_type))
14851485
("div32Ceil", divide32CeilFunction())
1486-
("clearStorageRange", clearStorageRangeFunction(*_type.baseType(), false))
1486+
("clearStorageRange", clearStorageRangeFunctionAssumingNoOverflow(*_type.baseType()))
14871487
.render();
14881488
});
14891489
}
@@ -1523,7 +1523,7 @@ std::string YulUtilFunctions::decreaseByteArraySizeFunction(ArrayType const& _ty
15231523
("functionName", functionName)
15241524
("dataPosition", arrayDataAreaFunction(_type))
15251525
("partialClearStorageSlot", partialClearStorageSlotFunction())
1526-
("clearStorageRange", clearStorageRangeFunction(*_type.baseType(), true))
1526+
("clearStorageRange", clearStorageRangeFunctionWrapping(*_type.baseType()))
15271527
("transitLongToShort", byteArrayTransitLongToShortFunction(_type))
15281528
("div32Ceil", divide32CeilFunction())
15291529
("encodeUsedSetLen", shortByteArrayEncodeUsedAreaSetLengthFunction())
@@ -1817,7 +1817,17 @@ std::string YulUtilFunctions::partialClearStorageSlotFunction()
18171817
});
18181818
}
18191819

1820-
std::string YulUtilFunctions::clearStorageRangeFunction(Type const& _type, bool _assumeEndAfterStart)
1820+
std::string YulUtilFunctions::clearStorageRangeFunctionAssumingNoOverflow(Type const& _type)
1821+
{
1822+
return clearStorageRangeFunction(_type, false);
1823+
}
1824+
1825+
std::string YulUtilFunctions::clearStorageRangeFunctionWrapping(Type const& _type)
1826+
{
1827+
return clearStorageRangeFunction(_type, true);
1828+
}
1829+
1830+
std::string YulUtilFunctions::clearStorageRangeFunction(Type const& _type, bool _canOverflow)
18211831
{
18221832
if (_type.storageBytes() < 32)
18231833
solAssert(_type.isValueType(), "");
@@ -1834,7 +1844,7 @@ std::string YulUtilFunctions::clearStorageRangeFunction(Type const& _type, bool
18341844
}
18351845
)")
18361846
("functionName", functionName)
1837-
("compare", _assumeEndAfterStart ? "sub" : "lt")
1847+
("compare", _canOverflow ? "sub" : "lt")
18381848
("setToZero", storageSetToZeroFunction(_type.storageBytes() < 32 ? *TypeProvider::uint256() : _type, VariableDeclaration::Location::Unspecified))
18391849
("increment", _type.storageSize().str())
18401850
.render();
@@ -1872,7 +1882,7 @@ std::string YulUtilFunctions::clearStorageArrayFunction(ArrayType const& _type)
18721882
(
18731883
"clearRange",
18741884
_type.baseType()->category() != Type::Category::Mapping ?
1875-
clearStorageRangeFunction((_type.baseType()->storageBytes() < 32) ? *TypeProvider::uint256() : *_type.baseType(), true) :
1885+
clearStorageRangeFunctionWrapping((_type.baseType()->storageBytes() < 32) ? *TypeProvider::uint256() : *_type.baseType()) :
18761886
""
18771887
)
18781888
("lenToSize", arrayConvertLengthToSize(_type))

Diff for: libsolidity/codegen/YulUtilFunctions.h

+12-4
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,13 @@ class YulUtilFunctions
265265
/// signature: (array) -> slot, offset
266266
std::string storageArrayPushZeroFunction(ArrayType const& _type);
267267

268-
/// @returns the name of a function that will clear the storage area given
269-
/// by the start and end (exclusive) parameters (slots).
270-
/// signature: (start, end)
271-
std::string clearStorageRangeFunction(Type const& _type, bool _assumeEndAfterStart);
268+
/// Calls clearStorageRangeFunction assuming no overflow occurs.
269+
/// i.e. it clears the range [start, end)
270+
std::string clearStorageRangeFunctionAssumingNoOverflow(Type const& _type);
271+
272+
/// Calls clearStorageRangeFunction assuming overflow may occur.
273+
/// i.e. it treats the storage as circular and clears by wrapping around.
274+
std::string clearStorageRangeFunctionWrapping(Type const& _type);
272275

273276
/// @returns the name of a function that will clear the given storage array
274277
/// signature: (slot) ->
@@ -564,6 +567,11 @@ class YulUtilFunctions
564567
std::string externalFunctionPointersEqualFunction();
565568

566569
private:
570+
/// @returns the name of a function that will clear the storage area given
571+
/// by the start and end (exclusive) parameters (slots).
572+
/// signature: (start, end)
573+
std::string clearStorageRangeFunction(Type const& _type, bool _canOverflow);
574+
567575
/// @returns the name of a function that copies a struct from calldata or memory to storage
568576
/// signature: (slot, value) ->
569577
std::string copyStructToStorageFunction(StructType const& _from, StructType const& _to);

0 commit comments

Comments
 (0)