[flang-commits] [flang] f19c46d - [flang][runtime] Iterate over array elements in user-defined derived type I/O
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Mar 10 10:25:58 PST 2023
Author: Peter Klausler
Date: 2023-03-10T10:25:53-08:00
New Revision: f19c46d431f797a1b6017b8ea6c9244e87663aa2
URL: https://github.com/llvm/llvm-project/commit/f19c46d431f797a1b6017b8ea6c9244e87663aa2
DIFF: https://github.com/llvm/llvm-project/commit/f19c46d431f797a1b6017b8ea6c9244e87663aa2.diff
LOG: [flang][runtime] Iterate over array elements in user-defined derived type I/O
It was only handling scalars; change to iterate over all array elements.
Differential Revision: https://reviews.llvm.org/D145752
Added:
Modified:
flang/runtime/descriptor-io.cpp
flang/runtime/descriptor-io.h
Removed:
################################################################################
diff --git a/flang/runtime/descriptor-io.cpp b/flang/runtime/descriptor-io.cpp
index 4a17a53b495a..c51a36b1a7bd 100644
--- a/flang/runtime/descriptor-io.cpp
+++ b/flang/runtime/descriptor-io.cpp
@@ -13,7 +13,8 @@ namespace Fortran::runtime::io::descr {
// User-defined derived type formatted I/O (maybe)
std::optional<bool> DefinedFormattedIo(IoStatementState &io,
- const Descriptor &descriptor, const typeInfo::SpecialBinding &special) {
+ const Descriptor &descriptor, const typeInfo::DerivedType &derived,
+ const typeInfo::SpecialBinding &special) {
std::optional<DataEdit> peek{io.GetNextDataEdit(0 /*to peek at it*/)};
if (peek &&
(peek->descriptor == DataEdit::DefinedDerivedType ||
@@ -33,8 +34,8 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
ioType, io.mutableModes().inNamelist ? "NAMELIST" : "LISTDIRECTED");
ioTypeLen = std::strlen(ioType);
}
- StaticDescriptor<1, true> statDesc;
- Descriptor &vListDesc{statDesc.descriptor()};
+ StaticDescriptor<1, true> vListStatDesc;
+ Descriptor &vListDesc{vListStatDesc.descriptor()};
vListDesc.Establish(TypeCategory::Integer, sizeof(int), nullptr, 1);
vListDesc.set_base_addr(edit.vList);
vListDesc.GetDimension(0).SetBounds(1, edit.vListEntries);
@@ -60,16 +61,36 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
// I/O subroutine reads counts towards READ(SIZE=).
startPos = io.InquirePos();
}
+ std::size_t numElements{descriptor.Elements()};
+ SubscriptValue subscripts[maxRank];
+ descriptor.GetLowerBounds(subscripts);
if (special.IsArgDescriptor(0)) {
+ // "dtv" argument is "class(t)", pass a descriptor
auto *p{special.GetProc<void (*)(const Descriptor &, int &, char *,
const Descriptor &, int &, char *, std::size_t, std::size_t)>()};
- p(descriptor, unit, ioType, vListDesc, ioStat, ioMsg, ioTypeLen,
- sizeof ioMsg);
+ StaticDescriptor<1, true, 10 /*?*/> elementStatDesc;
+ Descriptor &elementDesc{elementStatDesc.descriptor()};
+ elementDesc.Establish(
+ derived, nullptr, 0, nullptr, CFI_attribute_pointer);
+ for (; numElements-- > 0; descriptor.IncrementSubscripts(subscripts)) {
+ elementDesc.set_base_addr(descriptor.Element<char>(subscripts));
+ p(elementDesc, unit, ioType, vListDesc, ioStat, ioMsg, ioTypeLen,
+ sizeof ioMsg);
+ if (ioStat != IostatOk) {
+ break;
+ }
+ }
} else {
+ // "dtv" argument is "type(t)", pass a raw pointer
auto *p{special.GetProc<void (*)(const void *, int &, char *,
const Descriptor &, int &, char *, std::size_t, std::size_t)>()};
- p(descriptor.raw().base_addr, unit, ioType, vListDesc, ioStat, ioMsg,
- ioTypeLen, sizeof ioMsg);
+ for (; numElements-- > 0; descriptor.IncrementSubscripts(subscripts)) {
+ p(descriptor.Element<char>(subscripts), unit, ioType, vListDesc, ioStat,
+ ioMsg, ioTypeLen, sizeof ioMsg);
+ if (ioStat != IostatOk) {
+ break;
+ }
+ }
}
handler.Forward(ioStat, ioMsg, sizeof ioMsg);
external->PopChildIo(child);
@@ -93,6 +114,7 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io,
// User-defined derived type unformatted I/O
bool DefinedUnformattedIo(IoStatementState &io, const Descriptor &descriptor,
+ const typeInfo::DerivedType &derived,
const typeInfo::SpecialBinding &special) {
// Unformatted I/O must have an external unit (or child thereof).
IoErrorHandler &handler{io.GetIoErrorHandler()};
@@ -102,14 +124,34 @@ bool DefinedUnformattedIo(IoStatementState &io, const Descriptor &descriptor,
int unit{external->unitNumber()};
int ioStat{IostatOk};
char ioMsg[100];
+ std::size_t numElements{descriptor.Elements()};
+ SubscriptValue subscripts[maxRank];
+ descriptor.GetLowerBounds(subscripts);
if (special.IsArgDescriptor(0)) {
+ // "dtv" argument is "class(t)", pass a descriptor
auto *p{special.GetProc<void (*)(
const Descriptor &, int &, int &, char *, std::size_t)>()};
- p(descriptor, unit, ioStat, ioMsg, sizeof ioMsg);
+ StaticDescriptor<1, true, 10 /*?*/> elementStatDesc;
+ Descriptor &elementDesc{elementStatDesc.descriptor()};
+ elementDesc.Establish(derived, nullptr, 0, nullptr, CFI_attribute_pointer);
+ for (; numElements-- > 0; descriptor.IncrementSubscripts(subscripts)) {
+ elementDesc.set_base_addr(descriptor.Element<char>(subscripts));
+ p(elementDesc, unit, ioStat, ioMsg, sizeof ioMsg);
+ if (ioStat != IostatOk) {
+ break;
+ }
+ }
} else {
+ // "dtv" argument is "type(t)", pass a raw pointer
auto *p{special.GetProc<void (*)(
const void *, int &, int &, char *, std::size_t)>()};
- p(descriptor.raw().base_addr, unit, ioStat, ioMsg, sizeof ioMsg);
+ for (; numElements-- > 0; descriptor.IncrementSubscripts(subscripts)) {
+ p(descriptor.Element<char>(subscripts), unit, ioStat, ioMsg,
+ sizeof ioMsg);
+ if (ioStat != IostatOk) {
+ break;
+ }
+ }
}
handler.Forward(ioStat, ioMsg, sizeof ioMsg);
external->PopChildIo(child);
diff --git a/flang/runtime/descriptor-io.h b/flang/runtime/descriptor-io.h
index 8b2cf674f6b6..7bf55ded31d3 100644
--- a/flang/runtime/descriptor-io.h
+++ b/flang/runtime/descriptor-io.h
@@ -291,8 +291,8 @@ static bool DefaultComponentwiseIO(IoStatementState &io,
return true;
}
-std::optional<bool> DefinedFormattedIo(
- IoStatementState &, const Descriptor &, const typeInfo::SpecialBinding &);
+std::optional<bool> DefinedFormattedIo(IoStatementState &, const Descriptor &,
+ const typeInfo::DerivedType &, const typeInfo::SpecialBinding &);
template <Direction DIR>
static bool FormattedDerivedTypeIO(
@@ -308,15 +308,15 @@ static bool FormattedDerivedTypeIO(
? typeInfo::SpecialBinding::Which::ReadFormatted
: typeInfo::SpecialBinding::Which::WriteFormatted)}) {
if (std::optional<bool> wasDefined{
- DefinedFormattedIo(io, descriptor, *special)}) {
+ DefinedFormattedIo(io, descriptor, *type, *special)}) {
return *wasDefined; // user-defined I/O was applied
}
}
return DefaultComponentwiseIO<DIR>(io, descriptor, *type);
}
-bool DefinedUnformattedIo(
- IoStatementState &, const Descriptor &, const typeInfo::SpecialBinding &);
+bool DefinedUnformattedIo(IoStatementState &, const Descriptor &,
+ const typeInfo::DerivedType &, const typeInfo::SpecialBinding &);
// Unformatted I/O
template <Direction DIR>
@@ -332,7 +332,7 @@ static bool UnformattedDescriptorIO(
? typeInfo::SpecialBinding::Which::ReadUnformatted
: typeInfo::SpecialBinding::Which::WriteUnformatted)}) {
// User-defined derived type unformatted I/O
- return DefinedUnformattedIo(io, descriptor, *special);
+ return DefinedUnformattedIo(io, descriptor, *type, *special);
} else {
// Default derived type unformatted I/O
// TODO: If no component at any level has user defined READ or WRITE
More information about the flang-commits
mailing list