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