[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.
This commit is contained in:
Peter Klausler 2025-09-30 10:35:37 -07:00 committed by GitHub
parent 673e3051b0
commit 2c58d192a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 16 additions and 10 deletions

View File

@ -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 == ')';

View File

@ -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

View File

@ -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);

View File

@ -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)));

View File

@ -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} {}