Skip to content

Commit 896b5e5

Browse files
authored
[flang][cuda] Allow list-directed PRINT and WRITE stmt in device code (#87415)
The specification allow list-directed PRINT and WRITE statements to appear in device code. This patch relax the semantic check to allow them. 3.6.11. List-directed PRINT and WRITE statements to the default unit may be used when compiling for compute capability 2.0 and higher; all other uses of PRINT and WRITE are disallowed.
1 parent 54c24ec commit 896b5e5

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

flang/lib/Semantics/check-cuda.cpp

+64
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,73 @@ template <bool IsCUFKernelDo> class DeviceContextChecker {
277277
},
278278
ec.u);
279279
}
280+
template <typename SEEK, typename A>
281+
static const SEEK *GetIOControl(const A &stmt) {
282+
for (const auto &spec : stmt.controls) {
283+
if (const auto *result{std::get_if<SEEK>(&spec.u)}) {
284+
return result;
285+
}
286+
}
287+
return nullptr;
288+
}
289+
template <typename A> static bool IsInternalIO(const A &stmt) {
290+
if (stmt.iounit.has_value()) {
291+
return std::holds_alternative<Fortran::parser::Variable>(stmt.iounit->u);
292+
}
293+
if (auto *unit{GetIOControl<Fortran::parser::IoUnit>(stmt)}) {
294+
return std::holds_alternative<Fortran::parser::Variable>(unit->u);
295+
}
296+
return false;
297+
}
298+
void WarnOnIoStmt(const parser::CharBlock &source) {
299+
context_.Say(
300+
source, "I/O statement might not be supported on device"_warn_en_US);
301+
}
302+
template <typename A>
303+
void WarnIfNotInternal(const A &stmt, const parser::CharBlock &source) {
304+
if (!IsInternalIO(stmt)) {
305+
WarnOnIoStmt(source);
306+
}
307+
}
280308
void Check(const parser::ActionStmt &stmt, const parser::CharBlock &source) {
281309
common::visit(
282310
common::visitors{
311+
[&](const common::Indirection<parser::PrintStmt> &) {},
312+
[&](const common::Indirection<parser::WriteStmt> &x) {
313+
if (x.value().format) { // Formatted write to '*' or '6'
314+
if (std::holds_alternative<Fortran::parser::Star>(
315+
x.value().format->u)) {
316+
if (x.value().iounit) {
317+
if (std::holds_alternative<Fortran::parser::Star>(
318+
x.value().iounit->u)) {
319+
return;
320+
}
321+
}
322+
}
323+
}
324+
WarnIfNotInternal(x.value(), source);
325+
},
326+
[&](const common::Indirection<parser::CloseStmt> &x) {
327+
WarnOnIoStmt(source);
328+
},
329+
[&](const common::Indirection<parser::EndfileStmt> &x) {
330+
WarnOnIoStmt(source);
331+
},
332+
[&](const common::Indirection<parser::OpenStmt> &x) {
333+
WarnOnIoStmt(source);
334+
},
335+
[&](const common::Indirection<parser::ReadStmt> &x) {
336+
WarnIfNotInternal(x.value(), source);
337+
},
338+
[&](const common::Indirection<parser::InquireStmt> &x) {
339+
WarnOnIoStmt(source);
340+
},
341+
[&](const common::Indirection<parser::RewindStmt> &x) {
342+
WarnOnIoStmt(source);
343+
},
344+
[&](const common::Indirection<parser::BackspaceStmt> &x) {
345+
WarnOnIoStmt(source);
346+
},
283347
[&](const auto &x) {
284348
if (auto msg{ActionStmtChecker<IsCUFKernelDo>::WhyNotOk(x)}) {
285349
context_.Say(source, std::move(*msg));

flang/test/Semantics/cuf09.cuf

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ module m
77
do k=1,10
88
end do
99
end
10+
attributes(device) subroutine devsub2
11+
real, device :: x(10)
12+
print*,'from device'
13+
print '(f10.5)', (x(ivar), ivar = 1, 10)
14+
write(*,*), "Hello world from device!"
15+
!WARNING: I/O statement might not be supported on device
16+
write(12,'(10F4.1)'), x
17+
end
1018
end
1119

1220
program main

0 commit comments

Comments
 (0)