forked from OSchip/llvm-project
197 lines
8.6 KiB
C++
197 lines
8.6 KiB
C++
//===------- 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_DEBUG_H
|
|
#define _OMPTARGET_DEBUG_H
|
|
|
|
#include <atomic>
|
|
#include <mutex>
|
|
|
|
/// 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,
|
|
// Enable every flag.
|
|
OMP_INFOTYPE_ALL = 0xffffffff,
|
|
};
|
|
|
|
#define GCC_VERSION \
|
|
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
|
|
|
#if !defined(__clang__) && defined(__GNUC__) && GCC_VERSION < 70100
|
|
#define USED __attribute__((used))
|
|
#else
|
|
#define USED
|
|
#endif
|
|
|
|
// Add __attribute__((used)) to work around a bug in gcc 5/6.
|
|
USED inline std::atomic<uint32_t> &getInfoLevelInternal() {
|
|
static std::atomic<uint32_t> InfoLevel;
|
|
static std::once_flag Flag{};
|
|
std::call_once(Flag, []() {
|
|
if (char *EnvStr = getenv("LIBOMPTARGET_INFO"))
|
|
InfoLevel.store(std::stoi(EnvStr));
|
|
});
|
|
|
|
return InfoLevel;
|
|
}
|
|
|
|
USED inline uint32_t getInfoLevel() { return getInfoLevelInternal().load(); }
|
|
|
|
// Add __attribute__((used)) to work around a bug in gcc 5/6.
|
|
USED 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 <inttypes.h>
|
|
#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", _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", _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 <stdio.h>
|
|
|
|
#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_DEBUG_H
|