Halide  14.0.0
Halide compiler and libraries
printer.h
Go to the documentation of this file.
1 #ifndef HALIDE_RUNTIME_PRINTER_H
2 #define HALIDE_RUNTIME_PRINTER_H
3 namespace Halide {
4 namespace Runtime {
5 namespace Internal {
6 
10 
12 
13 // A class for constructing debug messages from the runtime. Dumps
14 // items into a stack array, then prints them when the object leaves
15 // scope using halide_print. Think of it as a stringstream that prints
16 // when it dies. Use it like this:
17 
18 // debug(user_context) << "A" << b << c << "\n";
19 
20 // If you use it like this:
21 
22 // debug d(user_context);
23 // d << "A";
24 // d << b;
25 // d << c << "\n";
26 
27 // Then remember the print only happens when the debug object leaves
28 // scope, which may print at a confusing time.
29 
30 namespace {
31 template<PrinterType printer_type, uint64_t buffer_length = default_printer_buffer_length>
32 class Printer {
33  char *buf, *dst, *end;
34  void *user_context;
35  bool own_mem;
36 
37 public:
38  explicit Printer(void *ctx, char *mem = nullptr)
39  : user_context(ctx), own_mem(mem == nullptr) {
40  if (mem != nullptr) {
41  buf = mem;
42  } else {
43  buf = (char *)malloc(buffer_length);
44  }
45 
46  dst = buf;
47  if (dst) {
48  end = buf + (buffer_length - 1);
49  *end = 0;
50  } else {
51  // Pointers equal ensures no writes to buffer via formatting code
52  end = dst;
53  }
54  }
55 
56  // Not movable, not copyable
57  Printer(const Printer &copy) = delete;
58  Printer &operator=(const Printer &) = delete;
59  Printer(Printer &&) = delete;
60  Printer &operator=(Printer &&) = delete;
61 
62  Printer &operator<<(const char *arg) {
63  dst = halide_string_to_string(dst, end, arg);
64  return *this;
65  }
66 
67  Printer &operator<<(int64_t arg) {
68  dst = halide_int64_to_string(dst, end, arg, 1);
69  return *this;
70  }
71 
72  Printer &operator<<(int32_t arg) {
73  dst = halide_int64_to_string(dst, end, arg, 1);
74  return *this;
75  }
76 
77  Printer &operator<<(uint64_t arg) {
78  dst = halide_uint64_to_string(dst, end, arg, 1);
79  return *this;
80  }
81 
82  Printer &operator<<(uint32_t arg) {
83  dst = halide_uint64_to_string(dst, end, arg, 1);
84  return *this;
85  }
86 
87  Printer &operator<<(double arg) {
88  dst = halide_double_to_string(dst, end, arg, 1);
89  return *this;
90  }
91 
92  Printer &operator<<(float arg) {
93  dst = halide_double_to_string(dst, end, arg, 0);
94  return *this;
95  }
96 
97  Printer &operator<<(const void *arg) {
98  dst = halide_pointer_to_string(dst, end, arg);
99  return *this;
100  }
101 
102  Printer &write_float16_from_bits(const uint16_t arg) {
103  double value = halide_float16_bits_to_double(arg);
104  dst = halide_double_to_string(dst, end, value, 1);
105  return *this;
106  }
107 
108  Printer &operator<<(const halide_type_t &t) {
109  dst = halide_type_to_string(dst, end, &t);
110  return *this;
111  }
112 
113  Printer &operator<<(const halide_buffer_t &buf) {
114  dst = halide_buffer_to_string(dst, end, &buf);
115  return *this;
116  }
117 
118  // Use it like a stringstream.
119  const char *str() {
120  if (buf) {
121  if (printer_type == StringStreamPrinterType) {
122  msan_annotate_is_initialized();
123  }
124  return buf;
125  } else {
126  return allocation_error();
127  }
128  }
129 
130  // Clear it. Useful for reusing a stringstream.
131  void clear() {
132  dst = buf;
133  if (dst) {
134  dst[0] = 0;
135  }
136  }
137 
138  // Returns the number of characters in the buffer
139  uint64_t size() const {
140  return (uint64_t)(dst - buf);
141  }
142 
143  uint64_t capacity() const {
144  return buffer_length;
145  }
146 
147  // Delete the last N characters
148  void erase(int n) {
149  if (dst) {
150  dst -= n;
151  if (dst < buf) {
152  dst = buf;
153  }
154  dst[0] = 0;
155  }
156  }
157 
158  const char *allocation_error() {
159  return "Printer buffer allocation failed.\n";
160  }
161 
162  void msan_annotate_is_initialized() {
163  (void)halide_msan_annotate_memory_is_initialized(user_context, buf, dst - buf + 1);
164  }
165 
166  ~Printer() {
167  if (!buf) {
168  halide_error(user_context, allocation_error());
169  } else {
170  msan_annotate_is_initialized();
171  if (printer_type == ErrorPrinterType) {
172  halide_error(user_context, buf);
173  } else if (printer_type == BasicPrinterType) {
174  halide_print(user_context, buf);
175  } else {
176  // It's a stringstream. Do nothing.
177  }
178  }
179 
180  if (own_mem) {
181  free(buf);
182  }
183  }
184 };
185 
186 // A class that supports << with all the same types as Printer, but
187 // does nothing and should compile to a no-op.
188 class SinkPrinter {
189 public:
190  explicit SinkPrinter(void *user_context) {
191  }
192 };
193 template<typename T>
194 SinkPrinter operator<<(const SinkPrinter &s, T) {
195  return s;
196 }
197 
198 template<uint64_t buffer_length = default_printer_buffer_length>
199 using BasicPrinter = Printer<BasicPrinterType, buffer_length>;
200 
201 template<uint64_t buffer_length = default_printer_buffer_length>
202 using ErrorPrinter = Printer<ErrorPrinterType, buffer_length>;
203 
204 template<uint64_t buffer_length = default_printer_buffer_length>
205 using StringStreamPrinter = Printer<StringStreamPrinterType, buffer_length>;
206 
207 using print = BasicPrinter<>;
208 using error = ErrorPrinter<>;
209 using stringstream = StringStreamPrinter<>;
210 
211 #ifdef DEBUG_RUNTIME
212 using debug = BasicPrinter<>;
213 #else
214 using debug = SinkPrinter;
215 #endif
216 } // namespace
217 
218 // A Printer that automatically reserves stack space for the printer buffer, rather than malloc.
219 // Note that this requires an explicit buffer_length, and it (generally) should be <= 256.
220 template<PrinterType printer_type, uint64_t buffer_length>
221 class StackPrinter : public Printer<printer_type, buffer_length> {
222  char scratch[buffer_length];
223 
224 public:
225  explicit StackPrinter(void *ctx)
226  : Printer<printer_type, buffer_length>(ctx, scratch) {
227  static_assert(buffer_length <= 256, "StackPrinter is meant only for small buffer sizes; you are probably making a mistake.");
228  }
229 };
230 
231 template<uint64_t buffer_length = default_printer_buffer_length>
233 
234 template<uint64_t buffer_length = default_printer_buffer_length>
236 
237 template<uint64_t buffer_length = default_printer_buffer_length>
239 
240 } // namespace Internal
241 } // namespace Runtime
242 } // namespace Halide
243 #endif
double halide_float16_bits_to_double(uint16_t)
Read bits representing a half precision floating point number and return the double that represents t...
int halide_msan_annotate_memory_is_initialized(void *user_context, const void *ptr, uint64_t len)
Annotate that a given range of memory has been initialized; only used when Target::MSAN is enabled.
void halide_print(void *user_context, const char *)
Print a message to stderr.
void halide_error(void *user_context, const char *)
Halide calls this function on runtime errors (for example bounds checking failures).
constexpr uint64_t default_printer_buffer_length
Definition: printer.h:11
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
std::ostream & operator<<(std::ostream &stream, const Expr &)
Emit an expression on an output stream (such as std::cout) in human-readable form.
Expr print(const std::vector< Expr > &values)
Create an Expr that prints out its value whenever it is evaluated.
unsigned __INT64_TYPE__ uint64_t
WEAK char * halide_buffer_to_string(char *dst, char *end, const halide_buffer_t *arg)
signed __INT64_TYPE__ int64_t
void * malloc(size_t)
WEAK char * halide_uint64_to_string(char *dst, char *end, uint64_t arg, int digits)
WEAK char * halide_double_to_string(char *dst, char *end, double arg, int scientific)
signed __INT32_TYPE__ int32_t
WEAK char * halide_string_to_string(char *dst, char *end, const char *arg)
unsigned __INT16_TYPE__ uint16_t
WEAK char * halide_type_to_string(char *dst, char *end, const halide_type_t *arg)
unsigned __INT32_TYPE__ uint32_t
WEAK char * halide_pointer_to_string(char *dst, char *end, const void *arg)
void free(void *)
WEAK char * halide_int64_to_string(char *dst, char *end, int64_t arg, int digits)
The raw representation of an image passed around by generated Halide code.
A runtime tag for a type in the halide type system.