Files
clang-p2996/flang/runtime/copy.cpp
peter klausler 79caf69cc0 [flang] Runtime implementation for default derived type formatted I/O
This is *not* user-defined derived type I/O, but rather Fortran's
built-in capabilities for using derived type data in I/O lists
and NAMELIST groups.

This feature depends on having the derived type description tables
that are created by Semantics available, passed through compilation
as initialized static objects to which pointers can be targeted
in the descriptors of I/O list items and NAMELIST groups.

NAMELIST processing now handles component references on input
(e.g., "&GROUP x%component = 123 /").

The C++ perspectives of the derived type information records
were transformed into proper classes when it was necessary to add
member functions to them.

The code in Semantics that generates derived type information
was changed to emit derived type components in component order,
not alphabetic order.

Differential Revision: https://reviews.llvm.org/D104485
2021-06-18 10:30:28 -07:00

65 lines
2.5 KiB
C++

//===-- 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 "allocatable.h"
#include "descriptor.h"
#include "terminator.h"
#include "type-info.h"
#include <cstring>
namespace Fortran::runtime {
void CopyElement(const Descriptor &to, const SubscriptValue toAt[],
const Descriptor &from, const SubscriptValue fromAt[],
Terminator &terminator) {
char *toPtr{to.Element<char>(toAt)};
const char *fromPtr{from.Element<const char>(fromAt)};
RUNTIME_CHECK(terminator, to.ElementBytes() == from.ElementBytes());
std::memcpy(toPtr, fromPtr, to.ElementBytes());
if (const auto *addendum{to.Addendum()}) {
if (const auto *derived{addendum->derivedType()}) {
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);
}
}
}
}
}
}
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);
}
}
} // namespace Fortran::runtime