xref: /llvm-project/offload/include/Shared/Debug.h (revision 330d8983d25d08580fc1642fea48b2473f47a9da)
1 //===-- Shared/Debug.h - Target independent OpenMP target RTL -- C++ ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Routines used to provide debug messages and information from libomptarget
10 // and plugin RTLs to the user.
11 //
12 // Each plugin RTL and libomptarget define TARGET_NAME and DEBUG_PREFIX for use
13 // when sending messages to the user. These indicate which RTL sent the message
14 //
15 // Debug and information messages are controlled by the environment variables
16 // LIBOMPTARGET_DEBUG and LIBOMPTARGET_INFO which is set upon initialization
17 // of libomptarget or the plugin RTL.
18 //
19 // To printf a pointer in hex with a fixed width of 16 digits and a leading 0x,
20 // use printf("ptr=" DPxMOD "...\n", DPxPTR(ptr));
21 //
22 // DPxMOD expands to:
23 //   "0x%0*" PRIxPTR
24 // where PRIxPTR expands to an appropriate modifier for the type uintptr_t on a
25 // specific platform, e.g. "lu" if uintptr_t is typedef'd as unsigned long:
26 //   "0x%0*lu"
27 //
28 // Ultimately, the whole statement expands to:
29 //   printf("ptr=0x%0*lu...\n",  // the 0* modifier expects an extra argument
30 //                               // specifying the width of the output
31 //   (int)(2*sizeof(uintptr_t)), // the extra argument specifying the width
32 //                               // 8 digits for 32bit systems
33 //                               // 16 digits for 64bit
34 //   (uintptr_t) ptr);
35 //
36 //===----------------------------------------------------------------------===//
37 
38 #ifndef OMPTARGET_SHARED_DEBUG_H
39 #define OMPTARGET_SHARED_DEBUG_H
40 
41 #include <atomic>
42 #include <mutex>
43 #include <string>
44 
45 /// 32-Bit field data attributes controlling information presented to the user.
46 enum OpenMPInfoType : uint32_t {
47   // Print data arguments and attributes upon entering an OpenMP device kernel.
48   OMP_INFOTYPE_KERNEL_ARGS = 0x0001,
49   // Indicate when an address already exists in the device mapping table.
50   OMP_INFOTYPE_MAPPING_EXISTS = 0x0002,
51   // Dump the contents of the device pointer map at kernel exit or failure.
52   OMP_INFOTYPE_DUMP_TABLE = 0x0004,
53   // Indicate when an address is added to the device mapping table.
54   OMP_INFOTYPE_MAPPING_CHANGED = 0x0008,
55   // Print kernel information from target device plugins.
56   OMP_INFOTYPE_PLUGIN_KERNEL = 0x0010,
57   // Print whenever data is transferred to the device
58   OMP_INFOTYPE_DATA_TRANSFER = 0x0020,
59   // Print whenever data does not have a viable device counterpart.
60   OMP_INFOTYPE_EMPTY_MAPPING = 0x0040,
61   // Enable every flag.
62   OMP_INFOTYPE_ALL = 0xffffffff,
63 };
64 
getInfoLevelInternal()65 inline std::atomic<uint32_t> &getInfoLevelInternal() {
66   static std::atomic<uint32_t> InfoLevel;
67   static std::once_flag Flag{};
68   std::call_once(Flag, []() {
69     if (char *EnvStr = getenv("LIBOMPTARGET_INFO"))
70       InfoLevel.store(std::stoi(EnvStr));
71   });
72 
73   return InfoLevel;
74 }
75 
getInfoLevel()76 inline uint32_t getInfoLevel() { return getInfoLevelInternal().load(); }
77 
getDebugLevel()78 inline uint32_t getDebugLevel() {
79   static uint32_t DebugLevel = 0;
80   static std::once_flag Flag{};
81   std::call_once(Flag, []() {
82     if (char *EnvStr = getenv("LIBOMPTARGET_DEBUG"))
83       DebugLevel = std::stoi(EnvStr);
84   });
85 
86   return DebugLevel;
87 }
88 
89 #undef USED
90 #undef GCC_VERSION
91 
92 #ifndef __STDC_FORMAT_MACROS
93 #define __STDC_FORMAT_MACROS
94 #endif
95 #include <inttypes.h>
96 #undef __STDC_FORMAT_MACROS
97 
98 #define DPxMOD "0x%0*" PRIxPTR
99 #define DPxPTR(ptr) ((int)(2 * sizeof(uintptr_t))), ((uintptr_t)(ptr))
100 #define GETNAME2(name) #name
101 #define GETNAME(name) GETNAME2(name)
102 
103 /// Print a generic message string from libomptarget or a plugin RTL
104 #define MESSAGE0(_str)                                                         \
105   do {                                                                         \
106     fprintf(stderr, GETNAME(TARGET_NAME) " message: %s\n", _str);              \
107   } while (0)
108 
109 /// Print a printf formatting string message from libomptarget or a plugin RTL
110 #define MESSAGE(_str, ...)                                                     \
111   do {                                                                         \
112     fprintf(stderr, GETNAME(TARGET_NAME) " message: " _str "\n", __VA_ARGS__); \
113   } while (0)
114 
115 /// Print fatal error message with an error string and error identifier
116 #define FATAL_MESSAGE0(_num, _str)                                             \
117   do {                                                                         \
118     fprintf(stderr, GETNAME(TARGET_NAME) " fatal error %d: %s\n", (int)_num,   \
119             _str);                                                             \
120     abort();                                                                   \
121   } while (0)
122 
123 /// Print fatal error message with a printf string and error identifier
124 #define FATAL_MESSAGE(_num, _str, ...)                                         \
125   do {                                                                         \
126     fprintf(stderr, GETNAME(TARGET_NAME) " fatal error %d: " _str "\n",        \
127             (int)_num, __VA_ARGS__);                                           \
128     abort();                                                                   \
129   } while (0)
130 
131 /// Print a generic error string from libomptarget or a plugin RTL
132 #define FAILURE_MESSAGE(...)                                                   \
133   do {                                                                         \
134     fprintf(stderr, GETNAME(TARGET_NAME) " error: ");                          \
135     fprintf(stderr, __VA_ARGS__);                                              \
136   } while (0)
137 
138 /// Print a generic information string used if LIBOMPTARGET_INFO=1
139 #define INFO_MESSAGE(_num, ...) INFO_MESSAGE_TO(stderr, _num, __VA_ARGS__)
140 
141 #define INFO_MESSAGE_TO(_stdDst, _num, ...)                                    \
142   do {                                                                         \
143     fprintf(_stdDst, GETNAME(TARGET_NAME) " device %d info: ", (int)_num);     \
144     fprintf(_stdDst, __VA_ARGS__);                                             \
145   } while (0)
146 
147 // Debugging messages
148 #ifdef OMPTARGET_DEBUG
149 #include <stdio.h>
150 
151 #define DEBUGP(prefix, ...)                                                    \
152   {                                                                            \
153     fprintf(stderr, "%s --> ", prefix);                                        \
154     fprintf(stderr, __VA_ARGS__);                                              \
155   }
156 
157 /// Emit a message for debugging
158 #define DP(...)                                                                \
159   do {                                                                         \
160     if (getDebugLevel() > 0) {                                                 \
161       DEBUGP(DEBUG_PREFIX, __VA_ARGS__);                                       \
162     }                                                                          \
163   } while (false)
164 
165 /// Emit a message for debugging or failure if debugging is disabled
166 #define REPORT(...)                                                            \
167   do {                                                                         \
168     if (getDebugLevel() > 0) {                                                 \
169       DP(__VA_ARGS__);                                                         \
170     } else {                                                                   \
171       FAILURE_MESSAGE(__VA_ARGS__);                                            \
172     }                                                                          \
173   } while (false)
174 #else
175 #define DEBUGP(prefix, ...)                                                    \
176   {}
177 #define DP(...)                                                                \
178   {}
179 #define REPORT(...) FAILURE_MESSAGE(__VA_ARGS__);
180 #endif // OMPTARGET_DEBUG
181 
182 /// Emit a message giving the user extra information about the runtime if
183 #define INFO(_flags, _id, ...)                                                 \
184   do {                                                                         \
185     if (getDebugLevel() > 0) {                                                 \
186       DEBUGP(DEBUG_PREFIX, __VA_ARGS__);                                       \
187     } else if (getInfoLevel() & _flags) {                                      \
188       INFO_MESSAGE(_id, __VA_ARGS__);                                          \
189     }                                                                          \
190   } while (false)
191 
192 #define DUMP_INFO(toStdOut, _flags, _id, ...)                                  \
193   do {                                                                         \
194     if (toStdOut) {                                                            \
195       INFO_MESSAGE_TO(stdout, _id, __VA_ARGS__);                               \
196     } else {                                                                   \
197       INFO(_flags, _id, __VA_ARGS__);                                          \
198     }                                                                          \
199   } while (false)
200 
201 #endif // OMPTARGET_SHARED_DEBUG_H
202