[llvm] [flang][runtime] Expand IOTYPE and V_LIST (PR #160744)
Peter Klausler via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 25 10:55:40 PDT 2025
https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/160744
>From 840b84b86cd4ff448733eb57621c442837cd75ee Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Thu, 25 Sep 2025 10:33:39 -0700
Subject: [PATCH] [flang][runtime] Expand IOTYPE and V_LIST
The IOTYPE and V_LIST dummy arguments to a defined formatted I/O
subroutine are extracted from a DT edit descriptor in a FORMAT.
They are currently stored in the DataEdit structure, and their
maximum sizes are rather small since DataEdits are sometimes returned
or passed by value.
This patch moves their storage into the FormattedIoStatementState
structure and enlarges them a bit.
Fixes https://github.com/llvm/llvm-project/issues/154954.
---
.../include/flang-rt/runtime/format-implementation.h | 4 ++--
flang-rt/include/flang-rt/runtime/format.h | 3 +--
flang-rt/include/flang-rt/runtime/io-stmt.h | 10 ++++++++--
flang-rt/lib/runtime/descriptor-io.cpp | 7 ++++---
flang-rt/unittests/Runtime/Format.cpp | 2 +-
5 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/flang-rt/include/flang-rt/runtime/format-implementation.h b/flang-rt/include/flang-rt/runtime/format-implementation.h
index de06524de32d3..46134146f5c13 100644
--- a/flang-rt/include/flang-rt/runtime/format-implementation.h
+++ b/flang-rt/include/flang-rt/runtime/format-implementation.h
@@ -532,7 +532,7 @@ RT_API_ATTRS common::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit(
ReportBadFormat(context, "Excessive DT'iotype' in FORMAT", start);
return common::nullopt;
}
- edit.ioType[edit.ioTypeChars++] = ch;
+ context.ioType[edit.ioTypeChars++] = ch;
if (ch == quote) {
++offset_;
}
@@ -556,7 +556,7 @@ RT_API_ATTRS common::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit(
ReportBadFormat(context, "Excessive DT(v_list) in FORMAT", start);
return common::nullopt;
}
- edit.vList[edit.vListEntries++] = n;
+ context.vList[edit.vListEntries++] = n;
auto ch{static_cast<char>(GetNextChar(context))};
if (ch != ',') {
ok = ch == ')';
diff --git a/flang-rt/include/flang-rt/runtime/format.h b/flang-rt/include/flang-rt/runtime/format.h
index 34e33edae546d..79a7dd713b1a1 100644
--- a/flang-rt/include/flang-rt/runtime/format.h
+++ b/flang-rt/include/flang-rt/runtime/format.h
@@ -86,12 +86,11 @@ struct DataEdit {
// defined I/O data edit descriptor
RT_OFFLOAD_VAR_GROUP_BEGIN
static constexpr std::size_t maxIoTypeChars{32};
- static constexpr std::size_t maxVListEntries{4};
+ static constexpr std::size_t maxVListEntries{16};
RT_OFFLOAD_VAR_GROUP_END
std::uint8_t ioTypeChars{0};
std::uint8_t vListEntries{0};
char ioType[maxIoTypeChars];
- int vList[maxVListEntries];
};
// Generates a sequence of DataEdits from a FORMAT statement or
diff --git a/flang-rt/include/flang-rt/runtime/io-stmt.h b/flang-rt/include/flang-rt/runtime/io-stmt.h
index 1c4f06c0a7082..21f152e082a21 100644
--- a/flang-rt/include/flang-rt/runtime/io-stmt.h
+++ b/flang-rt/include/flang-rt/runtime/io-stmt.h
@@ -61,8 +61,14 @@ using IoDirectionState = std::conditional_t<D == Direction::Input,
InputStatementState, OutputStatementState>;
// Common state for all kinds of formatted I/O
-template <Direction D> class FormattedIoStatementState {};
-template <> class FormattedIoStatementState<Direction::Input> {
+struct DefinedIoArgs {
+ char ioType[DataEdit::maxIoTypeChars]; // IOTYPE string
+ int vList[DataEdit::maxVListEntries]; // V_LIST(:) values
+};
+template <Direction D>
+class FormattedIoStatementState : public DefinedIoArgs {};
+template <>
+class FormattedIoStatementState<Direction::Input> : public DefinedIoArgs {
public:
RT_API_ATTRS std::size_t GetEditDescriptorChars() const;
RT_API_ATTRS void GotChar(int);
diff --git a/flang-rt/lib/runtime/descriptor-io.cpp b/flang-rt/lib/runtime/descriptor-io.cpp
index e00072510aff7..4483906ecb508 100644
--- a/flang-rt/lib/runtime/descriptor-io.cpp
+++ b/flang-rt/lib/runtime/descriptor-io.cpp
@@ -62,10 +62,11 @@ static RT_API_ATTRS common::optional<bool> DefinedFormattedIo(
: *io.GetNextDataEdit(1)};
char ioType[2 + edit.maxIoTypeChars];
auto ioTypeLen{std::size_t{2} /*"DT"*/ + edit.ioTypeChars};
+ auto &definedIoArgs{*io.get_if<DefinedIoArgs>()};
if (edit.descriptor == DataEdit::DefinedDerivedType) {
ioType[0] = 'D';
ioType[1] = 'T';
- runtime::memcpy(ioType + 2, edit.ioType, edit.ioTypeChars);
+ runtime::memcpy(ioType + 2, definedIoArgs.ioType, edit.ioTypeChars);
} else {
runtime::strcpy(
ioType, io.mutableModes().inNamelist ? "NAMELIST" : "LISTDIRECTED");
@@ -79,7 +80,7 @@ static RT_API_ATTRS common::optional<bool> DefinedFormattedIo(
if (integer8) {
// Convert v_list values to INTEGER(8)
for (int j{0}; j < edit.vListEntries; ++j) {
- vList64[j] = edit.vList[j];
+ vList64[j] = definedIoArgs.vList[j];
}
vListDesc.Establish(
TypeCategory::Integer, sizeof(std::int64_t), nullptr, 1);
@@ -89,7 +90,7 @@ static RT_API_ATTRS common::optional<bool> DefinedFormattedIo(
static_cast<SubscriptValue>(sizeof(std::int64_t)));
} else {
vListDesc.Establish(TypeCategory::Integer, sizeof(int), nullptr, 1);
- vListDesc.set_base_addr(edit.vList);
+ vListDesc.set_base_addr(definedIoArgs.vList);
vListDesc.GetDimension(0).SetBounds(1, edit.vListEntries);
vListDesc.GetDimension(0).SetByteStride(
static_cast<SubscriptValue>(sizeof(int)));
diff --git a/flang-rt/unittests/Runtime/Format.cpp b/flang-rt/unittests/Runtime/Format.cpp
index fe7403f26700b..cd52dc8c54ed5 100644
--- a/flang-rt/unittests/Runtime/Format.cpp
+++ b/flang-rt/unittests/Runtime/Format.cpp
@@ -22,7 +22,7 @@ using namespace std::literals::string_literals;
using ResultsTy = std::vector<std::string>;
// A test harness context for testing FormatControl
-class TestFormatContext : public IoErrorHandler {
+class TestFormatContext : public IoErrorHandler, public DefinedIoArgs {
public:
using CharType = char;
TestFormatContext() : IoErrorHandler{"format.cpp", 1} {}
More information about the llvm-commits
mailing list