//===-- Shared/Debug.h - Target independent OpenMP target RTL -- C++ ------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Routines used to provide debug messages and information from libomptarget // and plugin RTLs to the user. // // Each plugin RTL and libomptarget define TARGET_NAME and DEBUG_PREFIX for use // when sending messages to the user. These indicate which RTL sent the message // // Debug and information messages are controlled by the environment variables // LIBOMPTARGET_DEBUG and LIBOMPTARGET_INFO which is set upon initialization // of libomptarget or the plugin RTL. // // To printf a pointer in hex with a fixed width of 16 digits and a leading 0x, // use printf("ptr=" DPxMOD "...\n", DPxPTR(ptr)); // // DPxMOD expands to: // "0x%0*" PRIxPTR // where PRIxPTR expands to an appropriate modifier for the type uintptr_t on a // specific platform, e.g. "lu" if uintptr_t is typedef'd as unsigned long: // "0x%0*lu" // // Ultimately, the whole statement expands to: // printf("ptr=0x%0*lu...\n", // the 0* modifier expects an extra argument // // specifying the width of the output // (int)(2*sizeof(uintptr_t)), // the extra argument specifying the width // // 8 digits for 32bit systems // // 16 digits for 64bit // (uintptr_t) ptr); // //===----------------------------------------------------------------------===// #ifndef OMPTARGET_SHARED_DEBUG_H #define OMPTARGET_SHARED_DEBUG_H #include #include #include /// 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. OMP_INFOTYPE_KERNEL_ARGS = 0x0001, // Indicate when an address already exists in the device mapping table. OMP_INFOTYPE_MAPPING_EXISTS = 0x0002, // Dump the contents of the device pointer map at kernel exit or failure. OMP_INFOTYPE_DUMP_TABLE = 0x0004, // Indicate when an address is added to the device mapping table. OMP_INFOTYPE_MAPPING_CHANGED = 0x0008, // Print kernel information from target device plugins. OMP_INFOTYPE_PLUGIN_KERNEL = 0x0010, // Print whenever data is transferred to the device OMP_INFOTYPE_DATA_TRANSFER = 0x0020, // Print whenever data does not have a viable device counterpart. OMP_INFOTYPE_EMPTY_MAPPING = 0x0040, // Enable every flag. OMP_INFOTYPE_ALL = 0xffffffff, }; inline std::atomic &getInfoLevelInternal() { static std::atomic InfoLevel; static std::once_flag Flag{}; std::call_once(Flag, []() { if (char *EnvStr = getenv("LIBOMPTARGET_INFO")) InfoLevel.store(std::stoi(EnvStr)); }); return InfoLevel; } 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 #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif #include #undef __STDC_FORMAT_MACROS #define DPxMOD "0x%0*" PRIxPTR #define DPxPTR(ptr) ((int)(2 * sizeof(uintptr_t))), ((uintptr_t)(ptr)) #define GETNAME2(name) #name #define GETNAME(name) GETNAME2(name) /// Print a generic message string from libomptarget or a plugin RTL #define MESSAGE0(_str) \ do { \ fprintf(stderr, GETNAME(TARGET_NAME) " message: %s\n", _str); \ } while (0) /// Print a printf formatting string message from libomptarget or a plugin RTL #define MESSAGE(_str, ...) \ do { \ fprintf(stderr, GETNAME(TARGET_NAME) " message: " _str "\n", __VA_ARGS__); \ } while (0) /// Print fatal error message with an error string and error identifier #define FATAL_MESSAGE0(_num, _str) \ do { \ fprintf(stderr, GETNAME(TARGET_NAME) " fatal error %d: %s\n", (int)_num, \ _str); \ abort(); \ } while (0) /// Print fatal error message with a printf string and error identifier #define FATAL_MESSAGE(_num, _str, ...) \ do { \ fprintf(stderr, GETNAME(TARGET_NAME) " fatal error %d: " _str "\n", \ (int)_num, __VA_ARGS__); \ abort(); \ } while (0) /// Print a generic error string from libomptarget or a plugin RTL #define FAILURE_MESSAGE(...) \ do { \ fprintf(stderr, GETNAME(TARGET_NAME) " error: "); \ fprintf(stderr, __VA_ARGS__); \ } while (0) /// Print a generic information string used if LIBOMPTARGET_INFO=1 #define INFO_MESSAGE(_num, ...) \ do { \ fprintf(stderr, GETNAME(TARGET_NAME) " device %d info: ", (int)_num); \ fprintf(stderr, __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__); \ } else if (getInfoLevel() & _flags) { \ INFO_MESSAGE(_id, __VA_ARGS__); \ } \ } while (false) #endif // OMPTARGET_SHARED_DEBUG_H