From ec6091f4de8a530af198f259db1622e99b2bd954 Mon Sep 17 00:00:00 2001 From: Alex Duran Date: Tue, 2 Dec 2025 23:45:23 +0100 Subject: [PATCH] [OFFLOAD][LIBOMPTARGET] Start to update debug messages in libomptarget (#170265) * Add compatibility support for DP and REPORT macros * Define a set of predefined Debug Type for libomptarget * Start to update libomptarget files (OffloadRTL.cpp, device.cpp) --- offload/include/Shared/Debug.h | 323 +++++++++++++++++----------- offload/libomptarget/OffloadRTL.cpp | 9 +- offload/libomptarget/device.cpp | 15 +- 3 files changed, 205 insertions(+), 142 deletions(-) diff --git a/offload/include/Shared/Debug.h b/offload/include/Shared/Debug.h index 41613a37c354..9e657e64484c 100644 --- a/offload/include/Shared/Debug.h +++ b/offload/include/Shared/Debug.h @@ -39,6 +39,7 @@ #define OMPTARGET_SHARED_DEBUG_H #include +#include #include #include @@ -78,17 +79,6 @@ inline std::atomic &getInfoLevelInternal() { inline uint32_t getInfoLevel() { return getInfoLevelInternal().load(); } -inline uint32_t getDebugLevel() { - static uint32_t DebugLevel = 0; - static std::once_flag Flag{}; - std::call_once(Flag, []() { - if (char *EnvStr = getenv("LIBOMPTARGET_DEBUG")) - DebugLevel = std::stoi(EnvStr); - }); - - return DebugLevel; -} - #undef USED #undef GCC_VERSION @@ -147,46 +137,11 @@ inline uint32_t getDebugLevel() { fprintf(_stdDst, __VA_ARGS__); \ } while (0) -// Debugging messages -#ifdef OMPTARGET_DEBUG -#include - -#define DEBUGP(prefix, ...) \ - { \ - fprintf(stderr, "%s --> ", prefix); \ - fprintf(stderr, __VA_ARGS__); \ - } - -/// Emit a message for debugging -#define DP(...) \ - do { \ - if (getDebugLevel() > 0) { \ - DEBUGP(DEBUG_PREFIX, __VA_ARGS__); \ - } \ - } while (false) - -/// Emit a message for debugging or failure if debugging is disabled -#define REPORT(...) \ - do { \ - if (getDebugLevel() > 0) { \ - DP(__VA_ARGS__); \ - } else { \ - FAILURE_MESSAGE(__VA_ARGS__); \ - } \ - } while (false) -#else -#define DEBUGP(prefix, ...) \ - {} -#define DP(...) \ - {} -#define REPORT(...) FAILURE_MESSAGE(__VA_ARGS__); -#endif // OMPTARGET_DEBUG - /// Emit a message giving the user extra information about the runtime if #define INFO(_flags, _id, ...) \ do { \ - if (getDebugLevel() > 0) { \ - DEBUGP(DEBUG_PREFIX, __VA_ARGS__); \ + if (::llvm::offload::debug::isDebugEnabled()) { \ + DP(__VA_ARGS__); \ } else if (getInfoLevel() & _flags) { \ INFO_MESSAGE(_id, __VA_ARGS__); \ } \ @@ -203,17 +158,92 @@ inline uint32_t getDebugLevel() { namespace llvm::offload::debug { -#ifdef OMPTARGET_DEBUG +/// A raw_ostream that tracks `\n` and print the prefix after each +/// newline. Based on raw_ldbg_ostream from Support/DebugLog.h +class LLVM_ABI odbg_ostream final : public raw_ostream { +public: + enum IfLevel : uint32_t; + enum OnlyLevel : uint32_t; -struct DebugFilter { - StringRef Type; - uint32_t Level; -}; +private: + std::string Prefix; + raw_ostream &Os; + uint32_t BaseLevel; + bool ShouldPrefixNextString; + bool ShouldEmitNewLineOnDestruction; + bool NeedEndNewLine = false; -struct DebugSettings { - bool Enabled = false; - uint32_t DefaultLevel = 1; - llvm::SmallVector Filters; + /// If the stream is muted, writes to it are ignored + bool Muted = false; + + /// Split the line on newlines and insert the prefix before each + /// newline. Forward everything to the underlying stream. + void write_impl(const char *Ptr, size_t Size) final { + if (Muted) + return; + + NeedEndNewLine = false; + auto Str = StringRef(Ptr, Size); + auto Eol = Str.find('\n'); + // Handle `\n` occurring in the string, ensure to print the prefix at the + // beginning of each line. + while (Eol != StringRef::npos) { + // Take the line up to the newline (including the newline). + StringRef Line = Str.take_front(Eol + 1); + if (!Line.empty()) + writeWithPrefix(Line); + // We printed a newline, record here to print a prefix. + ShouldPrefixNextString = true; + Str = Str.drop_front(Eol + 1); + Eol = Str.find('\n'); + } + if (!Str.empty()) { + writeWithPrefix(Str); + NeedEndNewLine = true; + } + } + void emitPrefix() { Os.write(Prefix.c_str(), Prefix.size()); } + void writeWithPrefix(StringRef Str) { + if (ShouldPrefixNextString) { + emitPrefix(); + ShouldPrefixNextString = false; + } + Os.write(Str.data(), Str.size()); + } + +public: + explicit odbg_ostream(std::string Prefix, raw_ostream &Os, uint32_t BaseLevel, + bool ShouldPrefixNextString = true, + bool ShouldEmitNewLineOnDestruction = true) + : Prefix(std::move(Prefix)), Os(Os), BaseLevel(BaseLevel), + ShouldPrefixNextString(ShouldPrefixNextString), + ShouldEmitNewLineOnDestruction(ShouldEmitNewLineOnDestruction) { + SetUnbuffered(); + } + ~odbg_ostream() final { + if (ShouldEmitNewLineOnDestruction && NeedEndNewLine) + Os << '\n'; + } + odbg_ostream(const odbg_ostream &) = delete; + odbg_ostream &operator=(const odbg_ostream &) = delete; + odbg_ostream(odbg_ostream &&other) : Os(other.Os) { + Prefix = std::move(other.Prefix); + BaseLevel = other.BaseLevel; + ShouldPrefixNextString = other.ShouldPrefixNextString; + ShouldEmitNewLineOnDestruction = other.ShouldEmitNewLineOnDestruction; + NeedEndNewLine = other.NeedEndNewLine; + Muted = other.Muted; + } + + /// Forward the current_pos method to the underlying stream. + uint64_t current_pos() const final { return Os.tell(); } + + /// Some of the `<<` operators expect an lvalue, so we trick the type + /// system. + odbg_ostream &asLvalue() { return *this; } + + void shouldMute(const IfLevel Filter) { Muted = Filter > BaseLevel; } + void shouldMute(const OnlyLevel Filter) { Muted = BaseLevel != Filter; } }; /// dbgs - Return a circular-buffered debug stream. @@ -228,6 +258,19 @@ struct DebugSettings { return thestrm.strm; } +#ifdef OMPTARGET_DEBUG + +struct DebugFilter { + StringRef Type; + uint32_t Level; +}; + +struct DebugSettings { + bool Enabled = false; + uint32_t DefaultLevel = 1; + llvm::SmallVector Filters; +}; + [[maybe_unused]] static DebugFilter parseDebugFilter(StringRef Filter) { size_t Pos = Filter.find(':'); if (Pos == StringRef::npos) @@ -309,80 +352,6 @@ shouldPrintDebug(const char *Component, const char *Type, uint32_t &Level) { return false; } -/// A raw_ostream that tracks `\n` and print the prefix after each -/// newline. Based on raw_ldbg_ostream from Support/DebugLog.h -class LLVM_ABI odbg_ostream final : public raw_ostream { -public: - enum IfLevel : uint32_t; - enum OnlyLevel : uint32_t; - -private: - std::string Prefix; - raw_ostream &Os; - uint32_t BaseLevel; - bool ShouldPrefixNextString; - bool ShouldEmitNewLineOnDestruction; - - /// If the stream is muted, writes to it are ignored - bool Muted = false; - - /// Split the line on newlines and insert the prefix before each - /// newline. Forward everything to the underlying stream. - void write_impl(const char *Ptr, size_t Size) final { - if (Muted) - return; - - auto Str = StringRef(Ptr, Size); - auto Eol = Str.find('\n'); - // Handle `\n` occurring in the string, ensure to print the prefix at the - // beginning of each line. - while (Eol != StringRef::npos) { - // Take the line up to the newline (including the newline). - StringRef Line = Str.take_front(Eol + 1); - if (!Line.empty()) - writeWithPrefix(Line); - // We printed a newline, record here to print a prefix. - ShouldPrefixNextString = true; - Str = Str.drop_front(Eol + 1); - Eol = Str.find('\n'); - } - if (!Str.empty()) - writeWithPrefix(Str); - } - void emitPrefix() { Os.write(Prefix.c_str(), Prefix.size()); } - void writeWithPrefix(StringRef Str) { - if (ShouldPrefixNextString) { - emitPrefix(); - ShouldPrefixNextString = false; - } - Os.write(Str.data(), Str.size()); - } - -public: - explicit odbg_ostream(std::string Prefix, raw_ostream &Os, uint32_t BaseLevel, - bool ShouldPrefixNextString = true, - bool ShouldEmitNewLineOnDestruction = false) - : Prefix(std::move(Prefix)), Os(Os), BaseLevel(BaseLevel), - ShouldPrefixNextString(ShouldPrefixNextString), - ShouldEmitNewLineOnDestruction(ShouldEmitNewLineOnDestruction) { - SetUnbuffered(); - } - ~odbg_ostream() final { - if (ShouldEmitNewLineOnDestruction) - Os << '\n'; - } - - /// Forward the current_pos method to the underlying stream. - uint64_t current_pos() const final { return Os.tell(); } - - /// Some of the `<<` operators expect an lvalue, so we trick the type - /// system. - odbg_ostream &asLvalue() { return *this; } - - void shouldMute(const IfLevel Filter) { Muted = Filter > BaseLevel; } - void shouldMute(const OnlyLevel Filter) { Muted = BaseLevel != Filter; } -}; - /// Compute the prefix for the debug log in the form of: /// "Component --> " [[maybe_unused]] static std::string computePrefix(StringRef Component, @@ -463,6 +432,8 @@ static inline raw_ostream &operator<<(raw_ostream &Os, #else +inline bool isDebugEnabled() { return false; } + #define ODBG_NULL \ for (bool _c = false; _c; _c = false) \ ::llvm::nulls() @@ -479,4 +450,94 @@ static inline raw_ostream &operator<<(raw_ostream &Os, } // namespace llvm::offload::debug +namespace llvm::omp::target::debug { +using namespace llvm::offload::debug; + +enum OmpDebugLevel : uint32_t { + ODL_Default = 1, + ODL_Error = ODL_Default, + ODL_Detailed = 2, + ODL_Verbose = 3, + ODL_VeryVerbose = 4, + ODL_Dumping = 5 +}; + +/* Debug types to use in libomptarget */ +constexpr const char *ODT_Init = "Init"; +constexpr const char *ODT_Mapping = "Mapping"; +constexpr const char *ODT_Kernel = "Kernel"; +constexpr const char *ODT_DataTransfer = "DataTransfer"; +constexpr const char *ODT_Sync = "Sync"; +constexpr const char *ODT_Deinit = "Deinit"; +constexpr const char *ODT_Error = "Error"; +constexpr const char *ODT_KernelArgs = "KernelArgs"; +constexpr const char *ODT_MappingExists = "MappingExists"; +constexpr const char *ODT_DumpTable = "DumpTable"; +constexpr const char *ODT_MappingChanged = "MappingChanged"; +constexpr const char *ODT_PluginKernel = "PluginKernel"; +constexpr const char *ODT_EmptyMapping = "EmptyMapping"; + +static inline odbg_ostream reportErrorStream() { +#ifdef OMPTARGET_DEBUG + if (::llvm::offload::debug::isDebugEnabled()) { + uint32_t RealLevel = ODL_Error; + if (::llvm::offload::debug::shouldPrintDebug(GETNAME(TARGET_NAME), + (ODT_Error), RealLevel)) + return odbg_ostream{ + ::llvm::offload::debug::computePrefix(DEBUG_PREFIX, ODT_Error), + ::llvm::offload::debug::dbgs(), RealLevel}; + else + return odbg_ostream{"", ::llvm::nulls(), 1}; + } +#endif + return odbg_ostream{GETNAME(TARGET_NAME) " error: ", + ::llvm::offload::debug::dbgs(), ODL_Error}; +} + +#ifdef OMPTARGET_DEBUG +// Deprecated debug print macros +[[maybe_unused]] static std::string formatToStr(const char *format, ...) { + va_list args; + va_start(args, format); + size_t len = std::vsnprintf(NULL, 0, format, args); + va_end(args); + llvm::SmallVector vec(len + 1); + va_start(args, format); + std::vsnprintf(&vec[0], len + 1, format, args); + va_end(args); + return &vec[0]; +} + +// helper macro to support old DP and REPORT macros with printf syntax +#define FORMAT_TO_STR(Format, ...) \ + ::llvm::omp::target::debug::formatToStr(Format __VA_OPT__(, ) __VA_ARGS__) + +#define DP(...) ODBG() << FORMAT_TO_STR(__VA_ARGS__); + +#define REPORT_INT_OLD(...) \ + do { \ + if (::llvm::offload::debug::isDebugEnabled()) { \ + ODBG(::llvm::omp::target::debug::ODT_Error, \ + ::llvm::omp::target::debug::ODL_Error) \ + << FORMAT_TO_STR(__VA_ARGS__); \ + } else { \ + FAILURE_MESSAGE(__VA_ARGS__); \ + } \ + } while (false) + +#else +#define DP(...) \ + { \ + } +#define REPORT_INT_OLD(...) FAILURE_MESSAGE(__VA_ARGS__); +#endif // OMPTARGET_DEBUG + +// This is used for the new style REPORT macro +#define REPORT_INT() ::llvm::omp::target::debug::reportErrorStream() + +// Make REPORT compatible with old and new syntax +#define REPORT(...) REPORT_INT##__VA_OPT__(_OLD)(__VA_ARGS__) + +} // namespace llvm::omp::target::debug + #endif // OMPTARGET_SHARED_DEBUG_H diff --git a/offload/libomptarget/OffloadRTL.cpp b/offload/libomptarget/OffloadRTL.cpp index 0ae325bf496d..3a18d76aaae1 100644 --- a/offload/libomptarget/OffloadRTL.cpp +++ b/offload/libomptarget/OffloadRTL.cpp @@ -19,6 +19,7 @@ #ifdef OMPT_SUPPORT extern void llvm::omp::target::ompt::connectLibrary(); #endif +using namespace llvm::omp::target::debug; static std::mutex PluginMtx; static uint32_t RefCount = 0; @@ -35,7 +36,7 @@ void initRuntime() { RefCount++; if (RefCount == 1) { - ODBG() << "Init offload library!"; + ODBG(ODT_Init) << "Init offload library!"; #ifdef OMPT_SUPPORT // Initialize OMPT first llvm::omp::target::ompt::connectLibrary(); @@ -54,12 +55,12 @@ void deinitRuntime() { assert(PM && "Runtime not initialized"); if (RefCount == 1) { - DP("Deinit offload library!\n"); + ODBG(ODT_Deinit) << "Deinit offload library!"; // RTL deinitialization has started RTLAlive = false; while (RTLOngoingSyncs > 0) { - DP("Waiting for ongoing syncs to finish, count: %d\n", - RTLOngoingSyncs.load()); + ODBG(ODT_Sync) << "Waiting for ongoing syncs to finish, count:" + << RTLOngoingSyncs.load(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } PM->deinit(); diff --git a/offload/libomptarget/device.cpp b/offload/libomptarget/device.cpp index bf271b2a24aa..659ef689f67e 100644 --- a/offload/libomptarget/device.cpp +++ b/offload/libomptarget/device.cpp @@ -38,6 +38,7 @@ using namespace llvm::omp::target::ompt; #endif using namespace llvm::omp::target::plugin; +using namespace llvm::omp::target::debug; int HostDataToTargetTy::addEventIfNecessary(DeviceTy &Device, AsyncInfoTy &AsyncInfo) const { @@ -48,7 +49,7 @@ int HostDataToTargetTy::addEventIfNecessary(DeviceTy &Device, void *Event = getEvent(); bool NeedNewEvent = Event == nullptr; if (NeedNewEvent && Device.createEvent(&Event) != OFFLOAD_SUCCESS) { - REPORT("Failed to create event\n"); + REPORT() << "Failed to create event"; return OFFLOAD_FAIL; } @@ -56,7 +57,7 @@ int HostDataToTargetTy::addEventIfNecessary(DeviceTy &Device, // know if the target support event. But if a target doesn't, // recordEvent should always return success. if (Device.recordEvent(Event, AsyncInfo) != OFFLOAD_SUCCESS) { - REPORT("Failed to set dependence on event " DPxMOD "\n", DPxPTR(Event)); + REPORT() << "Failed to set dependence on event " << Event; return OFFLOAD_FAIL; } @@ -315,21 +316,21 @@ int32_t DeviceTy::dataFence(AsyncInfoTy &AsyncInfo) { } int32_t DeviceTy::notifyDataMapped(void *HstPtr, int64_t Size) { - DP("Notifying about new mapping: HstPtr=" DPxMOD ", Size=%" PRId64 "\n", - DPxPTR(HstPtr), Size); + ODBG(ODT_Mapping) << "Notifying about new mapping: HstPtr=" << HstPtr + << ", Size=" << Size; if (RTL->data_notify_mapped(RTLDeviceID, HstPtr, Size)) { - REPORT("Notifying about data mapping failed.\n"); + REPORT() << "Notifying about data mapping failed."; return OFFLOAD_FAIL; } return OFFLOAD_SUCCESS; } int32_t DeviceTy::notifyDataUnmapped(void *HstPtr) { - DP("Notifying about an unmapping: HstPtr=" DPxMOD "\n", DPxPTR(HstPtr)); + ODBG(ODT_Mapping) << "Notifying about an unmapping: HstPtr=" << HstPtr; if (RTL->data_notify_unmapped(RTLDeviceID, HstPtr)) { - REPORT("Notifying about data unmapping failed.\n"); + REPORT() << "Notifying about data unmapping failed."; return OFFLOAD_FAIL; } return OFFLOAD_SUCCESS;