From 2d5d3107444d244cf5fa2c75cb69000e3c6ca081 Mon Sep 17 00:00:00 2001 From: hunter <284050500@qq.com> Date: Tue, 26 Nov 2024 02:18:10 +0800 Subject: [PATCH 1/5] [flang]Add new intrinsic function backtrace and complete the TODO of abort --- .../flang/Optimizer/Builder/IntrinsicCall.h | 1 + .../flang/Optimizer/Builder/Runtime/Stop.h | 3 +++ flang/include/flang/Runtime/stop.h | 1 + flang/lib/Evaluate/intrinsics.cpp | 1 + flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 7 +++++++ flang/lib/Optimizer/Builder/Runtime/Stop.cpp | 7 +++++++ flang/runtime/stop.cpp | 21 ++++++++++++++++++- flang/test/Lower/Intrinsics/backtrace.f90 | 10 +++++++++ 8 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 flang/test/Lower/Intrinsics/backtrace.f90 diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index e83d1a42e3413..7f4b9ebf1d1c2 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -196,6 +196,7 @@ struct IntrinsicLibrary { fir::ExtendedValue genAssociated(mlir::Type, llvm::ArrayRef); mlir::Value genAtand(mlir::Type, llvm::ArrayRef); + void genBacktrace(llvm::ArrayRef); fir::ExtendedValue genBesselJn(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genBesselYn(mlir::Type, diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Stop.h b/flang/include/flang/Optimizer/Builder/Runtime/Stop.h index 6f764badf6f3a..be73cffff021e 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/Stop.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Stop.h @@ -30,6 +30,9 @@ 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 BACKTRACE intrinsic runtime routine. +void genBacktrace(fir::FirOpBuilder &builder, mlir::Location loc); + /// 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/include/flang/Runtime/stop.h b/flang/include/flang/Runtime/stop.h index f7c4ffe7403e8..d442f72bfe1fa 100644 --- a/flang/include/flang/Runtime/stop.h +++ b/flang/include/flang/Runtime/stop.h @@ -29,6 +29,7 @@ NORETURN void RTNAME(ProgramEndStatement)(NO_ARGUMENTS); // Extensions NORETURN void RTNAME(Exit)(int status DEFAULT_VALUE(EXIT_SUCCESS)); NORETURN void RTNAME(Abort)(NO_ARGUMENTS); +void RTNAME(Backtrace)(NO_ARGUMENTS); // Crash with an error message when the program dynamically violates a Fortran // constraint. diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 1e27c0ae4216c..599a7d0124b80 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -1333,6 +1333,7 @@ static const IntrinsicInterface intrinsicSubroutine[]{ {"stat", AnyInt, Rank::scalar, Optionality::optional, common::Intent::Out}}, {}, Rank::elemental, IntrinsicClass::atomicSubroutine}, + {"backtrace", {}, {}, Rank::elemental, IntrinsicClass::pureSubroutine}, {"co_broadcast", {{"a", AnyData, Rank::anyOrAssumedRank, Optionality::required, common::Intent::InOut}, diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index a2b327f45c693..c748c6583a5ce 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -150,6 +150,7 @@ static constexpr IntrinsicHandler handlers[]{ {"atan2pi", &I::genAtanpi}, {"atand", &I::genAtand}, {"atanpi", &I::genAtanpi}, + {"backtrace", &I::genBacktrace}, {"bessel_jn", &I::genBesselJn, {{{"n1", asValue}, {"n2", asValue}, {"x", asValue}}}, @@ -2681,6 +2682,12 @@ IntrinsicLibrary::genBesselJn(mlir::Type resultType, } } +// Backtrace +void IntrinsicLibrary::genBacktrace(llvm::ArrayRef args) { + assert(args.size() == 0); + fir::runtime::genBacktrace(builder, loc); +} + // BESSEL_YN fir::ExtendedValue IntrinsicLibrary::genBesselYn(mlir::Type resultType, diff --git a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp index 411181cc6dd1c..541e5f3b5d11a 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp @@ -28,6 +28,13 @@ void fir::runtime::genAbort(fir::FirOpBuilder &builder, mlir::Location loc) { builder.create(loc, abortFunc, std::nullopt); } +void fir::runtime::genBacktrace(fir::FirOpBuilder &builder, + mlir::Location loc) { + mlir::func::FuncOp backtraceFunc = + fir::runtime::getRuntimeFunc(loc, builder); + builder.create(loc, backtraceFunc, std::nullopt); +} + 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 index cfb36b4084020..57209dc37befa 100644 --- a/flang/runtime/stop.cpp +++ b/flang/runtime/stop.cpp @@ -15,6 +15,7 @@ #include #include #include +#include extern "C" { @@ -152,11 +153,29 @@ void RTNAME(PauseStatementText)(const char *code, std::size_t length) { std::exit(status); } +static void PrintBacktrace() { + // TODO: Need to parse DWARF information to print function line numbers + const int MAX_CALL_STACK = 999; + void *buffer[MAX_CALL_STACK]; + int nptrs = backtrace(buffer, MAX_CALL_STACK); + char **symbols = backtrace_symbols(buffer, nptrs); + if (symbols == nullptr) { + Fortran::runtime::Terminator{}.Crash("no symbols"); + std::exit(EXIT_FAILURE); + } + for (int i = 0; i < nptrs; i++) { + Fortran::runtime::Terminator{}.PrintCrashArgs("#%d %s\n", i, symbols[i]); + } + free(symbols); +} + [[noreturn]] void RTNAME(Abort)() { - // TODO: Add backtrace call, unless with `-fno-backtrace`. + PrintBacktrace(); std::abort(); } +void RTNAME(Backtrace)() { PrintBacktrace(); } + [[noreturn]] void RTNAME(ReportFatalUserError)( const char *message, const char *source, int line) { Fortran::runtime::Terminator{source, line}.Crash(message); diff --git a/flang/test/Lower/Intrinsics/backtrace.f90 b/flang/test/Lower/Intrinsics/backtrace.f90 new file mode 100644 index 0000000000000..9d5e7b4965baf --- /dev/null +++ b/flang/test/Lower/Intrinsics/backtrace.f90 @@ -0,0 +1,10 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPbacktrace_test() { +! CHECK: %[[VAL_0:.*]] = fir.call @_FortranABacktrace() {{.*}}: () -> none +! CHECK: return +! CHECK: } + +subroutine backtrace_test() + call backtrace +end subroutine From 6b5719316f5638a93424de60289d26a2120edd19 Mon Sep 17 00:00:00 2001 From: hunter <284050500@qq.com> Date: Tue, 26 Nov 2024 03:50:31 +0800 Subject: [PATCH 2/5] commit some suggestions --- .../Optimizer/Builder/Runtime/Intrinsics.cpp | 1 + flang/runtime/stop.cpp | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp index ded9579f2c1df..166c4ef650bb4 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp @@ -20,6 +20,7 @@ #include "flang/Runtime/time-intrinsic.h" #include "flang/Semantics/tools.h" #include "llvm/Support/Debug.h" + #include #include diff --git a/flang/runtime/stop.cpp b/flang/runtime/stop.cpp index 57209dc37befa..c3ec41be98b7f 100644 --- a/flang/runtime/stop.cpp +++ b/flang/runtime/stop.cpp @@ -15,7 +15,10 @@ #include #include #include + +#ifdef __linux__ #include +#endif extern "C" { @@ -154,19 +157,29 @@ void RTNAME(PauseStatementText)(const char *code, std::size_t length) { } static void PrintBacktrace() { +#ifdef __linux__ // TODO: Need to parse DWARF information to print function line numbers - const int MAX_CALL_STACK = 999; + constexpr int MAX_CALL_STACK{999}; void *buffer[MAX_CALL_STACK]; - int nptrs = backtrace(buffer, MAX_CALL_STACK); - char **symbols = backtrace_symbols(buffer, nptrs); + int nptrs{backtrace(buffer, MAX_CALL_STACK)}; + char **symbols{backtrace_symbols(buffer, nptrs)}; + if (symbols == nullptr) { Fortran::runtime::Terminator{}.Crash("no symbols"); std::exit(EXIT_FAILURE); } + for (int i = 0; i < nptrs; i++) { Fortran::runtime::Terminator{}.PrintCrashArgs("#%d %s\n", i, symbols[i]); } + free(symbols); + +#else + + // TODO: Windows platform implemention + +#endif } [[noreturn]] void RTNAME(Abort)() { From d28136f18fdcc953908a40a0c10d0687dc659ce4 Mon Sep 17 00:00:00 2001 From: hunter <284050500@qq.com> Date: Wed, 27 Nov 2024 01:44:45 +0800 Subject: [PATCH 3/5] [flang]Import the header file config.h in flang/runtime/stop.cpp and delete std::exit in PrintBacktrace --- .../Optimizer/Builder/Runtime/Intrinsics.cpp | 1 - flang/runtime/stop.cpp | 24 ++++++++----------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp index 166c4ef650bb4..ded9579f2c1df 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp @@ -20,7 +20,6 @@ #include "flang/Runtime/time-intrinsic.h" #include "flang/Semantics/tools.h" #include "llvm/Support/Debug.h" - #include #include diff --git a/flang/runtime/stop.cpp b/flang/runtime/stop.cpp index c3ec41be98b7f..639acc1dd4318 100644 --- a/flang/runtime/stop.cpp +++ b/flang/runtime/stop.cpp @@ -16,8 +16,9 @@ #include #include -#ifdef __linux__ -#include +#include "llvm/Config/config.h" +#ifdef HAVE_BACKTRACE +#include BACKTRACE_HEADER #endif extern "C" { @@ -157,27 +158,22 @@ void RTNAME(PauseStatementText)(const char *code, std::size_t length) { } static void PrintBacktrace() { -#ifdef __linux__ +#ifdef HAVE_BACKTRACE // TODO: Need to parse DWARF information to print function line numbers constexpr int MAX_CALL_STACK{999}; void *buffer[MAX_CALL_STACK]; int nptrs{backtrace(buffer, MAX_CALL_STACK)}; - char **symbols{backtrace_symbols(buffer, nptrs)}; - if (symbols == nullptr) { - Fortran::runtime::Terminator{}.Crash("no symbols"); - std::exit(EXIT_FAILURE); - } - - for (int i = 0; i < nptrs; i++) { - Fortran::runtime::Terminator{}.PrintCrashArgs("#%d %s\n", i, symbols[i]); + if (char **symbols{backtrace_symbols(buffer, nptrs)}) { + for (int i = 0; i < nptrs; i++) { + Fortran::runtime::Terminator{}.PrintCrashArgs("#%d %s\n", i, symbols[i]); + } + free(symbols); } - free(symbols); - #else - // TODO: Windows platform implemention + // TODO: Windows platform implementation #endif } From ca2ceb5a5b47b45a9ae05286430507ba5372eef7 Mon Sep 17 00:00:00 2001 From: hunter <284050500@qq.com> Date: Wed, 27 Nov 2024 10:30:46 +0800 Subject: [PATCH 4/5] [flang]Handle the case when a backtrace is not available --- flang/runtime/stop.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flang/runtime/stop.cpp b/flang/runtime/stop.cpp index 639acc1dd4318..1a1af6425009a 100644 --- a/flang/runtime/stop.cpp +++ b/flang/runtime/stop.cpp @@ -173,7 +173,8 @@ static void PrintBacktrace() { #else - // TODO: Windows platform implementation + // TODO: Need to implement the version for other platforms. + Fortran::runtime::Terminator{}.PrintCrashArgs("Handle the case when a backtrace is not available"); #endif } From c2e4ccaf6457e8a46bc765c29c8b49edb3682fd0 Mon Sep 17 00:00:00 2001 From: hunter <284050500@qq.com> Date: Thu, 28 Nov 2024 02:06:50 +0800 Subject: [PATCH 5/5] [flang]update format --- flang/runtime/stop.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flang/runtime/stop.cpp b/flang/runtime/stop.cpp index 1a1af6425009a..17d0ca661d9e8 100644 --- a/flang/runtime/stop.cpp +++ b/flang/runtime/stop.cpp @@ -174,7 +174,8 @@ static void PrintBacktrace() { #else // TODO: Need to implement the version for other platforms. - Fortran::runtime::Terminator{}.PrintCrashArgs("Handle the case when a backtrace is not available"); + Fortran::runtime::Terminator{}.PrintCrashArgs( + "Handle the case when a backtrace is not available"); #endif }