Skip to content

Commit

Permalink
[flang][runtime] Iterate over array elements in user-defined derived …
Browse files Browse the repository at this point in the history
…type I/O

It was only handling scalars; change to iterate over all array elements.

Differential Revision: https://reviews.llvm.org/D145752
  • Loading branch information
klausler committed Mar 10, 2023
1 parent 2cf632a commit f19c46d
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 15 deletions.
60 changes: 51 additions & 9 deletions flang/runtime/descriptor-io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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()};
Expand All @@ -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);
Expand Down
12 changes: 6 additions & 6 deletions flang/runtime/descriptor-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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>
Expand All @@ -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
Expand Down

0 comments on commit f19c46d

Please sign in to comment.