summaryrefslogtreecommitdiff
path: root/flang-rt
diff options
context:
space:
mode:
authorPeter Klausler <pklausler@nvidia.com>2025-09-30 10:35:37 -0700
committerGitHub <noreply@github.com>2025-09-30 10:35:37 -0700
commit2c58d192a2a6e54080ac36e0626487747dc7be5c (patch)
tree6c0abc5f9cba983f61d6dd18bd36c97170e09811 /flang-rt
parent673e3051b0ededcf9e028a86faae6d2ba8b09daa (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.
Diffstat (limited to 'flang-rt')
-rw-r--r--flang-rt/include/flang-rt/runtime/format-implementation.h4
-rw-r--r--flang-rt/include/flang-rt/runtime/format.h3
-rw-r--r--flang-rt/include/flang-rt/runtime/io-stmt.h10
-rw-r--r--flang-rt/lib/runtime/descriptor-io.cpp7
-rw-r--r--flang-rt/unittests/Runtime/Format.cpp2
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} {}