| 1964 | } |
| 1965 | |
| 1966 | std::string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, ArrayType const& _toType) |
| 1967 | { |
| 1968 | solAssert( |
| 1969 | (*_fromType.copyForLocation(_toType.location(), _toType.isPointer())).equals(dynamic_cast<ReferenceType const&>(_toType)), |
| 1970 | "" |
| 1971 | ); |
| 1972 | if (!_toType.isDynamicallySized()) |
| 1973 | solAssert(!_fromType.isDynamicallySized() && _fromType.length() <= _toType.length(), ""); |
| 1974 | |
| 1975 | if (_fromType.isByteArrayOrString()) |
| 1976 | return copyByteArrayToStorageFunction(_fromType, _toType); |
| 1977 | if (_toType.baseType()->isValueType()) |
| 1978 | return copyValueArrayToStorageFunction(_fromType, _toType); |
| 1979 | |
| 1980 | solAssert(_toType.storageStride() == 32); |
| 1981 | solAssert(!_fromType.baseType()->isValueType()); |
| 1982 | |
| 1983 | std::string functionName = "copy_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier(); |
| 1984 | return m_functionCollector.createFunction(functionName, [&](){ |
| 1985 | Whiskers templ(R"( |
| 1986 | function <functionName>(slot, value<?isFromDynamicCalldata>, len</isFromDynamicCalldata>) { |
| 1987 | <?fromStorage> if eq(slot, value) { leave } </fromStorage> |
| 1988 | let length := <arrayLength>(value<?isFromDynamicCalldata>, len</isFromDynamicCalldata>) |
| 1989 | |
| 1990 | <resizeArray>(slot, length) |
| 1991 | |
| 1992 | let srcPtr := <srcDataLocation>(value) |
| 1993 | |
| 1994 | let elementSlot := <dstDataLocation>(slot) |
| 1995 | |
| 1996 | for { let i := 0 } lt(i, length) {i := add(i, 1)} { |
| 1997 | <?fromCalldata> |
| 1998 | let <stackItems> := |
| 1999 | <?dynamicallyEncodedBase> |
| 2000 | <accessCalldataTail>(value, srcPtr) |
| 2001 | <!dynamicallyEncodedBase> |
| 2002 | srcPtr |
| 2003 | </dynamicallyEncodedBase> |
| 2004 | </fromCalldata> |
| 2005 | |
| 2006 | <?fromMemory> |
| 2007 | let <stackItems> := <readFromMemoryOrCalldata>(srcPtr) |
| 2008 | </fromMemory> |
| 2009 | |
| 2010 | <?fromStorage> |
| 2011 | let <stackItems> := srcPtr |
| 2012 | </fromStorage> |
| 2013 | |
| 2014 | <updateStorageValue>(elementSlot, <stackItems>) |
| 2015 | |
| 2016 | srcPtr := add(srcPtr, <srcStride>) |
| 2017 | |
| 2018 | elementSlot := add(elementSlot, <storageSize>) |
| 2019 | } |
| 2020 | } |
| 2021 | )"); |
| 2022 | if (_fromType.dataStoredIn(DataLocation::Storage)) |
| 2023 | solAssert(!_fromType.isValueType(), ""); |
no test coverage detected