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