1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // debug.h: Debugging utilities. A lot of the logging code is adapted from Chromium's
8 // base/logging.h.
9 
10 #ifndef COMMON_DEBUG_H_
11 #define COMMON_DEBUG_H_
12 
13 #include <assert.h>
14 #include <stdio.h>
15 
16 #include <iomanip>
17 #include <ios>
18 #include <sstream>
19 #include <string>
20 
21 #include "common/angleutils.h"
22 #include "common/platform.h"
23 
24 #if !defined(TRACE_OUTPUT_FILE)
25 #    define TRACE_OUTPUT_FILE "angle_debug.txt"
26 #endif
27 
28 namespace gl
29 {
30 
31 // Pairs a D3D begin event with an end event.
32 class ScopedPerfEventHelper : angle::NonCopyable
33 {
34   public:
35     ANGLE_FORMAT_PRINTF(2, 3)
36     ScopedPerfEventHelper(const char *format, ...);
37     ~ScopedPerfEventHelper();
38 
39   private:
40     const char *mFunctionName;
41 };
42 
43 using LogSeverity = int;
44 // Note: the log severities are used to index into the array of names,
45 // see g_logSeverityNames.
46 constexpr LogSeverity LOG_EVENT          = 0;
47 constexpr LogSeverity LOG_INFO           = 1;
48 constexpr LogSeverity LOG_WARN           = 2;
49 constexpr LogSeverity LOG_ERR            = 3;
50 constexpr LogSeverity LOG_FATAL          = 4;
51 constexpr LogSeverity LOG_NUM_SEVERITIES = 5;
52 
53 void Trace(LogSeverity severity, const char *message);
54 
55 // This class more or less represents a particular log message.  You
56 // create an instance of LogMessage and then stream stuff to it.
57 // When you finish streaming to it, ~LogMessage is called and the
58 // full message gets streamed to the appropriate destination.
59 //
60 // You shouldn't actually use LogMessage's constructor to log things,
61 // though.  You should use the ERR() and WARN() macros.
62 class LogMessage : angle::NonCopyable
63 {
64   public:
65     // Used for ANGLE_LOG(severity).
66     LogMessage(const char *function, int line, LogSeverity severity);
67     ~LogMessage();
stream()68     std::ostream &stream() { return mStream; }
69 
70     LogSeverity getSeverity() const;
71     std::string getMessage() const;
72 
73   private:
74     const char *mFunction;
75     const int mLine;
76     const LogSeverity mSeverity;
77 
78     std::ostringstream mStream;
79 };
80 
81 // Wraps the API/Platform-specific debug annotation functions.
82 // Also handles redirecting logging destination.
83 class DebugAnnotator : angle::NonCopyable
84 {
85   public:
DebugAnnotator()86     DebugAnnotator() {}
~DebugAnnotator()87     virtual ~DebugAnnotator() {}
88     virtual void beginEvent(const char *eventName, const char *eventMessage) = 0;
89     virtual void endEvent(const char *eventName)                             = 0;
90     virtual void setMarker(const char *markerName)                           = 0;
91     virtual bool getStatus()                                                 = 0;
92     // Log Message Handler that gets passed every log message,
93     // when debug annotations are initialized,
94     // replacing default handling by LogMessage.
95     virtual void logMessage(const LogMessage &msg) const = 0;
96 };
97 
98 void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
99 void UninitializeDebugAnnotations();
100 bool DebugAnnotationsActive();
101 bool DebugAnnotationsInitialized();
102 
103 void InitializeDebugMutexIfNeeded();
104 
105 namespace priv
106 {
107 // This class is used to explicitly ignore values in the conditional logging macros. This avoids
108 // compiler warnings like "value computed is not used" and "statement has no effect".
109 class LogMessageVoidify
110 {
111   public:
LogMessageVoidify()112     LogMessageVoidify() {}
113     // This has to be an operator with a precedence lower than << but higher than ?:
114     void operator&(std::ostream &) {}
115 };
116 
117 extern std::ostream *gSwallowStream;
118 
119 // Used by ANGLE_LOG_IS_ON to lazy-evaluate stream arguments.
120 bool ShouldCreatePlatformLogMessage(LogSeverity severity);
121 
122 template <int N, typename T>
FmtHex(std::ostream & os,T value)123 std::ostream &FmtHex(std::ostream &os, T value)
124 {
125     os << "0x";
126 
127     std::ios_base::fmtflags oldFlags = os.flags();
128     std::streamsize oldWidth         = os.width();
129     std::ostream::char_type oldFill  = os.fill();
130 
131     os << std::hex << std::uppercase << std::setw(N) << std::setfill('0') << value;
132 
133     os.flags(oldFlags);
134     os.width(oldWidth);
135     os.fill(oldFill);
136 
137     return os;
138 }
139 
140 template <typename T>
FmtHexAutoSized(std::ostream & os,T value)141 std::ostream &FmtHexAutoSized(std::ostream &os, T value)
142 {
143     constexpr int N = sizeof(T) * 2;
144     return priv::FmtHex<N>(os, value);
145 }
146 
147 template <typename T>
148 class FmtHexHelper
149 {
150   public:
FmtHexHelper(const char * prefix,T value)151     FmtHexHelper(const char *prefix, T value) : mPrefix(prefix), mValue(value) {}
FmtHexHelper(T value)152     explicit FmtHexHelper(T value) : mPrefix(nullptr), mValue(value) {}
153 
154   private:
155     const char *mPrefix;
156     T mValue;
157 
158     friend std::ostream &operator<<(std::ostream &os, const FmtHexHelper &fmt)
159     {
160         if (fmt.mPrefix)
161         {
162             os << fmt.mPrefix;
163         }
164         return FmtHexAutoSized(os, fmt.mValue);
165     }
166 };
167 
168 }  // namespace priv
169 
170 template <typename T>
FmtHex(T value)171 priv::FmtHexHelper<T> FmtHex(T value)
172 {
173     return priv::FmtHexHelper<T>(value);
174 }
175 
176 #if defined(ANGLE_PLATFORM_WINDOWS)
177 priv::FmtHexHelper<HRESULT> FmtHR(HRESULT value);
178 priv::FmtHexHelper<DWORD> FmtErr(DWORD value);
179 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
180 
181 template <typename T>
FmtHex(std::ostream & os,T value)182 std::ostream &FmtHex(std::ostream &os, T value)
183 {
184     return priv::FmtHexAutoSized(os, value);
185 }
186 
187 // A few definitions of macros that don't generate much code. These are used
188 // by ANGLE_LOG(). Since these are used all over our code, it's
189 // better to have compact code for these operations.
190 #define COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ...) \
191     ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_EVENT, ##__VA_ARGS__)
192 #define COMPACT_ANGLE_LOG_EX_INFO(ClassName, ...) \
193     ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_INFO, ##__VA_ARGS__)
194 #define COMPACT_ANGLE_LOG_EX_WARN(ClassName, ...) \
195     ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_WARN, ##__VA_ARGS__)
196 #define COMPACT_ANGLE_LOG_EX_ERR(ClassName, ...) \
197     ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_ERR, ##__VA_ARGS__)
198 #define COMPACT_ANGLE_LOG_EX_FATAL(ClassName, ...) \
199     ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_FATAL, ##__VA_ARGS__)
200 
201 #define COMPACT_ANGLE_LOG_EVENT COMPACT_ANGLE_LOG_EX_EVENT(LogMessage)
202 #define COMPACT_ANGLE_LOG_INFO COMPACT_ANGLE_LOG_EX_INFO(LogMessage)
203 #define COMPACT_ANGLE_LOG_WARN COMPACT_ANGLE_LOG_EX_WARN(LogMessage)
204 #define COMPACT_ANGLE_LOG_ERR COMPACT_ANGLE_LOG_EX_ERR(LogMessage)
205 #define COMPACT_ANGLE_LOG_FATAL COMPACT_ANGLE_LOG_EX_FATAL(LogMessage)
206 
207 #define ANGLE_LOG_IS_ON(severity) (::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_##severity))
208 
209 // Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold.
210 // Condition is evaluated once and only once.
211 #define ANGLE_LAZY_STREAM(stream, condition) \
212     !(condition) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify() & (stream)
213 
214 // We use the preprocessor's merging operator, "##", so that, e.g.,
215 // ANGLE_LOG(EVENT) becomes the token COMPACT_ANGLE_LOG_EVENT.  There's some funny
216 // subtle difference between ostream member streaming functions (e.g.,
217 // ostream::operator<<(int) and ostream non-member streaming functions
218 // (e.g., ::operator<<(ostream&, string&): it turns out that it's
219 // impossible to stream something like a string directly to an unnamed
220 // ostream. We employ a neat hack by calling the stream() member
221 // function of LogMessage which seems to avoid the problem.
222 #define ANGLE_LOG_STREAM(severity) COMPACT_ANGLE_LOG_##severity.stream()
223 
224 #define ANGLE_LOG(severity) ANGLE_LAZY_STREAM(ANGLE_LOG_STREAM(severity), ANGLE_LOG_IS_ON(severity))
225 
226 }  // namespace gl
227 
228 #if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
229 #    define ANGLE_TRACE_ENABLED
230 #endif
231 
232 #if !defined(NDEBUG) || defined(ANGLE_ENABLE_RELEASE_ASSERTS)
233 #    define ANGLE_ENABLE_ASSERTS
234 #endif
235 
236 #define INFO() ANGLE_LOG(INFO)
237 #define WARN() ANGLE_LOG(WARN)
238 #define ERR() ANGLE_LOG(ERR)
239 #define FATAL() ANGLE_LOG(FATAL)
240 
241 // A macro to log a performance event around a scope.
242 #if defined(ANGLE_TRACE_ENABLED)
243 #    if defined(_MSC_VER)
244 #        define EVENT(function, message, ...)                                                      \
245             gl::ScopedPerfEventHelper scopedPerfEventHelper##__LINE__("%s(" message ")", function, \
246                                                                       __VA_ARGS__)
247 #    else
248 #        define EVENT(function, message, ...)                                            \
249             gl::ScopedPerfEventHelper scopedPerfEventHelper("%s(" message ")", function, \
250                                                             ##__VA_ARGS__)
251 #    endif  // _MSC_VER
252 #else
253 #    define EVENT(message, ...) (void(0))
254 #endif
255 
256 // The state tracked by ANGLE will be validated with the driver state before each call
257 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
258 #    define ANGLE_STATE_VALIDATION_ENABLED
259 #endif
260 
261 #if defined(__GNUC__)
262 #    define ANGLE_CRASH() __builtin_trap()
263 #else
264 #    define ANGLE_CRASH() ((void)(*(volatile char *)0 = 0)), __assume(0)
265 #endif
266 
267 #if !defined(NDEBUG)
268 #    define ANGLE_ASSERT_IMPL(expression) assert(expression)
269 #else
270 // TODO(jmadill): Detect if debugger is attached and break.
271 #    define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH()
272 #endif  // !defined(NDEBUG)
273 
274 // Note that gSwallowStream is used instead of an arbitrary LOG() stream to avoid the creation of an
275 // object with a non-trivial destructor (LogMessage). On MSVC x86 (checked on 2015 Update 3), this
276 // causes a few additional pointless instructions to be emitted even at full optimization level,
277 // even though the : arm of the ternary operator is clearly never executed. Using a simpler object
278 // to be &'d with Voidify() avoids these extra instructions. Using a simpler POD object with a
279 // templated operator<< also works to avoid these instructions. However, this causes warnings on
280 // statically defined implementations of operator<<(std::ostream, ...) in some .cpp files, because
281 // they become defined-but-unreferenced functions. A reinterpret_cast of 0 to an ostream* also is
282 // not suitable, because some compilers warn of undefined behavior.
283 #define ANGLE_EAT_STREAM_PARAMETERS \
284     true ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify() & (*::gl::priv::gSwallowStream)
285 
286 // A macro asserting a condition and outputting failures to the debug log
287 #if defined(ANGLE_ENABLE_ASSERTS)
288 #    define ASSERT(expression)                                                                \
289         (expression ? static_cast<void>(0)                                                    \
290                     : (FATAL() << "\t! Assert failed in " << __FUNCTION__ << " (" << __FILE__ \
291                                << ":" << __LINE__ << "): " << #expression))
292 #else
293 #    define ASSERT(condition) ANGLE_EAT_STREAM_PARAMETERS << !(condition)
294 #endif  // defined(ANGLE_ENABLE_ASSERTS)
295 
296 #define UNREACHABLE_IS_NORETURN 0
297 
298 #define ANGLE_UNUSED_VARIABLE(variable) (static_cast<void>(variable))
299 
300 // A macro to indicate unimplemented functionality
301 #ifndef NOASSERT_UNIMPLEMENTED
302 #    define NOASSERT_UNIMPLEMENTED 1
303 #endif
304 
305 #if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
306 #    define UNIMPLEMENTED()                                                                       \
307         do                                                                                        \
308         {                                                                                         \
309             WARN() << "\t! Unimplemented: " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \
310                    << ")";                                                                        \
311             ASSERT(NOASSERT_UNIMPLEMENTED);                                                       \
312         } while (0)
313 
314 // A macro for code which is not expected to be reached under valid assumptions
315 #    define UNREACHABLE()                                                                    \
316         do                                                                                   \
317         {                                                                                    \
318             FATAL() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __FILE__ << ":" \
319                     << __LINE__ << ")";                                                      \
320         } while (0)
321 #else
322 #    define UNIMPLEMENTED()                 \
323         do                                  \
324         {                                   \
325             ASSERT(NOASSERT_UNIMPLEMENTED); \
326         } while (0)
327 
328 // A macro for code which is not expected to be reached under valid assumptions
329 #    define UNREACHABLE()  \
330         do                 \
331         {                  \
332             ASSERT(false); \
333         } while (0)
334 #endif  // defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
335 
336 #if defined(ANGLE_PLATFORM_WINDOWS)
337 #    define ANGLE_FUNCTION __FUNCTION__
338 #else
339 #    define ANGLE_FUNCTION __func__
340 #endif
341 
342 // Defining ANGLE_ENABLE_STRUCT_PADDING_WARNINGS will enable warnings when members are added to
343 // structs to enforce packing. This is helpful for diagnosing unexpected struct sizes when making
344 // fast cache variables.
345 #if defined(__clang__)
346 #    define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS \
347         _Pragma("clang diagnostic push") _Pragma("clang diagnostic error \"-Wpadded\"")
348 #    define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS _Pragma("clang diagnostic pop")
349 #elif defined(__GNUC__)
350 #    define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS \
351         _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic error \"-Wpadded\"")
352 #    define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS _Pragma("GCC diagnostic pop")
353 #elif defined(_MSC_VER)
354 #    define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS \
355         __pragma(warning(push)) __pragma(warning(error : 4820))
356 #    define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS __pragma(warning(pop))
357 #else
358 #    define ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
359 #    define ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
360 #endif
361 
362 #if defined(__clang__)
363 #    define ANGLE_DISABLE_EXTRA_SEMI_WARNING \
364         _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wextra-semi\"")
365 #    define ANGLE_REENABLE_EXTRA_SEMI_WARNING _Pragma("clang diagnostic pop")
366 #else
367 #    define ANGLE_DISABLE_EXTRA_SEMI_WARNING
368 #    define ANGLE_REENABLE_EXTRA_SEMI_WARNING
369 #endif
370 
371 #if defined(__clang__)
372 #    define ANGLE_DISABLE_SHADOWING_WARNING \
373         _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow-field\"")
374 #    define ANGLE_REENABLE_SHADOWING_WARNING _Pragma("clang diagnostic pop")
375 #else
376 #    define ANGLE_DISABLE_SHADOWING_WARNING
377 #    define ANGLE_REENABLE_SHADOWING_WARNING
378 #endif
379 
380 #if defined(__clang__)
381 #    define ANGLE_DISABLE_DESTRUCTOR_OVERRIDE_WARNING \
382         _Pragma("clang diagnostic push")              \
383             _Pragma("clang diagnostic ignored \"-Winconsistent-missing-destructor-override\"")
384 #    define ANGLE_REENABLE_DESTRUCTOR_OVERRIDE_WARNING _Pragma("clang diagnostic pop")
385 #else
386 #    define ANGLE_DISABLE_DESTRUCTOR_OVERRIDE_WARNING
387 #    define ANGLE_REENABLE_DESTRUCTOR_OVERRIDE_WARNING
388 #endif
389 
390 #endif  // COMMON_DEBUG_H_
391