2424// ===----------------------------------------------------------------------===//
2525
2626#include " llvm/Support/Debug.h"
27+ #include " llvm/ADT/StringExtras.h"
2728#include " llvm/Support/CommandLine.h"
2829#include " llvm/Support/ManagedStatic.h"
2930#include " llvm/Support/Signals.h"
3031#include " llvm/Support/circular_raw_ostream.h"
3132#include " llvm/Support/raw_ostream.h"
33+ #include < utility>
3234
3335#include " DebugOptions.h"
3436
3840
3941using namespace llvm ;
4042
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 optional
45+ // / integer.
46+ static std::pair<std::string, std::optional<int >>
47+ parseDebugType (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+
4164// Even though LLVM might be built with NDEBUG, define symbols that the code
4265// built without NDEBUG can depend on via the llvm/Support/Debug.h header.
4366namespace llvm {
4467// / Exported boolean set by the -debug option.
4568bool DebugFlag = false ;
4669
47- static ManagedStatic<std::vector<std::string>> CurrentDebugType;
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 level
74+ // / at least as high as the provided level.
75+ static ManagedStatic<std::vector<std::pair<std::string, std::optional<int >>>>
76+ CurrentDebugType;
4877
4978// / Return true if the specified string is the debug type
5079// / specified on the command line, or if none was specified on the command line
5180// / with the -debug-only=X option.
52- bool isCurrentDebugType (const char *DebugType) {
81+ bool isCurrentDebugType (const char *DebugType, int Level ) {
5382 if (CurrentDebugType->empty ())
5483 return true ;
84+ // Track if there is at least one debug type with a level, this is used
85+ // to allow to opt-out of some DebugType and leaving all the others enabled.
86+ bool HasEnabledDebugType = false ;
5587 // See if DebugType is in list. Note: do not use find() as that forces us to
5688 // unnecessarily create an std::string instance.
57- for (auto &d : *CurrentDebugType) {
58- if (d == DebugType)
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 ())
5995 return true ;
96+ return D.second >= Level;
6097 }
61- return false ;
98+ return !HasEnabledDebugType ;
6299}
63100
64101// / Set the current debug type, as if the -debug-only=X
@@ -73,8 +110,11 @@ void setCurrentDebugType(const char *Type) {
73110
74111void setCurrentDebugTypes (const char **Types, unsigned Count) {
75112 CurrentDebugType->clear ();
76- llvm::append_range (*CurrentDebugType, ArrayRef (Types, Count));
113+ CurrentDebugType->reserve (Count);
114+ for (const char *Type : ArrayRef (Types, Count))
115+ CurrentDebugType->push_back (parseDebugType (Type));
77116}
117+
78118} // namespace llvm
79119
80120// All Debug.h functionality is a no-op in NDEBUG mode.
@@ -114,10 +154,10 @@ struct DebugOnlyOpt {
114154 if (Val.empty ())
115155 return ;
116156 DebugFlag = true ;
117- SmallVector<StringRef,8 > dbgTypes ;
118- StringRef (Val).split (dbgTypes , ' ,' , -1 , false );
119- for (auto dbgType : dbgTypes )
120- CurrentDebugType->push_back (std::string (dbgType ));
157+ SmallVector<StringRef, 8 > DbgTypes ;
158+ StringRef (Val).split (DbgTypes , ' ,' , -1 , false );
159+ for (auto DbgType : DbgTypes )
160+ CurrentDebugType->push_back (parseDebugType (DbgType ));
121161 }
122162};
123163} // namespace
@@ -129,8 +169,13 @@ struct CreateDebugOnly {
129169 static void *call () {
130170 return new cl::opt<DebugOnlyOpt, true , cl::parser<std::string>>(
131171 " debug-only" ,
132- cl::desc (" Enable a specific type of debug output (comma separated list "
133- " of types)" ),
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." ),
134179 cl::Hidden, cl::value_desc (" debug string" ),
135180 cl::location (DebugOnlyOptLoc), cl::ValueRequired);
136181 }
0 commit comments