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