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