241 lines · cpp
1//===-- Debug.cpp - An easy way to add debug output to your code ----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements a handy way of adding debugging information to your10// code, without it being enabled all of the time, and without having to add11// command line options to enable it.12//13// In particular, just wrap your code with the LLVM_DEBUG() macro, and it will14// be enabled automatically if you specify '-debug' on the command-line.15// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify16// that your debug code belongs to class "foo". Then, on the command line, you17// can specify '-debug-only=foo' to enable JUST the debug information for the18// foo class.19//20// When compiling without assertions, the -debug-* options and all code in21// LLVM_DEBUG() statements disappears, so it does not affect the runtime of the22// code.23//24//===----------------------------------------------------------------------===//25 26#include "llvm/Support/Debug.h"27#include "llvm/ADT/StringExtras.h"28#include "llvm/Support/CommandLine.h"29#include "llvm/Support/ManagedStatic.h"30#include "llvm/Support/Signals.h"31#include "llvm/Support/circular_raw_ostream.h"32#include "llvm/Support/raw_ostream.h"33#include <utility>34 35#include "DebugOptions.h"36 37#undef isCurrentDebugType38#undef setCurrentDebugType39#undef setCurrentDebugTypes40 41using namespace llvm;42 43/// Parse a debug type string into a pair of the debug type and the debug level.44/// The expected format is "type[:level]", where the level is an optional45/// integer.46static std::pair<std::string, std::optional<int>>47parseDebugType(StringRef DbgType) {48 std::optional<int> Level;49 size_t ColonPos = DbgType.find(':');50 if (ColonPos != StringRef::npos) {51 StringRef LevelStr = DbgType.substr(ColonPos + 1);52 DbgType = DbgType.take_front(ColonPos);53 if (LevelStr.empty())54 Level = 0;55 else {56 int parsedLevel;57 if (to_integer(LevelStr, parsedLevel, 10))58 Level = parsedLevel;59 }60 }61 return std::make_pair(DbgType.str(), Level);62}63 64// Even though LLVM might be built with NDEBUG, define symbols that the code65// built without NDEBUG can depend on via the llvm/Support/Debug.h header.66namespace llvm {67/// Exported boolean set by the -debug option.68bool DebugFlag = false;69 70/// The current debug type and an optional debug level.71/// The debug level is the verbosity of the debug output.72/// 0 is a special level that acts as an opt-out for this specific debug type.73/// If provided, the debug output is enabled only if the user specified a level74/// at least as high as the provided level.75static ManagedStatic<std::vector<std::pair<std::string, std::optional<int>>>>76 CurrentDebugType;77 78/// Return true if the specified string is the debug type79/// specified on the command line, or if none was specified on the command line80/// with the -debug-only=X option.81bool isCurrentDebugType(const char *DebugType, int Level) {82 if (CurrentDebugType->empty())83 return true;84 // Track if there is at least one debug type with a level, this is used85 // to allow to opt-out of some DebugType and leaving all the others enabled.86 bool HasEnabledDebugType = false;87 // See if DebugType is in list. Note: do not use find() as that forces us to88 // unnecessarily create an std::string instance.89 for (auto &D : *CurrentDebugType) {90 HasEnabledDebugType =91 HasEnabledDebugType || (!D.second.has_value() || D.second.value() > 0);92 if (D.first != DebugType)93 continue;94 if (!D.second.has_value())95 return true;96 return D.second >= Level;97 }98 return !HasEnabledDebugType;99}100 101/// Set the current debug type, as if the -debug-only=X102/// option were specified. Note that DebugFlag also needs to be set to true for103/// debug output to be produced.104///105void setCurrentDebugTypes(const char **Types, unsigned Count);106 107void setCurrentDebugType(const char *Type) {108 setCurrentDebugTypes(&Type, 1);109}110 111void setCurrentDebugTypes(const char **Types, unsigned Count) {112 CurrentDebugType->clear();113 CurrentDebugType->reserve(Count);114 for (const char *Type : ArrayRef(Types, Count))115 CurrentDebugType->push_back(parseDebugType(Type));116}117 118} // namespace llvm119 120// All Debug.h functionality is a no-op in NDEBUG mode.121#ifndef NDEBUG122 123namespace {124struct CreateDebug {125 static void *call() {126 return new cl::opt<bool, true>("debug", cl::desc("Enable debug output"),127 cl::Hidden, cl::location(DebugFlag));128 }129};130 131// -debug-buffer-size - Buffer the last N characters of debug output132//until program termination.133struct CreateDebugBufferSize {134 static void *call() {135 return new cl::opt<unsigned>(136 "debug-buffer-size",137 cl::desc("Buffer the last N characters of debug output "138 "until program termination. "139 "[default 0 -- immediate print-out]"),140 cl::Hidden, cl::init(0));141 }142};143} // namespace144 145// -debug - Command line option to enable the DEBUG statements in the passes.146// This flag may only be enabled in debug builds.147static ManagedStatic<cl::opt<bool, true>, CreateDebug> Debug;148static ManagedStatic<cl::opt<unsigned>, CreateDebugBufferSize> DebugBufferSize;149 150namespace {151 152struct DebugOnlyOpt {153 void operator=(const std::string &Val) const {154 if (Val.empty())155 return;156 DebugFlag = true;157 SmallVector<StringRef, 8> DbgTypes;158 StringRef(Val).split(DbgTypes, ',', -1, false);159 for (auto DbgType : DbgTypes)160 CurrentDebugType->push_back(parseDebugType(DbgType));161 }162};163} // namespace164 165static DebugOnlyOpt DebugOnlyOptLoc;166 167namespace {168struct CreateDebugOnly {169 static void *call() {170 return new cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>(171 "debug-only",172 cl::desc(173 "Enable a specific type of debug output (comma separated list "174 "of types using the format \"type[:level]\", where the level "175 "is an optional integer. The level can be set to 1, 2, 3, etc. to "176 "control the verbosity of the output. Setting a debug-type level "177 "to zero acts as an opt-out for this specific debug-type without "178 "affecting the others."),179 cl::Hidden, cl::value_desc("debug string"),180 cl::location(DebugOnlyOptLoc), cl::ValueRequired);181 }182};183} // namespace184 185static ManagedStatic<cl::opt<DebugOnlyOpt, true, cl::parser<std::string>>,186 CreateDebugOnly>187 DebugOnly;188 189void llvm::initDebugOptions() {190 *Debug;191 *DebugBufferSize;192 *DebugOnly;193}194 195// Signal handlers - dump debug output on termination.196static void debug_user_sig_handler(void *Cookie) {197 // This is a bit sneaky. Since this is under #ifndef NDEBUG, we198 // know that debug mode is enabled and dbgs() really is a199 // circular_raw_ostream. If NDEBUG is defined, then dbgs() ==200 // errs() but this will never be invoked.201 llvm::circular_raw_ostream &dbgout =202 static_cast<circular_raw_ostream &>(llvm::dbgs());203 dbgout.flushBufferWithBanner();204}205 206/// dbgs - Return a circular-buffered debug stream.207raw_ostream &llvm::dbgs() {208 // Do one-time initialization in a thread-safe way.209 static struct dbgstream {210 circular_raw_ostream strm;211 212 dbgstream()213 : strm(errs(), "*** Debug Log Output ***\n",214 (!EnableDebugBuffering || !DebugFlag) ? 0 : *DebugBufferSize) {215 if (EnableDebugBuffering && DebugFlag && *DebugBufferSize != 0)216 // TODO: Add a handler for SIGUSER1-type signals so the user can217 // force a debug dump.218 sys::AddSignalHandler(&debug_user_sig_handler, nullptr);219 // Otherwise we've already set the debug stream buffer size to220 // zero, disabling buffering so it will output directly to errs().221 }222 } thestrm;223 224 return thestrm.strm;225}226 227#else228// Avoid "has no symbols" warning.229namespace llvm {230 /// dbgs - Return errs().231 raw_ostream &dbgs() {232 return errs();233 }234}235void llvm::initDebugOptions() {}236#endif237 238/// EnableDebugBuffering - Turn on signal handler installation.239///240bool llvm::EnableDebugBuffering = false;241