File: copy.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (89 lines) | stat: -rw-r--r-- 3,947 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//===-- runtime/copy.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "copy.h"
#include "terminator.h"
#include "type-info.h"
#include "flang/Runtime/allocatable.h"
#include "flang/Runtime/descriptor.h"
#include <cstring>

namespace Fortran::runtime {
RT_OFFLOAD_API_GROUP_BEGIN

RT_API_ATTRS void CopyElement(const Descriptor &to, const SubscriptValue toAt[],
    const Descriptor &from, const SubscriptValue fromAt[],
    Terminator &terminator) {
  char *toPtr{to.Element<char>(toAt)};
  char *fromPtr{from.Element<char>(fromAt)};
  RUNTIME_CHECK(terminator, to.ElementBytes() == from.ElementBytes());
  std::memcpy(toPtr, fromPtr, to.ElementBytes());
  // Deep copy allocatable and automatic components if any.
  if (const auto *addendum{to.Addendum()}) {
    if (const auto *derived{addendum->derivedType()};
        derived && !derived->noDestructionNeeded()) {
      RUNTIME_CHECK(terminator,
          from.Addendum() && derived == from.Addendum()->derivedType());
      const Descriptor &componentDesc{derived->component()};
      const typeInfo::Component *component{
          componentDesc.OffsetElement<typeInfo::Component>()};
      std::size_t nComponents{componentDesc.Elements()};
      for (std::size_t j{0}; j < nComponents; ++j, ++component) {
        if (component->genre() == typeInfo::Component::Genre::Allocatable ||
            component->genre() == typeInfo::Component::Genre::Automatic) {
          Descriptor &toDesc{
              *reinterpret_cast<Descriptor *>(toPtr + component->offset())};
          if (toDesc.raw().base_addr != nullptr) {
            toDesc.set_base_addr(nullptr);
            RUNTIME_CHECK(terminator, toDesc.Allocate() == CFI_SUCCESS);
            const Descriptor &fromDesc{*reinterpret_cast<const Descriptor *>(
                fromPtr + component->offset())};
            CopyArray(toDesc, fromDesc, terminator);
          }
        } else if (component->genre() == typeInfo::Component::Genre::Data &&
            component->derivedType() &&
            !component->derivedType()->noDestructionNeeded()) {
          SubscriptValue extents[maxRank];
          const typeInfo::Value *bounds{component->bounds()};
          for (int dim{0}; dim < component->rank(); ++dim) {
            SubscriptValue lb{bounds[2 * dim].GetValue(&to).value_or(0)};
            SubscriptValue ub{bounds[2 * dim + 1].GetValue(&to).value_or(0)};
            extents[dim] = ub >= lb ? ub - lb + 1 : 0;
          }
          const typeInfo::DerivedType &compType{*component->derivedType()};
          StaticDescriptor<maxRank, true, 0> toStaticDescriptor;
          Descriptor &toCompDesc{toStaticDescriptor.descriptor()};
          toCompDesc.Establish(compType, toPtr + component->offset(),
              component->rank(), extents);
          StaticDescriptor<maxRank, true, 0> fromStaticDescriptor;
          Descriptor &fromCompDesc{fromStaticDescriptor.descriptor()};
          fromCompDesc.Establish(compType, fromPtr + component->offset(),
              component->rank(), extents);
          CopyArray(toCompDesc, fromCompDesc, terminator);
        }
      }
    }
  }
}

RT_API_ATTRS void CopyArray(
    const Descriptor &to, const Descriptor &from, Terminator &terminator) {
  std::size_t elements{to.Elements()};
  RUNTIME_CHECK(terminator, elements == from.Elements());
  SubscriptValue toAt[maxRank], fromAt[maxRank];
  to.GetLowerBounds(toAt);
  from.GetLowerBounds(fromAt);
  while (elements-- > 0) {
    CopyElement(to, toAt, from, fromAt, terminator);
    to.IncrementSubscripts(toAt);
    from.IncrementSubscripts(fromAt);
  }
}

RT_OFFLOAD_API_GROUP_END
} // namespace Fortran::runtime