• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Debug_hpp
18 #define Debug_hpp
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 sw {
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 traps once if a debugger is attached.
51 void log_trap(const char *format, ...) CHECK_PRINTF_ARGS;
52 
53 }  // namespace sw
54 
55 // A macro to output a trace of a function call and its arguments to the
56 // debugging log. Disabled if SWIFTSHADER_DISABLE_TRACE is defined.
57 #if defined(SWIFTSHADER_DISABLE_TRACE)
58 #	define TRACE(message, ...) (void(0))
59 #else
60 #	define TRACE(message, ...) sw::trace("%s:%d TRACE: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__)
61 #endif
62 
63 // A macro to print a warning message to the debugging log and stderr to denote
64 // an issue that needs fixing.
65 #define FIXME(message, ...) sw::warn("%s:%d FIXME: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__)
66 
67 // A macro to print a warning message to the debugging log and stderr.
68 #define WARN(message, ...) sw::warn("%s:%d WARNING: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__)
69 
70 // A macro that delegates to:
71 //   abort() in debug builds (!NDEBUG || DCHECK_ALWAYS_ON)
72 // or
73 //   warn() in release builds (NDEBUG && !DCHECK_ALWAYS_ON)
74 #undef DABORT
75 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
76 #	define DABORT(message, ...) sw::abort("%s:%d ABORT: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__)
77 #else
78 #	define DABORT(message, ...) sw::warn("%s:%d WARNING: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__);
79 #endif
80 
81 // A macro asserting a condition.
82 // If the condition fails, the condition and message is passed to DABORT().
83 #undef ASSERT_MSG
84 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
85 #	define ASSERT_MSG(expression, format, ...)                                 \
86 		do                                                                      \
87 		{                                                                       \
88 			if(!(expression))                                                   \
89 			{                                                                   \
90 				DABORT("ASSERT(%s): " format "\n", #expression, ##__VA_ARGS__); \
91 			}                                                                   \
92 		} while(0)
93 #else
94 // Silence unused variable warnings without evaluating the expressions.
95 // TODO(b/154914395): Also ignore variadic arguments (similar to RR_WATCH expansion)
96 #	define ASSERT_MSG(expression, format, ...)    \
97 		do                                         \
98 		{                                          \
99 			(void)sizeof((int)(bool)(expression)); \
100 			(void)sizeof(format);                  \
101 		} while(0)
102 #endif
103 
104 // A macro asserting a condition.
105 // If the condition fails, the condition is passed to DABORT().
106 #undef ASSERT
107 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
108 #	define ASSERT(expression)                       \
109 		do                                           \
110 		{                                            \
111 			if(!(expression))                        \
112 			{                                        \
113 				DABORT("ASSERT(%s)\n", #expression); \
114 			}                                        \
115 		} while(0)
116 #else
117 // Silence unused variable warnings without evaluating the expressions.
118 #	define ASSERT(expression)                     \
119 		do                                         \
120 		{                                          \
121 			(void)sizeof((int)(bool)(expression)); \
122 		} while(0)
123 #endif
124 
125 // A macro to indicate functionality currently unimplemented, for a feature advertised
126 // as supported. Since this is a bug, a bug ID must be provided, in b/### format.
127 // For unimplemented functionality not advertised as supported, use UNSUPPORTED() instead.
128 #undef UNIMPLEMENTED
129 #define UNIMPLEMENTED(format, ...)                   \
130 	DABORT("UNIMPLEMENTED: " format, ##__VA_ARGS__); \
131 	static_assert(format[0] == 'b' && format[1] == '/' && format[2] >= '0' && format[2] <= '9', "explanation must start with bug reference in b/### format")
132 
133 // A macro to indicate unsupported functionality.
134 // This should be called when a Vulkan / SPIR-V feature is attempted to be used,
135 // but is not currently implemented by SwiftShader.
136 // Note that in a well-behaved application these should not be reached as the
137 // application should be respecting the advertised features / limits.
138 #undef UNSUPPORTED
139 #define UNSUPPORTED(format, ...) DABORT("UNSUPPORTED: " format, ##__VA_ARGS__)
140 
141 // A macro for code which should never be reached, even with misbehaving
142 // applications.
143 #undef UNREACHABLE
144 #define UNREACHABLE(format, ...) DABORT("UNREACHABLE: " format, ##__VA_ARGS__)
145 
146 // A macro asserting a condition and returning if false.
147 // Note this macro always evaluates the expression and also returns in Release builds.
148 #undef ASSERT_OR_RETURN
149 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
150 #	define ASSERT_OR_RETURN(expression) ASSERT(expression)
151 #else
152 #	define ASSERT_OR_RETURN(expression) \
153 		do                               \
154 		{                                \
155 			if(!(expression))            \
156 			{                            \
157 				return;                  \
158 			}                            \
159 		} while(0)
160 #endif
161 
162 // A macro to indicate unoptimized code paths.
163 #define UNOPTIMIZED(message, ...)                                                            \
164 	do                                                                                       \
165 	{                                                                                        \
166 		if(false)                                                                            \
167 		{                                                                                    \
168 			sw::warn("%s:%d UNOPTIMIZED: " message "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
169 		}                                                                                    \
170 	} while(0)
171 
172 #endif  // Debug_hpp
173