[llvm] [OFFLOAD] Add support for more fine grained debug messages control (PR #165416)
Alex Duran via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 19 20:35:18 PST 2025
================
@@ -198,4 +200,319 @@ inline uint32_t getDebugLevel() {
} \
} while (false)
+// New macros that will allow for more granular control over debugging output
+// Each message can be classified by Component, Type and Level
+// Component: The broad component of the offload runtime emitting the message.
+// Type: A cross-component classification of messages
+// Level: The verbosity level of the message
+//
+// The component is pulled from the TARGET_NAME macro, Type and Level can be
+// defined for each debug message but by default they are "default" and "1"
+// respectively.
+//
+// Constructing messages should be done using C++ stream style syntax.
+//
+// Usage examples:
+// ODBG("type1", 2) << "This is a level 2 message of type1";
+// ODBG("Init") << "This is a default level of the init type";
+// ODBG() << "This is a level 1 message of the default type";
+// ODBG("Init", 3) << NumDevices << " were initialized";
+// ODBG("Kernel") << "Launching " << KernelName << " on device " << DeviceId;
+//
+// Additionally, ODBG_IF_LEVEL can be used to have parts of a stream to provide
+// additional detail at different levels without needing to split the message.
+// Using ODBG_RESET_LEVEL will reset the level back to the original level.
+// E.g.:
+// ODBG("Mapping", 2) << "Function F"
+// << ODBG_IF_LEVEL(3) << " with argument value=" << Arg
+// << ODBG_IF_LEVEL(4) << " and address=" << &Arg
+// << ODBG_RESET_LEVEL() << " called";
+//
+// Similarly the ODBG_ONLY_LEVEL can be used to print parts of a stream only at
+// a specific level, e.g.:
+// ODBG() << "Starting computation "
+// << ODBG_ONLY_LEVEL(1) << "on a device"
+// << ODBG_ONLY_LEVEL(2) << "and mapping data on device" << DeviceId;
+// << ODBG_ONLY_LEVEL(3) << dumpDetailedMappingInfo(DeviceId);
+//
+// Message output can be controlled by setting LIBOMPTARGET_DEBUG or
+// LIBOFFLOAD_DEBUG environment variables. Their syntax is as follows:
+// [integer]|all|<type1>[:<level1>][,<type2>[:<level2>],...]
+//
+// 0 : Disable all debug messages
+// all : Enable all level 1 debug messages
+// integer : Set the default level for all messages
+// <type> : Enable only messages of the specified type and level (more than one
+// can be specified). Components are also supported as
+// types.
+// <level> : Set the verbosity level for the specified type (default is 1)
+//
+// Some examples:
+// LIBOFFLOAD_DEBUG=1 (Print all messages of level 1 or lower)
+// LIBOFFLOAD_DEBUG=5 (Print all messages of level 5 or lower)
+// LIBOFFLOAD_DEBUG=init (Print messages of type "init" of level 1 or lower)
+// LIBOFFLOAD_DEBUG=init:3,mapping:2 (Print messages of type "init" of level 3
+// or lower and messages of type "mapping" of
+// level 2 or lower)
+// LIBOFFLOAD_DEBUG=omptarget:4, init (Print messages from component "omptarget"
+// of level 4 or lower and messages of type
+// "init" of level 1 or lower)
+//
+// For very specific cases where more control is needed, use ODBG_STREAM or
+// ODBG_BASE. See below for details.
+
+namespace llvm::offload::debug {
+
+#ifdef OMPTARGET_DEBUG
+
+struct DebugFilter {
+ StringRef Type;
+ uint32_t Level;
+};
+
+struct DebugSettings {
+ bool Enabled = false;
+ uint32_t DefaultLevel = 1;
+ llvm::SmallVector<DebugFilter> Filters;
+};
+
+/// dbgs - Return a circular-buffered debug stream.
+[[maybe_unused]] static llvm::raw_ostream &dbgs() {
+ // Do one-time initialization in a thread-safe way.
+ static struct dbgstream {
+ llvm::circular_raw_ostream strm;
+
+ dbgstream() : strm(llvm::errs(), "*** Debug Log Output ***\n", 0) {}
+ } thestrm;
+
+ return thestrm.strm;
+}
+
+[[maybe_unused]] static DebugFilter parseDebugFilter(StringRef Filter) {
+ size_t Pos = Filter.find(':');
+ if (Pos == StringRef::npos)
+ return {Filter, 1};
+
+ StringRef Type = Filter.slice(0, Pos);
+ uint32_t Level = 1;
+ if (Filter.slice(Pos + 1, Filter.size()).getAsInteger(10, Level))
+ Level = 1;
+
+ return {Type, Level};
+}
+
+[[maybe_unused]] static DebugSettings &getDebugSettings() {
+ static DebugSettings Settings;
+ static std::once_flag Flag{};
+ std::call_once(Flag, []() {
+ // Eventually, we probably should allow the upper layers to set
+ // debug settings directly according to their own env var or
+ // other methods.
+ // For now, mantain compatibility with existing libomptarget env var
+ // and add a liboffload independent one.
+ char *Env = getenv("LIBOMPTARGET_DEBUG");
+ if (!Env) {
+ Env = getenv("LIBOFFLOAD_DEBUG");
----------------
adurang wrote:
Eventually we want to remove both from here, but for the time being my thought was to give preference to what is already in existence. But I don't have a strong opinion on this, do you prefer to change the orther?
https://github.com/llvm/llvm-project/pull/165416
More information about the llvm-commits
mailing list