Skip to content

Commit eb9ba24

Browse files
committed
[StandardInstrumentations] Add option to dump IR to a file on crash
We already have -print-on-crash which dumps the IR to stderr on a crash, but it's more useful to dump to a file. Introduce -print-on-crash-path to dump the IR to a file. Making -print-on-crash a string option is confusing if you only pass -print-on-crash and it swallows up the next command line arg, which is why this is a new option. Perhaps we could retire the dump to stderr version if people don't use it, but not sure how much people find that useful. Reviewed By: jamieschmeiser Differential Revision: https://reviews.llvm.org/D151170
1 parent 6f026ff commit eb9ba24

File tree

2 files changed

+43
-23
lines changed

2 files changed

+43
-23
lines changed

llvm/lib/Passes/StandardInstrumentations.cpp

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,16 @@ static cl::opt<std::string> DotCfgDir(
9696
cl::desc("Generate dot files into specified directory for changed IRs"),
9797
cl::Hidden, cl::init("./"));
9898

99-
// An option to print the IR that was being processed when a pass crashes.
100-
static cl::opt<bool>
101-
PrintCrashIR("print-on-crash",
102-
cl::desc("Print the last form of the IR before crash"),
103-
cl::Hidden);
99+
// Options to print the IR that was being processed when a pass crashes.
100+
static cl::opt<std::string> PrintOnCrashPath(
101+
"print-on-crash-path",
102+
cl::desc("Print the last form of the IR before crash to a file"),
103+
cl::Hidden);
104+
105+
static cl::opt<bool> PrintOnCrash(
106+
"print-on-crash",
107+
cl::desc("Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
108+
cl::Hidden);
104109

105110
static cl::opt<std::string> OptBisectPrintIRPath(
106111
"opt-bisect-print-ir-path",
@@ -2186,47 +2191,59 @@ StandardInstrumentations::StandardInstrumentations(
21862191
PrintCrashIRInstrumentation *PrintCrashIRInstrumentation::CrashReporter =
21872192
nullptr;
21882193

2189-
void PrintCrashIRInstrumentation::reportCrashIR() { dbgs() << SavedIR; }
2194+
void PrintCrashIRInstrumentation::reportCrashIR() {
2195+
if (!PrintOnCrashPath.empty()) {
2196+
std::error_code EC;
2197+
raw_fd_ostream Out(PrintOnCrashPath, EC);
2198+
if (EC)
2199+
report_fatal_error(errorCodeToError(EC));
2200+
Out << SavedIR;
2201+
} else {
2202+
dbgs() << SavedIR;
2203+
}
2204+
}
21902205

21912206
void PrintCrashIRInstrumentation::SignalHandler(void *) {
21922207
// Called by signal handlers so do not lock here
21932208
// Is the PrintCrashIRInstrumentation still alive?
21942209
if (!CrashReporter)
21952210
return;
21962211

2197-
assert(PrintCrashIR && "Did not expect to get here without option set.");
2212+
assert((PrintOnCrash || !PrintOnCrashPath.empty()) &&
2213+
"Did not expect to get here without option set.");
21982214
CrashReporter->reportCrashIR();
21992215
}
22002216

22012217
PrintCrashIRInstrumentation::~PrintCrashIRInstrumentation() {
22022218
if (!CrashReporter)
22032219
return;
22042220

2205-
assert(PrintCrashIR && "Did not expect to get here without option set.");
2221+
assert((PrintOnCrash || !PrintOnCrashPath.empty()) &&
2222+
"Did not expect to get here without option set.");
22062223
CrashReporter = nullptr;
22072224
}
22082225

22092226
void PrintCrashIRInstrumentation::registerCallbacks(
22102227
PassInstrumentationCallbacks &PIC) {
2211-
if (!PrintCrashIR || CrashReporter)
2228+
if ((!PrintOnCrash && PrintOnCrashPath.empty()) || CrashReporter)
22122229
return;
22132230

22142231
sys::AddSignalHandler(SignalHandler, nullptr);
22152232
CrashReporter = this;
22162233

2217-
PIC.registerBeforeNonSkippedPassCallback([&PIC, this](StringRef PassID,
2218-
Any IR) {
2219-
SavedIR.clear();
2220-
raw_string_ostream OS(SavedIR);
2221-
OS << formatv("*** Dump of {0}IR Before Last Pass {1}",
2222-
llvm::forcePrintModuleIR() ? "Module " : "", PassID);
2223-
if (!isInteresting(IR, PassID, PIC.getPassNameForClassName(PassID))) {
2224-
OS << " Filtered Out ***\n";
2225-
return;
2226-
}
2227-
OS << " Started ***\n";
2228-
unwrapAndPrint(OS, IR);
2229-
});
2234+
PIC.registerBeforeNonSkippedPassCallback(
2235+
[&PIC, this](StringRef PassID, Any IR) {
2236+
SavedIR.clear();
2237+
raw_string_ostream OS(SavedIR);
2238+
OS << formatv("*** Dump of {0}IR Before Last Pass {1}",
2239+
llvm::forcePrintModuleIR() ? "Module " : "", PassID);
2240+
if (!isInteresting(IR, PassID, PIC.getPassNameForClassName(PassID))) {
2241+
OS << " Filtered Out ***\n";
2242+
return;
2243+
}
2244+
OS << " Started ***\n";
2245+
unwrapAndPrint(OS, IR);
2246+
});
22302247
}
22312248

22322249
void StandardInstrumentations::registerCallbacks(

llvm/test/Other/print-on-crash.ll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33

44
; RUN: not --crash opt -print-on-crash -passes=trigger-crash < %s 2>&1 | FileCheck %s --check-prefix=CHECK_SIMPLE
55

6+
; RUN: not --crash opt -print-on-crash-path=%t -passes=trigger-crash < %s
7+
; RUN: FileCheck %s --check-prefix=CHECK_SIMPLE --input-file=%t
8+
69
; A test that the signal handler set by the hidden option -print-on-crash
710
; is not called when no pass crashes.
811

9-
; RUN: opt -print-on-crash -passes="default<O2>" < %s 2>&1 | FileCheck %s --check-prefix=CHECK_NO_CRASH
12+
; RUN: opt -disable-output -print-on-crash -passes="default<O2>" < %s 2>&1 | FileCheck %s --check-prefix=CHECK_NO_CRASH --allow-empty
1013

1114
; RUN: not --crash opt -print-on-crash -print-module-scope -passes=trigger-crash < %s 2>&1 | FileCheck %s --check-prefix=CHECK_MODULE
1215

0 commit comments

Comments
 (0)