1*c1db35f0Speter klausler //===-- runtime/copy.cpp -------------------------------------------------===// 2*c1db35f0Speter klausler // 3*c1db35f0Speter klausler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*c1db35f0Speter klausler // See https://llvm.org/LICENSE.txt for license information. 5*c1db35f0Speter klausler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*c1db35f0Speter klausler // 7*c1db35f0Speter klausler //===----------------------------------------------------------------------===// 8*c1db35f0Speter klausler 9*c1db35f0Speter klausler #include "copy.h" 10*c1db35f0Speter klausler #include "allocatable.h" 11*c1db35f0Speter klausler #include "descriptor.h" 12*c1db35f0Speter klausler #include "terminator.h" 13*c1db35f0Speter klausler #include "type-info.h" 14*c1db35f0Speter klausler #include <cstring> 15*c1db35f0Speter klausler 16*c1db35f0Speter klausler namespace Fortran::runtime { 17*c1db35f0Speter klausler 18*c1db35f0Speter klausler void CopyElement(const Descriptor &to, const SubscriptValue toAt[], 19*c1db35f0Speter klausler const Descriptor &from, const SubscriptValue fromAt[], 20*c1db35f0Speter klausler Terminator &terminator) { 21*c1db35f0Speter klausler char *toPtr{to.Element<char>(toAt)}; 22*c1db35f0Speter klausler const char *fromPtr{from.Element<const char>(fromAt)}; 23*c1db35f0Speter klausler RUNTIME_CHECK(terminator, to.ElementBytes() == from.ElementBytes()); 24*c1db35f0Speter klausler std::memcpy(toPtr, fromPtr, to.ElementBytes()); 25*c1db35f0Speter klausler if (const auto *addendum{to.Addendum()}) { 26*c1db35f0Speter klausler if (const auto *derived{addendum->derivedType()}) { 27*c1db35f0Speter klausler RUNTIME_CHECK(terminator, 28*c1db35f0Speter klausler from.Addendum() && derived == from.Addendum()->derivedType()); 29*c1db35f0Speter klausler const Descriptor &componentDesc{derived->component.descriptor()}; 30*c1db35f0Speter klausler const typeInfo::Component *component{ 31*c1db35f0Speter klausler componentDesc.OffsetElement<typeInfo::Component>()}; 32*c1db35f0Speter klausler std::size_t nComponents{componentDesc.Elements()}; 33*c1db35f0Speter klausler for (std::size_t j{0}; j < nComponents; ++j, ++component) { 34*c1db35f0Speter klausler if (component->genre == typeInfo::Component::Genre::Allocatable || 35*c1db35f0Speter klausler component->genre == typeInfo::Component::Genre::Automatic) { 36*c1db35f0Speter klausler Descriptor &toDesc{ 37*c1db35f0Speter klausler *reinterpret_cast<Descriptor *>(toPtr + component->offset)}; 38*c1db35f0Speter klausler if (toDesc.raw().base_addr != nullptr) { 39*c1db35f0Speter klausler toDesc.set_base_addr(nullptr); 40*c1db35f0Speter klausler RUNTIME_CHECK(terminator, toDesc.Allocate() == CFI_SUCCESS); 41*c1db35f0Speter klausler const Descriptor &fromDesc{*reinterpret_cast<const Descriptor *>( 42*c1db35f0Speter klausler fromPtr + component->offset)}; 43*c1db35f0Speter klausler CopyArray(toDesc, fromDesc, terminator); 44*c1db35f0Speter klausler } 45*c1db35f0Speter klausler } 46*c1db35f0Speter klausler } 47*c1db35f0Speter klausler } 48*c1db35f0Speter klausler } 49*c1db35f0Speter klausler } 50*c1db35f0Speter klausler 51*c1db35f0Speter klausler void CopyArray( 52*c1db35f0Speter klausler const Descriptor &to, const Descriptor &from, Terminator &terminator) { 53*c1db35f0Speter klausler std::size_t elements{to.Elements()}; 54*c1db35f0Speter klausler RUNTIME_CHECK(terminator, elements == from.Elements()); 55*c1db35f0Speter klausler SubscriptValue toAt[maxRank], fromAt[maxRank]; 56*c1db35f0Speter klausler to.GetLowerBounds(toAt); 57*c1db35f0Speter klausler from.GetLowerBounds(fromAt); 58*c1db35f0Speter klausler while (elements-- > 0) { 59*c1db35f0Speter klausler CopyElement(to, toAt, from, fromAt, terminator); 60*c1db35f0Speter klausler to.IncrementSubscripts(toAt); 61*c1db35f0Speter klausler from.IncrementSubscripts(fromAt); 62*c1db35f0Speter klausler } 63*c1db35f0Speter klausler } 64*c1db35f0Speter klausler } // namespace Fortran::runtime 65