Path: blob/main/contrib/llvm-project/llvm/lib/Support/Debug.cpp
35232 views
//===-- Debug.cpp - An easy way to add debug output to your code ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements a handy way of adding debugging information to your9// code, without it being enabled all of the time, and without having to add10// command line options to enable it.11//12// In particular, just wrap your code with the LLVM_DEBUG() macro, and it will13// be enabled automatically if you specify '-debug' on the command-line.14// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify15// that your debug code belongs to class "foo". Then, on the command line, you16// can specify '-debug-only=foo' to enable JUST the debug information for the17// foo class.18//19// When compiling without assertions, the -debug-* options and all code in20// LLVM_DEBUG() statements disappears, so it does not affect the runtime of the21// code.22//23//===----------------------------------------------------------------------===//2425#include "llvm/Support/Debug.h"26#include "llvm/Support/CommandLine.h"27#include "llvm/Support/ManagedStatic.h"28#include "llvm/Support/Signals.h"29#include "llvm/Support/circular_raw_ostream.h"30#include "llvm/Support/raw_ostream.h"3132#include "DebugOptions.h"3334#undef isCurrentDebugType35#undef setCurrentDebugType36#undef setCurrentDebugTypes3738using namespace llvm;3940// Even though LLVM might be built with NDEBUG, define symbols that the code41// built without NDEBUG can depend on via the llvm/Support/Debug.h header.42namespace llvm {43/// Exported boolean set by the -debug option.44bool DebugFlag = false;4546static ManagedStatic<std::vector<std::string>> CurrentDebugType;4748/// Return true if the specified string is the debug type49/// specified on the command line, or if none was specified on the command line50/// with the -debug-only=X option.51bool isCurrentDebugType(const char *DebugType) {52if (CurrentDebugType->empty())53return true;54// See if DebugType is in list. Note: do not use find() as that forces us to55// unnecessarily create an std::string instance.56for (auto &d : *CurrentDebugType) {57if (d == DebugType)58return true;59}60return false;61}6263/// Set the current debug type, as if the -debug-only=X64/// option were specified. Note that DebugFlag also needs to be set to true for65/// debug output to be produced.66///67void setCurrentDebugTypes(const char **Types, unsigned Count);6869void setCurrentDebugType(const char *Type) {70setCurrentDebugTypes(&Type, 1);71}7273void setCurrentDebugTypes(const char **Types, unsigned Count) {74CurrentDebugType->clear();75for (size_t T = 0; T < Count; ++T)76CurrentDebugType->push_back(Types[T]);77}78} // namespace llvm7980// All Debug.h functionality is a no-op in NDEBUG mode.81#ifndef NDEBUG8283namespace {84struct CreateDebug {85static void *call() {86return new cl::opt<bool, true>("debug", cl::desc("Enable debug output"),87cl::Hidden, cl::location(DebugFlag));88}89};9091// -debug-buffer-size - Buffer the last N characters of debug output92//until program termination.93struct CreateDebugBufferSize {94static void *call() {95return new cl::opt<unsigned>(96"debug-buffer-size",97cl::desc("Buffer the last N characters of debug output "98"until program termination. "99"[default 0 -- immediate print-out]"),100cl::Hidden, cl::init(0));101}102};103} // namespace104105// -debug - Command line option to enable the DEBUG statements in the passes.106// This flag may only be enabled in debug builds.107static ManagedStatic<cl::opt<bool, true>, CreateDebug> Debug;108static ManagedStatic<cl::opt<unsigned>, CreateDebugBufferSize> DebugBufferSize;109110namespace {111112struct DebugOnlyOpt {113void operator=(const std::string &Val) const {114if (Val.empty())115return;116DebugFlag = true;117SmallVector<StringRef,8> dbgTypes;118StringRef(Val).split(dbgTypes, ',', -1, false);119for (auto dbgType : dbgTypes)120CurrentDebugType->push_back(std::string(dbgType));121}122};123} // namespace124125static DebugOnlyOpt DebugOnlyOptLoc;126127namespace {128struct CreateDebugOnly {129static void *call() {130return new cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>(131"debug-only",132cl::desc("Enable a specific type of debug output (comma separated list "133"of types)"),134cl::Hidden, cl::value_desc("debug string"),135cl::location(DebugOnlyOptLoc), cl::ValueRequired);136}137};138} // namespace139140static ManagedStatic<cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>,141CreateDebugOnly>142DebugOnly;143144void llvm::initDebugOptions() {145*Debug;146*DebugBufferSize;147*DebugOnly;148}149150// Signal handlers - dump debug output on termination.151static void debug_user_sig_handler(void *Cookie) {152// This is a bit sneaky. Since this is under #ifndef NDEBUG, we153// know that debug mode is enabled and dbgs() really is a154// circular_raw_ostream. If NDEBUG is defined, then dbgs() ==155// errs() but this will never be invoked.156llvm::circular_raw_ostream &dbgout =157static_cast<circular_raw_ostream &>(llvm::dbgs());158dbgout.flushBufferWithBanner();159}160161/// dbgs - Return a circular-buffered debug stream.162raw_ostream &llvm::dbgs() {163// Do one-time initialization in a thread-safe way.164static struct dbgstream {165circular_raw_ostream strm;166167dbgstream()168: strm(errs(), "*** Debug Log Output ***\n",169(!EnableDebugBuffering || !DebugFlag) ? 0 : *DebugBufferSize) {170if (EnableDebugBuffering && DebugFlag && *DebugBufferSize != 0)171// TODO: Add a handler for SIGUSER1-type signals so the user can172// force a debug dump.173sys::AddSignalHandler(&debug_user_sig_handler, nullptr);174// Otherwise we've already set the debug stream buffer size to175// zero, disabling buffering so it will output directly to errs().176}177} thestrm;178179return thestrm.strm;180}181182#else183// Avoid "has no symbols" warning.184namespace llvm {185/// dbgs - Return errs().186raw_ostream &dbgs() {187return errs();188}189}190void llvm::initDebugOptions() {}191#endif192193/// EnableDebugBuffering - Turn on signal handler installation.194///195bool llvm::EnableDebugBuffering = false;196197198