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 | const char *fromPtr{from.Element<const char>(fromAt)}; |
24 | RUNTIME_CHECK(terminator, to.ElementBytes() == from.ElementBytes()); |
25 | std::memcpy(dest: toPtr, src: fromPtr, n: to.ElementBytes()); |
26 | if (const auto *addendum{to.Addendum()}) { |
27 | if (const auto *derived{addendum->derivedType()}) { |
28 | RUNTIME_CHECK(terminator, |
29 | from.Addendum() && derived == from.Addendum()->derivedType()); |
30 | const Descriptor &componentDesc{derived->component()}; |
31 | const typeInfo::Component *component{ |
32 | componentDesc.OffsetElement<typeInfo::Component>()}; |
33 | std::size_t nComponents{componentDesc.Elements()}; |
34 | for (std::size_t j{0}; j < nComponents; ++j, ++component) { |
35 | if (component->genre() == typeInfo::Component::Genre::Allocatable || |
36 | component->genre() == typeInfo::Component::Genre::Automatic) { |
37 | Descriptor &toDesc{ |
38 | *reinterpret_cast<Descriptor *>(toPtr + component->offset())}; |
39 | if (toDesc.raw().base_addr != nullptr) { |
40 | toDesc.set_base_addr(nullptr); |
41 | RUNTIME_CHECK(terminator, toDesc.Allocate() == CFI_SUCCESS); |
42 | const Descriptor &fromDesc{*reinterpret_cast<const Descriptor *>( |
43 | fromPtr + component->offset())}; |
44 | CopyArray(toDesc, fromDesc, terminator); |
45 | } |
46 | } |
47 | } |
48 | } |
49 | } |
50 | } |
51 | |
52 | RT_API_ATTRS void CopyArray( |
53 | const Descriptor &to, const Descriptor &from, Terminator &terminator) { |
54 | std::size_t elements{to.Elements()}; |
55 | RUNTIME_CHECK(terminator, elements == from.Elements()); |
56 | SubscriptValue toAt[maxRank], fromAt[maxRank]; |
57 | to.GetLowerBounds(toAt); |
58 | from.GetLowerBounds(fromAt); |
59 | while (elements-- > 0) { |
60 | CopyElement(to, toAt, from, fromAt, terminator); |
61 | to.IncrementSubscripts(toAt); |
62 | from.IncrementSubscripts(fromAt); |
63 | } |
64 | } |
65 | |
66 | RT_OFFLOAD_API_GROUP_END |
67 | } // namespace Fortran::runtime |
68 | |