diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp index 9ff6157f7487d..5f8586b9c8a88 100644 --- a/flang/lib/Lower/Runtime.cpp +++ b/flang/lib/Lower/Runtime.cpp @@ -169,12 +169,55 @@ void Fortran::lower::genUnlockStatement( void Fortran::lower::genPauseStatement( Fortran::lower::AbstractConverter &converter, - const Fortran::parser::PauseStmt &) { + const Fortran::parser::PauseStmt &stmt) { + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); mlir::Location loc = converter.getCurrentLocation(); - mlir::func::FuncOp callee = - fir::runtime::getRuntimeFunc(loc, builder); - fir::CallOp::create(builder, loc, callee, mlir::ValueRange{}); + Fortran::lower::StatementContext stmtCtx; + + llvm::SmallVector operands; + mlir::func::FuncOp callee; + mlir::FunctionType calleeType; + + if (stmt.v.has_value()) { + const auto &code = stmt.v.value(); + auto expr = + converter.genExprValue(*Fortran::semantics::GetExpr(code), stmtCtx); + expr.match( + // Character-valued expression -> call PauseStatementText (CHAR, LEN) + [&](const fir::CharBoxValue &x) { + callee = fir::runtime::getRuntimeFunc( + loc, builder); + calleeType = callee.getFunctionType(); + + operands.push_back( + builder.createConvert(loc, calleeType.getInput(0), x.getAddr())); + operands.push_back( + builder.createConvert(loc, calleeType.getInput(1), x.getLen())); + }, + // Unboxed value -> call PauseStatementInt which accepts an integer. + [&](fir::UnboxedValue x) { + callee = fir::runtime::getRuntimeFunc( + loc, builder); + calleeType = callee.getFunctionType(); + assert(calleeType.getNumInputs() >= 1); + mlir::Value cast = + builder.createConvert(loc, calleeType.getInput(0), x); + operands.push_back(cast); + }, + [&](auto) { + fir::emitFatalError(loc, "unhandled expression in PAUSE"); + }); + } else { + callee = + fir::runtime::getRuntimeFunc(loc, builder); + calleeType = callee.getFunctionType(); + } + + fir::CallOp::create(builder, loc, callee, operands); + + // NOTE: PAUSE does not terminate the current block. The program may resume + // and continue normal execution, so we do not emit control-flow terminators. } void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder, diff --git a/flang/test/Lower/pause-statement.f90 b/flang/test/Lower/pause-statement.f90 index f4c8f6fbc4385..465d82449c5bc 100644 --- a/flang/test/Lower/pause-statement.f90 +++ b/flang/test/Lower/pause-statement.f90 @@ -2,7 +2,31 @@ ! CHECK-LABEL: pause_test subroutine pause_test() - ! CHECK: fir.call @_Fortran{{.*}}PauseStatement() - ! CHECK-NEXT: return pause + ! CHECK: fir.call @_FortranA{{.*}}PauseStatement() + ! CHECK-NEXT: return +end subroutine + +! CHECK-LABEL: pause_code +subroutine pause_code() + pause 42 + ! CHECK: %[[c42:.*]] = arith.constant 42 : i32 + ! CHECK: fir.call @_FortranA{{.*}}PauseStatementInt(%[[c42]]) + ! CHECK-NEXT: return end subroutine + +! CHECK-LABEL: pause_msg +subroutine pause_msg() + pause "hello" + ! CHECK-DAG: %[[five:.*]] = arith.constant 5 : index + ! CHECK-DAG: %[[addr:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref> + ! CHECK-DAG: %[[str:.*]]:2 = hlfir.declare %[[addr]] typeparams %[[five]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QQ{{.*}}"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) + ! CHECK-DAG: %[[buff:.*]] = fir.convert %[[str]]#0 : (!fir.ref>) -> !fir.ref + ! CHECK-DAG: %[[len:.*]] = fir.convert %[[five]] : (index) -> i64 + ! CHECK: fir.call @_FortranA{{.*}}PauseStatementText(%[[buff]], %[[len]]) + ! CHECK-NEXT: return +end subroutine + +! CHECK-DAG: func private @_FortranA{{.*}}PauseStatement +! CHECK-DAG: func private @_FortranA{{.*}}PauseStatementInt +! CHECK-DAG: func private @_FortranA{{.*}}PauseStatementText