@@ -96,12 +96,13 @@ static constexpr std::tuple<
96
96
mkIOKey (BeginUnformattedInput), mkIOKey(BeginUnformattedOutput),
97
97
mkIOKey (BeginWait), mkIOKey(BeginWaitAll),
98
98
mkIOKey (CheckUnitNumberInRange64), mkIOKey(CheckUnitNumberInRange128),
99
- mkIOKey (EnableHandlers), mkIOKey(EndIoStatement), mkIOKey(GetIoLength),
100
- mkIOKey (GetIoMsg), mkIOKey(GetNewUnit), mkIOKey(GetSize),
101
- mkIOKey (InputAscii), mkIOKey(InputComplex32), mkIOKey(InputComplex64),
102
- mkIOKey (InputDerivedType), mkIOKey(InputDescriptor), mkIOKey(InputInteger),
103
- mkIOKey (InputLogical), mkIOKey(InputNamelist), mkIOKey(InputReal32),
104
- mkIOKey (InputReal64), mkIOKey(InquireCharacter), mkIOKey(InquireInteger64),
99
+ mkIOKey (EnableHandlers), mkIOKey(EndIoStatement),
100
+ mkIOKey (GetAsynchronousId), mkIOKey(GetIoLength), mkIOKey(GetIoMsg),
101
+ mkIOKey (GetNewUnit), mkIOKey(GetSize), mkIOKey(InputAscii),
102
+ mkIOKey (InputComplex32), mkIOKey(InputComplex64), mkIOKey(InputDerivedType),
103
+ mkIOKey (InputDescriptor), mkIOKey(InputInteger), mkIOKey(InputLogical),
104
+ mkIOKey (InputNamelist), mkIOKey(InputReal32), mkIOKey(InputReal64),
105
+ mkIOKey (InquireCharacter), mkIOKey(InquireInteger64),
105
106
mkIOKey (InquireLogical), mkIOKey(InquirePendingId), mkIOKey(OutputAscii),
106
107
mkIOKey (OutputComplex32), mkIOKey(OutputComplex64),
107
108
mkIOKey (OutputDerivedType), mkIOKey(OutputDescriptor),
@@ -1313,13 +1314,6 @@ mlir::Value genIOOption<Fortran::parser::IoControlSpec::Asynchronous>(
1313
1314
spec.v );
1314
1315
}
1315
1316
1316
- template <>
1317
- mlir::Value genIOOption<Fortran::parser::IdVariable>(
1318
- Fortran::lower::AbstractConverter &converter, mlir::Location loc,
1319
- mlir::Value cookie, const Fortran::parser::IdVariable &spec) {
1320
- TODO (loc, " asynchronous ID not implemented" );
1321
- }
1322
-
1323
1317
template <>
1324
1318
mlir::Value genIOOption<Fortran::parser::IoControlSpec::Pos>(
1325
1319
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
@@ -1334,35 +1328,21 @@ mlir::Value genIOOption<Fortran::parser::IoControlSpec::Rec>(
1334
1328
return genIntIOOption<mkIOKey (SetRec)>(converter, loc, cookie, spec);
1335
1329
}
1336
1330
1337
- // / Generate runtime call to query the read size after an input statement if
1338
- // / the statement has SIZE control-spec.
1339
- template <typename A>
1340
- static void genIOReadSize (Fortran::lower::AbstractConverter &converter,
1341
- mlir::Location loc, mlir::Value cookie,
1342
- const A &specList, bool checkResult) {
1343
- // This call is not conditional on the current IO status (ok) because the size
1344
- // needs to be filled even if some error condition (end-of-file...) was met
1345
- // during the input statement (in which case the runtime may return zero for
1346
- // the size read).
1347
- for (const auto &spec : specList)
1348
- if (const auto *size =
1349
- std::get_if<Fortran::parser::IoControlSpec::Size>(&spec.u )) {
1350
-
1351
- fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
1352
- mlir::func::FuncOp ioFunc =
1353
- getIORuntimeFunc<mkIOKey (GetSize)>(loc, builder);
1354
- auto sizeValue =
1355
- builder.create <fir::CallOp>(loc, ioFunc, mlir::ValueRange{cookie})
1356
- .getResult (0 );
1357
- Fortran::lower::StatementContext localStatementCtx;
1358
- fir::ExtendedValue var = converter.genExprAddr (
1359
- loc, Fortran::semantics::GetExpr (size->v ), localStatementCtx);
1360
- mlir::Value varAddr = fir::getBase (var);
1361
- mlir::Type varType = fir::unwrapPassByRefType (varAddr.getType ());
1362
- mlir::Value sizeCast = builder.createConvert (loc, varType, sizeValue);
1363
- builder.create <fir::StoreOp>(loc, sizeCast, varAddr);
1364
- break ;
1365
- }
1331
+ // / Generate runtime call to set some control variable.
1332
+ // / Generates "VAR = IoRuntimeKey(cookie)".
1333
+ template <typename IoRuntimeKey, typename VAR>
1334
+ static void genIOGetVar (Fortran::lower::AbstractConverter &converter,
1335
+ mlir::Location loc, mlir::Value cookie,
1336
+ const VAR &parserVar) {
1337
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
1338
+ mlir::func::FuncOp ioFunc = getIORuntimeFunc<IoRuntimeKey>(loc, builder);
1339
+ mlir::Value value =
1340
+ builder.create <fir::CallOp>(loc, ioFunc, mlir::ValueRange{cookie})
1341
+ .getResult (0 );
1342
+ Fortran::lower::StatementContext localStatementCtx;
1343
+ fir::ExtendedValue var = converter.genExprAddr (
1344
+ loc, Fortran::semantics::GetExpr (parserVar.v ), localStatementCtx);
1345
+ builder.createStoreWithConvert (loc, value, fir::getBase (var));
1366
1346
}
1367
1347
1368
1348
// ===----------------------------------------------------------------------===//
@@ -1412,6 +1392,12 @@ static void threadSpecs(Fortran::lower::AbstractConverter &converter,
1412
1392
// there is an error.
1413
1393
return ok;
1414
1394
},
1395
+ [&](const Fortran::parser::IdVariable &) -> mlir::Value {
1396
+ // ID is queried after the transfer so that ASYNCHROUNOUS= has
1397
+ // been processed and also to set it to zero if the transfer is
1398
+ // already finished.
1399
+ return ok;
1400
+ },
1415
1401
[&](const auto &x) {
1416
1402
return genIOOption (converter, loc, cookie, x);
1417
1403
}},
@@ -1602,21 +1588,6 @@ maybeGetInternalIODescriptor<Fortran::parser::PrintStmt>(
1602
1588
return std::nullopt;
1603
1589
}
1604
1590
1605
- template <typename A>
1606
- static bool isDataTransferAsynchronous (mlir::Location loc, const A &stmt) {
1607
- if (auto *asynch =
1608
- getIOControl<Fortran::parser::IoControlSpec::Asynchronous>(stmt)) {
1609
- // FIXME: should contain a string of YES or NO
1610
- TODO (loc, " asynchronous transfers not implemented in runtime" );
1611
- }
1612
- return false ;
1613
- }
1614
- template <>
1615
- bool isDataTransferAsynchronous<Fortran::parser::PrintStmt>(
1616
- mlir::Location, const Fortran::parser::PrintStmt &) {
1617
- return false ;
1618
- }
1619
-
1620
1591
template <typename A>
1621
1592
static bool isDataTransferNamelist (const A &stmt) {
1622
1593
if (stmt.format )
@@ -2043,7 +2014,7 @@ template <bool isInput>
2043
2014
mlir::func::FuncOp
2044
2015
getBeginDataTransferFunc (mlir::Location loc, fir::FirOpBuilder &builder,
2045
2016
bool isFormatted, bool isListOrNml, bool isInternal,
2046
- bool isInternalWithDesc, bool isAsync ) {
2017
+ bool isInternalWithDesc) {
2047
2018
if constexpr (isInput) {
2048
2019
if (isFormatted || isListOrNml) {
2049
2020
if (isInternal) {
@@ -2098,7 +2069,6 @@ void genBeginDataTransferCallArgs(
2098
2069
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
2099
2070
const A &stmt, mlir::FunctionType ioFuncTy, bool isFormatted,
2100
2071
bool isListOrNml, [[maybe_unused]] bool isInternal,
2101
- [[maybe_unused]] bool isAsync,
2102
2072
const std::optional<fir::ExtendedValue> &descRef, ConditionSpecInfo &csi,
2103
2073
Fortran::lower::StatementContext &stmtCtx) {
2104
2074
fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
@@ -2146,8 +2116,6 @@ void genBeginDataTransferCallArgs(
2146
2116
ioArgs.push_back ( // buffer length
2147
2117
getDefaultScratchLen (builder, loc, ioFuncTy.getInput (ioArgs.size ())));
2148
2118
} else { // external IO - maybe explicit format; unit
2149
- if (isAsync)
2150
- TODO (loc, " asynchronous" );
2151
2119
maybeGetFormatArgs ();
2152
2120
ioArgs.push_back (getIOUnit (converter, loc, stmt,
2153
2121
ioFuncTy.getInput (ioArgs.size ()), csi, stmtCtx,
@@ -2180,8 +2148,12 @@ genDataTransferStmt(Fortran::lower::AbstractConverter &converter,
2180
2148
isInternal ? maybeGetInternalIODescriptor (converter, loc, stmt, stmtCtx)
2181
2149
: std::nullopt;
2182
2150
const bool isInternalWithDesc = descRef.has_value ();
2183
- const bool isAsync = isDataTransferAsynchronous (loc, stmt);
2184
2151
const bool isNml = isDataTransferNamelist (stmt);
2152
+ // Flang runtime currently implement asynchronous IO synchronously, so
2153
+ // asynchronous IO statements are lowered as regular IO statements
2154
+ // (except that GetAsynchronousId may be called to set the ID variable
2155
+ // and SetAsynchronous will be call to tell the runtime that this is supposed
2156
+ // to be (or not) an asynchronous IO statements).
2185
2157
2186
2158
// Generate an EnableHandlers call and remaining specifier calls.
2187
2159
ConditionSpecInfo csi;
@@ -2192,13 +2164,13 @@ genDataTransferStmt(Fortran::lower::AbstractConverter &converter,
2192
2164
// Generate the begin data transfer function call.
2193
2165
mlir::func::FuncOp ioFunc = getBeginDataTransferFunc<isInput>(
2194
2166
loc, builder, isFormatted, isList || isNml, isInternal,
2195
- isInternalWithDesc, isAsync );
2167
+ isInternalWithDesc);
2196
2168
llvm::SmallVector<mlir::Value> ioArgs;
2197
2169
genBeginDataTransferCallArgs<
2198
2170
hasIOCtrl, isInput ? Fortran::runtime::io::DefaultInputUnit
2199
2171
: Fortran::runtime::io::DefaultOutputUnit>(
2200
2172
ioArgs, converter, loc, stmt, ioFunc.getFunctionType (), isFormatted,
2201
- isList || isNml, isInternal, isAsync, descRef, csi, stmtCtx);
2173
+ isList || isNml, isInternal, descRef, csi, stmtCtx);
2202
2174
mlir::Value cookie =
2203
2175
builder.create <fir::CallOp>(loc, ioFunc, ioArgs).getResult (0 );
2204
2176
@@ -2238,8 +2210,18 @@ genDataTransferStmt(Fortran::lower::AbstractConverter &converter,
2238
2210
2239
2211
builder.restoreInsertionPoint (insertPt);
2240
2212
if constexpr (hasIOCtrl) {
2241
- genIOReadSize (converter, loc, cookie, stmt.controls ,
2242
- csi.hasErrorConditionSpec ());
2213
+ for (const auto &spec : stmt.controls )
2214
+ if (const auto *size =
2215
+ std::get_if<Fortran::parser::IoControlSpec::Size>(&spec.u )) {
2216
+ // This call is not conditional on the current IO status (ok) because
2217
+ // the size needs to be filled even if some error condition
2218
+ // (end-of-file...) was met during the input statement (in which case
2219
+ // the runtime may return zero for the size read).
2220
+ genIOGetVar<mkIOKey (GetSize)>(converter, loc, cookie, *size);
2221
+ } else if (const auto *idVar =
2222
+ std::get_if<Fortran::parser::IdVariable>(&spec.u )) {
2223
+ genIOGetVar<mkIOKey (GetAsynchronousId)>(converter, loc, cookie, *idVar);
2224
+ }
2243
2225
}
2244
2226
// Generate end statement call/s.
2245
2227
mlir::Value result = genEndIO (converter, loc, cookie, csi, stmtCtx);
0 commit comments