• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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 #ifndef rr_Print_hpp
16 #define rr_Print_hpp
17 
18 #ifdef ENABLE_RR_PRINT
19 
20 #	include "Reactor.hpp"
21 
22 #	include <string>
23 #	include <vector>
24 
25 namespace rr {
26 
27 // PrintValue holds the printf format and value(s) for a single argument
28 // to Print(). A single argument can be expanded into multiple printf
29 // values - for example a Float4 will expand to "%f %f %f %f" and four
30 // scalar values.
31 // The PrintValue constructor accepts the following:
32 //   * Reactor LValues, RValues, Pointers.
33 //   * Standard Plain-Old-Value types (int, float, bool, etc)
34 //   * Custom types that specialize the PrintValue::Ty template struct.
35 //   * Static arrays in the form T[N] where T can be any of the above.
36 class PrintValue
37 {
38 public:
39 	// Ty is a template that can be specialized for printing type T.
40 	// Each specialization must expose:
41 	//  * A 'static std::string fmt(const T& v)' method that provides the
42 	//    printf format specifier.
43 	//  * A 'static std::vector<rr::Value*> val(const T& v)' method that
44 	//    returns all the printf format values.
45 	template<typename T>
46 	struct Ty
47 	{
48 		// static std::string fmt(const T& v);
49 		// static std::vector<rr::Value*> val(const T& v);
50 	};
51 
52 	// returns the printf values for all the values in the given array.
53 	template<typename T>
val(const T * list,int count)54 	static std::vector<Value *> val(const T *list, int count)
55 	{
56 		std::vector<Value *> values;
57 		values.reserve(count);
58 		for(int i = 0; i < count; i++)
59 		{
60 			auto v = val(list[i]);
61 			values.insert(values.end(), v.begin(), v.end());
62 		}
63 		return values;
64 	}
65 
66 	// fmt returns the comma-delimited list of printf format strings for
67 	// every element in the provided list, all enclosed in square brackets.
68 	template<typename T>
fmt(const T * list,int count)69 	static std::string fmt(const T *list, int count)
70 	{
71 		std::string out = "[";
72 		for(int i = 0; i < count; i++)
73 		{
74 			if(i > 0) { out += ", "; }
75 			out += fmt(list[i]);
76 		}
77 		return out + "]";
78 	}
79 
addr(const void * ptr)80 	static std::string addr(const void *ptr)
81 	{
82 		char buf[32];
83 		snprintf(buf, sizeof(buf), "%p", ptr);
84 		return buf;
85 	}
86 
87 	const std::string format;
88 	const std::vector<Value *> values;
89 
90 	// Constructs a PrintValue for the given value.
91 	template<typename T>
PrintValue(const T & v)92 	PrintValue(const T &v)
93 	    : format(fmt(v))
94 	    , values(val(v))
95 	{}
96 
97 	// Constructs a PrintValue for the given static array.
98 	template<typename T, int N>
PrintValue(const T (& v)[N])99 	PrintValue(const T (&v)[N])
100 	    : format(fmt(&v[0], N))
101 	    , values(val(&v[0], N))
102 	{}
103 
104 	// Constructs a PrintValue for the given array starting at arr of length
105 	// len.
106 	template<typename T>
PrintValue(const T * arr,int len)107 	PrintValue(const T *arr, int len)
108 	    : format(fmt(arr, len))
109 	    , values(val(arr, len))
110 	{}
111 
112 	// PrintValue constructors for plain-old-data values.
PrintValue(bool v)113 	PrintValue(bool v)
114 	    : format(v ? "true" : "false")
115 	{}
PrintValue(int8_t v)116 	PrintValue(int8_t v)
117 	    : format(std::to_string(v))
118 	{}
PrintValue(uint8_t v)119 	PrintValue(uint8_t v)
120 	    : format(std::to_string(v))
121 	{}
PrintValue(int16_t v)122 	PrintValue(int16_t v)
123 	    : format(std::to_string(v))
124 	{}
PrintValue(uint16_t v)125 	PrintValue(uint16_t v)
126 	    : format(std::to_string(v))
127 	{}
PrintValue(int32_t v)128 	PrintValue(int32_t v)
129 	    : format(std::to_string(v))
130 	{}
PrintValue(uint32_t v)131 	PrintValue(uint32_t v)
132 	    : format(std::to_string(v))
133 	{}
PrintValue(int64_t v)134 	PrintValue(int64_t v)
135 	    : format(std::to_string(v))
136 	{}
PrintValue(uint64_t v)137 	PrintValue(uint64_t v)
138 	    : format(std::to_string(v))
139 	{}
PrintValue(float v)140 	PrintValue(float v)
141 	    : format(std::to_string(v))
142 	{}
PrintValue(double v)143 	PrintValue(double v)
144 	    : format(std::to_string(v))
145 	{}
PrintValue(const char * v)146 	PrintValue(const char *v)
147 	    : format(v)
148 	{}
149 
150 	template<typename T>
PrintValue(T * v)151 	PrintValue(T *v)
152 	    : format(addr(v))
153 	{}
154 
155 	// vals is a helper to build composite value lists.
156 	// vals returns the full, sequential list of printf argument values used
157 	// to print all the provided variadic values.
158 	// vals() is intended to be used by implementations of
159 	// PrintValue::Ty<>::vals() to help declare aggregate types.
160 	// For example, if you were declaring a PrintValue::Ty<> specialization
161 	// for a custom Mat4x4 matrix formed from four Vector4 values, you'd
162 	// write:
163 	//
164 	// namespace rr
165 	// {
166 	//		template <> struct PrintValue::Ty<Mat4x4>
167 	//		{
168 	//			static std::string fmt(const Mat4x4& v)
169 	//			{
170 	//				return	"[a: <%f, %f, %f, %f>,"
171 	//				        " b: <%f, %f, %f, %f>,"
172 	//				        " c: <%f, %f, %f, %f>,"
173 	//				        " d: <%f, %f, %f, %f>]";
174 	//			}
175 	//			static std::vector<rr::Value*> val(const Mat4x4& v)
176 	//			{
177 	//				return PrintValue::vals(v.a, v.b, v.c, v.d);
178 	//			}
179 	//		};
180 	//	}
181 	template<typename... ARGS>
vals(ARGS...v)182 	static std::vector<Value *> vals(ARGS... v)
183 	{
184 		std::vector<std::vector<Value *>> lists = { val(v)... };
185 		std::vector<Value *> joined;
186 		for(const auto &list : lists)
187 		{
188 			joined.insert(joined.end(), list.begin(), list.end());
189 		}
190 		return joined;
191 	}
192 
193 	// returns the printf format specifier for the given type via the
194 	// PrintValue::Ty<T> specialization.
195 	template<typename T>
fmt(const T & v)196 	static std::string fmt(const T &v)
197 	{
198 		return Ty<T>::fmt(v);
199 	}
200 
201 	// returns the printf value for the given type with a
202 	// PrintValue::Ty<T> specialization.
203 	template<typename T>
val(const T & v)204 	static std::vector<Value *> val(const T &v)
205 	{
206 		return Ty<T>::val(v);
207 	}
208 };
209 
210 // PrintValue::Ty<T> specializations for basic types.
211 template<>
212 struct PrintValue::Ty<const char *>
213 {
fmtrr::PrintValue::Ty214 	static std::string fmt(const char *v) { return "%s"; }
215 	static std::vector<Value *> val(const char *v);
216 };
217 template<>
218 struct PrintValue::Ty<std::string>
219 {
fmtrr::PrintValue::Ty220 	static std::string fmt(const std::string &v) { return PrintValue::Ty<const char *>::fmt(v.c_str()); }
valrr::PrintValue::Ty221 	static std::vector<Value *> val(const std::string &v) { return PrintValue::Ty<const char *>::val(v.c_str()); }
222 };
223 
224 // PrintValue::Ty<T> specializations for standard Reactor types.
225 template<>
226 struct PrintValue::Ty<Bool>
227 {
fmtrr::PrintValue::Ty228 	static std::string fmt(const RValue<Bool> &v) { return "%s"; }
229 	static std::vector<Value *> val(const RValue<Bool> &v);
230 };
231 template<>
232 struct PrintValue::Ty<Byte>
233 {
fmtrr::PrintValue::Ty234 	static std::string fmt(const RValue<Byte> &v) { return "%d"; }
235 	static std::vector<Value *> val(const RValue<Byte> &v);
236 };
237 template<>
238 struct PrintValue::Ty<Byte4>
239 {
fmtrr::PrintValue::Ty240 	static std::string fmt(const RValue<Byte4> &v) { return "[%d, %d, %d, %d]"; }
241 	static std::vector<Value *> val(const RValue<Byte4> &v);
242 };
243 template<>
244 struct PrintValue::Ty<Int>
245 {
fmtrr::PrintValue::Ty246 	static std::string fmt(const RValue<Int> &v) { return "%d"; }
247 	static std::vector<Value *> val(const RValue<Int> &v);
248 };
249 template<>
250 struct PrintValue::Ty<Int2>
251 {
fmtrr::PrintValue::Ty252 	static std::string fmt(const RValue<Int2> &v) { return "[%d, %d]"; }
253 	static std::vector<Value *> val(const RValue<Int2> &v);
254 };
255 template<>
256 struct PrintValue::Ty<Int4>
257 {
fmtrr::PrintValue::Ty258 	static std::string fmt(const RValue<Int4> &v) { return "[%d, %d, %d, %d]"; }
259 	static std::vector<Value *> val(const RValue<Int4> &v);
260 };
261 template<>
262 struct PrintValue::Ty<UInt>
263 {
fmtrr::PrintValue::Ty264 	static std::string fmt(const RValue<UInt> &v) { return "%u"; }
265 	static std::vector<Value *> val(const RValue<UInt> &v);
266 };
267 template<>
268 struct PrintValue::Ty<UInt2>
269 {
fmtrr::PrintValue::Ty270 	static std::string fmt(const RValue<UInt2> &v) { return "[%u, %u]"; }
271 	static std::vector<Value *> val(const RValue<UInt2> &v);
272 };
273 template<>
274 struct PrintValue::Ty<UInt4>
275 {
fmtrr::PrintValue::Ty276 	static std::string fmt(const RValue<UInt4> &v) { return "[%u, %u, %u, %u]"; }
277 	static std::vector<Value *> val(const RValue<UInt4> &v);
278 };
279 template<>
280 struct PrintValue::Ty<Short>
281 {
fmtrr::PrintValue::Ty282 	static std::string fmt(const RValue<Short> &v) { return "%d"; }
283 	static std::vector<Value *> val(const RValue<Short> &v);
284 };
285 template<>
286 struct PrintValue::Ty<Short4>
287 {
fmtrr::PrintValue::Ty288 	static std::string fmt(const RValue<Short4> &v) { return "[%d, %d, %d, %d]"; }
289 	static std::vector<Value *> val(const RValue<Short4> &v);
290 };
291 template<>
292 struct PrintValue::Ty<UShort>
293 {
fmtrr::PrintValue::Ty294 	static std::string fmt(const RValue<UShort> &v) { return "%u"; }
295 	static std::vector<Value *> val(const RValue<UShort> &v);
296 };
297 template<>
298 struct PrintValue::Ty<UShort4>
299 {
fmtrr::PrintValue::Ty300 	static std::string fmt(const RValue<UShort4> &v) { return "[%u, %u, %u, %u]"; }
301 	static std::vector<Value *> val(const RValue<UShort4> &v);
302 };
303 template<>
304 struct PrintValue::Ty<Float>
305 {
fmtrr::PrintValue::Ty306 	static std::string fmt(const RValue<Float> &v) { return "%f"; }
307 	static std::vector<Value *> val(const RValue<Float> &v);
308 };
309 template<>
310 struct PrintValue::Ty<Float4>
311 {
fmtrr::PrintValue::Ty312 	static std::string fmt(const RValue<Float4> &v) { return "[%f, %f, %f, %f]"; }
313 	static std::vector<Value *> val(const RValue<Float4> &v);
314 };
315 template<>
316 struct PrintValue::Ty<Long>
317 {
fmtrr::PrintValue::Ty318 	static std::string fmt(const RValue<Long> &v) { return "%lld"; }
valrr::PrintValue::Ty319 	static std::vector<Value *> val(const RValue<Long> &v) { return { v.value() }; }
320 };
321 template<typename T>
322 struct PrintValue::Ty<Pointer<T>>
323 {
fmtrr::PrintValue::Ty324 	static std::string fmt(const RValue<Pointer<T>> &v) { return "%p"; }
valrr::PrintValue::Ty325 	static std::vector<Value *> val(const RValue<Pointer<T>> &v) { return { v.value() }; }
326 };
327 template<typename T>
328 struct PrintValue::Ty<Reference<T>>
329 {
fmtrr::PrintValue::Ty330 	static std::string fmt(const Reference<T> &v) { return PrintValue::Ty<T>::fmt(v); }
valrr::PrintValue::Ty331 	static std::vector<Value *> val(const Reference<T> &v) { return PrintValue::Ty<T>::val(v); }
332 };
333 template<typename T>
334 struct PrintValue::Ty<RValue<T>>
335 {
fmtrr::PrintValue::Ty336 	static std::string fmt(const RValue<T> &v) { return PrintValue::Ty<T>::fmt(v); }
valrr::PrintValue::Ty337 	static std::vector<Value *> val(const RValue<T> &v) { return PrintValue::Ty<T>::val(v); }
338 };
339 
340 // VPrintf emits a call to printf() using vals[0] as the format string,
341 // and vals[1..n] as the args.
342 void VPrintf(const std::vector<Value *> &vals);
343 
344 // Printv emits a call to printf() using the function, file and line,
345 // message and optional values.
346 // See Printv below.
347 void Printv(const char *function, const char *file, int line, const char *msg, std::initializer_list<PrintValue> vals);
348 
349 // Printv emits a call to printf() using the provided message and optional
350 // values.
351 // Printf replaces any bracketed indices in the message with string
352 // representations of the corresponding value in vals.
353 // For example:
354 //   Printv("{0} and {1}", "red", "green");
355 // Would print the string:
356 //   "red and green"
357 // Arguments can be indexed in any order.
358 // Invalid indices are not substituted.
Printv(const char * msg,std::initializer_list<PrintValue> vals)359 inline void Printv(const char *msg, std::initializer_list<PrintValue> vals)
360 {
361 	Printv(nullptr, nullptr, 0, msg, vals);
362 }
363 
364 // Print is a wrapper over Printv that wraps the variadic arguments into an
365 // initializer_list before calling Printv.
366 template<typename... ARGS>
Print(const char * msg,const ARGS &...vals)367 void Print(const char *msg, const ARGS &... vals)
368 {
369 	Printv(msg, { vals... });
370 }
371 
372 // Print is a wrapper over Printv that wraps the variadic arguments into an
373 // initializer_list before calling Printv.
374 template<typename... ARGS>
Print(const char * function,const char * file,int line,const char * msg,const ARGS &...vals)375 void Print(const char *function, const char *file, int line, const char *msg, const ARGS &... vals)
376 {
377 	Printv(function, file, line, msg, { vals... });
378 }
379 
380 // RR_LOG is a macro that calls Print(), automatically populating the
381 // function, file and line parameters and appending a newline to the string.
382 //
383 // RR_LOG() is intended to be used for debugging JIT compiled code, and is
384 // not intended for production use.
385 #	if defined(_WIN32)
386 #		define RR_LOG(msg, ...) Print(__FUNCSIG__, __FILE__, static_cast<int>(__LINE__), msg "\n", ##__VA_ARGS__)
387 #	else
388 #		define RR_LOG(msg, ...) Print(__PRETTY_FUNCTION__, __FILE__, static_cast<int>(__LINE__), msg "\n", ##__VA_ARGS__)
389 #	endif
390 
391 // Macro magic to perform variadic dispatch.
392 // See: https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/preprocessor/macros/__VA_ARGS__/count-arguments
393 // Note, this doesn't attempt to use the ##__VA_ARGS__ trick to handle 0
394 #	define RR_MSVC_EXPAND_BUG(X) X  // Helper macro to force expanding __VA_ARGS__ to satisfy MSVC compiler.
395 #	define RR_GET_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
396 #	define RR_COUNT_ARGUMENTS(...) RR_MSVC_EXPAND_BUG(RR_GET_NTH_ARG(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
397 static_assert(1 == RR_COUNT_ARGUMENTS(a), "RR_COUNT_ARGUMENTS broken");  // Sanity checks.
398 static_assert(2 == RR_COUNT_ARGUMENTS(a, b), "RR_COUNT_ARGUMENTS broken");
399 static_assert(3 == RR_COUNT_ARGUMENTS(a, b, c), "RR_COUNT_ARGUMENTS broken");
400 
401 // RR_WATCH_FMT(...) resolves to a string literal that lists all the
402 // arguments by name. This string can be passed to LOG() to print each of
403 // the arguments with their name and value.
404 //
405 // RR_WATCH_FMT(...) uses the RR_COUNT_ARGUMENTS helper macro to delegate to a
406 // corresponding RR_WATCH_FMT_n specialization macro below.
407 #	define RR_WATCH_CONCAT(a, b) a##b
408 #	define RR_WATCH_CONCAT2(a, b) RR_WATCH_CONCAT(a, b)
409 #	define RR_WATCH_FMT(...) RR_MSVC_EXPAND_BUG(RR_WATCH_CONCAT2(RR_WATCH_FMT_, RR_COUNT_ARGUMENTS(__VA_ARGS__))(__VA_ARGS__))
410 #	define RR_WATCH_FMT_1(_1) "\n  " #    _1 ": {0}"
411 #	define RR_WATCH_FMT_2(_1, _2) \
412 		RR_WATCH_FMT_1(_1)         \
413 		"\n  " #_2 ": {1}"
414 #	define RR_WATCH_FMT_3(_1, _2, _3) \
415 		RR_WATCH_FMT_2(_1, _2)         \
416 		"\n  " #_3 ": {2}"
417 #	define RR_WATCH_FMT_4(_1, _2, _3, _4) \
418 		RR_WATCH_FMT_3(_1, _2, _3)         \
419 		"\n  " #_4 ": {3}"
420 #	define RR_WATCH_FMT_5(_1, _2, _3, _4, _5) \
421 		RR_WATCH_FMT_4(_1, _2, _3, _4)         \
422 		"\n  " #_5 ": {4}"
423 #	define RR_WATCH_FMT_6(_1, _2, _3, _4, _5, _6) \
424 		RR_WATCH_FMT_5(_1, _2, _3, _4, _5)         \
425 		"\n  " #_6 ": {5}"
426 #	define RR_WATCH_FMT_7(_1, _2, _3, _4, _5, _6, _7) \
427 		RR_WATCH_FMT_6(_1, _2, _3, _4, _5, _6)         \
428 		"\n  " #_7 ": {6}"
429 #	define RR_WATCH_FMT_8(_1, _2, _3, _4, _5, _6, _7, _8) \
430 		RR_WATCH_FMT_7(_1, _2, _3, _4, _5, _6, _7)         \
431 		"\n  " #_8 ": {7}"
432 #	define RR_WATCH_FMT_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) \
433 		RR_WATCH_FMT_8(_1, _2, _3, _4, _5, _6, _7, _8)         \
434 		"\n  " #_9 ": {8}"
435 #	define RR_WATCH_FMT_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
436 		RR_WATCH_FMT_9(_1, _2, _3, _4, _5, _6, _7, _8, _9)           \
437 		"\n  " #_10 ": {9}"
438 #	define RR_WATCH_FMT_11(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
439 		RR_WATCH_FMT_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10)          \
440 		"\n  " #_11 ": {10}"
441 #	define RR_WATCH_FMT_12(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
442 		RR_WATCH_FMT_11(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11)          \
443 		"\n  " #_12 ": {11}"
444 
445 // RR_WATCH() is a helper that prints the name and value of all the supplied
446 // arguments.
447 // For example, if you had the Int and bool variables 'foo' and 'bar' that
448 // you want to print, you can simply write:
449 //    RR_WATCH(foo, bar)
450 // When this JIT compiled code is executed, it will print the string
451 // "foo: 1, bar: true" to stdout.
452 //
453 // RR_WATCH() is intended to be used for debugging JIT compiled code, and
454 // is not intended for production use.
455 #	define RR_WATCH(...) RR_LOG(RR_WATCH_FMT(__VA_ARGS__), __VA_ARGS__)
456 
457 }  // namespace rr
458 
459 #	define RR_PRINT_ONLY(x) x
460 #else
461 #	define RR_PRINT_ONLY(x)
462 #endif  // ENABLE_RR_PRINT
463 
464 #endif  // rr_Print_hpp
465