diff options
Diffstat (limited to 'lib/Support/PrettyStackTrace.cpp')
| -rw-r--r-- | lib/Support/PrettyStackTrace.cpp | 50 | 
1 files changed, 29 insertions, 21 deletions
diff --git a/lib/Support/PrettyStackTrace.cpp b/lib/Support/PrettyStackTrace.cpp index 987778a1bde6..f9f8cab9d933 100644 --- a/lib/Support/PrettyStackTrace.cpp +++ b/lib/Support/PrettyStackTrace.cpp @@ -16,9 +16,8 @@  #include "llvm-c/Core.h"  #include "llvm/ADT/SmallString.h"  #include "llvm/Config/config.h"     // Get autoconf configuration settings -#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Compiler.h"  #include "llvm/Support/Signals.h" -#include "llvm/Support/ThreadLocal.h"  #include "llvm/Support/Watchdog.h"  #include "llvm/Support/raw_ostream.h" @@ -28,7 +27,17 @@  using namespace llvm; -static ManagedStatic<sys::ThreadLocal<const PrettyStackTraceEntry> > PrettyStackTraceHead; +// If backtrace support is not enabled, compile out support for pretty stack +// traces.  This has the secondary effect of not requiring thread local storage +// when backtrace support is disabled. +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) + +// We need a thread local pointer to manage the stack of our stack trace +// objects, but we *really* cannot tolerate destructors running and do not want +// to pay any overhead of synchronizing. As a consequence, we use a raw +// thread-local variable. +static LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead = +    nullptr;  static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){    unsigned NextID = 0; @@ -46,12 +55,12 @@ static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){  /// PrintCurStackTrace - Print the current stack trace to the specified stream.  static void PrintCurStackTrace(raw_ostream &OS) {    // Don't print an empty trace. -  if (!PrettyStackTraceHead->get()) return; +  if (!PrettyStackTraceHead) return;    // If there are pretty stack frames registered, walk and emit them.    OS << "Stack dump:\n"; -  PrintStack(PrettyStackTraceHead->get(), OS); +  PrintStack(PrettyStackTraceHead, OS);    OS.flush();  } @@ -99,28 +108,23 @@ static void CrashHandler(void *) {  #endif  } +// defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#endif +  PrettyStackTraceEntry::PrettyStackTraceEntry() { +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)    // Link ourselves. -  NextEntry = PrettyStackTraceHead->get(); -  PrettyStackTraceHead->set(this); +  NextEntry = PrettyStackTraceHead; +  PrettyStackTraceHead = this; +#endif  }  PrettyStackTraceEntry::~PrettyStackTraceEntry() { -  // Do nothing if PrettyStackTraceHead is uninitialized. This can only happen -  // if a shutdown occurred after we created the PrettyStackTraceEntry. That -  // does occur in the following idiom: -  // -  // PrettyStackTraceProgram X(...); -  // llvm_shutdown_obj Y; -  // -  // Without this check, we may end up removing ourselves from the stack trace -  // after PrettyStackTraceHead has already been destroyed. -  if (!PrettyStackTraceHead.isConstructed()) -    return; -   -  assert(PrettyStackTraceHead->get() == this && +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +  assert(PrettyStackTraceHead == this &&           "Pretty stack trace entry destruction is out of order"); -  PrettyStackTraceHead->set(getNextEntry()); +  PrettyStackTraceHead = getNextEntry(); +#endif  }  void PrettyStackTraceString::print(raw_ostream &OS) const { @@ -135,15 +139,19 @@ void PrettyStackTraceProgram::print(raw_ostream &OS) const {    OS << '\n';  } +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)  static bool RegisterCrashPrinter() {    sys::AddSignalHandler(CrashHandler, nullptr);    return false;  } +#endif  void llvm::EnablePrettyStackTrace() { +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)    // The first time this is called, we register the crash printer.    static bool HandlerRegistered = RegisterCrashPrinter();    (void)HandlerRegistered; +#endif  }  void LLVMEnablePrettyStackTrace() {  | 
