Skip to content

Commit 70970d0

Browse files
sathvikreddy853Adityanath-madishettieugeneepshteyn
authored
[flang] Implement lowering for the PAUSE statement (Fixes #166821) (#167115)
Implements lowering for the Fortran `PAUSE` statement. - Handles PAUSE with no operand. - Handles PAUSE with integer argument. - Handles PAUSE with character literal argument. - Adds a new lowering test: flang/test/Lower/pause-statement.f90. Unlike STOP, PAUSE does not unconditionally terminate control flow. The lowering preserves labels and GOTOs, consistent with legacy Fortran behavior. Fixes: #166821 --------- Co-authored-by: aditya nath <adityanath5002@gmail.com> Co-authored-by: Eugene Epshteyn <eepshteyn@nvidia.com>
1 parent 3de11e9 commit 70970d0

File tree

2 files changed

+73
-6
lines changed

2 files changed

+73
-6
lines changed

flang/lib/Lower/Runtime.cpp

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,55 @@ void Fortran::lower::genUnlockStatement(
169169

170170
void Fortran::lower::genPauseStatement(
171171
Fortran::lower::AbstractConverter &converter,
172-
const Fortran::parser::PauseStmt &) {
172+
const Fortran::parser::PauseStmt &stmt) {
173+
173174
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
174175
mlir::Location loc = converter.getCurrentLocation();
175-
mlir::func::FuncOp callee =
176-
fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
177-
fir::CallOp::create(builder, loc, callee, mlir::ValueRange{});
176+
Fortran::lower::StatementContext stmtCtx;
177+
178+
llvm::SmallVector<mlir::Value> operands;
179+
mlir::func::FuncOp callee;
180+
mlir::FunctionType calleeType;
181+
182+
if (stmt.v.has_value()) {
183+
const auto &code = stmt.v.value();
184+
auto expr =
185+
converter.genExprValue(*Fortran::semantics::GetExpr(code), stmtCtx);
186+
expr.match(
187+
// Character-valued expression -> call PauseStatementText (CHAR, LEN)
188+
[&](const fir::CharBoxValue &x) {
189+
callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatementText)>(
190+
loc, builder);
191+
calleeType = callee.getFunctionType();
192+
193+
operands.push_back(
194+
builder.createConvert(loc, calleeType.getInput(0), x.getAddr()));
195+
operands.push_back(
196+
builder.createConvert(loc, calleeType.getInput(1), x.getLen()));
197+
},
198+
// Unboxed value -> call PauseStatementInt which accepts an integer.
199+
[&](fir::UnboxedValue x) {
200+
callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatementInt)>(
201+
loc, builder);
202+
calleeType = callee.getFunctionType();
203+
assert(calleeType.getNumInputs() >= 1);
204+
mlir::Value cast =
205+
builder.createConvert(loc, calleeType.getInput(0), x);
206+
operands.push_back(cast);
207+
},
208+
[&](auto) {
209+
fir::emitFatalError(loc, "unhandled expression in PAUSE");
210+
});
211+
} else {
212+
callee =
213+
fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
214+
calleeType = callee.getFunctionType();
215+
}
216+
217+
fir::CallOp::create(builder, loc, callee, operands);
218+
219+
// NOTE: PAUSE does not terminate the current block. The program may resume
220+
// and continue normal execution, so we do not emit control-flow terminators.
178221
}
179222

180223
void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder,

flang/test/Lower/pause-statement.f90

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,31 @@
22

33
! CHECK-LABEL: pause_test
44
subroutine pause_test()
5-
! CHECK: fir.call @_Fortran{{.*}}PauseStatement()
6-
! CHECK-NEXT: return
75
pause
6+
! CHECK: fir.call @_FortranA{{.*}}PauseStatement()
7+
! CHECK-NEXT: return
8+
end subroutine
9+
10+
! CHECK-LABEL: pause_code
11+
subroutine pause_code()
12+
pause 42
13+
! CHECK: %[[c42:.*]] = arith.constant 42 : i32
14+
! CHECK: fir.call @_FortranA{{.*}}PauseStatementInt(%[[c42]])
15+
! CHECK-NEXT: return
816
end subroutine
17+
18+
! CHECK-LABEL: pause_msg
19+
subroutine pause_msg()
20+
pause "hello"
21+
! CHECK-DAG: %[[five:.*]] = arith.constant 5 : index
22+
! CHECK-DAG: %[[addr:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref<!fir.char<1,5>>
23+
! CHECK-DAG: %[[str:.*]]:2 = hlfir.declare %[[addr]] typeparams %[[five]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQ{{.*}}"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>)
24+
! CHECK-DAG: %[[buff:.*]] = fir.convert %[[str]]#0 : (!fir.ref<!fir.char<1,5>>) -> !fir.ref<i8>
25+
! CHECK-DAG: %[[len:.*]] = fir.convert %[[five]] : (index) -> i64
26+
! CHECK: fir.call @_FortranA{{.*}}PauseStatementText(%[[buff]], %[[len]])
27+
! CHECK-NEXT: return
28+
end subroutine
29+
30+
! CHECK-DAG: func private @_FortranA{{.*}}PauseStatement
31+
! CHECK-DAG: func private @_FortranA{{.*}}PauseStatementInt
32+
! CHECK-DAG: func private @_FortranA{{.*}}PauseStatementText

0 commit comments

Comments
 (0)