| 3760 | } |
| 3761 | |
| 3762 | std::string YulUtilFunctions::copyStructToStorageFunction(StructType const& _from, StructType const& _to) |
| 3763 | { |
| 3764 | solAssert(_to.dataStoredIn(DataLocation::Storage), ""); |
| 3765 | solAssert(_from.structDefinition() == _to.structDefinition(), ""); |
| 3766 | |
| 3767 | std::string functionName = |
| 3768 | "copy_struct_to_storage_from_" + |
| 3769 | _from.identifier() + |
| 3770 | "_to_" + |
| 3771 | _to.identifier(); |
| 3772 | |
| 3773 | return m_functionCollector.createFunction(functionName, [&](auto& _arguments, auto&) { |
| 3774 | _arguments = {"slot", "value"}; |
| 3775 | Whiskers templ(R"( |
| 3776 | <?fromStorage> if iszero(eq(slot, value)) { </fromStorage> |
| 3777 | <#member> |
| 3778 | { |
| 3779 | <updateMemberCall> |
| 3780 | } |
| 3781 | </member> |
| 3782 | <?fromStorage> } </fromStorage> |
| 3783 | )"); |
| 3784 | templ("fromStorage", _from.dataStoredIn(DataLocation::Storage)); |
| 3785 | |
| 3786 | MemberList::MemberMap structMembers = _from.nativeMembers(nullptr); |
| 3787 | MemberList::MemberMap toStructMembers = _to.nativeMembers(nullptr); |
| 3788 | |
| 3789 | std::vector<std::map<std::string, std::string>> memberParams(structMembers.size()); |
| 3790 | for (size_t i = 0; i < structMembers.size(); ++i) |
| 3791 | { |
| 3792 | Type const& memberType = *structMembers[i].type; |
| 3793 | solAssert(memberType.memoryHeadSize() == 32, ""); |
| 3794 | auto const&[slotDiff, offset] = _to.storageOffsetsOfMember(structMembers[i].name); |
| 3795 | |
| 3796 | Whiskers t(R"( |
| 3797 | let memberSlot := add(slot, <memberStorageSlotDiff>) |
| 3798 | let memberSrcPtr := add(value, <memberOffset>) |
| 3799 | |
| 3800 | <?fromCalldata> |
| 3801 | let <memberValues> := |
| 3802 | <?dynamicallyEncodedMember> |
| 3803 | <accessCalldataTail>(value, memberSrcPtr) |
| 3804 | <!dynamicallyEncodedMember> |
| 3805 | memberSrcPtr |
| 3806 | </dynamicallyEncodedMember> |
| 3807 | |
| 3808 | <?isValueType> |
| 3809 | <memberValues> := <read>(<memberValues>) |
| 3810 | </isValueType> |
| 3811 | </fromCalldata> |
| 3812 | |
| 3813 | <?fromMemory> |
| 3814 | let <memberValues> := <read>(memberSrcPtr) |
| 3815 | </fromMemory> |
| 3816 | |
| 3817 | <?fromStorage> |
| 3818 | let <memberValues> := |
| 3819 | <?isValueType> |
nothing calls this directly
no test coverage detected