diff options
| author | Peter Klausler <pklausler@nvidia.com> | 2025-09-30 10:35:37 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-30 10:35:37 -0700 |
| commit | 2c58d192a2a6e54080ac36e0626487747dc7be5c (patch) | |
| tree | 6c0abc5f9cba983f61d6dd18bd36c97170e09811 | |
| parent | 673e3051b0ededcf9e028a86faae6d2ba8b09daa (diff) | |
[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.
| -rw-r--r-- | flang-rt/include/flang-rt/runtime/format-implementation.h | 4 | ||||
| -rw-r--r-- | flang-rt/include/flang-rt/runtime/format.h | 3 | ||||
| -rw-r--r-- | flang-rt/include/flang-rt/runtime/io-stmt.h | 10 | ||||
| -rw-r--r-- | flang-rt/lib/runtime/descriptor-io.cpp | 7 | ||||
| -rw-r--r-- | 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<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 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<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 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<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"); @@ -81,7 +82,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); @@ -91,7 +92,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 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<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} {} |
