- Notifications
You must be signed in to change notification settings - Fork 15.3k
[OFFLOAD] Add support for more fine grained debug messages control #165416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
2965164 7bc7ce8 c9fc54a da323af 562c93e b13c116 948354b 04e44a7 a045ce8 File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -42,6 +42,8 @@ | |
| #include <mutex> | ||
| #include <string> | ||
| | ||
| #include "llvm/Support/circular_raw_ostream.h" | ||
| | ||
| /// 32-Bit field data attributes controlling information presented to the user. | ||
| enum OpenMPInfoType : uint32_t { | ||
| // Print data arguments and attributes upon entering an OpenMP device kernel. | ||
| | @@ -198,4 +200,200 @@ 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. | ||
| // | ||
| // For liboffload and plugins, use OFFLOAD_DEBUG(...) | ||
adurang marked this conversation as resolved. Outdated Show resolved Hide resolved | ||
| // For libomptarget, use OPENMP_DEBUG(...) | ||
| // Constructing messages should be done using C++ stream style syntax. | ||
adurang marked this conversation as resolved. Outdated Show resolved Hide resolved | ||
| // | ||
| // Usage examples: | ||
| // OFFLOAD_DEBUG("type1", 2, "This is a level 2 message of type1"); | ||
| // OFFLOAD_DEBUG("Init", "This is a default level of the init type"); | ||
| // OPENMP_DEBUG("This is a level 1 message of the default type"); | ||
| // OFFLOAD_DEBUG("Init", 3, NumDevices << " were initialized\n"); | ||
| // OFFLOAD_DEBUG("Kernel", "Starting kernel " << KernelName << " on device " << | ||
| // 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>],...] | ||
adurang marked this conversation as resolved. Outdated Show resolved Hide resolved | ||
| // | ||
| // 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 OFFLOAD_DEBUG_RAW | ||
| // or OFFLOAD_DEBUG_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. | ||
| inline 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; | ||
| } | ||
| | ||
| inline 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}; | ||
| } | ||
| | ||
| inline DebugSettings &getDebugSettings() { | ||
| static DebugSettings Settings; | ||
| static std::once_flag Flag{}; | ||
| std::call_once(Flag, []() { | ||
| printf("Configuring debug settings\n"); | ||
adurang marked this conversation as resolved. Outdated Show resolved Hide resolved | ||
| // 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"); | ||
adurang marked this conversation as resolved. Show resolved Hide resolved | ||
| if (!Env) { | ||
| Env = getenv("LIBOFFLOAD_DEBUG"); | ||
| Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, Contributor Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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 order? Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guess it's not a big deal, but could definitely be simplified | ||
| if (!Env) | ||
| return; | ||
| } | ||
| | ||
| StringRef EnvRef(Env); | ||
| if (EnvRef == "0") | ||
| return; | ||
| | ||
| Settings.Enabled = true; | ||
| if (EnvRef.equals_insensitive("all")) | ||
| return; | ||
| | ||
| if (!EnvRef.getAsInteger(10, Settings.DefaultLevel)) | ||
| return; | ||
| | ||
| Settings.DefaultLevel = 1; | ||
| | ||
| SmallVector<StringRef> DbgTypes; | ||
| EnvRef.split(DbgTypes, ',', -1, false); | ||
| | ||
| for (auto &DT : DbgTypes) | ||
adurang marked this conversation as resolved. Outdated Show resolved Hide resolved | ||
| Settings.Filters.push_back(parseDebugFilter(DT)); | ||
| }); | ||
| | ||
| return Settings; | ||
| } | ||
| | ||
| inline bool isDebugEnabled() { return getDebugSettings().Enabled; } | ||
| | ||
| inline bool shouldPrintDebug(const char *Component, const char *Type, | ||
| uint32_t Level) { | ||
| const auto &Settings = getDebugSettings(); | ||
| if (!Settings.Enabled) | ||
| return false; | ||
| | ||
| if (Settings.Filters.empty()) | ||
| return Level <= Settings.DefaultLevel; | ||
| | ||
| for (const auto &DT : Settings.Filters) { | ||
| if (DT.Level < Level) | ||
| continue; | ||
| if (DT.Type.equals_insensitive(Type)) | ||
| return true; | ||
| if (DT.Type.equals_insensitive(Component)) | ||
| return true; | ||
| } | ||
| | ||
| return false; | ||
| } | ||
| | ||
| #define OFFLOAD_DEBUG_BASE(Component, Type, Level, ...) \ | ||
| do { \ | ||
| if (llvm::offload::debug::isDebugEnabled() && \ | ||
| llvm::offload::debug::shouldPrintDebug(Component, Type, Level)) \ | ||
| __VA_ARGS__; \ | ||
| } while (0) | ||
| | ||
| #define OFFLOAD_DEBUG_RAW(Type, Level, X) \ | ||
| OFFLOAD_DEBUG_BASE(GETNAME(TARGET_NAME), Type, Level, X) | ||
| | ||
| #define OFFLOAD_DEBUG_1(X) \ | ||
| OFFLOAD_DEBUG_BASE(GETNAME(TARGET_NAME), "default", 1, \ | ||
| llvm::offload::debug::dbgs() \ | ||
| << DEBUG_PREFIX << " --> " << X) | ||
| | ||
| #define OFFLOAD_DEBUG_2(Type, X) \ | ||
| OFFLOAD_DEBUG_BASE(GETNAME(TARGET_NAME), Type, 1, \ | ||
| llvm::offload::debug::dbgs() \ | ||
| << DEBUG_PREFIX << " --> " << X) | ||
| | ||
| #define OFFLOAD_DEBUG_3(Type, Level, X) \ | ||
| OFFLOAD_DEBUG_BASE(GETNAME(TARGET_NAME), Type, Level, \ | ||
| llvm::offload::debug::dbgs() \ | ||
| << DEBUG_PREFIX << " --> " << X) | ||
| | ||
| #define OFFLOAD_SELECT(Type, Level, X, NArgs, ...) OFFLOAD_DEBUG_##NArgs | ||
| | ||
| // To be used in liboffload and plugins | ||
| #define OFFLOAD_DEBUG(...) OFFLOAD_SELECT(__VA_ARGS__, 3, 2, 1)(__VA_ARGS__) | ||
| | ||
| // To be used in libomptarget only | ||
| #define OPENMP_DEBUG(...) OFFLOAD_DEBUG(__VA_ARGS__) | ||
| | ||
| #else | ||
| | ||
| // Don't print anything if debugging is disabled | ||
| #define OFFLOAD_DEBUG_BASE(Component, Type, Level, ...) | ||
| #define OFFLOAD_DEBUG_RAW(Type, Level, X) | ||
| #define OFFLOAD_DEBUG(...) | ||
| #define OPENMP_DEBUG(...) | ||
| | ||
| #endif | ||
| | ||
| } // namespace llvm::offload::debug | ||
| | ||
| #endif // OMPTARGET_SHARED_DEBUG_H | ||
Uh oh!
There was an error while loading. Please reload this page.