Index: llvm/include/llvm/Passes/StandardInstrumentations.h =================================================================== --- llvm/include/llvm/Passes/StandardInstrumentations.h +++ llvm/include/llvm/Passes/StandardInstrumentations.h @@ -73,6 +73,18 @@ bool DebugLogging; }; +// Print IR on crash. +class PrintCrashIRInstrumentation { +public: + PrintCrashIRInstrumentation() : SavedIR("IR Unknown") {} + void registerCallbacks(PassInstrumentationCallbacks &PIC); + + std::string getSavedIR() { return SavedIR; } + +protected: + std::string SavedIR; +}; + /// This class provides an interface to register all the standard pass /// instrumentations and manages their state (if any). class StandardInstrumentations { @@ -80,6 +92,7 @@ PrintPassInstrumentation PrintPass; TimePassesHandler TimePasses; OptNoneInstrumentation OptNone; + PrintCrashIRInstrumentation PrintCrashIR; public: StandardInstrumentations(bool DebugLogging) : PrintPass(DebugLogging) {} Index: llvm/lib/Passes/StandardInstrumentations.cpp =================================================================== --- llvm/lib/Passes/StandardInstrumentations.cpp +++ llvm/lib/Passes/StandardInstrumentations.cpp @@ -15,6 +15,7 @@ #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/ADT/Any.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LoopInfo.h" @@ -23,9 +24,11 @@ #include "llvm/IR/Module.h" #include "llvm/IR/PassInstrumentation.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Signals.h" #include using namespace llvm; @@ -43,6 +46,14 @@ cl::desc("Print all pass management debugging information. " "`-debug-pass-manager` must also be specified")); +// A hidden option to print the IR that was being processed when a pass +// crashes. Note that nothing will be output if there is no crash. This +// option is affected by the -print-module-scope option. +static cl::opt + PrintCrashIR("print-crash-IR", + cl::desc("Print the last form of the IR before crash"), + cl::init(false), cl::Hidden); + namespace { /// Extracting Module out of \p IR unit. Also fills a textual description @@ -189,6 +200,11 @@ llvm_unreachable("Unknown wrapped IR type"); } +void CrashedIRReporter(void *P) { + PrintCrashIRInstrumentation *PCII = (PrintCrashIRInstrumentation *)P; + dbgs() << PCII->getSavedIR(); +} + } // namespace PrintIRInstrumentation::~PrintIRInstrumentation() { @@ -338,10 +354,29 @@ }); } +void PrintCrashIRInstrumentation::registerCallbacks( + PassInstrumentationCallbacks &PIC) { + if (!PrintCrashIR) + return; + + sys::AddSignalHandler(CrashedIRReporter, this); + + PIC.registerBeforePassCallback([this](StringRef PassID, Any IR) { + SavedIR.clear(); + SmallString<80> Banner = + formatv("*** Dump of {0}IR Before Last Pass {1} Started ***", + llvm::forcePrintModuleIR() ? "Module " : "", PassID); + raw_string_ostream OS(SavedIR); + unwrapAndPrint(OS, IR, Banner, llvm::forcePrintModuleIR()); + return true; + }); +} + void StandardInstrumentations::registerCallbacks( PassInstrumentationCallbacks &PIC) { PrintIR.registerCallbacks(PIC); PrintPass.registerCallbacks(PIC); TimePasses.registerCallbacks(PIC); OptNone.registerCallbacks(PIC); + PrintCrashIR.registerCallbacks(PIC); }