From 2c58d192a2a6e54080ac36e0626487747dc7be5c Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Tue, 30 Sep 2025 10:35:37 -0700 Subject: [flang][runtime] Expand IOTYPE and V_LIST (#160744) 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. --- flang-rt/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 de06524de32d..46134146f5c1 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 FormatControl::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 FormatControl::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(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 34e33edae546..79a7dd713b1a 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 1cb72d87d3df..3de2309954a4 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; // Common state for all kinds of formatted I/O -template class FormattedIoStatementState {}; -template <> class FormattedIoStatementState { +struct DefinedIoArgs { + char ioType[DataEdit::maxIoTypeChars]; // IOTYPE string + int vList[DataEdit::maxVListEntries]; // V_LIST(:) values +}; +template +class FormattedIoStatementState : public DefinedIoArgs {}; +template <> +class FormattedIoStatementState : 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 42ac4c051663..e599e624fe02 100644 --- a/flang-rt/lib/runtime/descriptor-io.cpp +++ b/flang-rt/lib/runtime/descriptor-io.cpp @@ -64,10 +64,11 @@ static RT_API_ATTRS common::optional DefinedFormattedIo( : *io.GetNextDataEdit(1)}; char ioType[2 + edit.maxIoTypeChars]; auto ioTypeLen{std::size_t{2} /*"DT"*/ + edit.ioTypeChars}; + auto &definedIoArgs{*io.get_if()}; 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"); @@ -81,7 +82,7 @@ static RT_API_ATTRS common::optional 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); @@ -91,7 +92,7 @@ static RT_API_ATTRS common::optional DefinedFormattedIo( static_cast(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(sizeof(int))); diff --git a/flang-rt/unittests/Runtime/Format.cpp b/flang-rt/unittests/Runtime/Format.cpp index fe7403f26700..cd52dc8c54ed 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; // 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} {} -- cgit v1.2.3