Skip to content

Commit 2d5d310

Browse files
committed
[flang]Add new intrinsic function backtrace and complete the TODO of abort
1 parent 56feea7 commit 2d5d310

File tree

8 files changed

+50
-1
lines changed

8 files changed

+50
-1
lines changed

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ struct IntrinsicLibrary {
196196
fir::ExtendedValue genAssociated(mlir::Type,
197197
llvm::ArrayRef<fir::ExtendedValue>);
198198
mlir::Value genAtand(mlir::Type, llvm::ArrayRef<mlir::Value>);
199+
void genBacktrace(llvm::ArrayRef<fir::ExtendedValue>);
199200
fir::ExtendedValue genBesselJn(mlir::Type,
200201
llvm::ArrayRef<fir::ExtendedValue>);
201202
fir::ExtendedValue genBesselYn(mlir::Type,

flang/include/flang/Optimizer/Builder/Runtime/Stop.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ void genExit(fir::FirOpBuilder &, mlir::Location, mlir::Value status);
3030
/// Generate call to ABORT intrinsic runtime routine.
3131
void genAbort(fir::FirOpBuilder &, mlir::Location);
3232

33+
/// Generate call to BACKTRACE intrinsic runtime routine.
34+
void genBacktrace(fir::FirOpBuilder &builder, mlir::Location loc);
35+
3336
/// Generate call to crash the program with an error message when detecting
3437
/// an invalid situation at runtime.
3538
void genReportFatalUserError(fir::FirOpBuilder &, mlir::Location,

flang/include/flang/Runtime/stop.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ NORETURN void RTNAME(ProgramEndStatement)(NO_ARGUMENTS);
2929
// Extensions
3030
NORETURN void RTNAME(Exit)(int status DEFAULT_VALUE(EXIT_SUCCESS));
3131
NORETURN void RTNAME(Abort)(NO_ARGUMENTS);
32+
void RTNAME(Backtrace)(NO_ARGUMENTS);
3233

3334
// Crash with an error message when the program dynamically violates a Fortran
3435
// constraint.

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,7 @@ static const IntrinsicInterface intrinsicSubroutine[]{
13331333
{"stat", AnyInt, Rank::scalar, Optionality::optional,
13341334
common::Intent::Out}},
13351335
{}, Rank::elemental, IntrinsicClass::atomicSubroutine},
1336+
{"backtrace", {}, {}, Rank::elemental, IntrinsicClass::pureSubroutine},
13361337
{"co_broadcast",
13371338
{{"a", AnyData, Rank::anyOrAssumedRank, Optionality::required,
13381339
common::Intent::InOut},

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ static constexpr IntrinsicHandler handlers[]{
150150
{"atan2pi", &I::genAtanpi},
151151
{"atand", &I::genAtand},
152152
{"atanpi", &I::genAtanpi},
153+
{"backtrace", &I::genBacktrace},
153154
{"bessel_jn",
154155
&I::genBesselJn,
155156
{{{"n1", asValue}, {"n2", asValue}, {"x", asValue}}},
@@ -2681,6 +2682,12 @@ IntrinsicLibrary::genBesselJn(mlir::Type resultType,
26812682
}
26822683
}
26832684

2685+
// Backtrace
2686+
void IntrinsicLibrary::genBacktrace(llvm::ArrayRef<fir::ExtendedValue> args) {
2687+
assert(args.size() == 0);
2688+
fir::runtime::genBacktrace(builder, loc);
2689+
}
2690+
26842691
// BESSEL_YN
26852692
fir::ExtendedValue
26862693
IntrinsicLibrary::genBesselYn(mlir::Type resultType,

flang/lib/Optimizer/Builder/Runtime/Stop.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ void fir::runtime::genAbort(fir::FirOpBuilder &builder, mlir::Location loc) {
2828
builder.create<fir::CallOp>(loc, abortFunc, std::nullopt);
2929
}
3030

31+
void fir::runtime::genBacktrace(fir::FirOpBuilder &builder,
32+
mlir::Location loc) {
33+
mlir::func::FuncOp backtraceFunc =
34+
fir::runtime::getRuntimeFunc<mkRTKey(Backtrace)>(loc, builder);
35+
builder.create<fir::CallOp>(loc, backtraceFunc, std::nullopt);
36+
}
37+
3138
void fir::runtime::genReportFatalUserError(fir::FirOpBuilder &builder,
3239
mlir::Location loc,
3340
llvm::StringRef message) {

flang/runtime/stop.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <cfenv>
1616
#include <cstdio>
1717
#include <cstdlib>
18+
#include <execinfo.h>
1819

1920
extern "C" {
2021

@@ -152,11 +153,29 @@ void RTNAME(PauseStatementText)(const char *code, std::size_t length) {
152153
std::exit(status);
153154
}
154155

156+
static void PrintBacktrace() {
157+
// TODO: Need to parse DWARF information to print function line numbers
158+
const int MAX_CALL_STACK = 999;
159+
void *buffer[MAX_CALL_STACK];
160+
int nptrs = backtrace(buffer, MAX_CALL_STACK);
161+
char **symbols = backtrace_symbols(buffer, nptrs);
162+
if (symbols == nullptr) {
163+
Fortran::runtime::Terminator{}.Crash("no symbols");
164+
std::exit(EXIT_FAILURE);
165+
}
166+
for (int i = 0; i < nptrs; i++) {
167+
Fortran::runtime::Terminator{}.PrintCrashArgs("#%d %s\n", i, symbols[i]);
168+
}
169+
free(symbols);
170+
}
171+
155172
[[noreturn]] void RTNAME(Abort)() {
156-
// TODO: Add backtrace call, unless with `-fno-backtrace`.
173+
PrintBacktrace();
157174
std::abort();
158175
}
159176

177+
void RTNAME(Backtrace)() { PrintBacktrace(); }
178+
160179
[[noreturn]] void RTNAME(ReportFatalUserError)(
161180
const char *message, const char *source, int line) {
162181
Fortran::runtime::Terminator{source, line}.Crash(message);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
3+
! CHECK-LABEL: func.func @_QPbacktrace_test() {
4+
! CHECK: %[[VAL_0:.*]] = fir.call @_FortranABacktrace() {{.*}}: () -> none
5+
! CHECK: return
6+
! CHECK: }
7+
8+
subroutine backtrace_test()
9+
call backtrace
10+
end subroutine

0 commit comments

Comments
 (0)