Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 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 | |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 18 | #ifdef ENABLE_RR_PRINT |
| 19 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 20 | # include "Reactor.hpp" |
Nicolas Capens | 90fdde3 | 2022-06-27 12:29:57 -0400 | [diff] [blame] | 21 | # include "SIMD.hpp" |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 22 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 23 | # include <string> |
| 24 | # include <vector> |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 25 | |
| 26 | namespace rr { |
| 27 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 28 | // 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. |
| 37 | class PrintValue |
| 38 | { |
Ben Clayton | fc951cd | 2019-05-15 17:16:56 +0100 | [diff] [blame] | 39 | public: |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 40 | // 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 46 | template<typename T> |
| 47 | struct Ty |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 48 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 49 | // 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 54 | template<typename T> |
| 55 | static std::vector<Value *> val(const T *list, int count) |
| 56 | { |
| 57 | std::vector<Value *> values; |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 58 | values.reserve(count); |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 59 | for(int i = 0; i < count; i++) |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 60 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 61 | auto v = val(list[i]); |
| 62 | values.insert(values.end(), v.begin(), v.end()); |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 63 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 64 | return values; |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 65 | } |
| 66 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 67 | // fmt returns the comma-delimited list of printf format strings for |
| 68 | // every element in the provided list, all enclosed in square brackets. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 69 | template<typename T> |
| 70 | static std::string fmt(const T *list, int count) |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 71 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 72 | std::string out = "["; |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 73 | for(int i = 0; i < count; i++) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 74 | { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 75 | if(i > 0) { out += ", "; } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 76 | out += fmt(list[i]); |
| 77 | } |
| 78 | return out + "]"; |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 79 | } |
| 80 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 81 | static std::string addr(const void *ptr) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 82 | { |
| 83 | char buf[32]; |
| 84 | snprintf(buf, sizeof(buf), "%p", ptr); |
| 85 | return buf; |
| 86 | } |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 87 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 88 | const std::string format; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 89 | const std::vector<Value *> values; |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 90 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 91 | // Constructs a PrintValue for the given value. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 92 | template<typename T> |
| 93 | PrintValue(const T &v) |
| 94 | : format(fmt(v)) |
| 95 | , values(val(v)) |
| 96 | {} |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 97 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 98 | // Constructs a PrintValue for the given static array. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 99 | 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 Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 104 | |
| 105 | // Constructs a PrintValue for the given array starting at arr of length |
| 106 | // len. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 107 | template<typename T> |
| 108 | PrintValue(const T *arr, int len) |
| 109 | : format(fmt(arr, len)) |
| 110 | , values(val(arr, len)) |
| 111 | {} |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 112 | |
| 113 | // PrintValue constructors for plain-old-data values. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 114 | 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 Maiorano | 415d181 | 2020-02-11 16:22:55 -0500 | [diff] [blame] | 147 | PrintValue(const char *v) |
| 148 | : format(v) |
| 149 | {} |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 150 | |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 151 | template<typename T> |
Antonio Maiorano | 415d181 | 2020-02-11 16:22:55 -0500 | [diff] [blame] | 152 | PrintValue(T *v) |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 153 | : format(addr(v)) |
| 154 | {} |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 155 | |
| 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 Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 164 | // |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 165 | // 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 182 | template<typename... ARGS> |
| 183 | static std::vector<Value *> vals(ARGS... v) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 184 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 185 | std::vector<std::vector<Value *>> lists = { val(v)... }; |
| 186 | std::vector<Value *> joined; |
| 187 | for(const auto &list : lists) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 188 | { |
| 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 196 | template<typename T> |
| 197 | static std::string fmt(const T &v) |
| 198 | { |
| 199 | return Ty<T>::fmt(v); |
| 200 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 201 | |
| 202 | // returns the printf value for the given type with a |
| 203 | // PrintValue::Ty<T> specialization. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 204 | template<typename T> |
| 205 | static std::vector<Value *> val(const T &v) |
| 206 | { |
| 207 | return Ty<T>::val(v); |
| 208 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 209 | }; |
| 210 | |
| 211 | // PrintValue::Ty<T> specializations for basic types. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 212 | template<> |
| 213 | struct PrintValue::Ty<const char *> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 214 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 215 | static std::string fmt(const char *v) { return "%s"; } |
| 216 | static std::vector<Value *> val(const char *v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 217 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 218 | template<> |
| 219 | struct PrintValue::Ty<std::string> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 220 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 221 | 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 Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 223 | }; |
| 224 | |
| 225 | // PrintValue::Ty<T> specializations for standard Reactor types. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 226 | template<> |
| 227 | struct PrintValue::Ty<Bool> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 228 | { |
Antonio Maiorano | 415d181 | 2020-02-11 16:22:55 -0500 | [diff] [blame] | 229 | static std::string fmt(const RValue<Bool> &v) { return "%s"; } |
| 230 | static std::vector<Value *> val(const RValue<Bool> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 231 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 232 | template<> |
| 233 | struct PrintValue::Ty<Byte> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 234 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 235 | static std::string fmt(const RValue<Byte> &v) { return "%d"; } |
| 236 | static std::vector<Value *> val(const RValue<Byte> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 237 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 238 | template<> |
| 239 | struct PrintValue::Ty<Byte4> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 240 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 241 | static std::string fmt(const RValue<Byte4> &v) { return "[%d, %d, %d, %d]"; } |
| 242 | static std::vector<Value *> val(const RValue<Byte4> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 243 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 244 | template<> |
| 245 | struct PrintValue::Ty<Int> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 246 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 247 | static std::string fmt(const RValue<Int> &v) { return "%d"; } |
| 248 | static std::vector<Value *> val(const RValue<Int> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 249 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 250 | template<> |
| 251 | struct PrintValue::Ty<Int2> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 252 | { |
Antonio Maiorano | 415d181 | 2020-02-11 16:22:55 -0500 | [diff] [blame] | 253 | static std::string fmt(const RValue<Int2> &v) { return "[%d, %d]"; } |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 254 | static std::vector<Value *> val(const RValue<Int2> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 255 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 256 | template<> |
| 257 | struct PrintValue::Ty<Int4> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 258 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 259 | static std::string fmt(const RValue<Int4> &v) { return "[%d, %d, %d, %d]"; } |
| 260 | static std::vector<Value *> val(const RValue<Int4> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 261 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 262 | template<> |
| 263 | struct PrintValue::Ty<UInt> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 264 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 265 | static std::string fmt(const RValue<UInt> &v) { return "%u"; } |
| 266 | static std::vector<Value *> val(const RValue<UInt> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 267 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 268 | template<> |
| 269 | struct PrintValue::Ty<UInt2> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 270 | { |
Antonio Maiorano | 415d181 | 2020-02-11 16:22:55 -0500 | [diff] [blame] | 271 | static std::string fmt(const RValue<UInt2> &v) { return "[%u, %u]"; } |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 272 | static std::vector<Value *> val(const RValue<UInt2> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 273 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 274 | template<> |
| 275 | struct PrintValue::Ty<UInt4> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 276 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 277 | static std::string fmt(const RValue<UInt4> &v) { return "[%u, %u, %u, %u]"; } |
| 278 | static std::vector<Value *> val(const RValue<UInt4> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 279 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 280 | template<> |
| 281 | struct PrintValue::Ty<Short> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 282 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 283 | static std::string fmt(const RValue<Short> &v) { return "%d"; } |
| 284 | static std::vector<Value *> val(const RValue<Short> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 285 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 286 | template<> |
| 287 | struct PrintValue::Ty<Short4> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 288 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 289 | static std::string fmt(const RValue<Short4> &v) { return "[%d, %d, %d, %d]"; } |
| 290 | static std::vector<Value *> val(const RValue<Short4> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 291 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 292 | template<> |
| 293 | struct PrintValue::Ty<UShort> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 294 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 295 | static std::string fmt(const RValue<UShort> &v) { return "%u"; } |
| 296 | static std::vector<Value *> val(const RValue<UShort> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 297 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 298 | template<> |
| 299 | struct PrintValue::Ty<UShort4> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 300 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 301 | static std::string fmt(const RValue<UShort4> &v) { return "[%u, %u, %u, %u]"; } |
| 302 | static std::vector<Value *> val(const RValue<UShort4> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 303 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 304 | template<> |
| 305 | struct PrintValue::Ty<Float> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 306 | { |
Antonio Maiorano | 415d181 | 2020-02-11 16:22:55 -0500 | [diff] [blame] | 307 | static std::string fmt(const RValue<Float> &v) { return "%f"; } |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 308 | static std::vector<Value *> val(const RValue<Float> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 309 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 310 | template<> |
| 311 | struct PrintValue::Ty<Float4> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 312 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 313 | static std::string fmt(const RValue<Float4> &v) { return "[%f, %f, %f, %f]"; } |
| 314 | static std::vector<Value *> val(const RValue<Float4> &v); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 315 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 316 | template<> |
| 317 | struct PrintValue::Ty<Long> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 318 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 319 | static std::string fmt(const RValue<Long> &v) { return "%lld"; } |
Nicolas Capens | b6e8c3f | 2020-05-01 23:28:37 -0400 | [diff] [blame] | 320 | static std::vector<Value *> val(const RValue<Long> &v) { return { v.value() }; } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 321 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 322 | template<typename T> |
| 323 | struct PrintValue::Ty<Pointer<T>> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 324 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 325 | static std::string fmt(const RValue<Pointer<T>> &v) { return "%p"; } |
Nicolas Capens | b6e8c3f | 2020-05-01 23:28:37 -0400 | [diff] [blame] | 326 | static std::vector<Value *> val(const RValue<Pointer<T>> &v) { return { v.value() }; } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 327 | }; |
Sean Risser | 19e3080 | 2022-06-01 10:58:10 -0400 | [diff] [blame] | 328 | template<> |
Nicolas Capens | d1116fa | 2022-06-29 10:39:18 -0400 | [diff] [blame] | 329 | struct PrintValue::Ty<SIMD::Pointer> |
Sean Risser | 19e3080 | 2022-06-01 10:58:10 -0400 | [diff] [blame] | 330 | { |
Nicolas Capens | d1116fa | 2022-06-29 10:39:18 -0400 | [diff] [blame] | 331 | static std::string fmt(const SIMD::Pointer &v) |
Sean Risser | 19e3080 | 2022-06-01 10:58:10 -0400 | [diff] [blame] | 332 | { |
Nicolas Capens | d1116fa | 2022-06-29 10:39:18 -0400 | [diff] [blame] | 333 | if(v.isBasePlusOffset) |
| 334 | { |
| 335 | std::string format; |
Nicolas Capens | 16826bf | 2022-08-10 11:55:12 -0400 | [diff] [blame] | 336 | for(int i = 1; i < SIMD::Width; i++) { format += ", %d"; } |
Nicolas Capens | d1116fa | 2022-06-29 10:39:18 -0400 | [diff] [blame] | 337 | 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 Risser | 19e3080 | 2022-06-01 10:58:10 -0400 | [diff] [blame] | 345 | } |
| 346 | |
Nicolas Capens | d1116fa | 2022-06-29 10:39:18 -0400 | [diff] [blame] | 347 | static std::vector<Value *> val(const SIMD::Pointer &v) |
Sean Risser | 19e3080 | 2022-06-01 10:58:10 -0400 | [diff] [blame] | 348 | { |
| 349 | return v.getPrintValues(); |
| 350 | } |
| 351 | }; |
Nicolas Capens | 90fdde3 | 2022-06-27 12:29:57 -0400 | [diff] [blame] | 352 | template<> |
| 353 | struct 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 | }; |
| 363 | template<> |
| 364 | struct 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 | }; |
| 374 | template<> |
| 375 | struct 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 385 | template<typename T> |
| 386 | struct PrintValue::Ty<Reference<T>> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 387 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 388 | 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 Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 390 | }; |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 391 | template<typename T> |
| 392 | struct PrintValue::Ty<RValue<T>> |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 393 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 394 | 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 Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 396 | }; |
| 397 | |
Antonio Maiorano | 62427e0 | 2020-02-13 09:18:05 -0500 | [diff] [blame] | 398 | // VPrintf emits a call to printf() using vals[0] as the format string, |
| 399 | // and vals[1..n] as the args. |
| 400 | void VPrintf(const std::vector<Value *> &vals); |
| 401 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 402 | // Printv emits a call to printf() using the function, file and line, |
| 403 | // message and optional values. |
| 404 | // See Printv below. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 405 | void Printv(const char *function, const char *file, int line, const char *msg, std::initializer_list<PrintValue> vals); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 406 | |
| 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 417 | inline void Printv(const char *msg, std::initializer_list<PrintValue> vals) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 418 | { |
| 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 424 | template<typename... ARGS> |
Nicolas Capens | dac99e8 | 2020-11-19 04:18:58 +0000 | [diff] [blame] | 425 | void Print(const char *msg, const ARGS &...vals) |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 426 | { |
| 427 | Printv(msg, { vals... }); |
| 428 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 429 | |
| 430 | // Print is a wrapper over Printv that wraps the variadic arguments into an |
| 431 | // initializer_list before calling Printv. |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 432 | template<typename... ARGS> |
Nicolas Capens | dac99e8 | 2020-11-19 04:18:58 +0000 | [diff] [blame] | 433 | void Print(const char *function, const char *file, int line, const char *msg, const ARGS &...vals) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 434 | { |
Ben Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 435 | Printv(function, file, line, msg, { vals... }); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 436 | } |
| 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 443 | # 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 Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 448 | |
| 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 452 | # 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)) |
| 455 | static_assert(1 == RR_COUNT_ARGUMENTS(a), "RR_COUNT_ARGUMENTS broken"); // Sanity checks. |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 456 | static_assert(2 == RR_COUNT_ARGUMENTS(a, b), "RR_COUNT_ARGUMENTS broken"); |
| 457 | static_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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 465 | # 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 Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 502 | |
| 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 Clayton | 713b8d3 | 2019-12-17 20:37:56 +0000 | [diff] [blame] | 513 | # define RR_WATCH(...) RR_LOG(RR_WATCH_FMT(__VA_ARGS__), __VA_ARGS__) |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 514 | |
| 515 | } // namespace rr |
| 516 | |
Ben Clayton | fc951cd | 2019-05-15 17:16:56 +0100 | [diff] [blame] | 517 | # define RR_PRINT_ONLY(x) x |
| 518 | #else |
| 519 | # define RR_PRINT_ONLY(x) |
Ben Clayton | 2377845 | 2019-11-19 14:15:41 +0000 | [diff] [blame] | 520 | #endif // ENABLE_RR_PRINT |
| 521 | |
| 522 | #endif // rr_Print_hpp |