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 | RT_OFFLOAD_API_GROUP_BEGIN |
18 | |
19 | RT_API_ATTRS void CopyElement(const Descriptor &to, const SubscriptValue toAt[], |
20 | const Descriptor &from, const SubscriptValue fromAt[], |
21 | Terminator &terminator) { |
22 | char *toPtr{to.Element<char>(toAt)}; |
23 | char *fromPtr{from.Element<char>(fromAt)}; |
24 | RUNTIME_CHECK(terminator, to.ElementBytes() == from.ElementBytes()); |
25 | std::memcpy(dest: toPtr, src: fromPtr, n: to.ElementBytes()); |
26 | // Deep copy allocatable and automatic components if any. |
27 | if (const auto *addendum{to.Addendum()}) { |
28 | if (const auto *derived{addendum->derivedType()}; |
29 | derived && !derived->noDestructionNeeded()) { |
30 | RUNTIME_CHECK(terminator, |
31 | from.Addendum() && derived == from.Addendum()->derivedType()); |
32 | const Descriptor &componentDesc{derived->component()}; |
33 | const typeInfo::Component *component{ |
34 | componentDesc.OffsetElement<typeInfo::Component>()}; |
35 | std::size_t nComponents{componentDesc.Elements()}; |
36 | for (std::size_t j{0}; j < nComponents; ++j, ++component) { |
37 | if (component->genre() == typeInfo::Component::Genre::Allocatable || |
38 | component->genre() == typeInfo::Component::Genre::Automatic) { |
39 | Descriptor &toDesc{ |
40 | *reinterpret_cast<Descriptor *>(toPtr + component->offset())}; |
41 | if (toDesc.raw().base_addr != nullptr) { |
42 | toDesc.set_base_addr(nullptr); |
43 | RUNTIME_CHECK(terminator, toDesc.Allocate() == CFI_SUCCESS); |
44 | const Descriptor &fromDesc{*reinterpret_cast<const Descriptor *>( |
45 | fromPtr + component->offset())}; |
46 | CopyArray(toDesc, fromDesc, terminator); |
47 | } |
48 | } else if (component->genre() == typeInfo::Component::Genre::Data && |
49 | component->derivedType() && |
50 | !component->derivedType()->noDestructionNeeded()) { |
51 | SubscriptValue extents[maxRank]; |
52 | const typeInfo::Value *bounds{component->bounds()}; |
53 | for (int dim{0}; dim < component->rank(); ++dim) { |
54 | SubscriptValue lb{bounds[2 * dim].GetValue(&to).value_or(0)}; |
55 | SubscriptValue ub{bounds[2 * dim + 1].GetValue(&to).value_or(0)}; |
56 | extents[dim] = ub >= lb ? ub - lb + 1 : 0; |
57 | } |
58 | const typeInfo::DerivedType &compType{*component->derivedType()}; |
59 | StaticDescriptor<maxRank, true, 0> toStaticDescriptor; |
60 | Descriptor &toCompDesc{toStaticDescriptor.descriptor()}; |
61 | toCompDesc.Establish(compType, toPtr + component->offset(), |
62 | component->rank(), extents); |
63 | StaticDescriptor<maxRank, true, 0> fromStaticDescriptor; |
64 | Descriptor &fromCompDesc{fromStaticDescriptor.descriptor()}; |
65 | fromCompDesc.Establish(compType, fromPtr + component->offset(), |
66 | component->rank(), extents); |
67 | CopyArray(toCompDesc, fromCompDesc, terminator); |
68 | } |
69 | } |
70 | } |
71 | } |
72 | } |
73 | |
74 | RT_API_ATTRS void CopyArray( |
75 | const Descriptor &to, const Descriptor &from, Terminator &terminator) { |
76 | std::size_t elements{to.Elements()}; |
77 | RUNTIME_CHECK(terminator, elements == from.Elements()); |
78 | SubscriptValue toAt[maxRank], fromAt[maxRank]; |
79 | to.GetLowerBounds(toAt); |
80 | from.GetLowerBounds(fromAt); |
81 | while (elements-- > 0) { |
82 | CopyElement(to, toAt, from, fromAt, terminator); |
83 | to.IncrementSubscripts(toAt); |
84 | from.IncrementSubscripts(fromAt); |
85 | } |
86 | } |
87 | |
88 | RT_OFFLOAD_API_GROUP_END |
89 | } // namespace Fortran::runtime |
90 | |