diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Stop.h b/flang/include/flang/Optimizer/Builder/Runtime/Stop.h --- a/flang/include/flang/Optimizer/Builder/Runtime/Stop.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Stop.h @@ -27,6 +27,9 @@ /// Generate call to EXIT intrinsic runtime routine. void genExit(fir::FirOpBuilder &, mlir::Location, mlir::Value status); +/// Generate call to ABORT intrinsic runtime routine. +void genAbort(fir::FirOpBuilder &, mlir::Location); + /// Generate call to crash the program with an error message when detecting /// an invalid situation at runtime. void genReportFatalUserError(fir::FirOpBuilder &, mlir::Location, diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -441,6 +441,8 @@ getRuntimeCallGenerator(llvm::StringRef name, mlir::FunctionType soughtFuncType); + void genAbort(llvm::ArrayRef); + /// Lowering for the ABS intrinsic. The ABS intrinsic expects one argument in /// the llvm::ArrayRef. The ABS intrinsic is lowered into MLIR/FIR operation /// if the argument is an integer, into llvm intrinsics if the argument is @@ -685,6 +687,7 @@ /// argument must not be lowered by value. In which case, the lowering rules /// should be provided for all the intrinsic arguments for completeness. static constexpr IntrinsicHandler handlers[]{ + {"abort", &I::genAbort}, {"abs", &I::genAbs}, {"achar", &I::genChar}, {"adjustl", @@ -2105,6 +2108,12 @@ return builder.convertWithSemantics(loc, resultType, args[0]); } +// ABORT +void IntrinsicLibrary::genAbort(llvm::ArrayRef args) { + assert(args.size() == 0); + fir::runtime::genAbort(builder, loc); +} + // ABS mlir::Value IntrinsicLibrary::genAbs(mlir::Type resultType, llvm::ArrayRef args) { diff --git a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp --- a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp @@ -22,6 +22,12 @@ builder.create(loc, exitFunc, args); } +void fir::runtime::genAbort(fir::FirOpBuilder &builder, mlir::Location loc) { + mlir::func::FuncOp abortFunc = + fir::runtime::getRuntimeFunc(loc, builder); + builder.create(loc, abortFunc, llvm::None); +} + void fir::runtime::genReportFatalUserError(fir::FirOpBuilder &builder, mlir::Location loc, llvm::StringRef message) { diff --git a/flang/runtime/stop.cpp b/flang/runtime/stop.cpp --- a/flang/runtime/stop.cpp +++ b/flang/runtime/stop.cpp @@ -142,7 +142,10 @@ std::exit(status); } -[[noreturn]] void RTNAME(Abort)() { std::abort(); } +[[noreturn]] void RTNAME(Abort)() { + // TODO: Add backtrace call, unless with `-fno-backtrace`. + std::abort(); +} [[noreturn]] void RTNAME(ReportFatalUserError)( const char *message, const char *source, int line) { diff --git a/flang/test/Lower/Intrinsics/abort.f90 b/flang/test/Lower/Intrinsics/abort.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/Intrinsics/abort.f90 @@ -0,0 +1,10 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPabort_test() { +! CHECK: %[[VAL_0:.*]] = fir.call @_FortranAAbort() : () -> none +! CHECK: return +! CHECK: } + +subroutine abort_test() + call abort +end subroutine