1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // debug.h: Debugging utilities.
16
17 #ifndef rr_DEBUG_H_
18 #define rr_DEBUG_H_
19
20 #include <assert.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include <cctype>
25 #include <string>
26
27 #if !defined(TRACE_OUTPUT_FILE)
28 # define TRACE_OUTPUT_FILE "debug.txt"
29 #endif
30
31 #if defined(__GNUC__) || defined(__clang__)
32 # define CHECK_PRINTF_ARGS __attribute__((format(printf, 1, 2)))
33 #else
34 # define CHECK_PRINTF_ARGS
35 #endif
36
37 namespace rr {
38
39 // Outputs text to the debugging log
40 void trace(const char *format, ...) CHECK_PRINTF_ARGS;
trace()41 inline void trace() {}
42
43 // Outputs text to the debugging log and prints to stderr.
44 void warn(const char *format, ...) CHECK_PRINTF_ARGS;
warn()45 inline void warn() {}
46
47 // Outputs the message to the debugging log and stderr, and calls abort().
48 void abort(const char *format, ...) CHECK_PRINTF_ARGS;
49
50 // Outputs text to the debugging log, and asserts once if a debugger is attached.
51 void trace_assert(const char *format, ...) CHECK_PRINTF_ARGS;
52
53 } // namespace rr
54
55 // A macro to output a trace of a function call and its arguments to the
56 // debugging log. Disabled if RR_DISABLE_TRACE is defined.
57 #if defined(RR_DISABLE_TRACE)
58 # define TRACE(message, ...) (void(0))
59 # define TRACE_ASSERT(message, ...) (void(0))
60 #else
61 # define TRACE(message, ...) rr::trace("%s:%d TRACE: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__)
62 # define TRACE_ASSERT(message, ...) rr::trace_assert("%s:%d %s TRACE_ASSERT: " message "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
63 #endif
64
65 // A macro to print a warning message to the debugging log and stderr to denote
66 // an issue that needs fixing.
67 #define FIXME(message, ...) rr::warn("%s:%d FIXME: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__);
68
69 // A macro to print a warning message to the debugging log and stderr.
70 #define WARN(message, ...) rr::warn("%s:%d WARNING: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__);
71
72 // A macro that prints the message to the debugging log and stderr and
73 // immediately aborts execution of the application.
74 //
75 // Note: This will terminate the application regardless of build flags!
76 // Use with extreme caution!
77 #undef ABORT
78 #define ABORT(message, ...) rr::abort("%s:%d ABORT: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__)
79
80 // A macro that delegates to:
81 // ABORT() in debug builds (!NDEBUG || DCHECK_ALWAYS_ON)
82 // or
83 // WARN() in release builds (NDEBUG && !DCHECK_ALWAYS_ON)
84 #undef DABORT
85 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
86 # define DABORT(message, ...) ABORT(message, ##__VA_ARGS__)
87 #else
88 # define DABORT(message, ...) WARN(message, ##__VA_ARGS__)
89 #endif
90
91 // A macro asserting a condition.
92 // If the condition fails, the condition and message is passed to DABORT().
93 #undef ASSERT_MSG
94 #define ASSERT_MSG(expression, format, ...) \
95 do \
96 { \
97 if(!(expression)) \
98 { \
99 DABORT("ASSERT(%s): " format "\n", #expression, ##__VA_ARGS__); \
100 } \
101 } while(0)
102
103 // A macro asserting a condition.
104 // If the condition fails, the condition is passed to DABORT().
105 #undef ASSERT
106 #define ASSERT(expression) \
107 do \
108 { \
109 if(!(expression)) \
110 { \
111 DABORT("ASSERT(%s)\n", #expression); \
112 } \
113 } while(0)
114
115 // A macro to indicate functionality currently unimplemented, for a feature advertised
116 // as supported. This is similar to UNIMPLEMENTED() but does not check there's a bug
117 // number.
118 #undef UNIMPLEMENTED_NO_BUG
119 #define UNIMPLEMENTED_NO_BUG(format, ...) \
120 DABORT("UNIMPLEMENTED: " format, ##__VA_ARGS__);
121
122 // A macro to indicate functionality currently unimplemented, for a feature advertised
123 // as supported. Since this is a bug, a bug ID must be provided, in b/### format.
124 // For unimplemented functionality not advertised as supported, use UNSUPPORTED() instead.
125 #undef UNIMPLEMENTED
126 #define UNIMPLEMENTED(format, ...) \
127 static_assert(format[0] == 'b' && format[1] == '/' && format[2] >= '0' && format[2] <= '9', "explanation must start with bug reference in b/### format"); \
128 UNIMPLEMENTED_NO_BUG(format, ##__VA_ARGS__)
129
130 // A macro to indicate unsupported functionality.
131 // This should be called when a feature is attempted to be used, but is not
132 // currently implemented by Reactor.
133 // Note that in a well-behaved application these should not be reached as the
134 // application should be respecting the advertised features / limits.
135 #undef UNSUPPORTED
136 #define UNSUPPORTED(format, ...) DABORT("UNSUPPORTED: " format, ##__VA_ARGS__)
137
138 // A macro for code which should never be reached, even with misbehaving
139 // applications.
140 #undef UNREACHABLE
141 #define UNREACHABLE(format, ...) DABORT("UNREACHABLE: " format, ##__VA_ARGS__)
142
143 // A macro asserting a condition and performing a return.
144 #undef ASSERT_OR_RETURN
145 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
146 # define ASSERT_OR_RETURN(expression) ASSERT(expression)
147 #else
148 # define ASSERT_OR_RETURN(expression) \
149 do \
150 { \
151 if(!(expression)) \
152 { \
153 return; \
154 } \
155 } while(0)
156 #endif
157
158 #endif // rr_DEBUG_H_
159