peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 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" |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 10 | #include "terminator.h" |
| 11 | #include "type-info.h" |
Peter Klausler | 830c0b9 | 2021-09-01 23:00:53 | [diff] [blame] | 12 | #include "flang/Runtime/allocatable.h" |
| 13 | #include "flang/Runtime/descriptor.h" |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 14 | #include <cstring> |
| 15 | |
| 16 | namespace Fortran::runtime { |
Slava Zakharin | 76facde | 2023-12-28 21:50:43 | [diff] [blame] | 17 | RT_OFFLOAD_API_GROUP_BEGIN |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 18 | |
Slava Zakharin | 76facde | 2023-12-28 21:50:43 | [diff] [blame] | 19 | RT_API_ATTRS void CopyElement(const Descriptor &to, const SubscriptValue toAt[], |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 20 | const Descriptor &from, const SubscriptValue fromAt[], |
| 21 | Terminator &terminator) { |
| 22 | char *toPtr{to.Element<char>(toAt)}; |
jeanPerier | 0d0bd3e | 2024-02-15 08:05:33 | [diff] [blame] | 23 | char *fromPtr{from.Element<char>(fromAt)}; |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 24 | RUNTIME_CHECK(terminator, to.ElementBytes() == from.ElementBytes()); |
| 25 | std::memcpy(toPtr, fromPtr, to.ElementBytes()); |
jeanPerier | 0d0bd3e | 2024-02-15 08:05:33 | [diff] [blame] | 26 | // Deep copy allocatable and automatic components if any. |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 27 | if (const auto *addendum{to.Addendum()}) { |
jeanPerier | 0d0bd3e | 2024-02-15 08:05:33 | [diff] [blame] | 28 | if (const auto *derived{addendum->derivedType()}; |
| 29 | derived && !derived->noDestructionNeeded()) { |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 30 | RUNTIME_CHECK(terminator, |
| 31 | from.Addendum() && derived == from.Addendum()->derivedType()); |
peter klausler | 79caf69 | 2021-06-17 20:13:19 | [diff] [blame] | 32 | const Descriptor &componentDesc{derived->component()}; |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 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) { |
peter klausler | 79caf69 | 2021-06-17 20:13:19 | [diff] [blame] | 37 | if (component->genre() == typeInfo::Component::Genre::Allocatable || |
| 38 | component->genre() == typeInfo::Component::Genre::Automatic) { |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 39 | Descriptor &toDesc{ |
peter klausler | 79caf69 | 2021-06-17 20:13:19 | [diff] [blame] | 40 | *reinterpret_cast<Descriptor *>(toPtr + component->offset())}; |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 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 *>( |
peter klausler | 79caf69 | 2021-06-17 20:13:19 | [diff] [blame] | 45 | fromPtr + component->offset())}; |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 46 | CopyArray(toDesc, fromDesc, terminator); |
| 47 | } |
jeanPerier | 0d0bd3e | 2024-02-15 08:05:33 | [diff] [blame] | 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); |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 68 | } |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | } |
| 73 | |
Slava Zakharin | 76facde | 2023-12-28 21:50:43 | [diff] [blame] | 74 | RT_API_ATTRS void CopyArray( |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 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 | } |
Slava Zakharin | 76facde | 2023-12-28 21:50:43 | [diff] [blame] | 87 | |
| 88 | RT_OFFLOAD_API_GROUP_END |
peter klausler | c1db35f | 2021-05-20 17:37:03 | [diff] [blame] | 89 | } // namespace Fortran::runtime |