[flang-commits] [flang] [flang][DRAFT] Mark EXIT() intrinsic as not returning (PR #170603)

Eugene Epshteyn via flang-commits flang-commits at lists.llvm.org
Sun Dec 7 19:41:01 PST 2025


https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/170603

>From ce7db5501e0b4ff9853805f2bf4839f5431fdcd6 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 3 Dec 2025 23:38:09 -0500
Subject: [PATCH 1/3] [flang][DRAFT] unreachable after exit

---
 flang/lib/Optimizer/Builder/Runtime/Stop.cpp  |  2 ++
 flang/test/Lower/Intrinsics/exit-noreturn.f90 | 14 ++++++++++++++
 2 files changed, 16 insertions(+)
 create mode 100644 flang/test/Lower/Intrinsics/exit-noreturn.f90

diff --git a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp
index 5629371947641..98e3e940d92b7 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp
@@ -17,9 +17,11 @@ using namespace Fortran::runtime;
 void fir::runtime::genExit(fir::FirOpBuilder &builder, mlir::Location loc,
                            mlir::Value status) {
   auto exitFunc = fir::runtime::getRuntimeFunc<mkRTKey(Exit)>(loc, builder);
+  exitFunc->setAttr("noreturn", builder.getUnitAttr());
   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
       builder, loc, exitFunc.getFunctionType(), status);
   fir::CallOp::create(builder, loc, exitFunc, args);
+  builder.create<fir::UnreachableOp>(loc);
 }
 
 void fir::runtime::genAbort(fir::FirOpBuilder &builder, mlir::Location loc) {
diff --git a/flang/test/Lower/Intrinsics/exit-noreturn.f90 b/flang/test/Lower/Intrinsics/exit-noreturn.f90
new file mode 100644
index 0000000000000..456d0b8779f17
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/exit-noreturn.f90
@@ -0,0 +1,14 @@
+! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
+
+integer function test_exit(status)
+  integer, intent(in) :: status
+  if (status > 0) call exit(status)
+  if (status == 42) print *, "Unreachable"
+  test_exit = status
+end function test_exit
+
+! CHECK-LABEL: func.func @_QPtest_exit
+! CHECK: fir.call @_FortranAExit
+! CHECK-NEXT: fir.unreachable
+
+! CHECK: func.func private @_FortranAExit{{.*}} attributes {{.*}}noreturn

>From d69f1b604f9a2a6afef6c48784e514d9a630640a Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 3 Dec 2025 23:47:34 -0500
Subject: [PATCH 2/3] Added documentation for EXIT()

---
 flang/docs/Intrinsics.md | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/flang/docs/Intrinsics.md b/flang/docs/Intrinsics.md
index 31bead9f8bfdc..80c7589602c4b 100644
--- a/flang/docs/Intrinsics.md
+++ b/flang/docs/Intrinsics.md
@@ -981,6 +981,31 @@ program test_etime
 end program test_etime
 ```
 
+### Non-Standard Intrinsics: EXIT
+
+#### Description
+`EXIT([STATUS])` terminates the program execution.
+
+#### Usage and Info
+
+- **Standard:** GNU extension
+- **Class:** Subroutine
+- **Syntax:** `CALL EXIT([STATUS])`
+- **Arguments:**
+
+| Argument | Description |
+|----------|-------------|
+| `STATUS` | (Optional) Scalar INTEGER argument. If not present, then default success code is returned (usually, 0). |
+
+#### Example
+```Fortran
+program call_exit
+  integer :: status = 42
+  print *, "Exiting..."
+  call exit(status)
+end
+```
+
 ### Non-Standard Intrinsics: GETCWD
 
 #### Description

>From bce370d3a8adada6a989373f9fd2a517f57579b9 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Sun, 7 Dec 2025 22:40:50 -0500
Subject: [PATCH 3/3] genUnreachable() is now exposed as
 Fortran::lower::genUnreachable()

---
 flang/include/flang/Lower/Runtime.h          | 1 +
 flang/lib/Lower/Runtime.cpp                  | 2 +-
 flang/lib/Optimizer/Builder/Runtime/Stop.cpp | 4 +++-
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/flang/include/flang/Lower/Runtime.h b/flang/include/flang/Lower/Runtime.h
index 204093f9a766a..bfc8a87a75880 100644
--- a/flang/include/flang/Lower/Runtime.h
+++ b/flang/include/flang/Lower/Runtime.h
@@ -68,6 +68,7 @@ void genPointerAssociateRemapping(fir::FirOpBuilder &, mlir::Location,
 void genPointerAssociateLowerBounds(fir::FirOpBuilder &, mlir::Location,
                                     mlir::Value pointer, mlir::Value target,
                                     mlir::Value lbounds);
+void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc);
 } // namespace lower
 } // namespace Fortran
 
diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp
index 5f8586b9c8a88..8e67d6685581d 100644
--- a/flang/lib/Lower/Runtime.cpp
+++ b/flang/lib/Lower/Runtime.cpp
@@ -34,7 +34,7 @@ using namespace Fortran::runtime;
 
 /// Runtime calls that do not return to the caller indicate this condition by
 /// terminating the current basic block with an unreachable op.
-static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) {
+void Fortran::lower::genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) {
   mlir::Block *curBlock = builder.getBlock();
   mlir::Operation *parentOp = curBlock->getParentOp();
   if (parentOp->getDialect()->getNamespace() ==
diff --git a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp
index 98e3e940d92b7..d69225059703e 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp
@@ -10,6 +10,7 @@
 #include "flang/Optimizer/Builder/BoxValue.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
 #include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
+#include "flang/Lower/Runtime.h"
 #include "flang/Runtime/stop.h"
 
 using namespace Fortran::runtime;
@@ -21,13 +22,14 @@ void fir::runtime::genExit(fir::FirOpBuilder &builder, mlir::Location loc,
   llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
       builder, loc, exitFunc.getFunctionType(), status);
   fir::CallOp::create(builder, loc, exitFunc, args);
-  builder.create<fir::UnreachableOp>(loc);
+  Fortran::lower::genUnreachable(builder, loc);
 }
 
 void fir::runtime::genAbort(fir::FirOpBuilder &builder, mlir::Location loc) {
   mlir::func::FuncOp abortFunc =
       fir::runtime::getRuntimeFunc<mkRTKey(Abort)>(loc, builder);
   fir::CallOp::create(builder, loc, abortFunc, mlir::ValueRange{});
+  Fortran::lower::genUnreachable(builder, loc);
 }
 
 void fir::runtime::genReportFatalUserError(fir::FirOpBuilder &builder,



More information about the flang-commits mailing list