[flang-commits] [flang] [flang] Implement lowering for the PAUSE statement (Fixes #166821) (PR #167115)
via flang-commits
flang-commits at lists.llvm.org
Sat Nov 8 05:16:18 PST 2025
https://github.com/sathvikreddy853 updated https://github.com/llvm/llvm-project/pull/167115
>From faf6544603b16652369d28a3af4e97d00c58b95a Mon Sep 17 00:00:00 2001
From: Sathvik Reddy <sathvikreddy853 at gmail.com>
Date: Sat, 8 Nov 2025 10:53:37 +0530
Subject: [PATCH 1/3] [flang] Lower PAUSE statement with code and message
operands
This patch adds lowering support for the Fortran PAUSE statement to FIR.
It mirrors the STOP statement lowering logic to handle:
- PAUSE with no operand
- PAUSE <integer>
- PAUSE 'message'
Fixes #166821.
---
flang/lib/Lower/Runtime.cpp | 48 +++++++++++++++++++++++++++++++++----
1 file changed, 44 insertions(+), 4 deletions(-)
diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp
index cb555249125f6..d864b027c3183 100644
--- a/flang/lib/Lower/Runtime.cpp
+++ b/flang/lib/Lower/Runtime.cpp
@@ -263,12 +263,52 @@ void Fortran::lower::genSyncTeamStatement(
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<mkRTKey(PauseStatement)>(loc, builder);
- fir::CallOp::create(builder, loc, callee, mlir::ValueRange{});
+ Fortran::lower::StatementContext stmtCtx;
+ llvm::SmallVector<mlir::Value> operands;
+ mlir::func::FuncOp callee;
+ mlir::FunctionType calleeType;
+
+ if (stmt.v.has_value()) {
+ const Fortran::parser::StopCode &code = stmt.v.value();
+ auto expr = converter.genExprValue(*Fortran::semantics::GetExpr(code), stmtCtx);
+ LLVM_DEBUG(llvm::dbgs() << "pause expression: "; expr.dump(); llvm::dbgs() << '\n');
+ expr.match(
+ [&](const fir::CharBoxValue &x) {
+ callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatementText)>(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()));
+ },
+ [&](fir::UnboxedValue x) {
+ callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
+ calleeType = callee.getFunctionType();
+ mlir::Value cast =
+ builder.createConvert(loc, calleeType.getInput(0), x);
+ operands.push_back(cast);
+ },
+ [&](auto) {
+ mlir::emitError(loc, "unhandled expression in PAUSE");
+ std::exit(1);
+ });
+ } else {
+ callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
+ calleeType = callee.getFunctionType();
+ }
+
+ fir::CallOp::create(builder, loc, callee, operands);
+
+ auto blockIsUnterminated = [&builder]() {
+ mlir::Block *currentBlock = builder.getBlock();
+ return currentBlock->empty() ||
+ !currentBlock->back().hasTrait<mlir::OpTrait::IsTerminator>();
+ };
+ if (blockIsUnterminated())
+ genUnreachable(builder, loc);
}
void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder,
>From 8914d5ef9356b1601a6f7799d66af65138c3b268 Mon Sep 17 00:00:00 2001
From: Sathvik Reddy <sathvikreddy853 at gmail.com>
Date: Sat, 8 Nov 2025 14:55:25 +0530
Subject: [PATCH 2/3] [flang] add check for number of inputs and remove
unreachable block code
---
flang/lib/Lower/Runtime.cpp | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp
index d864b027c3183..48c70f4180de0 100644
--- a/flang/lib/Lower/Runtime.cpp
+++ b/flang/lib/Lower/Runtime.cpp
@@ -264,32 +264,39 @@ void Fortran::lower::genSyncTeamStatement(
void Fortran::lower::genPauseStatement(
Fortran::lower::AbstractConverter &converter,
const Fortran::parser::PauseStmt &stmt) {
+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
mlir::Location loc = converter.getCurrentLocation();
Fortran::lower::StatementContext stmtCtx;
+
llvm::SmallVector<mlir::Value> operands;
mlir::func::FuncOp callee;
mlir::FunctionType calleeType;
if (stmt.v.has_value()) {
- const Fortran::parser::StopCode &code = stmt.v.value();
+ const auto &code = stmt.v.value();
auto expr = converter.genExprValue(*Fortran::semantics::GetExpr(code), stmtCtx);
LLVM_DEBUG(llvm::dbgs() << "pause expression: "; expr.dump(); llvm::dbgs() << '\n');
expr.match(
+ // Character-valued expression -> call PauseStatementText (CHAR, LEN)
[&](const fir::CharBoxValue &x) {
callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatementText)>(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()));
},
+ // Numeric/unboxed value -> call PauseStatement which accepts an integer code.
[&](fir::UnboxedValue x) {
- callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
- calleeType = callee.getFunctionType();
- mlir::Value cast =
- builder.createConvert(loc, calleeType.getInput(0), x);
- operands.push_back(cast);
+ callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
+ calleeType = callee.getFunctionType();
+ if (calleeType.getNumInputs() >= 1) {
+ mlir::Value cast =
+ builder.createConvert(loc, calleeType.getInput(0), x);
+ operands.push_back(cast);
+ }
},
[&](auto) {
mlir::emitError(loc, "unhandled expression in PAUSE");
@@ -299,16 +306,13 @@ void Fortran::lower::genPauseStatement(
callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
calleeType = callee.getFunctionType();
}
-
+
fir::CallOp::create(builder, loc, callee, operands);
- auto blockIsUnterminated = [&builder]() {
- mlir::Block *currentBlock = builder.getBlock();
- return currentBlock->empty() ||
- !currentBlock->back().hasTrait<mlir::OpTrait::IsTerminator>();
- };
- if (blockIsUnterminated())
- genUnreachable(builder, loc);
+ // NOTE: PAUSE should not unconditionally terminate the current block.
+ // Unlike STOP, PAUSE does not necessarily abandon control flow, so do not
+ // subsequent control flow (e.g. GOTO/branches) to be generated.
+ // insert genUnreachable() here. Leaving the block un-terminated allows
}
void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder,
>From 99974a0e6306cb90e0085576fd9e0ed98732ac26 Mon Sep 17 00:00:00 2001
From: aditya nath <adityanath5002 at gmail.com>
Date: Sat, 8 Nov 2025 15:02:24 +0530
Subject: [PATCH 3/3] [flang] Update pause-statement testcase
---
flang/test/Lower/pause-statement.f90 | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/flang/test/Lower/pause-statement.f90 b/flang/test/Lower/pause-statement.f90
index f4c8f6fbc4385..926f81e96cefd 100644
--- a/flang/test/Lower/pause-statement.f90
+++ b/flang/test/Lower/pause-statement.f90
@@ -1,4 +1,4 @@
-! RUN: bbc %s -emit-fir --canonicalize -o - | FileCheck %s
+! RUN: bbc %s -emit-fir -hlfir=false --canonicalize -o - | FileCheck %s
! CHECK-LABEL: pause_test
subroutine pause_test()
@@ -6,3 +6,24 @@ subroutine pause_test()
! CHECK-NEXT: return
pause
end subroutine
+
+! CHECK-LABEL: pause_code
+subroutine pause_code()
+ pause 42
+ ! CHECK: fir.call @_Fortran{{.*}}PauseStatement
+ ! CHECK-NEXT: return
+end subroutine
+
+! CHECK-LABEL: pause_msg
+subroutine pause_msg()
+ pause "hello"
+ ! CHECK-DAG: %[[five:.*]] = arith.constant 5 : index
+ ! CHECK-DAG: %[[lit:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref<!fir.char<1,5>>
+ ! CHECK-DAG: %[[buff:.*]] = fir.convert %[[lit]] : (!fir.ref<!fir.char<1,5>>) -> !fir.ref<i8>
+ ! CHECK-DAG: %[[len:.*]] = fir.convert %[[five]] : (index) -> i64
+ ! CHECK: fir.call @_Fortran{{.*}}PauseStatementText(%[[buff]], %[[len]])
+ ! CHECK-NEXT: return
+end subroutine
+
+! CHECK-DAG: func private @_Fortran{{.*}}PauseStatement
+! CHECK-DAG: func private @_Fortran{{.*}}PauseStatementText
\ No newline at end of file
More information about the flang-commits
mailing list