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
3namespace Halide {
4namespace Runtime {
5namespace 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
30namespace {
31template<PrinterType printer_type, uint64_t buffer_length = default_printer_buffer_length>
32class Printer {
33 char *buf, *dst, *end;
34 void *user_context;
35 bool own_mem;
36
37public:
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.
188class SinkPrinter {
189public:
190 explicit SinkPrinter(void *user_context) {
191 }
192};
193template<typename T>
194SinkPrinter operator<<(const SinkPrinter &s, T) {
195 return s;
196}
197
198template<uint64_t buffer_length = default_printer_buffer_length>
199using BasicPrinter = Printer<BasicPrinterType, buffer_length>;
200
201template<uint64_t buffer_length = default_printer_buffer_length>
202using ErrorPrinter = Printer<ErrorPrinterType, buffer_length>;
203
204template<uint64_t buffer_length = default_printer_buffer_length>
205using StringStreamPrinter = Printer<StringStreamPrinterType, buffer_length>;
206
207using print = BasicPrinter<>;
208using error = ErrorPrinter<>;
209using stringstream = StringStreamPrinter<>;
210
211#ifdef DEBUG_RUNTIME
212using debug = BasicPrinter<>;
213#else
214using 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.
220template<PrinterType printer_type, uint64_t buffer_length>
221class StackPrinter : public Printer<printer_type, buffer_length> {
222 char scratch[buffer_length];
223
224public:
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
231template<uint64_t buffer_length = default_printer_buffer_length>
233
234template<uint64_t buffer_length = default_printer_buffer_length>
236
237template<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
signed __INT64_TYPE__ int64_t
WEAK char * halide_uint64_to_string(char *dst, char *end, uint64_t arg, int digits)
void * malloc(size_t)
WEAK char * halide_type_to_string(char *dst, char *end, const halide_type_t *arg)
signed __INT32_TYPE__ int32_t
unsigned __INT16_TYPE__ uint16_t
WEAK char * halide_int64_to_string(char *dst, char *end, int64_t arg, int digits)
WEAK char * halide_pointer_to_string(char *dst, char *end, const void *arg)
unsigned __INT32_TYPE__ uint32_t
WEAK char * halide_double_to_string(char *dst, char *end, double arg, int scientific)
WEAK char * halide_buffer_to_string(char *dst, char *end, const halide_buffer_t *arg)
void free(void *)
WEAK char * halide_string_to_string(char *dst, char *end, const char *arg)
The raw representation of an image passed around by generated Halide code.
A runtime tag for a type in the halide type system.