blob: 6d2b4d1a331ef1fd3dc9759acccc7bc27429b0be [file] [log] [blame]
Ben Clayton23778452019-11-19 14:15:41 +00001// 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
Ben Clayton23778452019-11-19 14:15:41 +000018#ifdef ENABLE_RR_PRINT
19
Ben Clayton713b8d32019-12-17 20:37:56 +000020# include "Reactor.hpp"
Nicolas Capens90fdde32022-06-27 12:29:57 -040021# include "SIMD.hpp"
Ben Clayton23778452019-11-19 14:15:41 +000022
Ben Clayton713b8d32019-12-17 20:37:56 +000023# include <string>
24# include <vector>
Ben Clayton23778452019-11-19 14:15:41 +000025
26namespace rr {
27
Nicolas Capens157ba262019-12-10 17:49:14 -050028// PrintValue holds the printf format and value(s) for a single argument
29// to Print(). A single argument can be expanded into multiple printf
30// values - for example a Float4 will expand to "%f %f %f %f" and four
31// scalar values.
32// The PrintValue constructor accepts the following:
33// * Reactor LValues, RValues, Pointers.
34// * Standard Plain-Old-Value types (int, float, bool, etc)
35// * Custom types that specialize the PrintValue::Ty template struct.
36// * Static arrays in the form T[N] where T can be any of the above.
37class PrintValue
38{
Ben Claytonfc951cd2019-05-15 17:16:56 +010039public:
Nicolas Capens157ba262019-12-10 17:49:14 -050040 // Ty is a template that can be specialized for printing type T.
41 // Each specialization must expose:
42 // * A 'static std::string fmt(const T& v)' method that provides the
43 // printf format specifier.
44 // * A 'static std::vector<rr::Value*> val(const T& v)' method that
45 // returns all the printf format values.
Ben Clayton713b8d32019-12-17 20:37:56 +000046 template<typename T>
47 struct Ty
Ben Clayton23778452019-11-19 14:15:41 +000048 {
Nicolas Capens157ba262019-12-10 17:49:14 -050049 // static std::string fmt(const T& v);
50 // static std::vector<rr::Value*> val(const T& v);
51 };
52
53 // returns the printf values for all the values in the given array.
Ben Clayton713b8d32019-12-17 20:37:56 +000054 template<typename T>
55 static std::vector<Value *> val(const T *list, int count)
56 {
57 std::vector<Value *> values;
Nicolas Capens157ba262019-12-10 17:49:14 -050058 values.reserve(count);
Nicolas Capens81bc9d92019-12-16 15:05:57 -050059 for(int i = 0; i < count; i++)
Ben Clayton23778452019-11-19 14:15:41 +000060 {
Nicolas Capens157ba262019-12-10 17:49:14 -050061 auto v = val(list[i]);
62 values.insert(values.end(), v.begin(), v.end());
Ben Clayton23778452019-11-19 14:15:41 +000063 }
Nicolas Capens157ba262019-12-10 17:49:14 -050064 return values;
Ben Clayton23778452019-11-19 14:15:41 +000065 }
66
Nicolas Capens157ba262019-12-10 17:49:14 -050067 // fmt returns the comma-delimited list of printf format strings for
68 // every element in the provided list, all enclosed in square brackets.
Ben Clayton713b8d32019-12-17 20:37:56 +000069 template<typename T>
70 static std::string fmt(const T *list, int count)
Ben Clayton23778452019-11-19 14:15:41 +000071 {
Nicolas Capens157ba262019-12-10 17:49:14 -050072 std::string out = "[";
Nicolas Capens81bc9d92019-12-16 15:05:57 -050073 for(int i = 0; i < count; i++)
Nicolas Capens157ba262019-12-10 17:49:14 -050074 {
Nicolas Capens81bc9d92019-12-16 15:05:57 -050075 if(i > 0) { out += ", "; }
Nicolas Capens157ba262019-12-10 17:49:14 -050076 out += fmt(list[i]);
77 }
78 return out + "]";
Ben Clayton23778452019-11-19 14:15:41 +000079 }
80
Ben Clayton713b8d32019-12-17 20:37:56 +000081 static std::string addr(const void *ptr)
Nicolas Capens157ba262019-12-10 17:49:14 -050082 {
83 char buf[32];
84 snprintf(buf, sizeof(buf), "%p", ptr);
85 return buf;
86 }
Ben Clayton23778452019-11-19 14:15:41 +000087
Nicolas Capens157ba262019-12-10 17:49:14 -050088 const std::string format;
Ben Clayton713b8d32019-12-17 20:37:56 +000089 const std::vector<Value *> values;
Ben Clayton23778452019-11-19 14:15:41 +000090
Nicolas Capens157ba262019-12-10 17:49:14 -050091 // Constructs a PrintValue for the given value.
Ben Clayton713b8d32019-12-17 20:37:56 +000092 template<typename T>
93 PrintValue(const T &v)
94 : format(fmt(v))
95 , values(val(v))
96 {}
Ben Clayton23778452019-11-19 14:15:41 +000097
Nicolas Capens157ba262019-12-10 17:49:14 -050098 // Constructs a PrintValue for the given static array.
Ben Clayton713b8d32019-12-17 20:37:56 +000099 template<typename T, int N>
100 PrintValue(const T (&v)[N])
101 : format(fmt(&v[0], N))
102 , values(val(&v[0], N))
103 {}
Nicolas Capens157ba262019-12-10 17:49:14 -0500104
105 // Constructs a PrintValue for the given array starting at arr of length
106 // len.
Ben Clayton713b8d32019-12-17 20:37:56 +0000107 template<typename T>
108 PrintValue(const T *arr, int len)
109 : format(fmt(arr, len))
110 , values(val(arr, len))
111 {}
Nicolas Capens157ba262019-12-10 17:49:14 -0500112
113 // PrintValue constructors for plain-old-data values.
Ben Clayton713b8d32019-12-17 20:37:56 +0000114 PrintValue(bool v)
115 : format(v ? "true" : "false")
116 {}
117 PrintValue(int8_t v)
118 : format(std::to_string(v))
119 {}
120 PrintValue(uint8_t v)
121 : format(std::to_string(v))
122 {}
123 PrintValue(int16_t v)
124 : format(std::to_string(v))
125 {}
126 PrintValue(uint16_t v)
127 : format(std::to_string(v))
128 {}
129 PrintValue(int32_t v)
130 : format(std::to_string(v))
131 {}
132 PrintValue(uint32_t v)
133 : format(std::to_string(v))
134 {}
135 PrintValue(int64_t v)
136 : format(std::to_string(v))
137 {}
138 PrintValue(uint64_t v)
139 : format(std::to_string(v))
140 {}
141 PrintValue(float v)
142 : format(std::to_string(v))
143 {}
144 PrintValue(double v)
145 : format(std::to_string(v))
146 {}
Antonio Maiorano415d1812020-02-11 16:22:55 -0500147 PrintValue(const char *v)
148 : format(v)
149 {}
Nicolas Capens157ba262019-12-10 17:49:14 -0500150
Ben Clayton713b8d32019-12-17 20:37:56 +0000151 template<typename T>
Antonio Maiorano415d1812020-02-11 16:22:55 -0500152 PrintValue(T *v)
Ben Clayton713b8d32019-12-17 20:37:56 +0000153 : format(addr(v))
154 {}
Nicolas Capens157ba262019-12-10 17:49:14 -0500155
156 // vals is a helper to build composite value lists.
157 // vals returns the full, sequential list of printf argument values used
158 // to print all the provided variadic values.
159 // vals() is intended to be used by implementations of
160 // PrintValue::Ty<>::vals() to help declare aggregate types.
161 // For example, if you were declaring a PrintValue::Ty<> specialization
162 // for a custom Mat4x4 matrix formed from four Vector4 values, you'd
163 // write:
Ben Clayton23778452019-11-19 14:15:41 +0000164 //
Nicolas Capens157ba262019-12-10 17:49:14 -0500165 // namespace rr
166 // {
167 // template <> struct PrintValue::Ty<Mat4x4>
168 // {
169 // static std::string fmt(const Mat4x4& v)
170 // {
171 // return "[a: <%f, %f, %f, %f>,"
172 // " b: <%f, %f, %f, %f>,"
173 // " c: <%f, %f, %f, %f>,"
174 // " d: <%f, %f, %f, %f>]";
175 // }
176 // static std::vector<rr::Value*> val(const Mat4x4& v)
177 // {
178 // return PrintValue::vals(v.a, v.b, v.c, v.d);
179 // }
180 // };
181 // }
Ben Clayton713b8d32019-12-17 20:37:56 +0000182 template<typename... ARGS>
183 static std::vector<Value *> vals(ARGS... v)
Nicolas Capens157ba262019-12-10 17:49:14 -0500184 {
Ben Clayton713b8d32019-12-17 20:37:56 +0000185 std::vector<std::vector<Value *>> lists = { val(v)... };
186 std::vector<Value *> joined;
187 for(const auto &list : lists)
Nicolas Capens157ba262019-12-10 17:49:14 -0500188 {
189 joined.insert(joined.end(), list.begin(), list.end());
190 }
191 return joined;
192 }
193
194 // returns the printf format specifier for the given type via the
195 // PrintValue::Ty<T> specialization.
Ben Clayton713b8d32019-12-17 20:37:56 +0000196 template<typename T>
197 static std::string fmt(const T &v)
198 {
199 return Ty<T>::fmt(v);
200 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500201
202 // returns the printf value for the given type with a
203 // PrintValue::Ty<T> specialization.
Ben Clayton713b8d32019-12-17 20:37:56 +0000204 template<typename T>
205 static std::vector<Value *> val(const T &v)
206 {
207 return Ty<T>::val(v);
208 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500209};
210
211// PrintValue::Ty<T> specializations for basic types.
Ben Clayton713b8d32019-12-17 20:37:56 +0000212template<>
213struct PrintValue::Ty<const char *>
Nicolas Capens157ba262019-12-10 17:49:14 -0500214{
Ben Clayton713b8d32019-12-17 20:37:56 +0000215 static std::string fmt(const char *v) { return "%s"; }
216 static std::vector<Value *> val(const char *v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500217};
Ben Clayton713b8d32019-12-17 20:37:56 +0000218template<>
219struct PrintValue::Ty<std::string>
Nicolas Capens157ba262019-12-10 17:49:14 -0500220{
Ben Clayton713b8d32019-12-17 20:37:56 +0000221 static std::string fmt(const std::string &v) { return PrintValue::Ty<const char *>::fmt(v.c_str()); }
222 static std::vector<Value *> val(const std::string &v) { return PrintValue::Ty<const char *>::val(v.c_str()); }
Nicolas Capens157ba262019-12-10 17:49:14 -0500223};
224
225// PrintValue::Ty<T> specializations for standard Reactor types.
Ben Clayton713b8d32019-12-17 20:37:56 +0000226template<>
227struct PrintValue::Ty<Bool>
Nicolas Capens157ba262019-12-10 17:49:14 -0500228{
Antonio Maiorano415d1812020-02-11 16:22:55 -0500229 static std::string fmt(const RValue<Bool> &v) { return "%s"; }
230 static std::vector<Value *> val(const RValue<Bool> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500231};
Ben Clayton713b8d32019-12-17 20:37:56 +0000232template<>
233struct PrintValue::Ty<Byte>
Nicolas Capens157ba262019-12-10 17:49:14 -0500234{
Ben Clayton713b8d32019-12-17 20:37:56 +0000235 static std::string fmt(const RValue<Byte> &v) { return "%d"; }
236 static std::vector<Value *> val(const RValue<Byte> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500237};
Ben Clayton713b8d32019-12-17 20:37:56 +0000238template<>
239struct PrintValue::Ty<Byte4>
Nicolas Capens157ba262019-12-10 17:49:14 -0500240{
Ben Clayton713b8d32019-12-17 20:37:56 +0000241 static std::string fmt(const RValue<Byte4> &v) { return "[%d, %d, %d, %d]"; }
242 static std::vector<Value *> val(const RValue<Byte4> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500243};
Ben Clayton713b8d32019-12-17 20:37:56 +0000244template<>
245struct PrintValue::Ty<Int>
Nicolas Capens157ba262019-12-10 17:49:14 -0500246{
Ben Clayton713b8d32019-12-17 20:37:56 +0000247 static std::string fmt(const RValue<Int> &v) { return "%d"; }
248 static std::vector<Value *> val(const RValue<Int> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500249};
Ben Clayton713b8d32019-12-17 20:37:56 +0000250template<>
251struct PrintValue::Ty<Int2>
Nicolas Capens157ba262019-12-10 17:49:14 -0500252{
Antonio Maiorano415d1812020-02-11 16:22:55 -0500253 static std::string fmt(const RValue<Int2> &v) { return "[%d, %d]"; }
Ben Clayton713b8d32019-12-17 20:37:56 +0000254 static std::vector<Value *> val(const RValue<Int2> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500255};
Ben Clayton713b8d32019-12-17 20:37:56 +0000256template<>
257struct PrintValue::Ty<Int4>
Nicolas Capens157ba262019-12-10 17:49:14 -0500258{
Ben Clayton713b8d32019-12-17 20:37:56 +0000259 static std::string fmt(const RValue<Int4> &v) { return "[%d, %d, %d, %d]"; }
260 static std::vector<Value *> val(const RValue<Int4> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500261};
Ben Clayton713b8d32019-12-17 20:37:56 +0000262template<>
263struct PrintValue::Ty<UInt>
Nicolas Capens157ba262019-12-10 17:49:14 -0500264{
Ben Clayton713b8d32019-12-17 20:37:56 +0000265 static std::string fmt(const RValue<UInt> &v) { return "%u"; }
266 static std::vector<Value *> val(const RValue<UInt> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500267};
Ben Clayton713b8d32019-12-17 20:37:56 +0000268template<>
269struct PrintValue::Ty<UInt2>
Nicolas Capens157ba262019-12-10 17:49:14 -0500270{
Antonio Maiorano415d1812020-02-11 16:22:55 -0500271 static std::string fmt(const RValue<UInt2> &v) { return "[%u, %u]"; }
Ben Clayton713b8d32019-12-17 20:37:56 +0000272 static std::vector<Value *> val(const RValue<UInt2> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500273};
Ben Clayton713b8d32019-12-17 20:37:56 +0000274template<>
275struct PrintValue::Ty<UInt4>
Nicolas Capens157ba262019-12-10 17:49:14 -0500276{
Ben Clayton713b8d32019-12-17 20:37:56 +0000277 static std::string fmt(const RValue<UInt4> &v) { return "[%u, %u, %u, %u]"; }
278 static std::vector<Value *> val(const RValue<UInt4> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500279};
Ben Clayton713b8d32019-12-17 20:37:56 +0000280template<>
281struct PrintValue::Ty<Short>
Nicolas Capens157ba262019-12-10 17:49:14 -0500282{
Ben Clayton713b8d32019-12-17 20:37:56 +0000283 static std::string fmt(const RValue<Short> &v) { return "%d"; }
284 static std::vector<Value *> val(const RValue<Short> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500285};
Ben Clayton713b8d32019-12-17 20:37:56 +0000286template<>
287struct PrintValue::Ty<Short4>
Nicolas Capens157ba262019-12-10 17:49:14 -0500288{
Ben Clayton713b8d32019-12-17 20:37:56 +0000289 static std::string fmt(const RValue<Short4> &v) { return "[%d, %d, %d, %d]"; }
290 static std::vector<Value *> val(const RValue<Short4> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500291};
Ben Clayton713b8d32019-12-17 20:37:56 +0000292template<>
293struct PrintValue::Ty<UShort>
Nicolas Capens157ba262019-12-10 17:49:14 -0500294{
Ben Clayton713b8d32019-12-17 20:37:56 +0000295 static std::string fmt(const RValue<UShort> &v) { return "%u"; }
296 static std::vector<Value *> val(const RValue<UShort> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500297};
Ben Clayton713b8d32019-12-17 20:37:56 +0000298template<>
299struct PrintValue::Ty<UShort4>
Nicolas Capens157ba262019-12-10 17:49:14 -0500300{
Ben Clayton713b8d32019-12-17 20:37:56 +0000301 static std::string fmt(const RValue<UShort4> &v) { return "[%u, %u, %u, %u]"; }
302 static std::vector<Value *> val(const RValue<UShort4> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500303};
Ben Clayton713b8d32019-12-17 20:37:56 +0000304template<>
305struct PrintValue::Ty<Float>
Nicolas Capens157ba262019-12-10 17:49:14 -0500306{
Antonio Maiorano415d1812020-02-11 16:22:55 -0500307 static std::string fmt(const RValue<Float> &v) { return "%f"; }
Ben Clayton713b8d32019-12-17 20:37:56 +0000308 static std::vector<Value *> val(const RValue<Float> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500309};
Ben Clayton713b8d32019-12-17 20:37:56 +0000310template<>
311struct PrintValue::Ty<Float4>
Nicolas Capens157ba262019-12-10 17:49:14 -0500312{
Ben Clayton713b8d32019-12-17 20:37:56 +0000313 static std::string fmt(const RValue<Float4> &v) { return "[%f, %f, %f, %f]"; }
314 static std::vector<Value *> val(const RValue<Float4> &v);
Nicolas Capens157ba262019-12-10 17:49:14 -0500315};
Ben Clayton713b8d32019-12-17 20:37:56 +0000316template<>
317struct PrintValue::Ty<Long>
Nicolas Capens157ba262019-12-10 17:49:14 -0500318{
Ben Clayton713b8d32019-12-17 20:37:56 +0000319 static std::string fmt(const RValue<Long> &v) { return "%lld"; }
Nicolas Capensb6e8c3f2020-05-01 23:28:37 -0400320 static std::vector<Value *> val(const RValue<Long> &v) { return { v.value() }; }
Nicolas Capens157ba262019-12-10 17:49:14 -0500321};
Ben Clayton713b8d32019-12-17 20:37:56 +0000322template<typename T>
323struct PrintValue::Ty<Pointer<T>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500324{
Ben Clayton713b8d32019-12-17 20:37:56 +0000325 static std::string fmt(const RValue<Pointer<T>> &v) { return "%p"; }
Nicolas Capensb6e8c3f2020-05-01 23:28:37 -0400326 static std::vector<Value *> val(const RValue<Pointer<T>> &v) { return { v.value() }; }
Nicolas Capens157ba262019-12-10 17:49:14 -0500327};
Sean Risser19e30802022-06-01 10:58:10 -0400328template<>
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400329struct PrintValue::Ty<SIMD::Pointer>
Sean Risser19e30802022-06-01 10:58:10 -0400330{
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400331 static std::string fmt(const SIMD::Pointer &v)
Sean Risser19e30802022-06-01 10:58:10 -0400332 {
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400333 if(v.isBasePlusOffset)
334 {
335 std::string format;
Nicolas Capens16826bf2022-08-10 11:55:12 -0400336 for(int i = 1; i < SIMD::Width; i++) { format += ", %d"; }
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400337 return "{%p + [%d" + format + "]}";
338 }
339 else
340 {
341 std::string format;
342 for(int i = 1; i < SIMD::Width; i++) { format += ", %p"; }
343 return "{%p" + format + "}";
344 }
Sean Risser19e30802022-06-01 10:58:10 -0400345 }
346
Nicolas Capensd1116fa2022-06-29 10:39:18 -0400347 static std::vector<Value *> val(const SIMD::Pointer &v)
Sean Risser19e30802022-06-01 10:58:10 -0400348 {
349 return v.getPrintValues();
350 }
351};
Nicolas Capens90fdde32022-06-27 12:29:57 -0400352template<>
353struct PrintValue::Ty<SIMD::Int>
354{
355 static std::string fmt(const RValue<SIMD::Int> &v)
356 {
357 std::string format;
358 for(int i = 1; i < SIMD::Width; i++) { format += ", %d"; }
359 return "[%d" + format + "]";
360 }
361 static std::vector<Value *> val(const RValue<SIMD::Int> &v);
362};
363template<>
364struct PrintValue::Ty<SIMD::UInt>
365{
366 static std::string fmt(const RValue<SIMD::UInt> &v)
367 {
368 std::string format;
369 for(int i = 1; i < SIMD::Width; i++) { format += ", %u"; }
370 return "[%u" + format + "]";
371 }
372 static std::vector<Value *> val(const RValue<SIMD::UInt> &v);
373};
374template<>
375struct PrintValue::Ty<SIMD::Float>
376{
377 static std::string fmt(const RValue<SIMD::Float> &v)
378 {
379 std::string format;
380 for(int i = 1; i < SIMD::Width; i++) { format += ", %f"; }
381 return "[%f" + format + "]";
382 }
383 static std::vector<Value *> val(const RValue<SIMD::Float> &v);
384};
Ben Clayton713b8d32019-12-17 20:37:56 +0000385template<typename T>
386struct PrintValue::Ty<Reference<T>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500387{
Ben Clayton713b8d32019-12-17 20:37:56 +0000388 static std::string fmt(const Reference<T> &v) { return PrintValue::Ty<T>::fmt(v); }
389 static std::vector<Value *> val(const Reference<T> &v) { return PrintValue::Ty<T>::val(v); }
Nicolas Capens157ba262019-12-10 17:49:14 -0500390};
Ben Clayton713b8d32019-12-17 20:37:56 +0000391template<typename T>
392struct PrintValue::Ty<RValue<T>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500393{
Ben Clayton713b8d32019-12-17 20:37:56 +0000394 static std::string fmt(const RValue<T> &v) { return PrintValue::Ty<T>::fmt(v); }
395 static std::vector<Value *> val(const RValue<T> &v) { return PrintValue::Ty<T>::val(v); }
Nicolas Capens157ba262019-12-10 17:49:14 -0500396};
397
Antonio Maiorano62427e02020-02-13 09:18:05 -0500398// VPrintf emits a call to printf() using vals[0] as the format string,
399// and vals[1..n] as the args.
400void VPrintf(const std::vector<Value *> &vals);
401
Nicolas Capens157ba262019-12-10 17:49:14 -0500402// Printv emits a call to printf() using the function, file and line,
403// message and optional values.
404// See Printv below.
Ben Clayton713b8d32019-12-17 20:37:56 +0000405void Printv(const char *function, const char *file, int line, const char *msg, std::initializer_list<PrintValue> vals);
Nicolas Capens157ba262019-12-10 17:49:14 -0500406
407// Printv emits a call to printf() using the provided message and optional
408// values.
409// Printf replaces any bracketed indices in the message with string
410// representations of the corresponding value in vals.
411// For example:
412// Printv("{0} and {1}", "red", "green");
413// Would print the string:
414// "red and green"
415// Arguments can be indexed in any order.
416// Invalid indices are not substituted.
Ben Clayton713b8d32019-12-17 20:37:56 +0000417inline void Printv(const char *msg, std::initializer_list<PrintValue> vals)
Nicolas Capens157ba262019-12-10 17:49:14 -0500418{
419 Printv(nullptr, nullptr, 0, msg, vals);
420}
421
422// Print is a wrapper over Printv that wraps the variadic arguments into an
423// initializer_list before calling Printv.
Ben Clayton713b8d32019-12-17 20:37:56 +0000424template<typename... ARGS>
Nicolas Capensdac99e82020-11-19 04:18:58 +0000425void Print(const char *msg, const ARGS &...vals)
Ben Clayton713b8d32019-12-17 20:37:56 +0000426{
427 Printv(msg, { vals... });
428}
Nicolas Capens157ba262019-12-10 17:49:14 -0500429
430// Print is a wrapper over Printv that wraps the variadic arguments into an
431// initializer_list before calling Printv.
Ben Clayton713b8d32019-12-17 20:37:56 +0000432template<typename... ARGS>
Nicolas Capensdac99e82020-11-19 04:18:58 +0000433void Print(const char *function, const char *file, int line, const char *msg, const ARGS &...vals)
Nicolas Capens157ba262019-12-10 17:49:14 -0500434{
Ben Clayton713b8d32019-12-17 20:37:56 +0000435 Printv(function, file, line, msg, { vals... });
Nicolas Capens157ba262019-12-10 17:49:14 -0500436}
437
438// RR_LOG is a macro that calls Print(), automatically populating the
439// function, file and line parameters and appending a newline to the string.
440//
441// RR_LOG() is intended to be used for debugging JIT compiled code, and is
442// not intended for production use.
Ben Clayton713b8d32019-12-17 20:37:56 +0000443# if defined(_WIN32)
444# define RR_LOG(msg, ...) Print(__FUNCSIG__, __FILE__, static_cast<int>(__LINE__), msg "\n", ##__VA_ARGS__)
445# else
446# define RR_LOG(msg, ...) Print(__PRETTY_FUNCTION__, __FILE__, static_cast<int>(__LINE__), msg "\n", ##__VA_ARGS__)
447# endif
Nicolas Capens157ba262019-12-10 17:49:14 -0500448
449// Macro magic to perform variadic dispatch.
450// See: https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/preprocessor/macros/__VA_ARGS__/count-arguments
451// Note, this doesn't attempt to use the ##__VA_ARGS__ trick to handle 0
Ben Clayton713b8d32019-12-17 20:37:56 +0000452# define RR_MSVC_EXPAND_BUG(X) X // Helper macro to force expanding __VA_ARGS__ to satisfy MSVC compiler.
453# define RR_GET_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
454# 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))
455static_assert(1 == RR_COUNT_ARGUMENTS(a), "RR_COUNT_ARGUMENTS broken"); // Sanity checks.
Nicolas Capens157ba262019-12-10 17:49:14 -0500456static_assert(2 == RR_COUNT_ARGUMENTS(a, b), "RR_COUNT_ARGUMENTS broken");
457static_assert(3 == RR_COUNT_ARGUMENTS(a, b, c), "RR_COUNT_ARGUMENTS broken");
458
459// RR_WATCH_FMT(...) resolves to a string literal that lists all the
460// arguments by name. This string can be passed to LOG() to print each of
461// the arguments with their name and value.
462//
463// RR_WATCH_FMT(...) uses the RR_COUNT_ARGUMENTS helper macro to delegate to a
464// corresponding RR_WATCH_FMT_n specialization macro below.
Ben Clayton713b8d32019-12-17 20:37:56 +0000465# define RR_WATCH_CONCAT(a, b) a##b
466# define RR_WATCH_CONCAT2(a, b) RR_WATCH_CONCAT(a, b)
467# define RR_WATCH_FMT(...) RR_MSVC_EXPAND_BUG(RR_WATCH_CONCAT2(RR_WATCH_FMT_, RR_COUNT_ARGUMENTS(__VA_ARGS__))(__VA_ARGS__))
468# define RR_WATCH_FMT_1(_1) "\n " # _1 ": {0}"
469# define RR_WATCH_FMT_2(_1, _2) \
470 RR_WATCH_FMT_1(_1) \
471 "\n " #_2 ": {1}"
472# define RR_WATCH_FMT_3(_1, _2, _3) \
473 RR_WATCH_FMT_2(_1, _2) \
474 "\n " #_3 ": {2}"
475# define RR_WATCH_FMT_4(_1, _2, _3, _4) \
476 RR_WATCH_FMT_3(_1, _2, _3) \
477 "\n " #_4 ": {3}"
478# define RR_WATCH_FMT_5(_1, _2, _3, _4, _5) \
479 RR_WATCH_FMT_4(_1, _2, _3, _4) \
480 "\n " #_5 ": {4}"
481# define RR_WATCH_FMT_6(_1, _2, _3, _4, _5, _6) \
482 RR_WATCH_FMT_5(_1, _2, _3, _4, _5) \
483 "\n " #_6 ": {5}"
484# define RR_WATCH_FMT_7(_1, _2, _3, _4, _5, _6, _7) \
485 RR_WATCH_FMT_6(_1, _2, _3, _4, _5, _6) \
486 "\n " #_7 ": {6}"
487# define RR_WATCH_FMT_8(_1, _2, _3, _4, _5, _6, _7, _8) \
488 RR_WATCH_FMT_7(_1, _2, _3, _4, _5, _6, _7) \
489 "\n " #_8 ": {7}"
490# define RR_WATCH_FMT_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) \
491 RR_WATCH_FMT_8(_1, _2, _3, _4, _5, _6, _7, _8) \
492 "\n " #_9 ": {8}"
493# define RR_WATCH_FMT_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
494 RR_WATCH_FMT_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) \
495 "\n " #_10 ": {9}"
496# define RR_WATCH_FMT_11(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
497 RR_WATCH_FMT_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
498 "\n " #_11 ": {10}"
499# define RR_WATCH_FMT_12(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
500 RR_WATCH_FMT_11(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
501 "\n " #_12 ": {11}"
Nicolas Capens157ba262019-12-10 17:49:14 -0500502
503// RR_WATCH() is a helper that prints the name and value of all the supplied
504// arguments.
505// For example, if you had the Int and bool variables 'foo' and 'bar' that
506// you want to print, you can simply write:
507// RR_WATCH(foo, bar)
508// When this JIT compiled code is executed, it will print the string
509// "foo: 1, bar: true" to stdout.
510//
511// RR_WATCH() is intended to be used for debugging JIT compiled code, and
512// is not intended for production use.
Ben Clayton713b8d32019-12-17 20:37:56 +0000513# define RR_WATCH(...) RR_LOG(RR_WATCH_FMT(__VA_ARGS__), __VA_ARGS__)
Ben Clayton23778452019-11-19 14:15:41 +0000514
515} // namespace rr
516
Ben Claytonfc951cd2019-05-15 17:16:56 +0100517# define RR_PRINT_ONLY(x) x
518#else
519# define RR_PRINT_ONLY(x)
Ben Clayton23778452019-11-19 14:15:41 +0000520#endif // ENABLE_RR_PRINT
521
522#endif // rr_Print_hpp