Halide 22.0.0 Halide compiler and libraries

Generator.h
Go to the documentation of this file.
1#ifndef HALIDE_GENERATOR_H_
2#define HALIDE_GENERATOR_H_
3
4/** \file
5 *
6 * Generator is a class used to encapsulate the building of Funcs in user
7 * pipelines. A Generator is agnostic to JIT vs AOT compilation; it can be used for
8 * either purpose, but is especially convenient to use for AOT compilation.
9 *
10 * A Generator explicitly declares the Inputs and Outputs associated for a given
11 * pipeline, and (optionally) separates the code for constructing the outputs from the code from
12 * scheduling them. For instance:
13 *
14 * \code
15 * class Blur : public Generator<Blur> {
16 * public:
17 * Input<Func> input{"input", UInt(16), 2};
18 * Output<Func> output{"output", UInt(16), 2};
19 * void generate() {
20 * blur_x(x, y) = (input(x, y) + input(x+1, y) + input(x+2, y))/3;
21 * blur_y(x, y) = (blur_x(x, y) + blur_x(x, y+1) + blur_x(x, y+2))/3;
22 * output(x, y) = blur(x, y);
23 * }
24 * void schedule() {
25 * blur_y.split(y, y, yi, 8).parallel(y).vectorize(x, 8);
26 * blur_x.store_at(blur_y, y).compute_at(blur_y, yi).vectorize(x, 8);
27 * }
28 * private:
29 * Var x, y, xi, yi;
30 * Func blur_x, blur_y;
31 * };
32 * \endcode
33 *
34 * Halide can compile a Generator into the correct pipeline by introspecting these
35 * values and constructing an appropriate signature based on them.
36 *
37 * A Generator provides implementations of two methods:
38 *
39 * - generate(), which must fill in all Output Func(s); it may optionally also do scheduling
40 * if no schedule() method is present.
41 * - schedule(), which (if present) should contain all scheduling code.
42 *
43 * Inputs can be any C++ scalar type:
44 *
45 * \code
46 * Input<float> radius{"radius"};
47 * Input<int32_t> increment{"increment"};
48 * \endcode
49 *
50 * An Input<Func> is (essentially) like an ImageParam, except that it may (or may
51 * not) not be backed by an actual buffer, and thus has no defined extents.
52 *
53 * \code
54 * Input<Func> input{"input", Float(32), 2};
55 * \endcode
56 *
57 * You can optionally make the type and/or dimensions of Input<Func> unspecified,
58 * in which case the value is simply inferred from the actual Funcs passed to them.
59 * Of course, if you specify an explicit Type or Dimension, we still require the
60 * input Func to match, or a compilation error results.
61 *
62 * \code
63 * Input<Func> input{ "input", 3 }; // require 3-dimensional Func,
64 * // but leave Type unspecified
65 * \endcode
66 *
67 * A Generator must explicitly list the output(s) it produces:
68 *
69 * \code
70 * Output<Func> output{"output", Float(32), 2};
71 * \endcode
72 *
73 * You can specify an output that returns a Tuple by specifying a list of Types:
74 *
75 * \code
76 * class Tupler : Generator<Tupler> {
77 * Input<Func> input{"input", Int(32), 2};
78 * Output<Func> output{"output", {Float(32), UInt(8)}, 2};
79 * void generate() {
80 * Var x, y;
81 * Expr a = cast<float>(input(x, y));
82 * Expr b = cast<uint8_t>(input(x, y));
83 * output(x, y) = Tuple(a, b);
84 * }
85 * };
86 * \endcode
87 *
88 * You can also specify Output<X> for any scalar type (except for Handle types);
89 * this is merely syntactic sugar on top of a zero-dimensional Func, but can be
90 * quite handy, especially when used with multiple outputs:
91 *
92 * \code
93 * Output<float> sum{"sum"}; // equivalent to Output<Func> {"sum", Float(32), 0}
94 * \endcode
95 *
96 * As with Input<Func>, you can optionally make the type and/or dimensions of an
97 * Output<Func> unspecified; any unspecified types must be resolved via an
98 * implicit GeneratorParam in order to use top-level compilation.
99 *
100 * You can also declare an *array* of Input or Output, by using an array type
101 * as the type parameter:
102 *
103 * \code
104 * // Takes exactly 3 images and outputs exactly 3 sums.
105 * class SumRowsAndColumns : Generator<SumRowsAndColumns> {
106 * Input<Func[3]> inputs{"inputs", Float(32), 2};
107 * Input<int32_t[2]> extents{"extents"};
108 * Output<Func[3]> sums{"sums", Float(32), 1};
109 * void generate() {
110 * assert(inputs.size() == sums.size());
111 * // assume all inputs are same extent
112 * Expr width = extent[0];
113 * Expr height = extent[1];
114 * for (size_t i = 0; i < inputs.size(); ++i) {
115 * RDom r(0, width, 0, height);
116 * sums[i]() = 0.f;
117 * sums[i]() += inputs[i](r.x, r.y);
118 * }
119 * }
120 * };
121 * \endcode
122 *
123 * You can also leave array size unspecified, with some caveats:
124 * - For ahead-of-time compilation, Inputs must have a concrete size specified
125 * via a GeneratorParam at build time (e.g., pyramid.size=3)
126 * - For JIT compilation via a Stub, Inputs array sizes will be inferred
127 * from the vector passed.
128 * - For ahead-of-time compilation, Outputs may specify a concrete size
129 * via a GeneratorParam at build time (e.g., pyramid.size=3), or the
130 * size can be specified via a resize() method.
131 *
132 * \code
133 * class Pyramid : public Generator<Pyramid> {
134 * public:
135 * GeneratorParam<int32_t> levels{"levels", 10};
136 * Input<Func> input{ "input", Float(32), 2 };
137 * Output<Func[]> pyramid{ "pyramid", Float(32), 2 };
138 * void generate() {
139 * pyramid.resize(levels);
140 * pyramid[0](x, y) = input(x, y);
141 * for (int i = 1; i < pyramid.size(); i++) {
142 * pyramid[i](x, y) = (pyramid[i-1](2*x, 2*y) +
143 * pyramid[i-1](2*x+1, 2*y) +
144 * pyramid[i-1](2*x, 2*y+1) +
145 * pyramid[i-1](2*x+1, 2*y+1))/4;
146 * }
147 * }
148 * };
149 * \endcode
150 *
151 * A Generator can also be customized via compile-time parameters (GeneratorParams),
152 * which affect code generation.
153 *
154 * GeneratorParams, Inputs, and Outputs are (by convention) always
155 * public and always declared at the top of the Generator class, in the order
156 *
157 * \code
158 * GeneratorParam(s)
159 * Input<Func>(s)
160 * Input<non-Func>(s)
161 * Output<Func>(s)
162 * \endcode
163 *
164 * Note that the Inputs and Outputs will appear in the C function call in the order
165 * they are declared. All Input<Func> and Output<Func> are represented as halide_buffer_t;
166 * all other Input<> are the appropriate C++ scalar type. (GeneratorParams are
167 * always referenced by name, not position, so their order is irrelevant.)
168 *
169 * All Inputs and Outputs must have explicit names, and all such names must match
170 * the regex [A-Za-z][A-Za-z_0-9]* (i.e., essentially a C/C++ variable name, with
171 * some extra restrictions on underscore use). By convention, the name should match
172 * the member-variable name.
173 *
174 * You can dynamically add Inputs and Outputs to your Generator via adding a
175 * configure() method; if present, it will be called before generate(). It can
176 * examine GeneratorParams but it may not examine predeclared Inputs or Outputs;
177 * the only thing it should do is call add_input<>() and/or add_output<>(), or call
178 * set_type()/set_dimensions()/set_array_size() on an Input or Output with an unspecified type.
179 * Added inputs will be appended (in order) after predeclared Inputs but before
180 * any Outputs; added outputs will be appended after predeclared Outputs.
181 *
182 * Note that the pointers returned by add_input() and add_output() are owned
183 * by the Generator and will remain valid for the Generator's lifetime; user code
184 * should not attempt to delete or free them.
185 *
186 * \code
187 * class MultiSum : public Generator<MultiSum> {
188 * public:
189 * GeneratorParam<int32_t> input_count{"input_count", 10};
190 * Output<Func> output{ "output", Float(32), 2 };
191 *
192 * void configure() {
193 * for (int i = 0; i < input_count; ++i) {
194 * extra_inputs.push_back(
195 * add_input<Func>("input_" + std::to_string(i), Float(32), 2);
196 * }
197 * }
198 *
199 * void generate() {
200 * Expr sum = 0.f;
201 * for (int i = 0; i < input_count; ++i) {
202 * sum += (*extra_inputs)[i](x, y);
203 * }
204 * output(x, y) = sum;
205 * }
206 * private:
207 * std::vector<Input<Func>* extra_inputs;
208 * };
209 * \endcode
210 *
211 * All Generators have two GeneratorParams that are implicitly provided
212 * by the base class:
213 *
214 * GeneratorParam<Target> target{"target", Target()};
215 * GeneratorParam<AutoschedulerParams> autoscheduler{"autoscheduler", {}}
216 *
217 * - 'target' is the Halide::Target for which the Generator is producing code.
218 * It is read-only during the Generator's lifetime, and must not be modified;
219 * its value should always be filled in by the calling code: either the Halide
220 * build system (for ahead-of-time compilation), or ordinary C++ code
221 * (for JIT compilation).
222 * - 'autoscheduler' is a string-to-string map that is used to indicates whether
223 * and how an auto-scheduler should be run for this Generator:
224 * - if empty, the Generator should schedule its Funcs as it sees fit; no autoscheduler will be run.
225 * - if the 'name' key is set, it should be one of the known autoschedulers
226 * provided with this release of Halide, which will be used to schedule
227 * the Funcs in the Generator. In this case, the Generator should only
228 * provide estimate()s for its Funcs, and not call any other scheduling methods.
229 * - Other keys may be specified in the params, on a per-autoscheduler
230 * basis, to optimize or enhance the automatically-generated schedule.
231 * See documentation for each autoscheduler for options.
232 *
233 * Generators are added to a global registry to simplify AOT build mechanics; this
234 * is done by simply using the HALIDE_REGISTER_GENERATOR macro at global scope:
235 *
236 * \code
237 * HALIDE_REGISTER_GENERATOR(ExampleGen, jit_example)
238 * \endcode
239 *
240 * The registered name of the Generator is provided must match the same rules as
241 * Input names, above.
242 *
243 * Note that the class name of the generated Stub class will match the registered
244 * name by default; if you want to vary it (typically, to include namespaces),
245 * you can add it as an optional third argument:
246 *
247 * \code
248 * HALIDE_REGISTER_GENERATOR(ExampleGen, jit_example, SomeNamespace::JitExampleStub)
249 * \endcode
250 *
251 * Note that a Generator is always executed with a specific Target assigned to it,
252 * that you can access via the get_target() method. (You should *not* use the
253 * global get_target_from_environment(), etc. methods provided in Target.h)
254 *
255 * (Note that there are older variations of Generator that differ from what's
256 * documented above; these are still supported but not described here. See
257 * https://github.com/halide/Halide/wiki/Old-Generator-Documentation for
258 * more information.)
259 */
260
261#include <algorithm>
262#include <functional>
263#include <iterator>
264#include <limits>
265#include <memory>
266#include <mutex>
267#include <set>
268#include <sstream>
269#include <string>
270#include <type_traits>
271#include <utility>
272#include <vector>
273
274#include "AbstractGenerator.h"
275#include "Func.h"
276#include "ImageParam.h"
277#include "ObjectInstanceRegistry.h"
278#include "Target.h"
279
280#if !(__cplusplus >= 201703L || _MSVC_LANG >= 201703L)
281#error "Halide requires C++17 or later; please upgrade your compiler."
282#endif
283
284 namespace Halide {
285
286 class GeneratorContext;
287
288 namespace Internal {
289
290 void generator_test();
291
292 class GeneratorBase;
293
294std::vector<Expr> parameter_constraints(const Parameter &p);
295
296 template<typename T>
297 HALIDE_NO_USER_CODE_INLINE std::string enum_to_string(const std::map<std::string, T> &enum_map, const T &t) {
298 for (const auto &key_value : enum_map) {
299 if (t == key_value.second) {
300 return key_value.first;
301 }
302 }
303 user_error << "Enumeration value not found.\n";
304 return "";
305}
306
307 template<typename T>
308T enum_from_string(const std::map<std::string, T> &enum_map, const std::string &s) {
309 auto it = enum_map.find(s);
310 user_assert(it != enum_map.end()) << "Enumeration value not found: " << s << "\n";
311 return it->second;
312}
313
314 extern const std::map<std::string, Halide::Type> &get_halide_type_enum_map();
315 inline std::string halide_type_to_enum_string(const Type &t) {
316 return enum_to_string(get_halide_type_enum_map(), t);
317}
318
319// Convert a Halide Type into a string representation of its C source.
320// e.g., Int(32) -> "Halide::Int(32)"
321std::string halide_type_to_c_source(const Type &t);
322
323// Convert a Halide Type into a string representation of its C Source.
324// e.g., Int(32) -> "int32_t"
325std::string halide_type_to_c_type(const Type &t);
326
327/** GeneratorFactoryProvider provides a way to customize the Generators
328 * that are visible to generate_filter_main (which otherwise would just
329 * look at the global registry of C++ Generators). */
330 class GeneratorFactoryProvider {
331 public:
332 GeneratorFactoryProvider() = default;
333 virtual ~GeneratorFactoryProvider() = default;
334
335 /** Return a list of all registered Generators that are available for use
336 * with the create() method. */
337 virtual std::vector<std::string> enumerate() const = 0;
338
339 /** Create an instance of the Generator that is registered under the given
340 * name. If the name isn't one returned by enumerate(), return nullptr
341 * rather than assert-fail; caller must check for a valid result. */
342 virtual AbstractGeneratorPtr create(const std::string &name,
343 const Halide::GeneratorContext &context) const = 0;
344
345 GeneratorFactoryProvider(const GeneratorFactoryProvider &) = delete;
346 GeneratorFactoryProvider &operator=(const GeneratorFactoryProvider &) = delete;
347 GeneratorFactoryProvider(GeneratorFactoryProvider &&) = delete;
348 GeneratorFactoryProvider &operator=(GeneratorFactoryProvider &&) = delete;
349};
350
351/** Return a GeneratorFactoryProvider that knows about all the currently-registered C++ Generators. */
352 const GeneratorFactoryProvider &get_registered_generators();
353
354/** generate_filter_main() is a convenient wrapper for GeneratorRegistry::create() +
355 * compile_to_files(); it can be trivially wrapped by a "real" main() to produce a
356 * command-line utility for ahead-of-time filter compilation. */
357 int generate_filter_main(int argc, char **argv);
358
359/** This overload of generate_filter_main lets you provide your own provider for how to enumerate and/or create
360 * the generators based on registration name; this is useful if you want to re-use the
361 * 'main' logic but avoid the global Generator registry (e.g. for bindings in languages
362 * other than C++). */
363 int generate_filter_main(int argc, char **argv, const GeneratorFactoryProvider &generator_factory_provider);
364
365// select_type<> is to std::conditional as switch is to if:
366// it allows a multiway compile-time type definition via the form
367//
368// select_type<cond<condition1, type1>,
369// cond<condition2, type2>,
370// ....
371// cond<conditionN, typeN>>::type
372//
373// Note that the conditions are evaluated in order; the first evaluating to true
374// is chosen.
375//
376// Note that if no conditions evaluate to true, the resulting type is illegal
377// and will produce a compilation error. (You can provide a default by simply
378// using cond<true, SomeType> as the final entry.)
379 template<bool B, typename T>
380 struct cond {
381 static constexpr bool value = B;
382 using type = T;
383};
384
385 template<typename First, typename... Rest>
386 struct select_type : std::conditional<First::value, typename First::type, typename select_type<Rest...>::type> {};
387
388 template<typename First>
389 struct select_type<First> {
390 using type = std::conditional_t<First::value, typename First::type, void>;
391};
392
393 template<typename... Args>
394 using select_type_t = typename select_type<Args...>::type;
395
396 class GeneratorParamInfo;
397
398 class GeneratorParamBase {
399 public:
400 explicit GeneratorParamBase(const std::string &name);
401 virtual ~GeneratorParamBase();
402
403 const std::string &name() const {
404 return name_;
405 }
406
407 // overload the set() function to call the right virtual method based on type.
408 // This allows us to attempt to set a GeneratorParam via a
409 // plain C++ type, even if we don't know the specific templated
410 // subclass. Attempting to set the wrong type will assert.
411 // Notice that there is no typed setter for Enums, for obvious reasons;
412 // setting enums in an unknown type must fallback to using set_from_string.
413 //
414 // It's always a bit iffy to use macros for this, but IMHO it clarifies the situation here.
415#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
416 virtual void set(const TYPE &new_value) = 0;
417
418 HALIDE_GENERATOR_PARAM_TYPED_SETTER(bool)
419 HALIDE_GENERATOR_PARAM_TYPED_SETTER(int8_t)
420 HALIDE_GENERATOR_PARAM_TYPED_SETTER(int16_t)
421 HALIDE_GENERATOR_PARAM_TYPED_SETTER(int32_t)
422 HALIDE_GENERATOR_PARAM_TYPED_SETTER(int64_t)
423 HALIDE_GENERATOR_PARAM_TYPED_SETTER(uint8_t)
424 HALIDE_GENERATOR_PARAM_TYPED_SETTER(uint16_t)
425 HALIDE_GENERATOR_PARAM_TYPED_SETTER(uint32_t)
426 HALIDE_GENERATOR_PARAM_TYPED_SETTER(uint64_t)
427 HALIDE_GENERATOR_PARAM_TYPED_SETTER(float)
428 HALIDE_GENERATOR_PARAM_TYPED_SETTER(double)
429 HALIDE_GENERATOR_PARAM_TYPED_SETTER(Target)
430 HALIDE_GENERATOR_PARAM_TYPED_SETTER(AutoschedulerParams)
431 HALIDE_GENERATOR_PARAM_TYPED_SETTER(Type)
432 HALIDE_GENERATOR_PARAM_TYPED_SETTER(LoopLevel)
433
434#undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
435
436 // Add overloads for string and char*
437 void set(const std::string &new_value) {
438 set_from_string(new_value);
439 }
440 void set(const char *new_value) {
441 set_from_string(std::string(new_value));
442 }
443
444 protected:
445 friend class GeneratorBase;
446 friend class GeneratorParamInfo;
447 friend class StubEmitter;
448
449 void check_value_readable() const;
450 void check_value_writable() const;
451
452 // All GeneratorParams are settable from string.
453 virtual void set_from_string(const std::string &value_string) = 0;
454
455 virtual std::string call_to_string(const std::string &v) const = 0;
456 virtual std::string get_c_type() const = 0;
457
458 virtual std::string get_type_decls() const {
459 return "";
460 }
461
462 virtual std::string get_default_value() const = 0;
463
464 virtual bool is_synthetic_param() const {
465 return false;
466 }
467
468 virtual bool is_looplevel_param() const {
469 return false;
470 }
471
472 void fail_wrong_type(const char *type);
473
474 private:
475 const std::string name_;
476
477 // Generator which owns this GeneratorParam. Note that this will be null
478 // initially; the GeneratorBase itself will set this field when it initially
479 // builds its info about params. However, since it (generally) isn't
480 // appropriate for GeneratorParam<> to be declared outside of a Generator,
481 // all reasonable non-testing code should expect this to be non-null.
482 GeneratorBase *generator{nullptr};
483
484 public:
485 GeneratorParamBase(const GeneratorParamBase &) = delete;
486 GeneratorParamBase &operator=(const GeneratorParamBase &) = delete;
487 GeneratorParamBase(GeneratorParamBase &&) = delete;
488 GeneratorParamBase &operator=(GeneratorParamBase &&) = delete;
489};
490
491// This is strictly some syntactic sugar to suppress certain compiler warnings.
492 template<typename FROM, typename TO>
493 struct Convert {
494 template<typename TO2 = TO, std::enable_if_t<!std::is_same_v<TO2, bool>> * = nullptr>
495 static TO2 value(const FROM &from) {
496 return static_cast<TO2>(from);
497 }
498
499 template<typename TO2 = TO, std::enable_if_t<std::is_same_v<TO2, bool>> * = nullptr>
500 static TO2 value(const FROM &from) {
501 return from != 0;
502 }
503};
504
505 template<typename T>
506 class GeneratorParamImpl : public GeneratorParamBase {
507 public:
508 using type = T;
509
510 GeneratorParamImpl(const std::string &name, const T &value)
511 : GeneratorParamBase(name), value_(value) {
512 }
513
514 T value() const {
515 this->check_value_readable();
516 return value_;
517 }
518
519 operator T() const {
520 return this->value();
521 }
522
523 operator Expr() const {
524 return make_const(type_of<T>(), this->value());
525 }
526
527#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
528 void set(const TYPE &new_value) override { \
529 typed_setter_impl<TYPE>(new_value, #TYPE); \
530 }
531
532 HALIDE_GENERATOR_PARAM_TYPED_SETTER(bool)
533 HALIDE_GENERATOR_PARAM_TYPED_SETTER(int8_t)
534 HALIDE_GENERATOR_PARAM_TYPED_SETTER(int16_t)
535 HALIDE_GENERATOR_PARAM_TYPED_SETTER(int32_t)
536 HALIDE_GENERATOR_PARAM_TYPED_SETTER(int64_t)
537 HALIDE_GENERATOR_PARAM_TYPED_SETTER(uint8_t)
538 HALIDE_GENERATOR_PARAM_TYPED_SETTER(uint16_t)
539 HALIDE_GENERATOR_PARAM_TYPED_SETTER(uint32_t)
540 HALIDE_GENERATOR_PARAM_TYPED_SETTER(uint64_t)
541 HALIDE_GENERATOR_PARAM_TYPED_SETTER(float)
542 HALIDE_GENERATOR_PARAM_TYPED_SETTER(double)
543 HALIDE_GENERATOR_PARAM_TYPED_SETTER(Target)
544 HALIDE_GENERATOR_PARAM_TYPED_SETTER(AutoschedulerParams)
545 HALIDE_GENERATOR_PARAM_TYPED_SETTER(Type)
546 HALIDE_GENERATOR_PARAM_TYPED_SETTER(LoopLevel)
547
548#undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
549
550 // Overload for std::string.
551 void set(const std::string &new_value) {
552 check_value_writable();
553 value_ = new_value;
554 }
555
556 protected:
557 virtual void set_impl(const T &new_value) {
558 check_value_writable();
559 value_ = new_value;
560 }
561
562 // Needs to be protected to allow GeneratorParam<LoopLevel>::set() override
563 T value_;
564
565 private:
566 // If FROM->T is not legal, fail
567 template<typename FROM, std::enable_if_t<!std::is_convertible_v<FROM, T>> * = nullptr>
568 HALIDE_ALWAYS_INLINE void typed_setter_impl(const FROM &, const char *msg) {
569 fail_wrong_type(msg);
570 }
571
572 // If FROM and T are identical, just assign
573 template<typename FROM, std::enable_if_t<std::is_same_v<FROM, T>> * = nullptr>
574 HALIDE_ALWAYS_INLINE void typed_setter_impl(const FROM &value, const char *msg) {
575 check_value_writable();
576 value_ = value;
577 }
578
579 // If both FROM->T and T->FROM are legal, ensure it's lossless
580 template<typename FROM, std::enable_if_t<
581 !std::is_same_v<FROM, T> &&
582 std::is_convertible_v<FROM, T> &&
583 std::is_convertible_v<T, FROM>> * = nullptr>
584 HALIDE_ALWAYS_INLINE void typed_setter_impl(const FROM &value, const char *msg) {
585 check_value_writable();
586 const T t = Convert<FROM, T>::value(value);
587 const FROM value2 = Convert<T, FROM>::value(t);
588 if (value2 != value) {
589 fail_wrong_type(msg);
590 }
591 value_ = t;
592 }
593
594 // If FROM->T is legal but T->FROM is not, just assign
595 template<typename FROM, std::enable_if_t<
596 !std::is_same_v<FROM, T> &&
597 std::is_convertible_v<FROM, T> &&
598 !std::is_convertible_v<T, FROM>> * = nullptr>
599 HALIDE_ALWAYS_INLINE void typed_setter_impl(const FROM &value, const char *msg) {
600 check_value_writable();
601 value_ = value;
602 }
603};
604
605// Stubs for type-specific implementations of GeneratorParam, to avoid
606// many complex enable_if<> statements that were formerly spread through the
607// implementation. Note that not all of these need to be templated classes,
608// (e.g. for GeneratorParam_Target, T == Target always), but are declared
609// that way for symmetry of declaration.
610 template<typename T>
611 class GeneratorParam_Target : public GeneratorParamImpl<T> {
612 public:
613 GeneratorParam_Target(const std::string &name, const T &value)
614 : GeneratorParamImpl<T>(name, value) {
615 }
616
617 void set_from_string(const std::string &new_value_string) override {
618 this->set(Target(new_value_string));
619 }
620
621 std::string get_default_value() const override {
622 return this->value().to_string();
623 }
624
625 std::string call_to_string(const std::string &v) const override {
626 std::ostringstream oss;
627 oss << v << ".to_string()";
628 return oss.str();
629 }
630
631 std::string get_c_type() const override {
632 return "Target";
633 }
634};
635
636 class GeneratorParam_AutoSchedulerParams : public GeneratorParamImpl<AutoschedulerParams> {
637 public:
638 GeneratorParam_AutoSchedulerParams();
639
640 void set_from_string(const std::string &new_value_string) override;
641 std::string get_default_value() const override;
642 std::string call_to_string(const std::string &v) const override;
643 std::string get_c_type() const override;
644
645 private:
646 friend class GeneratorBase;
647
648 bool try_set(const std::string &key, const std::string &value);
649};
650
651 class GeneratorParam_LoopLevel : public GeneratorParamImpl<LoopLevel> {
652 public:
653 GeneratorParam_LoopLevel(const std::string &name, const LoopLevel &value)
654 : GeneratorParamImpl<LoopLevel>(name, value) {
655 }
656
657 using GeneratorParamImpl<LoopLevel>::set;
658
659 void set(const LoopLevel &value) override {
660 // Don't call check_value_writable(): It's OK to set a LoopLevel after generate().
661 // check_value_writable();
662
663 // This looks odd, but is deliberate:
664
665 // First, mutate the existing contents to match the value passed in,
666 // so that any existing usage of the LoopLevel now uses the newer value.
667 // (Strictly speaking, this is really only necessary if this method
668 // is called after generate(): before generate(), there is no usage
669 // to be concerned with.)
670 value_.set(value);
671
672 // Then, reset the value itself so that it points to the same LoopLevelContents
673 // as the value passed in. (Strictly speaking, this is really only
674 // useful if this method is called before generate(): afterwards, it's
675 // too late to alter the code to refer to a different LoopLevelContents.)
676 value_ = value;
677 }
678
679 void set_from_string(const std::string &new_value_string) override {
680 if (new_value_string == "root") {
681 this->set(LoopLevel::root());
682 } else if (new_value_string == "inlined") {
683 this->set(LoopLevel::inlined());
684 } else {
685 user_error << "Unable to parse " << this->name() << ": " << new_value_string;
686 }
687 }
688
689 std::string get_default_value() const override {
690 // This is dodgy but safe in this case: we want to
691 // see what the value of our LoopLevel is *right now*,
692 // so we make a copy and lock the copy so we can inspect it.
693 // (Note that ordinarily this is a bad idea, since LoopLevels
694 // can be mutated later on; however, this method is only
695 // called by the Generator infrastructure, on LoopLevels that
696 // will never be mutated, so this is really just an elaborate way
697 // to avoid runtime assertions.)
698 LoopLevel copy;
699 copy.set(this->value());
700 copy.lock();
701 if (copy.is_inlined()) {
702 return "LoopLevel::inlined()";
703 } else if (copy.is_root()) {
704 return "LoopLevel::root()";
705 } else {
706 internal_error;
707 return "";
708 }
709 }
710
711 std::string call_to_string(const std::string &v) const override {
712 internal_error;
713 return std::string();
714 }
715
716 std::string get_c_type() const override {
717 return "LoopLevel";
718 }
719
720 bool is_looplevel_param() const override {
721 return true;
722 }
723};
724
725 template<typename T>
726 class GeneratorParam_Arithmetic : public GeneratorParamImpl<T> {
727 public:
728 GeneratorParam_Arithmetic(const std::string &name,
729 const T &value,
730 const T &min = std::numeric_limits<T>::lowest(),
731 const T &max = std::numeric_limits<T>::max())
732 : GeneratorParamImpl<T>(name, value), min(min), max(max) {
733 // call set() to ensure value is clamped to min/max
734 this->set(value);
735 }
736
737 void set_impl(const T &new_value) override {
738 user_assert(new_value >= min && new_value <= max) << "Value out of range: " << new_value;
739 GeneratorParamImpl<T>::set_impl(new_value);
740 }
741
742 void set_from_string(const std::string &new_value_string) override {
743 std::istringstream iss(new_value_string);
744 T t;
745 // All one-byte ints int8 and uint8 should be parsed as integers, not chars --
746 // including 'char' itself. (Note that sizeof(bool) is often-but-not-always-1,
747 // so be sure to exclude that case.)
748 if (sizeof(T) == sizeof(char) && !std::is_same_v<T, bool>) {
749 int i;
750 iss >> i;
751 t = (T)i;
752 } else {
753 iss >> t;
754 }
755 user_assert(!iss.fail() && iss.get() == EOF) << "Unable to parse: " << new_value_string;
756 this->set(t);
757 }
758
759 std::string get_default_value() const override {
760 std::ostringstream oss;
761 oss << this->value();
762 if (std::is_same_v<T, float>) {
763 // If the constant has no decimal point ("1")
764 // we must append one before appending "f"
765 if (oss.str().find('.') == std::string::npos) {
766 oss << ".";
767 }
768 oss << "f";
769 }
770 return oss.str();
771 }
772
773 std::string call_to_string(const std::string &v) const override {
774 std::ostringstream oss;
775 oss << "std::to_string(" << v << ")";
776 return oss.str();
777 }
778
779 std::string get_c_type() const override {
780 std::ostringstream oss;
781 if (std::is_same_v<T, float>) {
782 return "float";
783 } else if (std::is_same_v<T, double>) {
784 return "double";
785 } else if (std::is_integral_v<T>) {
786 if (std::is_unsigned_v<T>) {
787 oss << "u";
788 }
789 oss << "int" << (sizeof(T) * 8) << "_t";
790 return oss.str();
791 } else {
792 user_error << "Unknown arithmetic type\n";
793 return "";
794 }
795 }
796
797 private:
798 const T min, max;
799};
800
801 template<typename T>
802 class GeneratorParam_Bool : public GeneratorParam_Arithmetic<T> {
803 public:
804 GeneratorParam_Bool(const std::string &name, const T &value)
805 : GeneratorParam_Arithmetic<T>(name, value) {
806 }
807
808 void set_from_string(const std::string &new_value_string) override {
809 bool v = false;
810 if (new_value_string == "true" || new_value_string == "True") {
811 v = true;
812 } else if (new_value_string == "false" || new_value_string == "False") {
813 v = false;
814 } else {
815 user_assert(false) << "Unable to parse bool: " << new_value_string;
816 }
817 this->set(v);
818 }
819
820 std::string get_default_value() const override {
821 return this->value() ? "true" : "false";
822 }
823
824 std::string call_to_string(const std::string &v) const override {
825 std::ostringstream oss;
826 oss << "std::string((" << v << ") ? \"true\" : \"false\")";
827 return oss.str();
828 }
829
830 std::string get_c_type() const override {
831 return "bool";
832 }
833};
834
835 template<typename T>
836 class GeneratorParam_Enum : public GeneratorParamImpl<T> {
837 public:
838 GeneratorParam_Enum(const std::string &name, const T &value, const std::map<std::string, T> &enum_map)
839 : GeneratorParamImpl<T>(name, value), enum_map(enum_map) {
840 }
841
842 // define a "set" that takes our specific enum (but don't hide the inherited virtual functions)
843 using GeneratorParamImpl<T>::set;
844
845 template<typename T2 = T, std::enable_if_t<!std::is_same_v<T2, Type>> * = nullptr>
846 void set(const T &e) {
847 this->set_impl(e);
848 }
849
850 void set_from_string(const std::string &new_value_string) override {
851 auto it = enum_map.find(new_value_string);
852 user_assert(it != enum_map.end()) << "Enumeration value not found: " << new_value_string;
853 this->set_impl(it->second);
854 }
855
856 std::string call_to_string(const std::string &v) const override {
857 return "Enum_" + this->name() + "_map().at(" + v + ")";
858 }
859
860 std::string get_c_type() const override {
861 return "Enum_" + this->name();
862 }
863
864 std::string get_default_value() const override {
865 return "Enum_" + this->name() + "::" + enum_to_string(enum_map, this->value());
866 }
867
868 std::string get_type_decls() const override {
869 std::ostringstream oss;
870 oss << "enum class Enum_" << this->name() << " {\n";
871 for (const auto &key_value : enum_map) {
872 oss << " " << key_value.first << ",\n";
873 }
874 oss << "};\n";
875 oss << "\n";
876
877 // TODO: since we generate the enums, we could probably just use a vector (or array!) rather than a map,
878 // since we can ensure that the enum values are a nice tight range.
879 oss << "inline HALIDE_NO_USER_CODE_INLINE const std::map<Enum_" << this->name() << ", std::string>& Enum_" << this->name() << "_map() {\n";
880 oss << " static const std::map<Enum_" << this->name() << ", std::string> m = {\n";
881 for (const auto &key_value : enum_map) {
882 oss << " { Enum_" << this->name() << "::" << key_value.first << ", \"" << key_value.first << "\"},\n";
883 }
884 oss << " };\n";
885 oss << " return m;\n";
886 oss << "};\n";
887 return oss.str();
888 }
889
890 private:
891 const std::map<std::string, T> enum_map;
892};
893
894 template<typename T>
895 class GeneratorParam_Type : public GeneratorParam_Enum<T> {
896 public:
897 GeneratorParam_Type(const std::string &name, const T &value)
898 : GeneratorParam_Enum<T>(name, value, get_halide_type_enum_map()) {
899 }
900
901 std::string call_to_string(const std::string &v) const override {
902 return "Halide::Internal::halide_type_to_enum_string(" + v + ")";
903 }
904
905 std::string get_c_type() const override {
906 return "Type";
907 }
908
909 std::string get_default_value() const override {
910 return halide_type_to_c_source(this->value());
911 }
912
913 std::string get_type_decls() const override {
914 return "";
915 }
916};
917
918 template<typename T>
919 class GeneratorParam_String : public Internal::GeneratorParamImpl<T> {
920 public:
921 GeneratorParam_String(const std::string &name, const std::string &value)
922 : GeneratorParamImpl<T>(name, value) {
923 }
924 void set_from_string(const std::string &new_value_string) override {
925 this->set(new_value_string);
926 }
927
928 std::string get_default_value() const override {
929 return "\"" + this->value() + "\"";
930 }
931
932 std::string call_to_string(const std::string &v) const override {
933 return v;
934 }
935
936 std::string get_c_type() const override {
937 return "std::string";
938 }
939};
940
941 template<typename T>
942 using GeneratorParamImplBase =
943 select_type_t<
944 cond<std::is_same_v<T, Target>, GeneratorParam_Target<T>>,
945 cond<std::is_same_v<T, LoopLevel>, GeneratorParam_LoopLevel>,
946 cond<std::is_same_v<T, std::string>, GeneratorParam_String<T>>,
947 cond<std::is_same_v<T, Type>, GeneratorParam_Type<T>>,
948 cond<std::is_same_v<T, bool>, GeneratorParam_Bool<T>>,
949 cond<std::is_arithmetic_v<T>, GeneratorParam_Arithmetic<T>>,
950 cond<std::is_enum_v<T>, GeneratorParam_Enum<T>>>;
951
952} // namespace Internal
953
954/** GeneratorParam is a templated class that can be used to modify the behavior
955 * of the Generator at code-generation time. GeneratorParams are commonly
956 * specified in build files (e.g. Makefile) to customize the behavior of
957 * a given Generator, thus they have a very constrained set of types to allow
958 * for efficient specification via command-line flags. A GeneratorParam can be:
959 * - any float or int type.
960 * - bool
961 * - enum
962 * - Halide::Target
963 * - Halide::Type
964 * - std::string
965 * Please don't use std::string unless there's no way to do what you want with some
966 * other type; in particular, don't use this if you can use enum instead.
967 * All GeneratorParams have a default value. Arithmetic types can also
968 * optionally specify min and max. Enum types must specify a string-to-value
969 * map.
970 *
971 * Halide::Type is treated as though it were an enum, with the mappings:
972 *
973 * "int8" Halide::Int(8)
974 * "int16" Halide::Int(16)
975 * "int32" Halide::Int(32)
976 * "int64" Halide::Int(64)
977 * "uint8" Halide::UInt(8)
978 * "uint16" Halide::UInt(16)
979 * "uint32" Halide::UInt(32)
980 * "uint64" Halide::UInt(64)
981 * "float16" Halide::Float(16)
982 * "float32" Halide::Float(32)
983 * "float64" Halide::Float(64)
984 * "bfloat16" Halide::BFloat(16)
985 *
986 * No vector Types are currently supported by this mapping.
987 *
988 */
989 template<typename T>
990 class GeneratorParam : public Internal::GeneratorParamImplBase<T> {
991 public:
992 template<typename T2 = T, std::enable_if_t<!std::is_same_v<T2, std::string>> * = nullptr>
993 GeneratorParam(const std::string &name, const T &value)
994 : Internal::GeneratorParamImplBase<T>(name, value) {
995 }
996
997 GeneratorParam(const std::string &name, const T &value, const T &min, const T &max)
998 : Internal::GeneratorParamImplBase<T>(name, value, min, max) {
999 }
1000
1001 GeneratorParam(const std::string &name, const T &value, const std::map<std::string, T> &enum_map)
1002 : Internal::GeneratorParamImplBase<T>(name, value, enum_map) {
1003 }
1004
1005 GeneratorParam(const std::string &name, const std::string &value)
1006 : Internal::GeneratorParamImplBase<T>(name, value) {
1007 }
1008};
1009
1010/** Addition between GeneratorParam<T> and any type that supports operator+ with T.
1011 * Returns type of underlying operator+. */
1012// @{
1013 template<typename Other, typename T>
1014 auto operator+(const Other &a, const GeneratorParam<T> &b) -> decltype(a + (T)b) {
1015 return a + (T)b;
1016}
1017 template<typename Other, typename T>
1018 auto operator+(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a + b) {
1019 return (T)a + b;
1020}
1021// @}
1022
1023/** Subtraction between GeneratorParam<T> and any type that supports operator- with T.
1024 * Returns type of underlying operator-. */
1025// @{
1026 template<typename Other, typename T>
1027 auto operator-(const Other &a, const GeneratorParam<T> &b) -> decltype(a - (T)b) {
1028 return a - (T)b;
1029}
1030 template<typename Other, typename T>
1031 auto operator-(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a - b) {
1032 return (T)a - b;
1033}
1034// @}
1035
1036/** Multiplication between GeneratorParam<T> and any type that supports operator* with T.
1037 * Returns type of underlying operator*. */
1038// @{
1039 template<typename Other, typename T>
1040 auto operator*(const Other &a, const GeneratorParam<T> &b) -> decltype(a * (T)b) {
1041 return a * (T)b;
1042}
1043 template<typename Other, typename T>
1044 auto operator*(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a * b) {
1045 return (T)a * b;
1046}
1047// @}
1048
1049/** Division between GeneratorParam<T> and any type that supports operator/ with T.
1050 * Returns type of underlying operator/. */
1051// @{
1052 template<typename Other, typename T>
1053 auto operator/(const Other &a, const GeneratorParam<T> &b) -> decltype(a / (T)b) {
1054 return a / (T)b;
1055}
1056 template<typename Other, typename T>
1057 auto operator/(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a / b) {
1058 return (T)a / b;
1059}
1060// @}
1061
1062/** Modulo between GeneratorParam<T> and any type that supports operator% with T.
1063 * Returns type of underlying operator%. */
1064// @{
1065 template<typename Other, typename T>
1066 auto operator%(const Other &a, const GeneratorParam<T> &b) -> decltype(a % (T)b) {
1067 return a % (T)b;
1068}
1069 template<typename Other, typename T>
1070 auto operator%(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a % b) {
1071 return (T)a % b;
1072}
1073// @}
1074
1075/** Greater than comparison between GeneratorParam<T> and any type that supports operator> with T.
1076 * Returns type of underlying operator>. */
1077// @{
1078 template<typename Other, typename T>
1079 auto operator>(const Other &a, const GeneratorParam<T> &b) -> decltype(a > (T)b) {
1080 return a > (T)b;
1081}
1082 template<typename Other, typename T>
1083 auto operator>(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a > b) {
1084 return (T)a > b;
1085}
1086// @}
1087
1088/** Less than comparison between GeneratorParam<T> and any type that supports operator< with T.
1089 * Returns type of underlying operator<. */
1090// @{
1091 template<typename Other, typename T>
1092 auto operator<(const Other &a, const GeneratorParam<T> &b) -> decltype(a < (T)b) {
1093 return a < (T)b;
1094}
1095 template<typename Other, typename T>
1096 auto operator<(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a < b) {
1097 return (T)a < b;
1098}
1099// @}
1100
1101/** Greater than or equal comparison between GeneratorParam<T> and any type that supports operator>= with T.
1102 * Returns type of underlying operator>=. */
1103// @{
1104 template<typename Other, typename T>
1105 auto operator>=(const Other &a, const GeneratorParam<T> &b) -> decltype(a >= (T)b) {
1106 return a >= (T)b;
1107}
1108 template<typename Other, typename T>
1109 auto operator>=(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a >= b) {
1110 return (T)a >= b;
1111}
1112// @}
1113
1114/** Less than or equal comparison between GeneratorParam<T> and any type that supports operator<= with T.
1115 * Returns type of underlying operator<=. */
1116// @{
1117 template<typename Other, typename T>
1118 auto operator<=(const Other &a, const GeneratorParam<T> &b) -> decltype(a <= (T)b) {
1119 return a <= (T)b;
1120}
1121 template<typename Other, typename T>
1122 auto operator<=(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a <= b) {
1123 return (T)a <= b;
1124}
1125// @}
1126
1127/** Equality comparison between GeneratorParam<T> and any type that supports operator== with T.
1128 * Returns type of underlying operator==. */
1129// @{
1130 template<typename Other, typename T>
1131 auto operator==(const Other &a, const GeneratorParam<T> &b) -> decltype(a == (T)b) {
1132 return a == (T)b;
1133}
1134 template<typename Other, typename T>
1135 auto operator==(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a == b) {
1136 return (T)a == b;
1137}
1138// @}
1139
1140/** Inequality comparison between between GeneratorParam<T> and any type that supports operator!= with T.
1141 * Returns type of underlying operator!=. */
1142// @{
1143 template<typename Other, typename T>
1144 auto operator!=(const Other &a, const GeneratorParam<T> &b) -> decltype(a != (T)b) {
1145 return a != (T)b;
1146}
1147 template<typename Other, typename T>
1148 auto operator!=(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a != b) {
1149 return (T)a != b;
1150}
1151// @}
1152
1153/** Logical and between between GeneratorParam<T> and any type that supports operator&& with T.
1154 * Returns type of underlying operator&&. */
1155// @{
1156 template<typename Other, typename T>
1157 auto operator&&(const Other &a, const GeneratorParam<T> &b) -> decltype(a && (T)b) {
1158 return a && (T)b;
1159}
1160 template<typename Other, typename T>
1161 auto operator&&(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a && b) {
1162 return (T)a && b;
1163}
1164 template<typename T>
1165 auto operator&&(const GeneratorParam<T> &a, const GeneratorParam<T> &b) -> decltype((T)a && (T)b) {
1166 return (T)a && (T)b;
1167}
1168// @}
1169
1170/** Logical or between between GeneratorParam<T> and any type that supports operator|| with T.
1171 * Returns type of underlying operator||. */
1172// @{
1173 template<typename Other, typename T>
1174 auto operator||(const Other &a, const GeneratorParam<T> &b) -> decltype(a || (T)b) {
1175 return a || (T)b;
1176}
1177 template<typename Other, typename T>
1178 auto operator||(const GeneratorParam<T> &a, const Other &b) -> decltype((T)a || b) {
1179 return (T)a || b;
1180}
1181 template<typename T>
1182 auto operator||(const GeneratorParam<T> &a, const GeneratorParam<T> &b) -> decltype((T)a || (T)b) {
1183 return (T)a || (T)b;
1184}
1185// @}
1186
1187/* min and max are tricky as the language support for these is in the std
1188 * namespace. In order to make this work, forwarding functions are used that
1189 * are declared in a namespace that has std::min and std::max in scope.
1190 */
1191 namespace Internal {
1192 namespace GeneratorMinMax {
1193
1194 using std::max;
1195 using std::min;
1196
1197 template<typename Other, typename T>
1198 auto min_forward(const Other &a, const GeneratorParam<T> &b) -> decltype(min(a, (T)b)) {
1199 return min(a, (T)b);
1200}
1201 template<typename Other, typename T>
1202 auto min_forward(const GeneratorParam<T> &a, const Other &b) -> decltype(min((T)a, b)) {
1203 return min((T)a, b);
1204}
1205
1206 template<typename Other, typename T>
1207 auto max_forward(const Other &a, const GeneratorParam<T> &b) -> decltype(max(a, (T)b)) {
1208 return max(a, (T)b);
1209}
1210 template<typename Other, typename T>
1211 auto max_forward(const GeneratorParam<T> &a, const Other &b) -> decltype(max((T)a, b)) {
1212 return max((T)a, b);
1213}
1214
1215} // namespace GeneratorMinMax
1216} // namespace Internal
1217
1218/** Compute minimum between GeneratorParam<T> and any type that supports min with T.
1219 * Will automatically import std::min. Returns type of underlying min call. */
1220// @{
1221 template<typename Other, typename T>
1222 auto min(const Other &a, const GeneratorParam<T> &b) -> decltype(Internal::GeneratorMinMax::min_forward(a, b)) {
1223 return Internal::GeneratorMinMax::min_forward(a, b);
1224}
1225 template<typename Other, typename T>
1226 auto min(const GeneratorParam<T> &a, const Other &b) -> decltype(Internal::GeneratorMinMax::min_forward(a, b)) {
1227 return Internal::GeneratorMinMax::min_forward(a, b);
1228}
1229// @}
1230
1231/** Compute the maximum value between GeneratorParam<T> and any type that supports max with T.
1232 * Will automatically import std::max. Returns type of underlying max call. */
1233// @{
1234 template<typename Other, typename T>
1235 auto max(const Other &a, const GeneratorParam<T> &b) -> decltype(Internal::GeneratorMinMax::max_forward(a, b)) {
1236 return Internal::GeneratorMinMax::max_forward(a, b);
1237}
1238 template<typename Other, typename T>
1239 auto max(const GeneratorParam<T> &a, const Other &b) -> decltype(Internal::GeneratorMinMax::max_forward(a, b)) {
1240 return Internal::GeneratorMinMax::max_forward(a, b);
1241}
1242// @}
1243
1244/** Not operator for GeneratorParam */
1245 template<typename T>
1246 auto operator!(const GeneratorParam<T> &a) -> decltype(!(T)a) {
1247 return !(T)a;
1248}
1249
1250 namespace Internal {
1251
1252 template<typename T2>
1253 class GeneratorInput_Buffer;
1254
1255/**
1256 * StubInputBuffer is the placeholder that a Stub uses when it requires
1257 * a Buffer for an input (rather than merely a Func or Expr). It is constructed
1258 * to allow only two possible sorts of input:
1259 * -- Assignment of an Input<Buffer<>>, with compatible type and dimensions,
1260 * essentially allowing us to pipe a parameter from an enclosing Generator to an internal Stub.
1261 * -- Assignment of a Buffer<>, with compatible type and dimensions,
1262 * causing the Input<Buffer<>> to become a precompiled buffer in the generated code.
1263 */
1264 template<typename T = void, int Dims = Buffer<>::AnyDims>
1265 class StubInputBuffer {
1266 friend class StubInput;
1267 template<typename T2>
1268 friend class GeneratorInput_Buffer;
1269 template<typename T2, int D2>
1270 friend class StubInputBuffer;
1271
1272 Parameter parameter_;
1273
1274 HALIDE_NO_USER_CODE_INLINE explicit StubInputBuffer(const Parameter &p)
1275 : parameter_(p) {
1276 // Create an empty 1-element buffer with the right runtime typing and dimensions,
1277 // which we'll use only to pass to can_convert_from() to verify this
1278 // Parameter is compatible with our constraints.
1279 Buffer<> other(p.type(), nullptr, std::vector<int>(p.dimensions(), 1));
1280 internal_assert((Buffer<T, Dims>::can_convert_from(other)));
1281 }
1282
1283 template<typename T2, int D2>
1284 HALIDE_NO_USER_CODE_INLINE static Parameter parameter_from_buffer(const Buffer<T2, D2> &b) {
1285 internal_assert(b.defined());
1286 user_assert((Buffer<T, Dims>::can_convert_from(b)));
1287 Parameter p(b.type(), true, b.dimensions());
1288 p.set_buffer(b);
1289 return p;
1290 }
1291
1292 public:
1293 StubInputBuffer() = default;
1294
1295 // *not* explicit -- this ctor should only be used when you want
1296 // to pass a literal Buffer<> for a Stub Input; this Buffer<> will be
1297 // compiled into the Generator's product, rather than becoming
1298 // a runtime Parameter.
1299 template<typename T2, int D2>
1300 StubInputBuffer(const Buffer<T2, D2> &b)
1301 : parameter_(parameter_from_buffer(b)) {
1302 }
1303
1304 template<typename T2>
1305 static std::vector<Parameter> to_parameter_vector(const StubInputBuffer<T2> &t) {
1306 return {t.parameter_};
1307 }
1308
1309 template<typename T2>
1310 static std::vector<Parameter> to_parameter_vector(const std::vector<StubInputBuffer<T2>> &v) {
1311 std::vector<Parameter> r;
1312 r.reserve(v.size());
1313 for (const auto &s : v) {
1314 r.push_back(s.parameter_);
1315 }
1316 return r;
1317 }
1318};
1319
1320 class AbstractGenerator;
1321
1322 class StubOutputBufferBase {
1323 protected:
1324 Func f;
1325 std::shared_ptr<AbstractGenerator> generator;
1326
1327 Target get_target() const;
1328
1329 StubOutputBufferBase();
1330 explicit StubOutputBufferBase(const Func &f, const std::shared_ptr<AbstractGenerator> &generator);
1331
1332 public:
1333 Realization realize(std::vector<int32_t> sizes);
1334
1335 template<typename... Args>
1336 Realization realize(Args &&...args) {
1337 return f.realize(std::forward<Args>(args)..., get_target());
1338 }
1339
1340 template<typename Dst>
1341 void realize(Dst dst) {
1342 f.realize(dst, get_target());
1343 }
1344};
1345
1346/**
1347 * StubOutputBuffer is the placeholder that a Stub uses when it requires
1348 * a Buffer for an output (rather than merely a Func). It is constructed
1349 * to allow only two possible sorts of things:
1350 * -- Assignment to an Output<Buffer<>>, with compatible type and dimensions,
1351 * essentially allowing us to pipe a parameter from the result of a Stub to an
1352 * enclosing Generator
1353 * -- Realization into a Buffer<>; this is useful only in JIT compilation modes
1354 * (and shouldn't be usable otherwise)
1355 *
1356 * It is deliberate that StubOutputBuffer is not (easily) convertible to Func.
1357 */
1358 template<typename T = void>
1359 class StubOutputBuffer : public StubOutputBufferBase {
1360 template<typename T2>
1361 friend class GeneratorOutput_Buffer;
1362 explicit StubOutputBuffer(const Func &fn, const std::shared_ptr<AbstractGenerator> &gen)
1363 : StubOutputBufferBase(fn, gen) {
1364 }
1365
1366 public:
1367 StubOutputBuffer() = default;
1368
1369 static std::vector<StubOutputBuffer<T>> to_output_buffers(const std::vector<Func> &v,
1370 const std::shared_ptr<AbstractGenerator> &gen) {
1371 std::vector<StubOutputBuffer<T>> result;
1372 for (const Func &f : v) {
1373 result.push_back(StubOutputBuffer<T>(f, gen));
1374 }
1375 return result;
1376 }
1377};
1378
1379// This is a union-like class that allows for convenient initialization of Stub Inputs
1380// via initializer-list syntax; it is only used in situations where the
1381// downstream consumer will be able to explicitly check that each value is
1382// of the expected/required kind.
1383 class StubInput {
1384 const ArgInfoKind kind_;
1385 // Exactly one of the following fields should be defined:
1386 const Parameter parameter_;
1387 const Func func_;
1388 const Expr expr_;
1389
1390 public:
1391 // *not* explicit.
1392 template<typename T2>
1393 StubInput(const StubInputBuffer<T2> &b)
1394 : kind_(ArgInfoKind::Buffer), parameter_(b.parameter_), func_(), expr_() {
1395 }
1396 StubInput(const Parameter &p)
1397 : kind_(ArgInfoKind::Buffer), parameter_(p), func_(), expr_() {
1398 }
1399 StubInput(const Func &f)
1400 : kind_(ArgInfoKind::Function), parameter_(), func_(f), expr_() {
1401 }
1402 StubInput(const Expr &e)
1403 : kind_(ArgInfoKind::Scalar), parameter_(), func_(), expr_(e) {
1404 }
1405
1406 ArgInfoKind kind() const {
1407 return kind_;
1408 }
1409
1410 Parameter parameter() const {
1411 internal_assert(kind_ == ArgInfoKind::Buffer);
1412 return parameter_;
1413 }
1414
1415 Func func() const {
1416 internal_assert(kind_ == ArgInfoKind::Function);
1417 return func_;
1418 }
1419
1420 Expr expr() const {
1421 internal_assert(kind_ == ArgInfoKind::Scalar);
1422 return expr_;
1423 }
1424};
1425
1426/** GIOBase is the base class for all GeneratorInput<> and GeneratorOutput<>
1427 * instantiations; it is not part of the public API and should never be
1428 * used directly by user code.
1429 *
1430 * Every GIOBase instance can be either a single value or an array-of-values;
1431 * each of these values can be an Expr or a Func. (Note that for an
1432 * array-of-values, the types/dimensions of all values in the array must match.)
1433 *
1434 * A GIOBase can have multiple Types, in which case it represents a Tuple.
1435 * (Note that Tuples are currently only supported for GeneratorOutput, but
1436 * it is likely that GeneratorInput will be extended to support Tuple as well.)
1437 *
1438 * The array-size, type(s), and dimensions can all be left "unspecified" at
1439 * creation time, in which case they may assume values provided by a Stub.
1440 * (It is important to note that attempting to use a GIOBase with unspecified
1441 * values will assert-fail; you must ensure that all unspecified values are
1442 * filled in prior to use.)
1443 */
1444 class GIOBase {
1445 public:
1446 virtual ~GIOBase() = default;
1447
1448 // These should only be called from configure() methods.
1449 // TODO: find a way to enforce this. Better yet, find a way to remove these.
1450 void set_type(const Type &type);
1451 void set_dimensions(int dims);
1452 void set_array_size(int size);
1453
1454 protected:
1455 bool array_size_defined() const;
1456 size_t array_size() const;
1457 virtual bool is_array() const;
1458
1459 const std::string &name() const;
1460 ArgInfoKind kind() const;
1461
1462 bool gio_types_defined() const;
1463 const std::vector<Type> &gio_types() const;
1464 Type gio_type() const;
1465
1466 bool dims_defined() const;
1467 int dims() const;
1468
1469 const std::vector<Func> &funcs() const;
1470 const std::vector<Expr> &exprs() const;
1471
1472 GIOBase(size_t array_size,
1473 const std::string &name,
1474 ArgInfoKind kind,
1475 const std::vector<Type> &types,
1476 int dims);
1477
1478 friend class GeneratorBase;
1479 friend class GeneratorParamInfo;
1480
1481 mutable int array_size_; // always 1 if is_array() == false.
1482 // -1 if is_array() == true but unspecified.
1483
1484 const std::string name_;
1485 const ArgInfoKind kind_;
1486 mutable std::vector<Type> types_; // empty if type is unspecified
1487 mutable int dims_; // -1 if dim is unspecified
1488
1489 // Exactly one of these will have nonzero length
1490 std::vector<Func> funcs_;
1491 std::vector<Expr> exprs_;
1492
1493 // Generator which owns this Input or Output. Note that this will be null
1494 // initially; the GeneratorBase itself will set this field when it initially
1495 // builds its info about params. However, since it isn't
1496 // appropriate for Input<> or Output<> to be declared outside of a Generator,
1497 // all reasonable non-testing code should expect this to be non-null.
1498 GeneratorBase *generator{nullptr};
1499
1500 std::string array_name(size_t i) const;
1501
1502 virtual void verify_internals();
1503
1504 void check_matching_array_size(size_t size) const;
1505 void check_matching_types(const std::vector<Type> &t) const;
1506 void check_matching_dims(int d) const;
1507
1508 template<typename ElemType>
1509 const std::vector<ElemType> &get_values() const;
1510
1511 void check_gio_access() const;
1512
1513 virtual void check_value_writable() const = 0;
1514
1515 virtual const char *input_or_output() const = 0;
1516
1517 private:
1518 template<typename T>
1519 friend class GeneratorParam_Synthetic;
1520 friend class GeneratorStub;
1521
1522 public:
1523 GIOBase(const GIOBase &) = delete;
1524 GIOBase &operator=(const GIOBase &) = delete;
1525 GIOBase(GIOBase &&) = delete;
1526 GIOBase &operator=(GIOBase &&) = delete;
1527};
1528
1529 template<>
1530 inline const std::vector<Expr> &GIOBase::get_values<Expr>() const {
1531 return exprs();
1532}
1533
1534 template<>
1535 inline const std::vector<Func> &GIOBase::get_values<Func>() const {
1536 return funcs();
1537}
1538
1539 class GeneratorInputBase : public GIOBase {
1540 protected:
1541 GeneratorInputBase(size_t array_size,
1542 const std::string &name,
1543 ArgInfoKind kind,
1544 const std::vector<Type> &t,
1545 int d);
1546
1547 GeneratorInputBase(const std::string &name, ArgInfoKind kind, const std::vector<Type> &t, int d);
1548
1549 friend class GeneratorBase;
1550 friend class GeneratorParamInfo;
1551
1552 std::vector<Parameter> parameters_;
1553
1554 Parameter parameter() const;
1555
1556 void init_internals();
1557 void set_inputs(const std::vector<StubInput> &inputs);
1558 bool inputs_set = false;
1559
1560 virtual void set_def_min_max();
1561
1562 void verify_internals() override;
1563
1564 friend class StubEmitter;
1565
1566 virtual std::string get_c_type() const = 0;
1567
1568 void check_value_writable() const override;
1569
1570 const char *input_or_output() const override {
1571 return "Input";
1572 }
1573
1574 void set_estimate_impl(const Var &var, const Expr &min, const Expr &extent);
1575 void set_estimates_impl(const Region &estimates);
1576
1577 public:
1578 ~GeneratorInputBase() override;
1579};
1580
1581 template<typename T, typename ValueType>
1582 class GeneratorInputImpl : public GeneratorInputBase {
1583 protected:
1584 using TBase = std::remove_all_extents_t<T>;
1585
1586 bool is_array() const override {
1587 return std::is_array_v<T>;
1588 }
1589
1590 template<typename T2 = T, std::enable_if_t<
1591 // Only allow T2 not-an-array
1592 !std::is_array_v<T2>> * = nullptr>
1593 GeneratorInputImpl(const std::string &name, ArgInfoKind kind, const std::vector<Type> &t, int d)
1594 : GeneratorInputBase(name, kind, t, d) {
1595 }
1596
1597 template<typename T2 = T, std::enable_if_t<
1598 // Only allow T2[kSomeConst]
1599 std::is_array_v<T2> && std::rank_v<T2> == 1 && (std::extent_v<T2, 0> > 0)> * = nullptr>
1600 GeneratorInputImpl(const std::string &name, ArgInfoKind kind, const std::vector<Type> &t, int d)
1601 : GeneratorInputBase(std::extent_v<T2, 0>, name, kind, t, d) {
1602 }
1603
1604 template<typename T2 = T, std::enable_if_t<
1605 // Only allow T2[]
1606 std::is_array_v<T2> && std::rank_v<T2> == 1 && std::extent_v<T2, 0> == 0> * = nullptr>
1607 GeneratorInputImpl(const std::string &name, ArgInfoKind kind, const std::vector<Type> &t, int d)
1608 : GeneratorInputBase(-1, name, kind, t, d) {
1609 }
1610
1611 public:
1612 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1613 size_t size() const {
1614 this->check_gio_access();
1615 return get_values<ValueType>().size();
1616 }
1617
1618 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1619 const ValueType &operator[](size_t i) const {
1620 this->check_gio_access();
1621 return get_values<ValueType>()[i];
1622 }
1623
1624 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1625 const ValueType &at(size_t i) const {
1626 this->check_gio_access();
1627 return get_values<ValueType>().at(i);
1628 }
1629
1630 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1631 typename std::vector<ValueType>::const_iterator begin() const {
1632 this->check_gio_access();
1633 return get_values<ValueType>().begin();
1634 }
1635
1636 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1637 typename std::vector<ValueType>::const_iterator end() const {
1638 this->check_gio_access();
1639 return get_values<ValueType>().end();
1640 }
1641};
1642
1643// When forwarding methods to ImageParam, Func, etc., we must take
1644// care with the return types: many of the methods return a reference-to-self
1645// (e.g., ImageParam&); since we create temporaries for most of these forwards,
1646// returning a ref will crater because it refers to a now-defunct section of the
1647// stack. Happily, simply removing the reference is solves this, since all of the
1648// types in question satisfy the property of copies referring to the same underlying
1649// structure (returning references is just an optimization). Since this is verbose
1650// and used in several places, we'll use a helper macro:
1651#define HALIDE_FORWARD_METHOD(Class, Method) \
1652 template<typename... Args> \
1653 inline auto Method(Args &&...args) -> std::remove_reference_t<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))> { \
1654 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1655 }
1656
1657#define HALIDE_FORWARD_METHOD_CONST(Class, Method) \
1658 template<typename... Args> \
1659 inline auto Method(Args &&...args) const -> std::remove_reference_t<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))> { \
1660 this->check_gio_access(); \
1661 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1662 }
1663
1664 template<typename T>
1665 class GeneratorInput_Buffer : public GeneratorInputImpl<T, Func> {
1666 private:
1667 using Super = GeneratorInputImpl<T, Func>;
1668
1669 protected:
1670 using TBase = typename Super::TBase;
1671
1672 friend class ::Halide::Func;
1673 friend class ::Halide::Stage;
1674
1675 std::string get_c_type() const override {
1676 if (TBase::has_static_halide_type) {
1677 return "Halide::Internal::StubInputBuffer<" +
1678 halide_type_to_c_type(TBase::static_halide_type()) +
1679 ">";
1680 } else {
1681 return "Halide::Internal::StubInputBuffer<>";
1682 }
1683 }
1684
1685 template<typename T2>
1686 T2 as() const {
1687 return (T2) * this;
1688 }
1689
1690 public:
1691 explicit GeneratorInput_Buffer(const std::string &name)
1692 : Super(name, ArgInfoKind::Buffer,
1693 TBase::has_static_halide_type ? std::vector<Type>{TBase::static_halide_type()} : std::vector<Type>{},
1694 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
1695 }
1696
1697 GeneratorInput_Buffer(const std::string &name, const Type &t, int d)
1698 : Super(name, ArgInfoKind::Buffer, {t}, d) {
1699 static_assert(!TBase::has_static_halide_type, "You can only specify a Type argument for Input<Buffer<T>> if T is void or omitted.");
1700 static_assert(!TBase::has_static_dimensions, "You can only specify a dimension argument for Input<Buffer<T, D>> if D is -1 or omitted.");
1701 }
1702
1703 GeneratorInput_Buffer(const std::string &name, const Type &t)
1704 : Super(name, ArgInfoKind::Buffer, {t}, -1) {
1705 static_assert(!TBase::has_static_halide_type, "You can only specify a Type argument for Input<Buffer<T>> if T is void or omitted.");
1706 }
1707
1708 GeneratorInput_Buffer(const std::string &name, int d)
1709 : Super(name, ArgInfoKind::Buffer,
1710 TBase::has_static_halide_type ? std::vector<Type>{TBase::static_halide_type()} : std::vector<Type>{},
1711 d) {
1712 static_assert(!TBase::has_static_dimensions, "You can only specify a dimension argument for Input<Buffer<T, D>> if D is -1 or omitted.");
1713 }
1714
1715 template<typename... Args>
1716 Expr operator()(Args &&...args) const {
1717 this->check_gio_access();
1718 return Func(*this)(std::forward<Args>(args)...);
1719 }
1720
1721 Expr operator()(std::vector<Expr> args) const {
1722 this->check_gio_access();
1723 return Func(*this)(std::move(args));
1724 }
1725
1726 template<typename T2>
1727 operator StubInputBuffer<T2>() const {
1728 user_assert(!this->is_array()) << "Cannot assign an array type to a non-array type for Input " << this->name();
1729 return StubInputBuffer<T2>(this->parameters_.at(0));
1730 }
1731
1732 operator Func() const {
1733 this->check_gio_access();
1734 return this->funcs().at(0);
1735 }
1736
1737 operator ExternFuncArgument() const {
1738 this->check_gio_access();
1739 return ExternFuncArgument(this->parameters_.at(0));
1740 }
1741
1742 GeneratorInput_Buffer<T> &set_estimate(Var var, Expr min, Expr extent) {
1743 this->check_gio_access();
1744 this->set_estimate_impl(var, min, extent);
1745 return *this;
1746 }
1747
1748 GeneratorInput_Buffer<T> &set_estimates(const Region &estimates) {
1749 this->check_gio_access();
1750 this->set_estimates_impl(estimates);
1751 return *this;
1752 }
1753
1754 Func in() {
1755 this->check_gio_access();
1756 return Func(*this).in();
1757 }
1758
1759 Func in(const Func &other) {
1760 this->check_gio_access();
1761 return Func(*this).in(other);
1762 }
1763
1764 Func in(const std::vector<Func> &others) {
1765 this->check_gio_access();
1766 return Func(*this).in(others);
1767 }
1768
1769 operator ImageParam() const {
1770 this->check_gio_access();
1771 user_assert(!this->is_array()) << "Cannot convert an Input<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->name();
1772 return ImageParam(this->parameters_.at(0), Func(*this));
1773 }
1774
1775 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1776 size_t size() const {
1777 this->check_gio_access();
1778 return this->parameters_.size();
1779 }
1780
1781 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1782 ImageParam operator[](size_t i) const {
1783 this->check_gio_access();
1784 return ImageParam(this->parameters_.at(i), this->funcs().at(i));
1785 }
1786
1787 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1788 ImageParam at(size_t i) const {
1789 this->check_gio_access();
1790 return ImageParam(this->parameters_.at(i), this->funcs().at(i));
1791 }
1792
1793 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1794 std::vector<ImageParam>::const_iterator begin() const {
1795 user_error << "Input<Buffer<>>::begin() is not supported.";
1796 return {};
1797 }
1798
1799 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
1800 std::vector<ImageParam>::const_iterator end() const {
1801 user_error << "Input<Buffer<>>::end() is not supported.";
1802 return {};
1803 }
1804
1805 /** Forward methods to the ImageParam. */
1806 // @{
1807 HALIDE_FORWARD_METHOD(ImageParam, dim)
1808 HALIDE_FORWARD_METHOD_CONST(ImageParam, dim)
1809 HALIDE_FORWARD_METHOD_CONST(ImageParam, host_alignment)
1810 HALIDE_FORWARD_METHOD(ImageParam, set_host_alignment)
1811 HALIDE_FORWARD_METHOD(ImageParam, store_in)
1812 HALIDE_FORWARD_METHOD_CONST(ImageParam, dimensions)
1813 HALIDE_FORWARD_METHOD_CONST(ImageParam, left)
1814 HALIDE_FORWARD_METHOD_CONST(ImageParam, right)
1815 HALIDE_FORWARD_METHOD_CONST(ImageParam, top)
1816 HALIDE_FORWARD_METHOD_CONST(ImageParam, bottom)
1817 HALIDE_FORWARD_METHOD_CONST(ImageParam, width)
1818 HALIDE_FORWARD_METHOD_CONST(ImageParam, height)
1819 HALIDE_FORWARD_METHOD_CONST(ImageParam, channels)
1820 HALIDE_FORWARD_METHOD_CONST(ImageParam, trace_loads)
1821 HALIDE_FORWARD_METHOD_CONST(ImageParam, add_trace_tag)
1822 HALIDE_FORWARD_METHOD_CONST(ImageParam, type)
1823 // }@
1824};
1825
1826 template<typename T>
1827 class GeneratorInput_Func : public GeneratorInputImpl<T, Func> {
1828 private:
1829 using Super = GeneratorInputImpl<T, Func>;
1830
1831 protected:
1832 using TBase = typename Super::TBase;
1833
1834 std::string get_c_type() const override {
1835 return "Func";
1836 }
1837
1838 template<typename T2>
1839 T2 as() const {
1840 return (T2) * this;
1841 }
1842
1843 public:
1844 GeneratorInput_Func(const std::string &name, const Type &t, int d)
1845 : Super(name, ArgInfoKind::Function, {t}, d) {
1846 }
1847
1848 // unspecified type
1849 GeneratorInput_Func(const std::string &name, int d)
1850 : Super(name, ArgInfoKind::Function, {}, d) {
1851 }
1852
1853 // unspecified dimension
1854 GeneratorInput_Func(const std::string &name, const Type &t)
1855 : Super(name, ArgInfoKind::Function, {t}, -1) {
1856 }
1857
1858 // unspecified type & dimension
1859 explicit GeneratorInput_Func(const std::string &name)
1860 : Super(name, ArgInfoKind::Function, {}, -1) {
1861 }
1862
1863 GeneratorInput_Func(size_t array_size, const std::string &name, const Type &t, int d)
1864 : Super(array_size, name, ArgInfoKind::Function, {t}, d) {
1865 }
1866
1867 // unspecified type
1868 GeneratorInput_Func(size_t array_size, const std::string &name, int d)
1869 : Super(array_size, name, ArgInfoKind::Function, {}, d) {
1870 }
1871
1872 // unspecified dimension
1873 GeneratorInput_Func(size_t array_size, const std::string &name, const Type &t)
1874 : Super(array_size, name, ArgInfoKind::Function, {t}, -1) {
1875 }
1876
1877 // unspecified type & dimension
1878 GeneratorInput_Func(size_t array_size, const std::string &name)
1879 : Super(array_size, name, ArgInfoKind::Function, {}, -1) {
1880 }
1881
1882 template<typename... Args>
1883 Expr operator()(Args &&...args) const {
1884 this->check_gio_access();
1885 return this->funcs().at(0)(std::forward<Args>(args)...);
1886 }
1887
1888 Expr operator()(const std::vector<Expr> &args) const {
1889 this->check_gio_access();
1890 return this->funcs().at(0)(args);
1891 }
1892
1893 operator Func() const {
1894 this->check_gio_access();
1895 return this->funcs().at(0);
1896 }
1897
1898 operator ExternFuncArgument() const {
1899 this->check_gio_access();
1900 return ExternFuncArgument(this->parameters_.at(0));
1901 }
1902
1903 GeneratorInput_Func<T> &set_estimate(Var var, Expr min, Expr extent) {
1904 this->check_gio_access();
1905 this->set_estimate_impl(var, min, extent);
1906 return *this;
1907 }
1908
1909 GeneratorInput_Func<T> &set_estimates(const Region &estimates) {
1910 this->check_gio_access();
1911 this->set_estimates_impl(estimates);
1912 return *this;
1913 }
1914
1915 Func in() {
1916 this->check_gio_access();
1917 return Func(*this).in();
1918 }
1919
1920 Func in(const Func &other) {
1921 this->check_gio_access();
1922 return Func(*this).in(other);
1923 }
1924
1925 Func in(const std::vector<Func> &others) {
1926 this->check_gio_access();
1927 return Func(*this).in(others);
1928 }
1929
1930 /** Forward const methods to the underlying Func. (Non-const methods
1931 * aren't available for Input<Func>.) */
1932 // @{
1933 HALIDE_FORWARD_METHOD_CONST(Func, args)
1934 HALIDE_FORWARD_METHOD_CONST(Func, defined)
1935 HALIDE_FORWARD_METHOD_CONST(Func, dimensions)
1936 HALIDE_FORWARD_METHOD_CONST(Func, has_update_definition)
1937 HALIDE_FORWARD_METHOD_CONST(Func, num_update_definitions)
1938 HALIDE_FORWARD_METHOD_CONST(Func, outputs)
1939 HALIDE_FORWARD_METHOD_CONST(Func, rvars)
1940 HALIDE_FORWARD_METHOD_CONST(Func, type)
1941 HALIDE_FORWARD_METHOD_CONST(Func, types)
1942 HALIDE_FORWARD_METHOD_CONST(Func, update_args)
1943 HALIDE_FORWARD_METHOD_CONST(Func, update_value)
1944 HALIDE_FORWARD_METHOD_CONST(Func, update_values)
1945 HALIDE_FORWARD_METHOD_CONST(Func, value)
1946 HALIDE_FORWARD_METHOD_CONST(Func, values)
1947 // }@
1948};
1949
1950 template<typename T>
1951 class GeneratorInput_DynamicScalar : public GeneratorInputImpl<T, Expr> {
1952 private:
1953 using Super = GeneratorInputImpl<T, Expr>;
1954
1955 static_assert(std::is_same_v<std::remove_all_extents_t<T>, Expr>, "GeneratorInput_DynamicScalar is only legal to use with T=Expr for now");
1956
1957 protected:
1958 std::string get_c_type() const override {
1959 return "Expr";
1960 }
1961
1962 public:
1963 explicit GeneratorInput_DynamicScalar(const std::string &name)
1964 : Super(name, ArgInfoKind::Scalar, {}, 0) {
1965 user_assert(!std::is_array_v<T>) << "Input<Expr[]> is not allowed";
1966 }
1967
1968 /** You can use this Input as an expression in a halide
1969 * function definition */
1970 operator Expr() const {
1971 this->check_gio_access();
1972 return this->exprs().at(0);
1973 }
1974
1975 /** Using an Input as the argument to an external stage treats it
1976 * as an Expr */
1977 operator ExternFuncArgument() const {
1978 this->check_gio_access();
1979 return ExternFuncArgument(this->exprs().at(0));
1980 }
1981
1982 void set_estimate(const Expr &value) {
1983 this->check_gio_access();
1984 for (Parameter &p : this->parameters_) {
1985 p.set_estimate(value);
1986 }
1987 }
1988
1989 Type type() const {
1990 return Expr(*this).type();
1991 }
1992};
1993
1994 template<typename T>
1995 class GeneratorInput_Scalar : public GeneratorInputImpl<T, Expr> {
1996 private:
1997 using Super = GeneratorInputImpl<T, Expr>;
1998
1999 protected:
2000 using TBase = typename Super::TBase;
2001
2002 const TBase def_{TBase()};
2003 const Expr def_expr_;
2004
2005 void set_def_min_max() override {
2006 for (Parameter &p : this->parameters_) {
2007 // No: we want to leave the Parameter unset here.
2008 // p.set_scalar<TBase>(def_);
2009 p.set_default_value(def_expr_);
2010 }
2011 }
2012
2013 std::string get_c_type() const override {
2014 return "Expr";
2015 }
2016
2017 // Expr() doesn't accept a pointer type in its ctor; add a SFINAE adapter
2018 // so that pointer (aka handle) Inputs will get cast to uint64.
2019 template<typename TBase2 = TBase, std::enable_if_t<!std::is_pointer_v<TBase2>> * = nullptr>
2020 static Expr TBaseToExpr(const TBase2 &value) {
2021 return cast<TBase>(Expr(value));
2022 }
2023
2024 template<typename TBase2 = TBase, std::enable_if_t<std::is_pointer_v<TBase2>> * = nullptr>
2025 static Expr TBaseToExpr(const TBase2 &value) {
2026 user_assert(value == 0) << "Zero is the only legal default value for Inputs which are pointer types.\n";
2027 return Expr();
2028 }
2029
2030 public:
2031 explicit GeneratorInput_Scalar(const std::string &name)
2032 : Super(name, ArgInfoKind::Scalar, {type_of<TBase>()}, 0), def_(static_cast<TBase>(0)), def_expr_(Expr()) {
2033 }
2034
2035 GeneratorInput_Scalar(const std::string &name, const TBase &def)
2036 : Super(name, ArgInfoKind::Scalar, {type_of<TBase>()}, 0), def_(def), def_expr_(TBaseToExpr(def)) {
2037 }
2038
2039 GeneratorInput_Scalar(size_t array_size,
2040 const std::string &name)
2041 : Super(array_size, name, ArgInfoKind::Scalar, {type_of<TBase>()}, 0), def_(static_cast<TBase>(0)), def_expr_(Expr()) {
2042 }
2043
2044 GeneratorInput_Scalar(size_t array_size,
2045 const std::string &name,
2046 const TBase &def)
2047 : Super(array_size, name, ArgInfoKind::Scalar, {type_of<TBase>()}, 0), def_(def), def_expr_(TBaseToExpr(def)) {
2048 }
2049
2050 /** You can use this Input as an expression in a halide
2051 * function definition */
2052 operator Expr() const {
2053 this->check_gio_access();
2054 return this->exprs().at(0);
2055 }
2056
2057 /** Using an Input as the argument to an external stage treats it
2058 * as an Expr */
2059 operator ExternFuncArgument() const {
2060 this->check_gio_access();
2061 return ExternFuncArgument(this->exprs().at(0));
2062 }
2063
2064 template<typename T2 = T, std::enable_if_t<std::is_pointer_v<T2>> * = nullptr>
2065 void set_estimate(const TBase &value) {
2066 this->check_gio_access();
2067 user_assert(value == nullptr) << "nullptr is the only valid estimate for Input<PointerType>";
2068 Expr e = reinterpret(type_of<T2>(), cast<uint64_t>(0));
2069 for (Parameter &p : this->parameters_) {
2070 p.set_estimate(e);
2071 }
2072 }
2073
2074 template<typename T2 = T, std::enable_if_t<!std::is_array_v<T2> && !std::is_pointer_v<T2>> * = nullptr>
2075 void set_estimate(const TBase &value) {
2076 this->check_gio_access();
2077 Expr e = Expr(value);
2078 if (std::is_same_v<T2, bool>) {
2079 e = cast<bool>(e);
2080 }
2081 for (Parameter &p : this->parameters_) {
2082 p.set_estimate(e);
2083 }
2084 }
2085
2086 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2087 void set_estimate(size_t index, const TBase &value) {
2088 this->check_gio_access();
2089 Expr e = Expr(value);
2090 if (std::is_same_v<T2, bool>) {
2091 e = cast<bool>(e);
2092 }
2093 this->parameters_.at(index).set_estimate(e);
2094 }
2095
2096 Type type() const {
2097 return Expr(*this).type();
2098 }
2099};
2100
2101 template<typename T>
2102 class GeneratorInput_Arithmetic : public GeneratorInput_Scalar<T> {
2103 private:
2104 using Super = GeneratorInput_Scalar<T>;
2105
2106 protected:
2107 using TBase = typename Super::TBase;
2108
2109 const Expr min_, max_;
2110
2111 void set_def_min_max() override {
2112 Super::set_def_min_max();
2113 // Don't set min/max for bool
2114 if (!std::is_same_v<TBase, bool>) {
2115 for (Parameter &p : this->parameters_) {
2116 if (min_.defined()) {
2117 p.set_min_value(min_);
2118 }
2119 if (max_.defined()) {
2120 p.set_max_value(max_);
2121 }
2122 }
2123 }
2124 }
2125
2126 public:
2127 explicit GeneratorInput_Arithmetic(const std::string &name)
2128 : Super(name), min_(Expr()), max_(Expr()) {
2129 }
2130
2131 GeneratorInput_Arithmetic(const std::string &name,
2132 const TBase &def)
2133 : Super(name, def), min_(Expr()), max_(Expr()) {
2134 }
2135
2136 GeneratorInput_Arithmetic(size_t array_size,
2137 const std::string &name)
2138 : Super(array_size, name), min_(Expr()), max_(Expr()) {
2139 }
2140
2141 GeneratorInput_Arithmetic(size_t array_size,
2142 const std::string &name,
2143 const TBase &def)
2144 : Super(array_size, name, def), min_(Expr()), max_(Expr()) {
2145 }
2146
2147 GeneratorInput_Arithmetic(const std::string &name,
2148 const TBase &def,
2149 const TBase &min,
2150 const TBase &max)
2151 : Super(name, def), min_(min), max_(max) {
2152 }
2153
2154 GeneratorInput_Arithmetic(size_t array_size,
2155 const std::string &name,
2156 const TBase &def,
2157 const TBase &min,
2158 const TBase &max)
2159 : Super(array_size, name, def), min_(min), max_(max) {
2160 }
2161};
2162
2163 template<typename>
2164 using type_sink_t = void;
2165
2166 template<typename T2, typename = void>
2167 struct has_static_halide_type_method : std::false_type {};
2168
2169 template<typename T2>
2170 struct has_static_halide_type_method<T2, type_sink_t<decltype(T2::static_halide_type())>> : std::true_type {};
2171
2172 template<typename... Args>
2173 inline constexpr bool has_static_halide_type_method_v = has_static_halide_type_method<Args...>::value;
2174
2175 template<typename T, typename TBase = std::remove_all_extents_t<T>>
2176 using GeneratorInputImplBase =
2177 select_type_t<
2178 cond<has_static_halide_type_method_v<TBase>, GeneratorInput_Buffer<T>>,
2179 cond<std::is_same_v<TBase, Func>, GeneratorInput_Func<T>>,
2180 cond<std::is_arithmetic_v<TBase>, GeneratorInput_Arithmetic<T>>,
2181 cond<std::is_scalar_v<TBase>, GeneratorInput_Scalar<T>>,
2182 cond<std::is_same_v<TBase, Expr>, GeneratorInput_DynamicScalar<T>>>;
2183
2184} // namespace Internal
2185
2186 template<typename T>
2187 class GeneratorInput : public Internal::GeneratorInputImplBase<T> {
2188 private:
2189 using Super = Internal::GeneratorInputImplBase<T>;
2190
2191 protected:
2192 using TBase = typename Super::TBase;
2193
2194 // Trick to avoid ambiguous ctor between Func-with-dim and int-with-default-value;
2195 // since we can't use std::enable_if on ctors, define the argument to be one that
2196 // can only be properly resolved for TBase=Func.
2197 struct Unused;
2198 using IntIfNonScalar =
2199 Internal::select_type_t<
2200 Internal::cond<Internal::has_static_halide_type_method_v<TBase>, int>,
2201 Internal::cond<std::is_same_v<TBase, Func>, int>,
2202 Internal::cond<true, Unused>>;
2203
2204 public:
2205 // Mark all of these explicit (not just single-arg versions) so that
2206 // we disallow copy-list-initialization form (i.e., Input foo{"foo"} is ok,
2207 // but Input foo = {"foo"} is not).
2208 explicit GeneratorInput(const std::string &name)
2209 : Super(name) {
2210 }
2211
2212 explicit GeneratorInput(const std::string &name, const TBase &def)
2213 : Super(name, def) {
2214 }
2215
2216 explicit GeneratorInput(size_t array_size, const std::string &name, const TBase &def)
2217 : Super(array_size, name, def) {
2218 }
2219
2220 explicit GeneratorInput(const std::string &name,
2221 const TBase &def, const TBase &min, const TBase &max)
2222 : Super(name, def, min, max) {
2223 }
2224
2225 explicit GeneratorInput(size_t array_size, const std::string &name,
2226 const TBase &def, const TBase &min, const TBase &max)
2227 : Super(array_size, name, def, min, max) {
2228 }
2229
2230 explicit GeneratorInput(const std::string &name, const Type &t, int d)
2231 : Super(name, t, d) {
2232 }
2233
2234 explicit GeneratorInput(const std::string &name, const Type &t)
2235 : Super(name, t) {
2236 }
2237
2238 // Avoid ambiguity between Func-with-dim and int-with-default
2239 explicit GeneratorInput(const std::string &name, IntIfNonScalar d)
2240 : Super(name, d) {
2241 }
2242
2243 explicit GeneratorInput(size_t array_size, const std::string &name, const Type &t, int d)
2244 : Super(array_size, name, t, d) {
2245 }
2246
2247 explicit GeneratorInput(size_t array_size, const std::string &name, const Type &t)
2248 : Super(array_size, name, t) {
2249 }
2250
2251 // Avoid ambiguity between Func-with-dim and int-with-default
2252 // template <typename T2 = T, std::enable_if_t<std::is_same_v<TBase, Func>> * = nullptr>
2253 explicit GeneratorInput(size_t array_size, const std::string &name, IntIfNonScalar d)
2254 : Super(array_size, name, d) {
2255 }
2256
2257 explicit GeneratorInput(size_t array_size, const std::string &name)
2258 : Super(array_size, name) {
2259 }
2260};
2261
2262 namespace Internal {
2263
2264 class GeneratorOutputBase : public GIOBase {
2265 protected:
2266 template<typename T2, std::enable_if_t<std::is_same_v<T2, Func>> * = nullptr>
2267 HALIDE_NO_USER_CODE_INLINE T2 as() const {
2268 static_assert(std::is_same_v<T2, Func>, "Only Func allowed here");
2269 internal_assert(kind() != ArgInfoKind::Scalar);
2270 internal_assert(exprs_.empty());
2271 user_assert(!funcs_.empty()) << "No funcs_ are defined yet";
2272 user_assert(funcs_.size() == 1) << "Use [] to access individual Funcs in Output<Func[]>";
2273 return funcs_[0];
2274 }
2275
2276 public:
2277 /** Forward schedule-related methods to the underlying Func. */
2278 // @{
2279 HALIDE_FORWARD_METHOD(Func, add_trace_tag)
2280 HALIDE_FORWARD_METHOD(Func, align_bounds)
2281 HALIDE_FORWARD_METHOD(Func, align_extent)
2282 HALIDE_FORWARD_METHOD(Func, align_storage)
2283 HALIDE_FORWARD_METHOD(Func, always_partition)
2284 HALIDE_FORWARD_METHOD(Func, always_partition_all)
2285 HALIDE_FORWARD_METHOD_CONST(Func, args)
2286 HALIDE_FORWARD_METHOD(Func, bound)
2287 HALIDE_FORWARD_METHOD(Func, bound_extent)
2288 HALIDE_FORWARD_METHOD(Func, compute_at)
2289 HALIDE_FORWARD_METHOD(Func, compute_inline)
2290 HALIDE_FORWARD_METHOD(Func, compute_root)
2291 HALIDE_FORWARD_METHOD(Func, compute_with)
2292 HALIDE_FORWARD_METHOD(Func, copy_to_device)
2293 HALIDE_FORWARD_METHOD(Func, copy_to_host)
2294 HALIDE_FORWARD_METHOD(Func, define_extern)
2295 HALIDE_FORWARD_METHOD_CONST(Func, defined)
2296 HALIDE_FORWARD_METHOD_CONST(Func, dimensions)
2297 HALIDE_FORWARD_METHOD(Func, fold_storage)
2298 HALIDE_FORWARD_METHOD(Func, fuse)
2299 HALIDE_FORWARD_METHOD(Func, gpu)
2300 HALIDE_FORWARD_METHOD(Func, gpu_blocks)
2301 HALIDE_FORWARD_METHOD(Func, gpu_single_thread)
2302 HALIDE_FORWARD_METHOD(Func, gpu_threads)
2303 HALIDE_FORWARD_METHOD(Func, gpu_tile)
2304 HALIDE_FORWARD_METHOD_CONST(Func, has_update_definition)
2305 HALIDE_FORWARD_METHOD(Func, hexagon)
2306 HALIDE_FORWARD_METHOD(Func, in)
2307 HALIDE_FORWARD_METHOD(Func, memoize)
2308 HALIDE_FORWARD_METHOD(Func, never_partition)
2309 HALIDE_FORWARD_METHOD(Func, never_partition_all)
2310 HALIDE_FORWARD_METHOD_CONST(Func, num_update_definitions)
2311 HALIDE_FORWARD_METHOD_CONST(Func, outputs)
2312 HALIDE_FORWARD_METHOD(Func, parallel)
2313 HALIDE_FORWARD_METHOD(Func, partition)
2314 HALIDE_FORWARD_METHOD(Func, prefetch)
2315 HALIDE_FORWARD_METHOD(Func, print_loop_nest)
2316 HALIDE_FORWARD_METHOD(Func, rename)
2317 HALIDE_FORWARD_METHOD(Func, reorder)
2318 HALIDE_FORWARD_METHOD(Func, reorder_storage)
2319 HALIDE_FORWARD_METHOD_CONST(Func, rvars)
2320 HALIDE_FORWARD_METHOD(Func, serial)
2321 HALIDE_FORWARD_METHOD(Func, set_estimate)
2322 HALIDE_FORWARD_METHOD(Func, specialize)
2323 HALIDE_FORWARD_METHOD(Func, specialize_fail)
2324 HALIDE_FORWARD_METHOD(Func, split)
2325 HALIDE_FORWARD_METHOD(Func, store_at)
2326 HALIDE_FORWARD_METHOD(Func, store_root)
2327 HALIDE_FORWARD_METHOD(Func, tile)
2328 HALIDE_FORWARD_METHOD(Func, trace_stores)
2329 HALIDE_FORWARD_METHOD_CONST(Func, type)
2330 HALIDE_FORWARD_METHOD_CONST(Func, types)
2331 HALIDE_FORWARD_METHOD(Func, unroll)
2332 HALIDE_FORWARD_METHOD(Func, update)
2333 HALIDE_FORWARD_METHOD_CONST(Func, update_args)
2334 HALIDE_FORWARD_METHOD_CONST(Func, update_value)
2335 HALIDE_FORWARD_METHOD_CONST(Func, update_values)
2336 HALIDE_FORWARD_METHOD_CONST(Func, value)
2337 HALIDE_FORWARD_METHOD_CONST(Func, values)
2338 HALIDE_FORWARD_METHOD(Func, vectorize)
2339
2340 // }@
2341
2342#undef HALIDE_OUTPUT_FORWARD
2343#undef HALIDE_OUTPUT_FORWARD_CONST
2344
2345 using GIOBase::set_type;
2346
2347 /** Set types dynamically for tuple outputs. */
2348 void set_type(const std::vector<Type> &types);
2349
2350 protected:
2351 GeneratorOutputBase(size_t array_size,
2352 const std::string &name,
2353 ArgInfoKind kind,
2354 const std::vector<Type> &t,
2355 int d);
2356
2357 GeneratorOutputBase(const std::string &name,
2358 ArgInfoKind kind,
2359 const std::vector<Type> &t,
2360 int d);
2361
2362 friend class GeneratorBase;
2363 friend class StubEmitter;
2364
2365 void init_internals();
2366 void resize(size_t size);
2367
2368 virtual std::string get_c_type() const {
2369 return "Func";
2370 }
2371
2372 void check_value_writable() const override;
2373
2374 const char *input_or_output() const override {
2375 return "Output";
2376 }
2377
2378 public:
2379 ~GeneratorOutputBase() override;
2380};
2381
2382 template<typename T>
2383 class GeneratorOutputImpl : public GeneratorOutputBase {
2384 protected:
2385 using TBase = std::remove_all_extents_t<T>;
2386 using ValueType = Func;
2387
2388 bool is_array() const override {
2389 return std::is_array_v<T>;
2390 }
2391
2392 template<typename T2 = T, std::enable_if_t<
2393 // Only allow T2 not-an-array
2394 !std::is_array_v<T2>> * = nullptr>
2395 GeneratorOutputImpl(const std::string &name, ArgInfoKind kind, const std::vector<Type> &t, int d)
2396 : GeneratorOutputBase(name, kind, t, d) {
2397 }
2398
2399 template<typename T2 = T, std::enable_if_t<
2400 // Only allow T2[kSomeConst]
2401 std::is_array_v<T2> && std::rank_v<T2> == 1 && (std::extent_v<T2, 0> > 0)> * = nullptr>
2402 GeneratorOutputImpl(const std::string &name, ArgInfoKind kind, const std::vector<Type> &t, int d)
2403 : GeneratorOutputBase(std::extent_v<T2, 0>, name, kind, t, d) {
2404 }
2405
2406 template<typename T2 = T, std::enable_if_t<
2407 // Only allow T2[]
2408 std::is_array_v<T2> && std::rank_v<T2> == 1 && std::extent_v<T2, 0> == 0> * = nullptr>
2409 GeneratorOutputImpl(const std::string &name, ArgInfoKind kind, const std::vector<Type> &t, int d)
2410 : GeneratorOutputBase(-1, name, kind, t, d) {
2411 }
2412
2413 public:
2414 template<typename... Args, typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * = nullptr>
2415 FuncRef operator()(Args &&...args) const {
2416 this->check_gio_access();
2417 return get_values<ValueType>().at(0)(std::forward<Args>(args)...);
2418 }
2419
2420 template<typename ExprOrVar, typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * = nullptr>
2421 FuncRef operator()(std::vector<ExprOrVar> args) const {
2422 this->check_gio_access();
2423 return get_values<ValueType>().at(0)(std::move(args));
2424 }
2425
2426 template<typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * = nullptr>
2427 operator Func() const {
2428 this->check_gio_access();
2429 return get_values<ValueType>().at(0);
2430 }
2431
2432 template<typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * = nullptr>
2433 operator Stage() const {
2434 this->check_gio_access();
2435 return get_values<ValueType>().at(0);
2436 }
2437
2438 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2439 size_t size() const {
2440 this->check_gio_access();
2441 return get_values<ValueType>().size();
2442 }
2443
2444 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2445 const ValueType &operator[](size_t i) const {
2446 this->check_gio_access();
2447 return get_values<ValueType>()[i];
2448 }
2449
2450 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2451 const ValueType &at(size_t i) const {
2452 this->check_gio_access();
2453 return get_values<ValueType>().at(i);
2454 }
2455
2456 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2457 std::vector<ValueType>::const_iterator begin() const {
2458 this->check_gio_access();
2459 return get_values<ValueType>().begin();
2460 }
2461
2462 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2463 std::vector<ValueType>::const_iterator end() const {
2464 this->check_gio_access();
2465 return get_values<ValueType>().end();
2466 }
2467
2468 template<typename T2 = T, std::enable_if_t<
2469 // Only allow T2[]
2470 std::is_array_v<T2> && std::rank_v<T2> == 1 && std::extent_v<T2, 0> == 0> * = nullptr>
2471 void resize(size_t size) {
2472 this->check_gio_access();
2473 GeneratorOutputBase::resize(size);
2474 }
2475};
2476
2477 template<typename T>
2478 class GeneratorOutput_Buffer : public GeneratorOutputImpl<T> {
2479 private:
2480 using Super = GeneratorOutputImpl<T>;
2481
2482 HALIDE_NO_USER_CODE_INLINE void assign_from_func(const Func &f) {
2483 this->check_value_writable();
2484
2485 internal_assert(f.defined());
2486
2487 if (this->gio_types_defined()) {
2488 const auto &my_types = this->gio_types();
2489 user_assert(my_types.size() == f.types().size())
2490 << "Cannot assign Func \"" << f.name()
2491 << "\" to Output \"" << this->name() << "\"\n"
2492 << "Output " << this->name()
2493 << " is declared to have " << my_types.size() << " tuple elements"
2494 << " but Func " << f.name()
2495 << " has " << f.types().size() << " tuple elements.\n";
2496 for (size_t i = 0; i < my_types.size(); i++) {
2497 user_assert(my_types[i] == f.types().at(i))
2498 << "Cannot assign Func \"" << f.name()
2499 << "\" to Output \"" << this->name() << "\"\n"
2500 << (my_types.size() > 1 ? "In tuple element " + std::to_string(i) + ", " : "")
2501 << "Output " << this->name()
2502 << " has declared type " << my_types[i]
2503 << " but Func " << f.name()
2504 << " has type " << f.types().at(i) << "\n";
2505 }
2506 }
2507 if (this->dims_defined()) {
2508 user_assert(f.dimensions() == this->dims())
2509 << "Cannot assign Func \"" << f.name()
2510 << "\" to Output \"" << this->name() << "\"\n"
2511 << "Output " << this->name()
2512 << " has declared dimensionality " << this->dims()
2513 << " but Func " << f.name()
2514 << " has dimensionality " << f.dimensions() << "\n";
2515 }
2516
2517 internal_assert(this->exprs_.empty() && this->funcs_.size() == 1);
2518 user_assert(!this->funcs_.at(0).defined());
2519 this->funcs_[0] = f;
2520 }
2521
2522 protected:
2523 using TBase = typename Super::TBase;
2524
2525 explicit GeneratorOutput_Buffer(const std::string &name)
2526 : Super(name, ArgInfoKind::Buffer,
2527 TBase::has_static_halide_type ? std::vector<Type>{TBase::static_halide_type()} : std::vector<Type>{},
2528 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
2529 }
2530
2531 GeneratorOutput_Buffer(const std::string &name, const std::vector<Type> &t, int d)
2532 : Super(name, ArgInfoKind::Buffer, t, d) {
2533 internal_assert(!t.empty());
2534 internal_assert(d != -1);
2535 static_assert(!TBase::has_static_halide_type, "You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2536 static_assert(!TBase::has_static_dimensions, "You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2537 }
2538
2539 GeneratorOutput_Buffer(const std::string &name, const std::vector<Type> &t)
2540 : Super(name, ArgInfoKind::Buffer, t, -1) {
2541 internal_assert(!t.empty());
2542 static_assert(!TBase::has_static_halide_type, "You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2543 }
2544
2545 GeneratorOutput_Buffer(const std::string &name, int d)
2546 : Super(name, ArgInfoKind::Buffer,
2547 TBase::has_static_halide_type ? std::vector<Type>{TBase::static_halide_type()} : std::vector<Type>{},
2548 d) {
2549 internal_assert(d != -1);
2550 static_assert(!TBase::has_static_dimensions, "You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2551 }
2552
2553 GeneratorOutput_Buffer(size_t array_size, const std::string &name)
2554 : Super(array_size, name, ArgInfoKind::Buffer,
2555 TBase::has_static_halide_type ? std::vector<Type>{TBase::static_halide_type()} : std::vector<Type>{},
2556 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
2557 }
2558
2559 GeneratorOutput_Buffer(size_t array_size, const std::string &name, const std::vector<Type> &t, int d)
2560 : Super(array_size, name, ArgInfoKind::Buffer, t, d) {
2561 internal_assert(!t.empty());
2562 internal_assert(d != -1);
2563 static_assert(!TBase::has_static_halide_type, "You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2564 static_assert(!TBase::has_static_dimensions, "You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2565 }
2566
2567 GeneratorOutput_Buffer(size_t array_size, const std::string &name, const std::vector<Type> &t)
2568 : Super(array_size, name, ArgInfoKind::Buffer, t, -1) {
2569 internal_assert(!t.empty());
2570 static_assert(!TBase::has_static_halide_type, "You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2571 }
2572
2573 GeneratorOutput_Buffer(size_t array_size, const std::string &name, int d)
2574 : Super(array_size, name, ArgInfoKind::Buffer,
2575 TBase::has_static_halide_type ? std::vector<Type>{TBase::static_halide_type()} : std::vector<Type>{},
2576 d) {
2577 internal_assert(d != -1);
2578 static_assert(!TBase::has_static_dimensions, "You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2579 }
2580
2581 HALIDE_NO_USER_CODE_INLINE std::string get_c_type() const override {
2582 if (TBase::has_static_halide_type) {
2583 return "Halide::Internal::StubOutputBuffer<" +
2584 halide_type_to_c_type(TBase::static_halide_type()) +
2585 ">";
2586 } else {
2587 return "Halide::Internal::StubOutputBuffer<>";
2588 }
2589 }
2590
2591 template<typename T2, std::enable_if_t<!std::is_same_v<T2, Func>> * = nullptr>
2592 HALIDE_NO_USER_CODE_INLINE T2 as() const {
2593 return (T2) * this;
2594 }
2595
2596 public:
2597 // Allow assignment from a Buffer<> to an Output<Buffer<>>;
2598 // this allows us to use a statically-compiled buffer inside a Generator
2599 // to assign to an output.
2600 // TODO: This used to take the buffer as a const ref. This no longer works as
2601 // using it in a Pipeline might change the dev field so it is currently
2602 // not considered const. We should consider how this really ought to work.
2603 template<typename T2, int D2>
2604 HALIDE_NO_USER_CODE_INLINE GeneratorOutput_Buffer<T> &operator=(Buffer<T2, D2> &buffer) {
2605 this->check_gio_access();
2606 this->check_value_writable();
2607
2608 user_assert(T::can_convert_from(buffer))
2609 << "Cannot assign to the Output \"" << this->name()
2610 << "\": the expression is not convertible to the same Buffer type and/or dimensions.\n";
2611
2612 if (this->gio_types_defined()) {
2613 user_assert(Type(buffer.type()) == this->gio_type())
2614 << "Output " << this->name() << " should have type=" << this->gio_type() << " but saw type=" << Type(buffer.type()) << "\n";
2615 }
2616 if (this->dims_defined()) {
2617 user_assert(buffer.dimensions() == this->dims())
2618 << "Output " << this->name() << " should have dim=" << this->dims() << " but saw dim=" << buffer.dimensions() << "\n";
2619 }
2620
2621 internal_assert(this->exprs_.empty() && this->funcs_.size() == 1);
2622 user_assert(!this->funcs_.at(0).defined());
2623 this->funcs_.at(0)(_) = buffer(_);
2624
2625 return *this;
2626 }
2627
2628 // Allow assignment from a StubOutputBuffer to an Output<Buffer>;
2629 // this allows us to pipeline the results of a Stub to the results
2630 // of the enclosing Generator.
2631 template<typename T2>
2632 GeneratorOutput_Buffer<T> &operator=(const StubOutputBuffer<T2> &stub_output_buffer) {
2633 this->check_gio_access();
2634 assign_from_func(stub_output_buffer.f);
2635 return *this;
2636 }
2637
2638 // Allow assignment from a Func to an Output<Buffer>;
2639 // this allows us to use helper functions that return a plain Func
2640 // to simply set the output(s) without needing a wrapper Func.
2641 GeneratorOutput_Buffer<T> &operator=(const Func &f) {
2642 this->check_gio_access();
2643 assign_from_func(f);
2644 return *this;
2645 }
2646
2647 operator OutputImageParam() const {
2648 this->check_gio_access();
2649 user_assert(!this->is_array()) << "Cannot convert an Output<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->name();
2650 internal_assert(this->exprs_.empty() && this->funcs_.size() == 1);
2651 return this->funcs_.at(0).output_buffer();
2652 }
2653
2654 // Forward set_estimates() to Func (rather than OutputImageParam) so that it can
2655 // handle Tuple-valued outputs correctly.
2656 GeneratorOutput_Buffer<T> &set_estimates(const Region &estimates) {
2657 user_assert(!this->is_array()) << "Cannot call set_estimates() on an array Output; use an explicit subscript operator: " << this->name();
2658 internal_assert(this->exprs_.empty() && this->funcs_.size() == 1);
2659 this->funcs_.at(0).set_estimates(estimates);
2660 return *this;
2661 }
2662
2663 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2664 const Func &operator[](size_t i) const {
2665 this->check_gio_access();
2666 return this->template get_values<Func>()[i];
2667 }
2668
2669 // Allow Output<Buffer[]>.compute_root() (or other scheduling directive that requires nonconst)
2670 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2671 Func operator[](size_t i) {
2672 this->check_gio_access();
2673 return this->template get_values<Func>()[i];
2674 }
2675
2676 /** Forward methods to the OutputImageParam. */
2677 // @{
2678 HALIDE_FORWARD_METHOD(OutputImageParam, dim)
2679 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, dim)
2680 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, host_alignment)
2681 HALIDE_FORWARD_METHOD(OutputImageParam, set_host_alignment)
2682 HALIDE_FORWARD_METHOD(OutputImageParam, store_in)
2683 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, dimensions)
2684 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, left)
2685 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, right)
2686 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, top)
2687 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, bottom)
2688 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, width)
2689 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, height)
2690 HALIDE_FORWARD_METHOD_CONST(OutputImageParam, channels)
2691 // }@
2692};
2693
2694 template<typename T>
2695 class GeneratorOutput_Func : public GeneratorOutputImpl<T> {
2696 private:
2697 using Super = GeneratorOutputImpl<T>;
2698
2699 HALIDE_NO_USER_CODE_INLINE Func &get_assignable_func_ref(size_t i) {
2700 internal_assert(this->exprs_.empty() && this->funcs_.size() > i);
2701 return this->funcs_.at(i);
2702 }
2703
2704 protected:
2705 using TBase = typename Super::TBase;
2706
2707 explicit GeneratorOutput_Func(const std::string &name)
2708 : Super(name, ArgInfoKind::Function, std::vector<Type>{}, -1) {
2709 }
2710
2711 GeneratorOutput_Func(const std::string &name, const std::vector<Type> &t, int d)
2712 : Super(name, ArgInfoKind::Function, t, d) {
2713 }
2714
2715 GeneratorOutput_Func(const std::string &name, const std::vector<Type> &t)
2716 : Super(name, ArgInfoKind::Function, t, -1) {
2717 }
2718
2719 GeneratorOutput_Func(const std::string &name, int d)
2720 : Super(name, ArgInfoKind::Function, {}, d) {
2721 }
2722
2723 GeneratorOutput_Func(size_t array_size, const std::string &name, const std::vector<Type> &t, int d)
2724 : Super(array_size, name, ArgInfoKind::Function, t, d) {
2725 }
2726
2727 public:
2728 // Allow Output<Func> = Func
2729 template<typename T2 = T, std::enable_if_t<!std::is_array_v<T2>> * = nullptr>
2730 GeneratorOutput_Func<T> &operator=(const Func &f) {
2731 this->check_gio_access();
2732 this->check_value_writable();
2733
2734 // Don't bother verifying the Func type, dimensions, etc., here:
2735 // That's done later, when we produce the pipeline.
2736 get_assignable_func_ref(0) = f;
2737 return *this;
2738 }
2739
2740 // Allow Output<Func[]> = Func
2741 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2742 Func &operator[](size_t i) {
2743 this->check_gio_access();
2744 this->check_value_writable();
2745 return get_assignable_func_ref(i);
2746 }
2747
2748 // Allow Func = Output<Func[]>
2749 template<typename T2 = T, std::enable_if_t<std::is_array_v<T2>> * = nullptr>
2750 const Func &operator[](size_t i) const {
2751 this->check_gio_access();
2752 return Super::operator[](i);
2753 }
2754
2755 GeneratorOutput_Func<T> &set_estimate(const Var &var, const Expr &min, const Expr &extent) {
2756 this->check_gio_access();
2757 internal_assert(this->exprs_.empty() && !this->funcs_.empty());
2758 for (Func &f : this->funcs_) {
2759 f.set_estimate(var, min, extent);
2760 }
2761 return *this;
2762 }
2763
2764 GeneratorOutput_Func<T> &set_estimates(const Region &estimates) {
2765 this->check_gio_access();
2766 internal_assert(this->exprs_.empty() && !this->funcs_.empty());
2767 for (Func &f : this->funcs_) {
2768 f.set_estimates(estimates);
2769 }
2770 return *this;
2771 }
2772};
2773
2774 template<typename T>
2775 class GeneratorOutput_Arithmetic : public GeneratorOutputImpl<T> {
2776 private:
2777 using Super = GeneratorOutputImpl<T>;
2778
2779 protected:
2780 using TBase = typename Super::TBase;
2781
2782 explicit GeneratorOutput_Arithmetic(const std::string &name)
2783 : Super(name, ArgInfoKind::Function, {type_of<TBase>()}, 0) {
2784 }
2785
2786 GeneratorOutput_Arithmetic(size_t array_size, const std::string &name)
2787 : Super(array_size, name, ArgInfoKind::Function, {type_of<TBase>()}, 0) {
2788 }
2789};
2790
2791 template<typename T, typename TBase = std::remove_all_extents_t<T>>
2792 using GeneratorOutputImplBase =
2793 select_type_t<
2794 cond<has_static_halide_type_method_v<TBase>, GeneratorOutput_Buffer<T>>,
2795 cond<std::is_same_v<TBase, Func>, GeneratorOutput_Func<T>>,
2796 cond<std::is_arithmetic_v<TBase>, GeneratorOutput_Arithmetic<T>>>;
2797
2798} // namespace Internal
2799
2800 template<typename T>
2801 class GeneratorOutput : public Internal::GeneratorOutputImplBase<T> {
2802 private:
2803 using Super = Internal::GeneratorOutputImplBase<T>;
2804
2805 protected:
2806 using TBase = typename Super::TBase;
2807
2808 public:
2809 // Mark all of these explicit (not just single-arg versions) so that
2810 // we disallow copy-list-initialization form (i.e., Output foo{"foo"} is ok,
2811 // but Output foo = {"foo"} is not).
2812 explicit GeneratorOutput(const std::string &name)
2813 : Super(name) {
2814 }
2815
2816 explicit GeneratorOutput(const char *name)
2817 : GeneratorOutput(std::string(name)) {
2818 }
2819
2820 explicit GeneratorOutput(size_t array_size, const std::string &name)
2821 : Super(array_size, name) {
2822 }
2823
2824 explicit GeneratorOutput(const std::string &name, int d)
2825 : Super(name, d) {
2826 }
2827
2828 explicit GeneratorOutput(const std::string &name, const Type &t)
2829 : Super(name, {t}) {
2830 }
2831
2832 explicit GeneratorOutput(const std::string &name, const std::vector<Type> &t)
2833 : Super(name, t) {
2834 }
2835
2836 explicit GeneratorOutput(const std::string &name, const Type &t, int d)
2837 : Super(name, {t}, d) {
2838 }
2839
2840 explicit GeneratorOutput(const std::string &name, const std::vector<Type> &t, int d)
2841 : Super(name, t, d) {
2842 }
2843
2844 explicit GeneratorOutput(size_t array_size, const std::string &name, int d)
2845 : Super(array_size, name, d) {
2846 }
2847
2848 explicit GeneratorOutput(size_t array_size, const std::string &name, const Type &t)
2849 : Super(array_size, name, {t}) {
2850 }
2851
2852 explicit GeneratorOutput(size_t array_size, const std::string &name, const std::vector<Type> &t)
2853 : Super(array_size, name, t) {
2854 }
2855
2856 explicit GeneratorOutput(size_t array_size, const std::string &name, const Type &t, int d)
2857 : Super(array_size, name, {t}, d) {
2858 }
2859
2860 explicit GeneratorOutput(size_t array_size, const std::string &name, const std::vector<Type> &t, int d)
2861 : Super(array_size, name, t, d) {
2862 }
2863
2864 // TODO: This used to take the buffer as a const ref. This no longer works as
2865 // using it in a Pipeline might change the dev field so it is currently
2866 // not considered const. We should consider how this really ought to work.
2867 template<typename T2, int D2>
2868 GeneratorOutput<T> &operator=(Buffer<T2, D2> &buffer) {
2869 Super::operator=(buffer);
2870 return *this;
2871 }
2872
2873 template<typename T2>
2874 GeneratorOutput<T> &operator=(const Internal::StubOutputBuffer<T2> &stub_output_buffer) {
2875 Super::operator=(stub_output_buffer);
2876 return *this;
2877 }
2878
2879 GeneratorOutput<T> &operator=(const Func &f) {
2880 Super::operator=(f);
2881 return *this;
2882 }
2883};
2884
2885 namespace Internal {
2886
2887 template<typename T>
2888T parse_scalar(const std::string &value) {
2889 std::istringstream iss(value);
2890 T t;
2891 iss >> t;
2892 user_assert(!iss.fail() && iss.get() == EOF) << "Unable to parse: " << value;
2893 return t;
2894}
2895
2896std::vector<Type> parse_halide_type_list(const std::string &types);
2897
2898 enum class SyntheticParamType { Type,
2899 Dim,
2900 ArraySize };
2901
2902// This is a type of GeneratorParam used internally to create 'synthetic' params
2903// (e.g. image.type, image.dim); it is not possible for user code to instantiate it.
2904 template<typename T>
2905 class GeneratorParam_Synthetic : public GeneratorParamImpl<T> {
2906 public:
2907 void set_from_string(const std::string &new_value_string) override {
2908 // If error_msg is not empty, this is unsettable:
2909 // display error_msg as a user error.
2910 if (!error_msg.empty()) {
2911 user_error << error_msg;
2912 }
2913 set_from_string_impl<T>(new_value_string);
2914 }
2915
2916 std::string get_default_value() const override {
2917 internal_error;
2918 return std::string();
2919 }
2920
2921 std::string call_to_string(const std::string &v) const override {
2922 internal_error;
2923 return std::string();
2924 }
2925
2926 std::string get_c_type() const override {
2927 internal_error;
2928 return std::string();
2929 }
2930
2931 bool is_synthetic_param() const override {
2932 return true;
2933 }
2934
2935 private:
2936 friend class GeneratorParamInfo;
2937
2938 static std::unique_ptr<Internal::GeneratorParamBase> make(
2939 GeneratorBase *generator,
2940 const std::string &generator_name,
2941 const std::string &gpname,
2942 GIOBase &gio,
2943 SyntheticParamType which,
2944 bool defined) {
2945 std::string error_msg = defined ? "Cannot set the GeneratorParam " + gpname + " for " + generator_name + " because the value is explicitly specified in the C++ source." : "";
2946 return std::unique_ptr<GeneratorParam_Synthetic<T>>(
2947 new GeneratorParam_Synthetic<T>(gpname, gio, which, error_msg));
2948 }
2949
2950 GeneratorParam_Synthetic(const std::string &name, GIOBase &gio, SyntheticParamType which, const std::string &error_msg = "")
2951 : GeneratorParamImpl<T>(name, T()), gio(gio), which(which), error_msg(error_msg) {
2952 }
2953
2954 template<typename T2 = T, std::enable_if_t<std::is_same_v<T2, ::Halide::Type>> * = nullptr>
2955 void set_from_string_impl(const std::string &new_value_string) {
2956 internal_assert(which == SyntheticParamType::Type);
2957 gio.types_ = parse_halide_type_list(new_value_string);
2958 }
2959
2960 template<typename T2 = T, std::enable_if_t<std::is_integral_v<T2>> * = nullptr>
2961 void set_from_string_impl(const std::string &new_value_string) {
2962 if (which == SyntheticParamType::Dim) {
2963 gio.dims_ = parse_scalar<T2>(new_value_string);
2964 } else if (which == SyntheticParamType::ArraySize) {
2965 gio.array_size_ = parse_scalar<T2>(new_value_string);
2966 } else {
2967 internal_error;
2968 }
2969 }
2970
2971 GIOBase &gio;
2972 const SyntheticParamType which;
2973 const std::string error_msg;
2974};
2975
2976} // namespace Internal
2977
2978/** GeneratorContext is a class that is used when using Generators (or Stubs) directly;
2979 * it is used to allow the outer context (typically, either a Generator or "top-level" code)
2980 * to specify certain information to the inner context to ensure that inner and outer
2981 * Generators are compiled in a compatible way.
2982 *
2983 * If you are using this at "top level" (e.g. with the JIT), you can construct a GeneratorContext
2984 * with a Target:
2985 * \code
2986 * auto my_stub = MyStub(
2987 * GeneratorContext(get_target_from_environment()),
2988 * // inputs
2989 * { ... },
2990 * // generator params
2991 * { ... }
2992 * );
2993 * \endcode
2994 *
2995 * Note that all Generators embed a GeneratorContext, so if you are using a Stub
2996 * from within a Generator, you can just pass 'context()' for the GeneratorContext:
2997 * \code
2998 * struct SomeGen : Generator<SomeGen> {
2999 * void generate() {
3000 * ...
3001 * auto my_stub = MyStub(
3002 * context(), // GeneratorContext
3003 * // inputs
3004 * { ... },
3005 * // generator params
3006 * { ... }
3007 * );
3008 * ...
3009 * }
3010 * };
3011 * \endcode
3012 */
3013 class GeneratorContext {
3014 public:
3015 friend class Internal::GeneratorBase;
3016
3017 explicit GeneratorContext(const Target &t);
3018 explicit GeneratorContext(const Target &t,
3019 const AutoschedulerParams &autoscheduler_params);
3020
3021 GeneratorContext() = default;
3022 GeneratorContext(const GeneratorContext &) = default;
3023 GeneratorContext &operator=(const GeneratorContext &) = default;
3024 GeneratorContext(GeneratorContext &&) = default;
3025 GeneratorContext &operator=(GeneratorContext &&) = default;
3026
3027 const Target &target() const {
3028 return target_;
3029 }
3030 const AutoschedulerParams &autoscheduler_params() const {
3031 return autoscheduler_params_;
3032 }
3033
3034 // Return a copy of this GeneratorContext that uses the given Target.
3035 // This method is rarely needed; it's really provided as a convenience
3036 // for use with init_from_context().
3037 GeneratorContext with_target(const Target &t) const;
3038
3039 template<typename T>
3040 std::unique_ptr<T> create() const {
3041 return T::create(*this);
3042 }
3043 template<typename T, typename... Args>
3044 std::unique_ptr<T> apply(const Args &...args) const {
3045 auto t = this->create<T>();
3046 t->apply(args...);
3047 return t;
3048 }
3049
3050 private:
3051 Target target_;
3052 AutoschedulerParams autoscheduler_params_;
3053};
3054
3055 class NamesInterface {
3056 // Names in this class are only intended for use in derived classes.
3057 protected:
3058 // Import a consistent list of Halide names that can be used in
3059 // Halide generators without qualification.
3060 using Expr = Halide::Expr;
3061 using EvictionKey = Halide::EvictionKey;
3062 using ExternFuncArgument = Halide::ExternFuncArgument;
3063 using Func = Halide::Func;
3064 using GeneratorContext = Halide::GeneratorContext;
3065 using ImageParam = Halide::ImageParam;
3066 using LoopLevel = Halide::LoopLevel;
3067 using MemoryType = Halide::MemoryType;
3068 using NameMangling = Halide::NameMangling;
3069 using Partition = Halide::Partition;
3070 using Pipeline = Halide::Pipeline;
3071 using PrefetchBoundStrategy = Halide::PrefetchBoundStrategy;
3072 using RDom = Halide::RDom;
3073 using RVar = Halide::RVar;
3074 using TailStrategy = Halide::TailStrategy;
3075 using Target = Halide::Target;
3076 using Tuple = Halide::Tuple;
3077 using Type = Halide::Type;
3078 using Var = Halide::Var;
3079 template<typename T>
3080 static Expr cast(Expr e) {
3081 return Halide::cast<T>(e);
3082 }
3083 static Expr cast(Halide::Type t, Expr e) {
3084 return Halide::cast(t, std::move(e));
3085 }
3086 template<typename T>
3087 using GeneratorParam = Halide::GeneratorParam<T>;
3088 template<typename T = void, int D = -1>
3089 using Buffer = Halide::Buffer<T, D>;
3090 template<typename T>
3091 using Param = Halide::Param<T>;
3092 static Type Bool(int lanes = 1) {
3093 return Halide::Bool(lanes);
3094 }
3095 static Type Float(int bits, int lanes = 1) {
3096 return Halide::Float(bits, lanes);
3097 }
3098 static Type Int(int bits, int lanes = 1) {
3099 return Halide::Int(bits, lanes);
3100 }
3101 static Type UInt(int bits, int lanes = 1) {
3102 return Halide::UInt(bits, lanes);
3103 }
3104};
3105
3106 namespace Internal {
3107
3108 template<typename...>
3109 struct NoRealizations : std::false_type {};
3110
3111 template<>
3112 struct NoRealizations<> : std::true_type {};
3113
3114 template<typename T, typename... Args>
3115 struct NoRealizations<T, Args...> {
3116 static const bool value = !std::is_convertible_v<T, Realization> && NoRealizations<Args...>::value;
3117};
3118
3119 template<typename... Args>
3120 inline constexpr bool no_realizations_v = NoRealizations<Args...>::value;
3121
3122// Note that these functions must never return null:
3123// if they cannot return a valid Generator, they must assert-fail.
3124 using GeneratorFactory = std::function<AbstractGeneratorPtr(const GeneratorContext &context)>;
3125
3126 class GeneratorParamInfo {
3127 // names used across all params, inputs, and outputs.
3128 std::set<std::string> names;
3129
3130 // Ordered-list of non-null ptrs to GeneratorParam<> fields.
3131 std::vector<Internal::GeneratorParamBase *> filter_generator_params;
3132
3133 // Ordered-list of non-null ptrs to Input<> fields.
3134 std::vector<Internal::GeneratorInputBase *> filter_inputs;
3135
3136 // Ordered-list of non-null ptrs to Output<> fields; empty if old-style Generator.
3137 std::vector<Internal::GeneratorOutputBase *> filter_outputs;
3138
3139 // list of synthetic GP's that we dynamically created; this list only exists to simplify
3140 // lifetime management, and shouldn't be accessed directly outside of our ctor/dtor,
3141 // regardless of friend access.
3142 std::vector<std::unique_ptr<Internal::GeneratorParamBase>> owned_synthetic_params;
3143
3144 // list of dynamically-added inputs and outputs, here only for lifetime management.
3145 std::vector<std::unique_ptr<Internal::GIOBase>> owned_extras;
3146
3147 public:
3148 friend class GeneratorBase;
3149
3150 GeneratorParamInfo(GeneratorBase *generator, size_t size);
3151
3152 const std::vector<Internal::GeneratorParamBase *> &generator_params() const {
3153 return filter_generator_params;
3154 }
3155 const std::vector<Internal::GeneratorInputBase *> &inputs() const {
3156 return filter_inputs;
3157 }
3158 const std::vector<Internal::GeneratorOutputBase *> &outputs() const {
3159 return filter_outputs;
3160 }
3161};
3162
3163 class GeneratorBase : public NamesInterface, public AbstractGenerator {
3164 public:
3165 ~GeneratorBase() override;
3166
3167 /** Given a data type, return an estimate of the "natural" vector size
3168 * for that data type when compiling for the current target. */
3169 int natural_vector_size(Halide::Type t) const {
3170 return get_target().natural_vector_size(t);
3171 }
3172
3173 /** Given a data type, return an estimate of the "natural" vector size
3174 * for that data type when compiling for the current target. */
3175 template<typename data_t>
3176 int natural_vector_size() const {
3177 return get_target().natural_vector_size<data_t>();
3178 }
3179
3180 /**
3181 * set_inputs is a variadic wrapper around set_inputs_vector, which makes usage much simpler
3182 * in many cases, as it constructs the relevant entries for the vector for you, which
3183 * is often a bit unintuitive at present. The arguments are passed in Input<>-declaration-order,
3184 * and the types must be compatible. Array inputs are passed as std::vector<> of the relevant type.
3185 *
3186 * Note: at present, scalar input types must match *exactly*, i.e., for Input<uint8_t>, you
3187 * must pass an argument that is actually uint8_t; an argument that is int-that-will-fit-in-uint8
3188 * will assert-fail at Halide compile time.
3189 */
3190 template<typename... Args>
3191 void set_inputs(const Args &...args) {
3192 // set_inputs_vector() checks this too, but checking it here allows build_inputs() to avoid out-of-range checks.
3193 GeneratorParamInfo &pi = this->param_info();
3194 user_assert(sizeof...(args) == pi.inputs().size())
3195 << "Expected exactly " << pi.inputs().size()
3196 << " inputs but got " << sizeof...(args) << "\n";
3197 set_inputs_vector(build_inputs(std::forward_as_tuple<const Args &...>(args...), std::make_index_sequence<sizeof...(Args)>{}));
3198 }
3199
3200 Realization realize(std::vector<int32_t> sizes) {
3201 this->check_scheduled("realize");
3202 return get_pipeline().realize(std::move(sizes), get_target());
3203 }
3204
3205 // Only enable if none of the args are Realization; otherwise we can incorrectly
3206 // select this method instead of the Realization-as-outparam variant
3207 template<typename... Args, std::enable_if_t<no_realizations_v<Args...>> * = nullptr>
3208 Realization realize(Args &&...args) {
3209 this->check_scheduled("realize");
3210 return get_pipeline().realize(std::forward<Args>(args)..., get_target());
3211 }
3212
3213 void realize(Realization r) {
3214 this->check_scheduled("realize");
3215 get_pipeline().realize(r, get_target());
3216 }
3217
3218 // Return the Pipeline that has been built by the generate() method.
3219 // This method can only be called from the schedule() method.
3220 // (This may be relaxed in the future to allow calling from generate() as
3221 // long as all Outputs have been defined.)
3222 Pipeline get_pipeline();
3223
3224 protected:
3225 void claim_name(const std::string &name, const char *param_type) {
3226 user_assert(param_info_ptr->names.count(name) == 0)
3227 << "Cannot add " << param_type << " with name " << name
3228 << ". It is already taken by another input or output parameter.";
3229 param_info_ptr->names.insert(name);
3230 }
3231
3232 public:
3233 // Create Input<Func> with dynamic type & dimensions
3234 template<typename T,
3235 std::enable_if_t<std::is_same_v<T, Halide::Func>> * = nullptr>
3236 GeneratorInput<T> *add_input(const std::string &name, const Type &t, int dimensions) {
3237 check_exact_phase(GeneratorBase::ConfigureCalled);
3238 claim_name(name, "input");
3239 auto *p = new GeneratorInput<T>(name, t, dimensions);
3240 p->generator = this;
3241 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3242 param_info_ptr->filter_inputs.push_back(p);
3243 return p;
3244 }
3245
3246 // Create Input<Buffer> with dynamic type & dimensions
3247 template<typename T,
3248 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * = nullptr>
3249 GeneratorInput<T> *add_input(const std::string &name, const Type &t, int dimensions) {
3250 static_assert(!T::has_static_halide_type, "You can only call this version of add_input() for a Buffer<T, D> where T is void or omitted .");
3251 static_assert(!T::has_static_dimensions, "You can only call this version of add_input() for a Buffer<T, D> where D is -1 or omitted.");
3252 check_exact_phase(GeneratorBase::ConfigureCalled);
3253 claim_name(name, "input");
3254 auto *p = new GeneratorInput<T>(name, t, dimensions);
3255 p->generator = this;
3256 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3257 param_info_ptr->filter_inputs.push_back(p);
3258 return p;
3259 }
3260
3261 // Create Input<Buffer> with compile-time type
3262 template<typename T,
3263 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * = nullptr>
3264 GeneratorInput<T> *add_input(const std::string &name, int dimensions) {
3265 static_assert(T::has_static_halide_type, "You can only call this version of add_input() for a Buffer<T, D> where T is not void.");
3266 static_assert(!T::has_static_dimensions, "You can only call this version of add_input() for a Buffer<T, D> where D is -1 or omitted.");
3267 check_exact_phase(GeneratorBase::ConfigureCalled);
3268 claim_name(name, "input");
3269 auto *p = new GeneratorInput<T>(name, dimensions);
3270 p->generator = this;
3271 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3272 param_info_ptr->filter_inputs.push_back(p);
3273 return p;
3274 }
3275
3276 // Create Input<Buffer> with compile-time type & dimensions
3277 template<typename T,
3278 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * = nullptr>
3279 GeneratorInput<T> *add_input(const std::string &name) {
3280 static_assert(T::has_static_halide_type, "You can only call this version of add_input() for a Buffer<T, D> where T is not void.");
3281 static_assert(T::has_static_dimensions, "You can only call this version of add_input() for a Buffer<T, D> where D is not -1.");
3282 check_exact_phase(GeneratorBase::ConfigureCalled);
3283 claim_name(name, "input");
3284 auto *p = new GeneratorInput<T>(name);
3285 p->generator = this;
3286 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3287 param_info_ptr->filter_inputs.push_back(p);
3288 return p;
3289 }
3290 // Create Input<scalar>
3291 template<typename T,
3292 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
3293 GeneratorInput<T> *add_input(const std::string &name) {
3294 check_exact_phase(GeneratorBase::ConfigureCalled);
3295 claim_name(name, "input");
3296 auto *p = new GeneratorInput<T>(name);
3297 p->generator = this;
3298 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3299 param_info_ptr->filter_inputs.push_back(p);
3300 return p;
3301 }
3302 // Create Input<Expr> with dynamic type
3303 template<typename T,
3304 std::enable_if_t<std::is_same_v<T, Expr>> * = nullptr>
3305 GeneratorInput<T> *add_input(const std::string &name, const Type &type) {
3306 check_exact_phase(GeneratorBase::ConfigureCalled);
3307 claim_name(name, "input");
3308 auto *p = new GeneratorInput<Expr>(name);
3309 p->generator = this;
3310 p->set_type(type);
3311 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3312 param_info_ptr->filter_inputs.push_back(p);
3313 return p;
3314 }
3315
3316 // Create Output<Func> with dynamic type & dimensions
3317 template<typename T,
3318 std::enable_if_t<std::is_same_v<T, Halide::Func>> * = nullptr>
3319 GeneratorOutput<T> *add_output(const std::string &name, const std::vector<Type> &t, int dimensions) {
3320 check_exact_phase(GeneratorBase::ConfigureCalled);
3321 claim_name(name, "output");
3322 auto *p = new GeneratorOutput<T>(name, t, dimensions);
3323 p->generator = this;
3324 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3325 param_info_ptr->filter_outputs.push_back(p);
3326 return p;
3327 }
3328
3329 template<typename T,
3330 std::enable_if_t<std::is_same_v<T, Halide::Func>> * = nullptr>
3331 GeneratorOutput<T> *add_output(const std::string &name, const Type &t, int dimensions) {
3332 return add_output<T>(name, std::vector<Type>{t}, dimensions);
3333 }
3334
3335 // Create Output<Buffer> with dynamic type & dimensions
3336 template<typename T,
3337 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * = nullptr>
3338 GeneratorOutput<T> *add_output(const std::string &name, const std::vector<Type> &t, int dimensions) {
3339 static_assert(!T::has_static_halide_type, "You can only call this version of add_output() for a Buffer<T, D> where T is void or omitted .");
3340 static_assert(!T::has_static_dimensions, "You can only call this version of add_output() for a Buffer<T, D> where D is -1 or omitted.");
3341 check_exact_phase(GeneratorBase::ConfigureCalled);
3342 claim_name(name, "output");
3343 auto *p = new GeneratorOutput<T>(name, t, dimensions);
3344 p->generator = this;
3345 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3346 param_info_ptr->filter_outputs.push_back(p);
3347 return p;
3348 }
3349
3350 template<typename T,
3351 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * = nullptr>
3352 GeneratorOutput<T> *add_output(const std::string &name, const Type &t, int dimensions) {
3353 return add_output<T>(name, std::vector<Type>{t}, dimensions);
3354 }
3355
3356 // Create Output<Buffer> with either a compile-time type or a
3357 // to-be-set-later type and dynamic dimensions
3358 template<typename T,
3359 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * = nullptr>
3360 GeneratorOutput<T> *add_output(const std::string &name, int dimensions) {
3361 static_assert(!T::has_static_dimensions, "You can only call this version of add_output() for a Buffer<T, D> where D is -1 or omitted.");
3362 check_exact_phase(GeneratorBase::ConfigureCalled);
3363 claim_name(name, "output");
3364 auto *p = new GeneratorOutput<T>(name, dimensions);
3365 p->generator = this;
3366 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3367 param_info_ptr->filter_outputs.push_back(p);
3368 return p;
3369 }
3370
3371 // Create Output<Buffer> with compile-time dimensions and dynamic type
3372 template<typename T,
3373 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * = nullptr>
3374 GeneratorOutput<T> *add_output(const std::string &name, const std::vector<Type> &t) {
3375 static_assert(!T::has_static_halide_type, "You can only call this version of add_output() for a Buffer<T, D> where T is void or omitted.");
3376 static_assert(T::has_static_dimensions, "You can only call this version of add_output() for a Buffer<void, D> where D is not -1.");
3377 check_exact_phase(GeneratorBase::ConfigureCalled);
3378 claim_name(name, "output");
3379 auto *p = new GeneratorOutput<T>(name, t);
3380 p->generator = this;
3381 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3382 param_info_ptr->filter_outputs.push_back(p);
3383 return p;
3384 }
3385
3386 template<typename T,
3387 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * = nullptr>
3388 GeneratorOutput<T> *add_output(const std::string &name, const Type &t) {
3389 return add_output<T>(name, std::vector<Type>{t});
3390 }
3391
3392 // Create Output<Buffer> with compile-time type and dimensions
3393 template<typename T,
3394 std::enable_if_t<!std::is_arithmetic_v<T> && !std::is_same_v<T, Halide::Func>> * = nullptr>
3395 GeneratorOutput<T> *add_output(const std::string &name) {
3396 static_assert(T::has_static_halide_type, "You can only call this version of add_output() for a Buffer<T, D> where T is not void.");
3397 static_assert(T::has_static_dimensions, "You can only call this version of add_output() for a Buffer<T, D> where D is not -1.");
3398 check_exact_phase(GeneratorBase::ConfigureCalled);
3399 claim_name(name, "output");
3400 auto *p = new GeneratorOutput<T>(name);
3401 p->generator = this;
3402 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3403 param_info_ptr->filter_outputs.push_back(p);
3404 return p;
3405 }
3406
3407 void add_requirement(const Expr &condition, const std::vector<Expr> &error_args);
3408
3409 template<typename... Args,
3410 typename = std::enable_if_t<all_are_printable_args_v<Args...>>>
3411 HALIDE_NO_USER_CODE_INLINE void add_requirement(const Expr &condition, Args &&...error_args) {
3412 std::vector<Expr> collected_args;
3413 Internal::collect_print_args(collected_args, std::forward<Args>(error_args)...);
3414 add_requirement(condition, collected_args);
3415 }
3416
3417 void trace_pipeline() {
3418 get_pipeline().trace_pipeline();
3419 }
3420
3421 protected:
3422 GeneratorBase(size_t size);
3423 void set_generator_names(const std::string &registered_name, const std::string &stub_name);
3424
3425 // Note that it is explicitly legal to override init_from_context(), so that you can (say)
3426 // create a modified context with a different Target (eg with features enabled or disabled), but...
3427 //
3428 // *** WARNING ***
3429 //
3430 // Modifying the context here can be fraught with subtle hazards, especially when used
3431 // in conjunction with compiling to multitarget output. Adding or removing Feature
3432 // flags could break your build (if you are lucky), or cause subtle runtime failures (if unlucky)...
3433 //
3434 // e.g. in the latter case, say you decided to enable AVX512_SapphireRapids as an experiment,
3435 // and override init_from_context() to do just that. You'd end up being crashy on pre-AVX512
3436 // hardware, because the code that Halide injects to do runtime CPU feature detection at runtime
3437 // doesn't know it needs to do the runtime detection for this flag.
3438 //
3439 // Even if you are using multitarget output, using this as a 'hook' to enable or disable Features
3440 // can produce hard-to-maintain code in the long term: Halide has dozens of feature flags now,
3441 // many of which are orthogonal to each other and/or specific to a certain architecture
3442 // (or sub-architecture). The interaction between 'orthogonal' flags like this is essentially
3443 // Undefined Behavior (e.g. if I enable the SSE41 Feature on a Target where arch = RISCV, what happens?
3444 // Is it ignored? Does it fail to compile? Something else?). The point here is that adding Features
3445 // here may end up eventually getting added to a Target you didn't anticipate and have adverse consequences.
3446 //
3447 // With all that in mind, here are some guidelines we think will make long-term code maintenance
3448 // less painful for you:
3449 //
3450 // - Override this method *only* for temporary debugging purposes; e.g. if you
3451 // need to add the `profile` feature to a specific Generator, but your build system doesn't easily
3452 // let you specify per-Generator target features, this is the right tool for the job.
3453 //
3454 // - If your build system makes it infeasible to customize the build Target in a reasonable way,
3455 // it may be appropriate to permanently override this method to enable specific Features for
3456 // specific Generators (e.g., enabling `strict_float` is a likely example). In that case,
3457 // we would suggest:
3458 //
3459 // - *NEVER* change the arch/bits/os of the Target.
3460 // - Only add Features; don't remove Features.
3461 // - For Features that are architecture-specific, always check the arch/bits/os
3462 // of the Target to be sure it's what you expect... e.g. if you are enabling
3463 // AVX512, only do so if compiling for an x86-64 Target. Even if your code
3464 // doesn't target any other architecture at the present time, Future You will be
3465 // happier.
3466 // - If you mutate a target conditionally based on the incoming target, try to do so
3467 // so based only on the Target's arch/bits/os, and not at the Features set on the target.
3468 // If examining Features is unavoidable (e.g. enable $FOO only if $BAR is enabled),
3469 // do so as conservatively as possible, and always validate that the rest of the Target
3470 // is sensible for what you are doing.
3471 //
3472 // Furthermore, if you override this, please don't try to directly set the `target` (etc) GeneratorParams
3473 // directly; instead, construct the new GeneratorContext you want and call the superclass
3474 // implementation of init_from_context.
3475 //
3476 // TL;DR: overrides to this method should probably never be checked in to your source control system
3477 // (rather, the override should be temporary and local, for experimentation). If you must check in
3478 // overrides to this method, be paranoid that the Target you get could be something you don't expect.
3479 //
3480 virtual void init_from_context(const Halide::GeneratorContext &context);
3481
3482 virtual void call_configure() = 0;
3483 virtual void call_generate() = 0;
3484 virtual void call_schedule() = 0;
3485
3486 void pre_build();
3487 void post_build();
3488 void pre_configure();
3489 void post_configure();
3490 void pre_generate();
3491 void post_generate();
3492 void pre_schedule();
3493 void post_schedule();
3494
3495 template<typename T>
3496 using Input = GeneratorInput<T>;
3497
3498 template<typename T>
3499 using Output = GeneratorOutput<T>;
3500
3501 // A Generator's creation and usage must go in a certain phase to ensure correctness;
3502 // the state machine here is advanced and checked at various points to ensure
3503 // this is the case.
3504 enum Phase {
3505 // Generator has just come into being.
3506 Created,
3507
3508 // Generator has had its configure() method called. (For Generators without
3509 // a configure() method, this phase will be skipped and will advance
3510 // directly to InputsSet.)
3511 ConfigureCalled,
3512
3513 // All Input<>/Param<> fields have been set. (Applicable only in JIT mode;
3514 // in AOT mode, this can be skipped, going Created->GenerateCalled directly.)
3515 InputsSet,
3516
3517 // Generator has had its generate() method called.
3518 GenerateCalled,
3519
3520 // Generator has had its schedule() method (if any) called.
3521 ScheduleCalled,
3522 } phase{Created};
3523
3524 void check_exact_phase(Phase expected_phase) const;
3525 void check_min_phase(Phase expected_phase) const;
3526 void advance_phase(Phase new_phase);
3527
3528 void ensure_configure_has_been_called();
3529
3530 Target get_target() const {
3531 return target;
3532 }
3533 bool using_autoscheduler() const {
3534 return !autoscheduler_.value().name.empty();
3535 }
3536
3537 // These must remain here for legacy code that access the fields directly.
3538 GeneratorParam<Target> target{"target", Target()};
3539 GeneratorParam_AutoSchedulerParams autoscheduler_;
3540
3541 private:
3542 friend void ::Halide::Internal::generator_test();
3543 friend class GeneratorParamBase;
3544 friend class GIOBase;
3545 friend class GeneratorInputBase;
3546 friend class GeneratorOutputBase;
3547 friend class GeneratorParamInfo;
3548 friend class StubOutputBufferBase;
3549
3550 const size_t size;
3551
3552 // Lazily-allocated-and-inited struct with info about our various Params.
3553 // Do not access directly: use the param_info() getter.
3554 std::unique_ptr<GeneratorParamInfo> param_info_ptr;
3555
3556 std::string generator_registered_name, generator_stub_name;
3557 Pipeline pipeline;
3558
3559 struct Requirement {
3560 Expr condition;
3561 std::vector<Expr> error_args;
3562 };
3563 std::vector<Requirement> requirements;
3564
3565 // Return our GeneratorParamInfo.
3566 GeneratorParamInfo &param_info();
3567
3568 template<typename T>
3569 T *find_by_name(const std::string &name, const std::vector<T *> &v) {
3570 for (T *t : v) {
3571 if (t->name() == name) {
3572 return t;
3573 }
3574 }
3575 return nullptr;
3576 }
3577
3578 Internal::GeneratorInputBase *find_input_by_name(const std::string &name);
3579 Internal::GeneratorOutputBase *find_output_by_name(const std::string &name);
3580
3581 void check_scheduled(const char *m) const;
3582
3583 void build_params(bool force = false);
3584
3585 // Provide private, unimplemented, wrong-result-type methods here
3586 // so that Generators don't attempt to call the global methods
3587 // of the same name by accident: use the get_target() method instead.
3588 void get_host_target();
3589 void get_jit_target_from_environment();
3590 void get_target_from_environment();
3591
3592 void set_inputs_vector(const std::vector<std::vector<StubInput>> &inputs);
3593
3594 static void check_input_is_singular(Internal::GeneratorInputBase *in);
3595 static void check_input_is_array(Internal::GeneratorInputBase *in);
3596 static void check_input_kind(Internal::GeneratorInputBase *in, Internal::ArgInfoKind kind);
3597
3598 // Allow Buffer<> if:
3599 // -- we are assigning it to an Input<Buffer<>> (with compatible type and dimensions),
3600 // causing the Input<Buffer<>> to become a precompiled buffer in the generated code.
3601 // -- we are assigningit to an Input<Func>, in which case we just Func-wrap the Buffer<>.
3602 template<typename T, int Dims>
3603 std::vector<StubInput> build_input(size_t i, const Buffer<T, Dims> &arg) {
3604 auto *in = param_info().inputs().at(i);
3605 check_input_is_singular(in);
3606 const auto k = in->kind();
3607 if (k == Internal::ArgInfoKind::Buffer) {
3608 Halide::Buffer<> b = arg;
3609 StubInputBuffer<> sib(b);
3610 StubInput si(sib);
3611 return {si};
3612 } else if (k == Internal::ArgInfoKind::Function) {
3613 Halide::Func f(arg.name() + "_im");
3614 f(Halide::_) = arg(Halide::_);
3615 StubInput si(f);
3616 return {si};
3617 } else {
3618 check_input_kind(in, Internal::ArgInfoKind::Buffer); // just to trigger assertion
3619 return {};
3620 }
3621 }
3622
3623 // Allow Input<Buffer<>> if:
3624 // -- we are assigning it to another Input<Buffer<>> (with compatible type and dimensions),
3625 // allowing us to simply pipe a parameter from an enclosing Generator to the Invoker.
3626 // -- we are assigningit to an Input<Func>, in which case we just Func-wrap the Input<Buffer<>>.
3627 template<typename T, int Dims>
3628 std::vector<StubInput> build_input(size_t i, const GeneratorInput<Buffer<T, Dims>> &arg) {
3629 auto *in = param_info().inputs().at(i);
3630 check_input_is_singular(in);
3631 const auto k = in->kind();
3632 if (k == Internal::ArgInfoKind::Buffer) {
3633 StubInputBuffer<> sib = arg;
3634 StubInput si(sib);
3635 return {si};
3636 } else if (k == Internal::ArgInfoKind::Function) {
3637 Halide::Func f = arg.funcs().at(0);
3638 StubInput si(f);
3639 return {si};
3640 } else {
3641 check_input_kind(in, Internal::ArgInfoKind::Buffer); // just to trigger assertion
3642 return {};
3643 }
3644 }
3645
3646 // Allow Func iff we are assigning it to an Input<Func> (with compatible type and dimensions).
3647 std::vector<StubInput> build_input(size_t i, const Func &arg) {
3648 auto *in = param_info().inputs().at(i);
3649 check_input_kind(in, Internal::ArgInfoKind::Function);
3650 check_input_is_singular(in);
3651 const Halide::Func &f = arg;
3652 StubInput si(f);
3653 return {si};
3654 }
3655
3656 // Allow vector<Func> iff we are assigning it to an Input<Func[]> (with compatible type and dimensions).
3657 std::vector<StubInput> build_input(size_t i, const std::vector<Func> &arg) {
3658 auto *in = param_info().inputs().at(i);
3659 check_input_kind(in, Internal::ArgInfoKind::Function);
3660 check_input_is_array(in);
3661 // My kingdom for a list comprehension...
3662 std::vector<StubInput> siv;
3663 siv.reserve(arg.size());
3664 for (const auto &f : arg) {
3665 siv.emplace_back(f);
3666 }
3667 return siv;
3668 }
3669
3670 // Expr must be Input<Scalar>.
3671 std::vector<StubInput> build_input(size_t i, const Expr &arg) {
3672 auto *in = param_info().inputs().at(i);
3673 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3674 check_input_is_singular(in);
3675 StubInput si(arg);
3676 return {si};
3677 }
3678
3679 // (Array form)
3680 std::vector<StubInput> build_input(size_t i, const std::vector<Expr> &arg) {
3681 auto *in = param_info().inputs().at(i);
3682 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3683 check_input_is_array(in);
3684 std::vector<StubInput> siv;
3685 siv.reserve(arg.size());
3686 for (const auto &value : arg) {
3687 siv.emplace_back(value);
3688 }
3689 return siv;
3690 }
3691
3692 // Any other type must be convertible to Expr and must be associated with an Input<Scalar>.
3693 // Use is_arithmetic since some Expr conversions are explicit.
3694 template<typename T,
3695 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
3696 std::vector<StubInput> build_input(size_t i, const T &arg) {
3697 auto *in = param_info().inputs().at(i);
3698 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3699 check_input_is_singular(in);
3700 // We must use an explicit Expr() ctor to preserve the type
3701 Expr e(arg);
3702 StubInput si(e);
3703 return {si};
3704 }
3705
3706 // (Array form)
3707 template<typename T, std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
3708 std::vector<StubInput> build_input(size_t i, const std::vector<T> &arg) {
3709 auto *in = param_info().inputs().at(i);
3710 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3711 check_input_is_array(in);
3712 std::vector<StubInput> siv;
3713 siv.reserve(arg.size());
3714 for (const auto &value : arg) {
3715 // We must use an explicit Expr() ctor to preserve the type;
3716 // otherwise, implicit conversions can downgrade (e.g.) float -> int
3717 Expr e(value);
3718 siv.emplace_back(e);
3719 }
3720 return siv;
3721 }
3722
3723 template<typename... Args, size_t... Indices>
3724 std::vector<std::vector<StubInput>> build_inputs(const std::tuple<const Args &...> &t, std::index_sequence<Indices...>) {
3725 return {build_input(Indices, std::get<Indices>(t))...};
3726 }
3727
3728 // Note that this deliberately ignores inputs/outputs with multiple array values
3729 // (ie, one name per input or output, regardless of array_size())
3730 template<typename T>
3731 static void get_arguments(std::vector<AbstractGenerator::ArgInfo> &args, ArgInfoDirection dir, const T &t) {
3732 for (auto *e : t) {
3733 args.push_back({e->name(),
3734 dir,
3735 e->kind(),
3736 e->gio_types_defined() ? e->gio_types() : std::vector<Type>{},
3737 e->dims_defined() ? e->dims() : 0});
3738 }
3739 }
3740
3741 public:
3742 // AbstractGenerator methods
3743 std::string name() override;
3744 GeneratorContext context() const override;
3745 std::vector<ArgInfo> arginfos() override;
3746 bool allow_out_of_order_inputs_and_outputs() const override;
3747
3748 void set_generatorparam_value(const std::string &name, const std::string &value) override;
3749 void set_generatorparam_value(const std::string &name, const LoopLevel &loop_level) override;
3750
3751 std::vector<Parameter> input_parameter(const std::string &name) override;
3752 std::vector<Func> output_func(const std::string &name) override;
3753
3754 // This is overridden in the concrete Generator<> subclass.
3755 // Pipeline build_pipeline() override;
3756
3757 void bind_input(const std::string &name, const std::vector<Parameter> &v) override;
3758 void bind_input(const std::string &name, const std::vector<Func> &v) override;
3759 void bind_input(const std::string &name, const std::vector<Expr> &v) override;
3760
3761 bool emit_cpp_stub(const std::string &stub_file_path) override;
3762 bool emit_hlpipe(const std::string &hlpipe_file_path) override;
3763
3764 GeneratorBase(const GeneratorBase &) = delete;
3765 GeneratorBase &operator=(const GeneratorBase &) = delete;
3766 GeneratorBase(GeneratorBase &&that) = delete;
3767 GeneratorBase &operator=(GeneratorBase &&that) = delete;
3768};
3769
3770 class GeneratorRegistry {
3771 public:
3772 static void register_factory(const std::string &name, GeneratorFactory generator_factory);
3773 static void unregister_factory(const std::string &name);
3774 static std::vector<std::string> enumerate();
3775 // This method returns nullptr if it cannot return a valid Generator;
3776 // the caller is responsible for checking the result.
3777 static AbstractGeneratorPtr create(const std::string &name,
3778 const Halide::GeneratorContext &context);
3779
3780 private:
3781 using GeneratorFactoryMap = std::map<const std::string, GeneratorFactory>;
3782
3783 GeneratorFactoryMap factories;
3784 std::mutex mutex;
3785
3786 static GeneratorRegistry &get_registry();
3787
3788 GeneratorRegistry() = default;
3789
3790 public:
3791 GeneratorRegistry(const GeneratorRegistry &) = delete;
3792 GeneratorRegistry &operator=(const GeneratorRegistry &) = delete;
3793 GeneratorRegistry(GeneratorRegistry &&that) = delete;
3794 GeneratorRegistry &operator=(GeneratorRegistry &&that) = delete;
3795};
3796
3797} // namespace Internal
3798
3799 template<class T>
3800 class Generator : public Internal::GeneratorBase {
3801 protected:
3802 Generator()
3803 : Internal::GeneratorBase(sizeof(T)) {
3804 }
3805
3806 public:
3807 static std::unique_ptr<T> create(const Halide::GeneratorContext &context) {
3808 // We must have an object of type T (not merely GeneratorBase) to call a protected method,
3809 // because CRTP is a weird beast.
3810 auto g = std::make_unique<T>();
3811 g->init_from_context(context);
3812 return g;
3813 }
3814
3815 // This is public but intended only for use by the HALIDE_REGISTER_GENERATOR() macro.
3816 static std::unique_ptr<T> create(const Halide::GeneratorContext &context,
3817 const std::string &registered_name,
3818 const std::string &stub_name) {
3819 auto g = create(context);
3820 g->set_generator_names(registered_name, stub_name);
3821 return g;
3822 }
3823
3824 template<typename... Args>
3825 void apply(const Args &...args) {
3826 call_configure();
3827 set_inputs(args...);
3828 call_generate();
3829 call_schedule();
3830 }
3831
3832 template<typename T2>
3833 std::unique_ptr<T2> create() const {
3834 return T2::create(context());
3835 }
3836
3837 template<typename T2, typename... Args>
3838 std::unique_ptr<T2> apply(const Args &...args) const {
3839 auto t = this->create<T2>();
3840 t->apply(args...);
3841 return t;
3842 }
3843
3844 private:
3845 // std::is_member_function_pointer will fail if there is no member of that name,
3846 // so we use a little SFINAE to detect if there are method-shaped members.
3847 template<typename>
3848 using type_sink_t = void;
3849
3850 template<typename T2, typename = void>
3851 struct has_configure_method : std::false_type {};
3852
3853 template<typename T2>
3854 struct has_configure_method<T2, type_sink_t<decltype(std::declval<T2>().configure())>> : std::true_type {};
3855
3856 template<typename T2>
3857 static constexpr bool has_configure_method_v = has_configure_method<T2>::value;
3858
3859 template<typename T2, typename = void>
3860 struct has_generate_method : std::false_type {};
3861
3862 template<typename T2>
3863 struct has_generate_method<T2, type_sink_t<decltype(std::declval<T2>().generate())>> : std::true_type {};
3864
3865 template<typename T2>
3866 static constexpr bool has_generate_method_v = has_generate_method<T2>::value;
3867
3868 template<typename T2, typename = void>
3869 struct has_schedule_method : std::false_type {};
3870
3871 template<typename T2>
3872 struct has_schedule_method<T2, type_sink_t<decltype(std::declval<T2>().schedule())>> : std::true_type {};
3873
3874 template<typename T2>
3875 static constexpr bool has_schedule_method_v = has_schedule_method<T2>::value;
3876
3877 Pipeline build_pipeline_impl() {
3878 T *t = (T *)this;
3879 // No: configure() must be called prior to this
3880 // (and in fact, prior to calling set_inputs).
3881 //
3882 // t->call_configure_impl();
3883
3884 t->call_generate_impl();
3885 t->call_schedule_impl();
3886 return get_pipeline();
3887 }
3888
3889 void call_configure_impl() {
3890 pre_configure();
3891 if constexpr (has_configure_method_v<T>) {
3892 T *t = (T *)this;
3893 static_assert(std::is_void_v<decltype(t->configure())>, "configure() must return void");
3894 t->configure();
3895 }
3896 post_configure();
3897 }
3898
3899 void call_generate_impl() {
3900 pre_generate();
3901 static_assert(has_generate_method_v<T>, "Expected a generate() method here.");
3902 T *t = (T *)this;
3903 static_assert(std::is_void_v<decltype(t->generate())>, "generate() must return void");
3904 t->generate();
3905 post_generate();
3906 }
3907
3908 void call_schedule_impl() {
3909 pre_schedule();
3910 if constexpr (has_schedule_method_v<T>) {
3911 T *t = (T *)this;
3912 static_assert(std::is_void_v<decltype(t->schedule())>, "schedule() must return void");
3913 t->schedule();
3914 }
3915 post_schedule();
3916 }
3917
3918 protected:
3919 Pipeline build_pipeline() override {
3920 ensure_configure_has_been_called();
3921 return this->build_pipeline_impl();
3922 }
3923
3924 void call_configure() override {
3925 this->call_configure_impl();
3926 }
3927
3928 void call_generate() override {
3929 this->call_generate_impl();
3930 }
3931
3932 void call_schedule() override {
3933 this->call_schedule_impl();
3934 }
3935
3936 private:
3937 friend void ::Halide::Internal::generator_test();
3938 friend void ::Halide::Internal::generator_test();
3939 friend class ::Halide::GeneratorContext;
3940
3941 public:
3942 Generator(const Generator &) = delete;
3943 Generator &operator=(const Generator &) = delete;
3944 Generator(Generator &&that) = delete;
3945 Generator &operator=(Generator &&that) = delete;
3946};
3947
3948 namespace Internal {
3949
3950 class RegisterGenerator {
3951 public:
3952 RegisterGenerator(const char *registered_name, GeneratorFactory generator_factory);
3953};
3954
3955// -----------------------------
3956
3957/** ExecuteGeneratorArgs is the set of arguments to execute_generator().
3958 */
3959 struct ExecuteGeneratorArgs {
3960 // Output directory for all files generated. Must not be empty.
3961 std::string output_dir;
3962
3963 // Type(s) of outputs to produce. Must not be empty.
3964 std::set<OutputFileType> output_types;
3965
3966 // Target(s) to use when generating. Must not be empty.
3967 // If list contains multiple entries, a multitarget output will be produced.
3968 std::vector<Target> targets;
3969
3970 // When generating multitarget output, use these as the suffixes for each Target
3971 // specified by the targets field. If empty, the canonical string form of
3972 // each Target will be used. If nonempty, it must be the same length as the
3973 // targets vector.
3974 std::vector<std::string> suffixes;
3975
3976 // Name of the generator to execute (or empty if none, e.g. if generating a runtime)
3977 // Must be one recognized by the specified GeneratorFactoryProvider.
3978 std::string generator_name;
3979
3980 // Name to use for the generated function. May include C++ namespaces,
3981 // e.g. "HalideTest::AnotherNamespace::cxx_mangling". If empty, use `generator_name`.
3982 std::string function_name;
3983
3984 // Base filename for all outputs (differentated by file extension).
3985 // If empty, use `function_name` (ignoring any C++ namespaces).
3986 std::string file_base_name;
3987
3988 // The name of a standalone runtime to generate. Only honors EMIT_OPTIONS 'o'
3989 // and 'static_library'. When multiple targets are specified, it picks a
3990 // runtime that is compatible with all of the targets, or fails if it cannot
3991 // find one. Flags across all of the targets that do not affect runtime code
3992 // generation, such as `no_asserts` and `no_runtime`, are ignored.
3993 std::string runtime_name;
3994
3995 // The mode in which to build the Generator.
3996 enum BuildMode {
3997 // Build it as written.
3998 Default,
3999
4000 // Build a version suitable for using for gradient descent calculation.
4001 Gradient,
4002 } build_mode = Default;
4003
4004 // The fn that will produce Generator(s) from the name specified.
4005 // (Note that `generator_name` is the only value that will ever be passed
4006 // for name here; it is provided for ease of interoperation with existing code.)
4007 //
4008 // If null, the default global registry of Generators will be used.
4009 using CreateGeneratorFn = std::function<AbstractGeneratorPtr(const std::string &name, const GeneratorContext &context)>;
4010 CreateGeneratorFn create_generator = nullptr;
4011
4012 // Values to substitute for GeneratorParams in the selected Generator.
4013 // Should not contain `target`.
4014 //
4015 // If any of the generator param names specified in this map are unknown
4016 // to the Generator created, an error will occur.
4017 GeneratorParamsMap generator_params;
4018
4019 // Compiler Logger to use, for diagnostic work. If null, don't do any logging.
4020 CompilerLoggerFactory compiler_logger_factory = nullptr;
4021
4022 // If true, log the path of all output files to stdout.
4023 bool log_outputs = false;
4024};
4025
4026/**
4027 * Execute a Generator for AOT compilation -- this provides the implementation of
4028 * the command-line Generator interface `generate_filter_main()`, but with a structured
4029 * API that is more suitable for calling directly from code (vs command line).
4030 */
4031 void execute_generator(const ExecuteGeneratorArgs &args);
4032
4033// -----------------------------
4034
4035} // namespace Internal
4036
4037/** Create a Generator from the currently-registered Generators, use it to create a Callable.
4038 * Any GeneratorParams specified will be applied to the Generator before compilation.
4039 * If the name isn't registered, assert-fail. */
4040// @{
4041 Callable create_callable_from_generator(const GeneratorContext &context,
4042 const std::string &name,
4043 const GeneratorParamsMap &generator_params = {});
4044 Callable create_callable_from_generator(const Target &target,
4045 const std::string &name,
4046 const GeneratorParamsMap &generator_params = {});
4047// @}
4048
4049} // namespace Halide
4050
4051// Define this namespace at global scope so that anonymous namespaces won't
4052// defeat our static_assert check; define a dummy type inside so we can
4053// check for type aliasing injected by anonymous namespace usage
4054 namespace halide_register_generator {
4055 struct halide_global_ns;
4056};
4057
4058#define _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
4059 namespace halide_register_generator { \
4060 struct halide_global_ns; \
4061 namespace GEN_REGISTRY_NAME##_ns { \
4062 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4063 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
4064 using GenType = std::remove_pointer_t<decltype(new GEN_CLASS_NAME)>; /* NOLINT(bugprone-macro-parentheses) */ \
4065 return GenType::create(context, #GEN_REGISTRY_NAME, #FULLY_QUALIFIED_STUB_NAME); \
4066 } \
4067 } \
4068 namespace { \
4069 auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
4070 } \
4071 } \
4072 static_assert(std::is_same_v<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>, \
4073 "HALIDE_REGISTER_GENERATOR must be used at global scope");
4074
4075#define _HALIDE_REGISTER_GENERATOR2(GEN_CLASS_NAME, GEN_REGISTRY_NAME) \
4076 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME)
4077
4078#define _HALIDE_REGISTER_GENERATOR3(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
4079 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)
4080
4081// MSVC has a broken implementation of variadic macros: it expands __VA_ARGS__
4082// as a single token in argument lists (rather than multiple tokens).
4083// Jump through some hoops to work around this.
4084#define __HALIDE_REGISTER_ARGCOUNT_IMPL(_1, _2, _3, COUNT, ...) \
4085 COUNT
4086
4087#define _HALIDE_REGISTER_ARGCOUNT_IMPL(ARGS) \
4088 __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS
4089
4090#define _HALIDE_REGISTER_ARGCOUNT(...) \
4091 _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0))
4092
4093#define ___HALIDE_REGISTER_CHOOSER(COUNT) \
4094 _HALIDE_REGISTER_GENERATOR##COUNT
4095
4096#define __HALIDE_REGISTER_CHOOSER(COUNT) \
4097 ___HALIDE_REGISTER_CHOOSER(COUNT)
4098
4099#define _HALIDE_REGISTER_CHOOSER(COUNT) \
4100 __HALIDE_REGISTER_CHOOSER(COUNT)
4101
4102#define _HALIDE_REGISTER_GENERATOR_PASTE(A, B) \
4103 A B
4104
4105#define HALIDE_REGISTER_GENERATOR(...) \
4106 _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__))
4107
4108// HALIDE_REGISTER_GENERATOR_ALIAS() can be used to create an an alias-with-a-particular-set-of-param-values
4109// for a given Generator in the build system. Normally, you wouldn't want to do this;
4110// however, some existing Halide clients have build systems that make it challenging to
4111// specify GeneratorParams inside the build system, and this allows a somewhat simpler
4112// customization route for them. It's highly recommended you don't use this for new code.
4113//
4114// The final argument is really an initializer-list of GeneratorParams, in the form
4115// of an initializer-list for map<string, string>:
4116//
4117// { { "gp-name", "gp-value"} [, { "gp2-name", "gp2-value" }] }
4118//
4119// It is specified as a variadic template argument to allow for the fact that the embedded commas
4120// would otherwise confuse the preprocessor; since (in this case) all we're going to do is
4121// pass it thru as-is, this is fine (and even MSVC's 'broken' __VA_ARGS__ should be OK here).
4122#define HALIDE_REGISTER_GENERATOR_ALIAS(GEN_REGISTRY_NAME, ORIGINAL_REGISTRY_NAME, ...) \
4123 namespace halide_register_generator { \
4124 struct halide_global_ns; \
4125 namespace ORIGINAL_REGISTRY_NAME##_ns { \
4126 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4127 } \
4128 namespace GEN_REGISTRY_NAME##_ns { \
4129 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
4130 auto g = ORIGINAL_REGISTRY_NAME##_ns::factory(context); \
4131 const Halide::GeneratorParamsMap m = __VA_ARGS__; \
4132 g->set_generatorparam_values(m); \
4133 return g; \
4134 } \
4135 } \
4136 namespace { \
4137 auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
4138 } \
4139 } \
4140 static_assert(std::is_same_v<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>, \
4141 "HALIDE_REGISTER_GENERATOR_ALIAS must be used at global scope");
4142
4143// The HALIDE_GENERATOR_PYSTUB macro is used to produce "PyStubs" -- i.e., CPython wrappers to let a C++ Generator
4144// be called from Python. It shouldn't be necessary to use by anything but the build system in most cases.
4145
4146#define HALIDE_GENERATOR_PYSTUB(GEN_REGISTRY_NAME, MODULE_NAME) \
4147 static_assert(PY_MAJOR_VERSION >= 3, "Python bindings for Halide require Python 3+"); \
4148 extern "C" PyObject *_halide_pystub_impl(const char *module_name, const Halide::Internal::GeneratorFactory &factory); \
4149 namespace halide_register_generator::GEN_REGISTRY_NAME##_ns { \
4150 extern std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4151 } \
4152 extern "C" HALIDE_EXPORT_SYMBOL PyObject *PyInit_##MODULE_NAME() { \
4153 const auto factory = halide_register_generator::GEN_REGISTRY_NAME##_ns::factory; \
4154 return _halide_pystub_impl(#MODULE_NAME, factory); \
4155 }
4156
4157#endif // HALIDE_GENERATOR_H_
AbstractGenerator.h
internal_error
#define internal_error
Definition: Error.h:229
user_error
#define user_error
Definition: Error.h:228
internal_assert
#define internal_assert(c)
Definition: Error.h:232
user_assert
#define user_assert(c)
Definition: Error.h:233
Func.h
Defines Func - the front-end handle on a halide function, and related classes.
HALIDE_GENERATOR_PARAM_TYPED_SETTER
#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE)
Definition: Generator.h:527
HALIDE_FORWARD_METHOD
#define HALIDE_FORWARD_METHOD(Class, Method)
Definition: Generator.h:1651
HALIDE_FORWARD_METHOD_CONST
#define HALIDE_FORWARD_METHOD_CONST(Class, Method)
Definition: Generator.h:1657
HALIDE_ALWAYS_INLINE
#define HALIDE_ALWAYS_INLINE
Definition: HalideRuntime.h:49
ImageParam.h
Classes for declaring image parameters to halide pipelines.
ObjectInstanceRegistry.h
Provides a single global registry of Generators, GeneratorParams, and Params indexed by this pointer.
Target.h
Defines the structure that describes a Halide target.
HALIDE_NO_USER_CODE_INLINE
#define HALIDE_NO_USER_CODE_INLINE
Definition: Util.h:47
Halide::Buffer<>
Halide::Buffer::type
Type type() const
Definition: Buffer.h:534
Halide::Buffer::defined
bool defined() const
Check if this Buffer refers to an existing Buffer.
Definition: Buffer.h:380
Halide::Callable
Definition: Callable.h:82
Halide::EvictionKey
Helper class for identifying purpose of an Expr passed to memoize.
Definition: Func.h:713
Halide::Func
A halide function.
Definition: Func.h:728
Halide::Func::defined
bool defined() const
Does this function have at least a pure definition.
Halide::Func::dimensions
int dimensions() const
The dimensionality (number of arguments) of this function.
Halide::Func::types
const std::vector< Type > & types() const
Halide::Func::realize
Realization realize(std::vector< int32_t > sizes={}, const Target &target=Target())
Evaluate this function over some rectangular domain and return the resulting buffer or buffers.
Halide::Func::name
const std::string & name() const
The name of this function, either given during construction, or automatically generated.
Halide::Func::in
Func in(const Func &f)
Creates and returns a new identity Func that wraps this Func.
Halide::FuncRef
A fragment of front-end syntax of the form f(x, y, z), where x, y, z are Vars or Exprs.
Definition: Func.h:502
Halide::GeneratorContext
GeneratorContext is a class that is used when using Generators (or Stubs) directly; it is used to all...
Definition: Generator.h:3013
Halide::GeneratorContext::with_target
GeneratorContext with_target(const Target &t) const
Halide::GeneratorContext::GeneratorContext
GeneratorContext(const Target &t)
Halide::GeneratorContext::apply
std::unique_ptr< T > apply(const Args &...args) const
Definition: Generator.h:3044
Halide::GeneratorContext::create
std::unique_ptr< T > create() const
Definition: Generator.h:3040
Halide::GeneratorContext::operator=
GeneratorContext & operator=(GeneratorContext &&)=default
Halide::GeneratorContext::operator=
GeneratorContext & operator=(const GeneratorContext &)=default
Halide::GeneratorContext::target
const Target & target() const
Definition: Generator.h:3027
Halide::GeneratorContext::GeneratorContext
GeneratorContext(const Target &t, const AutoschedulerParams &autoscheduler_params)
Halide::GeneratorContext::GeneratorContext
GeneratorContext()=default
Halide::GeneratorContext::GeneratorContext
GeneratorContext(const GeneratorContext &)=default
Halide::GeneratorContext::autoscheduler_params
const AutoschedulerParams & autoscheduler_params() const
Definition: Generator.h:3030
Halide::GeneratorContext::GeneratorContext
GeneratorContext(GeneratorContext &&)=default
Halide::Generator
Definition: Generator.h:3800
Halide::Generator::call_generate
void call_generate() override
Definition: Generator.h:3928
Halide::Generator::Generator
Generator(Generator &&that)=delete
Halide::Generator::create
static std::unique_ptr< T > create(const Halide::GeneratorContext &context, const std::string &registered_name, const std::string &stub_name)
Definition: Generator.h:3816
Halide::Generator::call_schedule
void call_schedule() override
Definition: Generator.h:3932
Halide::Generator::apply
std::unique_ptr< T2 > apply(const Args &...args) const
Definition: Generator.h:3838
Halide::Generator::create
static std::unique_ptr< T > create(const Halide::GeneratorContext &context)
Definition: Generator.h:3807
Halide::Generator::operator=
Generator & operator=(Generator &&that)=delete
Halide::Generator::Generator
Generator()
Definition: Generator.h:3802
Halide::Generator::operator=
Generator & operator=(const Generator &)=delete
Halide::Generator::apply
void apply(const Args &...args)
Definition: Generator.h:3825
Halide::Generator::call_configure
void call_configure() override
Definition: Generator.h:3924
Halide::Generator::create
std::unique_ptr< T2 > create() const
Definition: Generator.h:3833
Halide::Generator::build_pipeline
Pipeline build_pipeline() override
Build and return the Pipeline for this AbstractGenerator.
Definition: Generator.h:3919
Halide::Generator::Generator
Generator(const Generator &)=delete
Halide::GeneratorInput
Definition: Generator.h:2187
Halide::GeneratorInput::GeneratorInput
GeneratorInput(size_t array_size, const std::string &name, const Type &t)
Definition: Generator.h:2247
Halide::GeneratorInput::GeneratorInput
GeneratorInput(const std::string &name, const TBase &def)
Definition: Generator.h:2212
Halide::GeneratorInput::GeneratorInput
GeneratorInput(const std::string &name, const TBase &def, const TBase &min, const TBase &max)
Definition: Generator.h:2220
Halide::GeneratorInput::TBase
typename Super::TBase TBase
Definition: Generator.h:2192
Halide::GeneratorInput::IntIfNonScalar
Internal::select_type_t< Internal::cond< Internal::has_static_halide_type_method_v< TBase >, int >, Internal::cond< std::is_same_v< TBase, Func >, int >, Internal::cond< true, Unused > > IntIfNonScalar
Definition: Generator.h:2202
Halide::GeneratorInput::GeneratorInput
GeneratorInput(size_t array_size, const std::string &name, const TBase &def, const TBase &min, const TBase &max)
Definition: Generator.h:2225
Halide::GeneratorInput::GeneratorInput
GeneratorInput(size_t array_size, const std::string &name, IntIfNonScalar d)
Definition: Generator.h:2253
Halide::GeneratorInput::GeneratorInput
GeneratorInput(const std::string &name, const Type &t)
Definition: Generator.h:2234
Halide::GeneratorInput::GeneratorInput
GeneratorInput(size_t array_size, const std::string &name)
Definition: Generator.h:2257
Halide::GeneratorInput::GeneratorInput
GeneratorInput(size_t array_size, const std::string &name, const Type &t, int d)
Definition: Generator.h:2243
Halide::GeneratorInput::GeneratorInput
GeneratorInput(const std::string &name)
Definition: Generator.h:2208
Halide::GeneratorInput::GeneratorInput
GeneratorInput(const std::string &name, const Type &t, int d)
Definition: Generator.h:2230
Halide::GeneratorInput::GeneratorInput
GeneratorInput(size_t array_size, const std::string &name, const TBase &def)
Definition: Generator.h:2216
Halide::GeneratorInput::GeneratorInput
GeneratorInput(const std::string &name, IntIfNonScalar d)
Definition: Generator.h:2239
Halide::GeneratorOutput
Definition: Generator.h:2801
Halide::GeneratorOutput::TBase
typename Super::TBase TBase
Definition: Generator.h:2806
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(const std::string &name)
Definition: Generator.h:2812
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(const std::string &name, const std::vector< Type > &t, int d)
Definition: Generator.h:2840
Halide::GeneratorOutput::operator=
GeneratorOutput< T > & operator=(const Internal::StubOutputBuffer< T2 > &stub_output_buffer)
Definition: Generator.h:2874
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(const char *name)
Definition: Generator.h:2816
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(const std::string &name, const std::vector< Type > &t)
Definition: Generator.h:2832
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(size_t array_size, const std::string &name, int d)
Definition: Generator.h:2844
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(size_t array_size, const std::string &name, const Type &t, int d)
Definition: Generator.h:2856
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(const std::string &name, const Type &t, int d)
Definition: Generator.h:2836
Halide::GeneratorOutput::operator=
GeneratorOutput< T > & operator=(Buffer< T2, D2 > &buffer)
Definition: Generator.h:2868
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
Definition: Generator.h:2860
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(const std::string &name, int d)
Definition: Generator.h:2824
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(size_t array_size, const std::string &name)
Definition: Generator.h:2820
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(const std::string &name, const Type &t)
Definition: Generator.h:2828
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(size_t array_size, const std::string &name, const std::vector< Type > &t)
Definition: Generator.h:2852
Halide::GeneratorOutput::GeneratorOutput
GeneratorOutput(size_t array_size, const std::string &name, const Type &t)
Definition: Generator.h:2848
Halide::GeneratorOutput::operator=
GeneratorOutput< T > & operator=(const Func &f)
Definition: Generator.h:2879
Halide::GeneratorParam
GeneratorParam is a templated class that can be used to modify the behavior of the Generator at code-...
Definition: Generator.h:990
Halide::GeneratorParam::GeneratorParam
GeneratorParam(const std::string &name, const std::string &value)
Definition: Generator.h:1005
Halide::GeneratorParam::GeneratorParam
GeneratorParam(const std::string &name, const T &value, const T &min, const T &max)
Definition: Generator.h:997
Halide::GeneratorParam::GeneratorParam
GeneratorParam(const std::string &name, const T &value)
Definition: Generator.h:993
Halide::GeneratorParam::GeneratorParam
GeneratorParam(const std::string &name, const T &value, const std::map< std::string, T > &enum_map)
Definition: Generator.h:1001
Halide::ImageParam
An Image parameter to a halide pipeline.
Definition: ImageParam.h:23
Halide::Internal::AbstractGenerator
AbstractGenerator is an ABC that defines the API a Generator must provide to work with the existing G...
Definition: AbstractGenerator.h:56
Halide::Internal::Function
A reference-counted handle to Halide's internal representation of a function.
Definition: Function.h:39
Halide::Internal::GIOBase
GIOBase is the base class for all GeneratorInput<> and GeneratorOutput<> instantiations; it is not pa...
Definition: Generator.h:1444
Halide::Internal::GIOBase::array_size_
int array_size_
Definition: Generator.h:1481
Halide::Internal::GIOBase::name
const std::string & name() const
Halide::Internal::GIOBase::operator=
GIOBase & operator=(const GIOBase &)=delete
Halide::Internal::GIOBase::array_size
size_t array_size() const
Halide::Internal::GIOBase::input_or_output
virtual const char * input_or_output() const =0
Halide::Internal::GIOBase::GIOBase
GIOBase(size_t array_size, const std::string &name, ArgInfoKind kind, const std::vector< Type > &types, int dims)
Halide::Internal::GIOBase::check_matching_dims
void check_matching_dims(int d) const
Halide::Internal::GIOBase::kind
ArgInfoKind kind() const
Halide::Internal::GIOBase::array_size_defined
bool array_size_defined() const
Halide::Internal::GIOBase::gio_types
const std::vector< Type > & gio_types() const
Halide::Internal::GIOBase::dims_defined
bool dims_defined() const
Halide::Internal::GIOBase::operator=
GIOBase & operator=(GIOBase &&)=delete
Halide::Internal::GIOBase::funcs
const std::vector< Func > & funcs() const
Halide::Internal::GIOBase::gio_type
Type gio_type() const
Halide::Internal::GIOBase::types_
std::vector< Type > types_
Definition: Generator.h:1486
Halide::Internal::GIOBase::check_matching_types
void check_matching_types(const std::vector< Type > &t) const
Halide::Internal::GIOBase::array_name
std::string array_name(size_t i) const
Halide::Internal::GIOBase::check_value_writable
virtual void check_value_writable() const =0
Halide::Internal::GIOBase::GIOBase
GIOBase(const GIOBase &)=delete
Halide::Internal::GIOBase::check_matching_array_size
void check_matching_array_size(size_t size) const
Halide::Internal::GIOBase::GeneratorStub
friend class GeneratorStub
Definition: Generator.h:1520
Halide::Internal::GIOBase::GIOBase
GIOBase(GIOBase &&)=delete
Halide::Internal::GIOBase::check_gio_access
void check_gio_access() const
Halide::Internal::GIOBase::set_dimensions
void set_dimensions(int dims)
Halide::Internal::GIOBase::set_array_size
void set_array_size(int size)
Halide::Internal::GIOBase::funcs_
std::vector< Func > funcs_
Definition: Generator.h:1490
Halide::Internal::GIOBase::name_
const std::string name_
Definition: Generator.h:1484
Halide::Internal::GIOBase::kind_
const ArgInfoKind kind_
Definition: Generator.h:1485
Halide::Internal::GIOBase::is_array
virtual bool is_array() const
Halide::Internal::GIOBase::verify_internals
virtual void verify_internals()
Halide::Internal::GIOBase::~GIOBase
virtual ~GIOBase()=default
Halide::Internal::GIOBase::exprs_
std::vector< Expr > exprs_
Definition: Generator.h:1491
Halide::Internal::GIOBase::set_type
void set_type(const Type &type)
Halide::Internal::GIOBase::dims_
int dims_
Definition: Generator.h:1487
Halide::Internal::GIOBase::gio_types_defined
bool gio_types_defined() const
Halide::Internal::GIOBase::generator
GeneratorBase * generator
Definition: Generator.h:1498
Halide::Internal::GIOBase::exprs
const std::vector< Expr > & exprs() const
Halide::Internal::GIOBase::dims
int dims() const
Halide::Internal::GIOBase::get_values
const std::vector< ElemType > & get_values() const
Halide::Internal::GeneratorBase
Definition: Generator.h:3163
Halide::Internal::GeneratorBase::context
GeneratorContext context() const override
Return the Target and autoscheduler info that this Generator was created with.
Halide::Internal::GeneratorBase::ensure_configure_has_been_called
void ensure_configure_has_been_called()
Halide::Internal::GeneratorBase::name
std::string name() override
Return the name of this Generator.
Halide::Internal::GeneratorBase::StubOutputBufferBase
friend class StubOutputBufferBase
Definition: Generator.h:3548
Halide::Internal::GeneratorBase::call_schedule
virtual void call_schedule()=0
Halide::Internal::GeneratorBase::allow_out_of_order_inputs_and_outputs
bool allow_out_of_order_inputs_and_outputs() const override
By default, a Generator must declare all Inputs before all Outputs.
Halide::Internal::GeneratorBase::target
GeneratorParam< Target > target
Definition: Generator.h:3538
Halide::Internal::GeneratorBase::get_pipeline
Pipeline get_pipeline()
Halide::Internal::GeneratorBase::bind_input
void bind_input(const std::string &name, const std::vector< Parameter > &v) override
Rebind a specified Input to refer to the given piece of IR, replacing the default ImageParam / Param ...
Halide::Internal::GeneratorBase::add_input
GeneratorInput< T > * add_input(const std::string &name)
Definition: Generator.h:3279
Halide::Internal::GeneratorBase::output_func
std::vector< Func > output_func(const std::string &name) override
Given the name of an output, return the Func(s) for that output.
Halide::Internal::GeneratorBase::claim_name
void claim_name(const std::string &name, const char *param_type)
Definition: Generator.h:3225
Halide::Internal::GeneratorBase::input_parameter
std::vector< Parameter > input_parameter(const std::string &name) override
Given the name of an input, return the Parameter(s) for that input.
Halide::Internal::GeneratorBase::bind_input
void bind_input(const std::string &name, const std::vector< Func > &v) override
Halide::Internal::GeneratorBase::bind_input
void bind_input(const std::string &name, const std::vector< Expr > &v) override
Halide::Internal::GeneratorBase::emit_hlpipe
bool emit_hlpipe(const std::string &hlpipe_file_path) override
Emit a Serialized Halide Pipeline (.hlpipe) file to the given path.
Halide::Internal::GeneratorBase::realize
Realization realize(Args &&...args)
Definition: Generator.h:3208
Halide::Internal::GeneratorBase::GeneratorBase
GeneratorBase(const GeneratorBase &)=delete
Halide::Internal::GeneratorBase::call_generate
virtual void call_generate()=0
Halide::Internal::GeneratorBase::add_output
GeneratorOutput< T > * add_output(const std::string &name)
Definition: Generator.h:3395
Halide::Internal::GeneratorBase::GeneratorBase
GeneratorBase(size_t size)
Halide::Internal::GeneratorBase::natural_vector_size
int natural_vector_size() const
Given a data type, return an estimate of the "natural" vector size for that data type when compiling ...
Definition: Generator.h:3176
Halide::Internal::GeneratorBase::GeneratorInputBase
friend class GeneratorInputBase
Definition: Generator.h:3545
Halide::Internal::GeneratorBase::get_target
Target get_target() const
Definition: Generator.h:3530
Halide::Internal::GeneratorBase::~GeneratorBase
~GeneratorBase() override
Halide::Internal::GeneratorBase::init_from_context
virtual void init_from_context(const Halide::GeneratorContext &context)
Halide::Internal::GeneratorBase::pre_schedule
void pre_schedule()
Halide::Internal::GeneratorBase::pre_generate
void pre_generate()
Halide::Internal::GeneratorBase::add_output
GeneratorOutput< T > * add_output(const std::string &name, const Type &t)
Definition: Generator.h:3388
Halide::Internal::GeneratorBase::check_exact_phase
void check_exact_phase(Phase expected_phase) const
Halide::Internal::GeneratorBase::post_configure
void post_configure()
Halide::Internal::GeneratorBase::set_generatorparam_value
void set_generatorparam_value(const std::string &name, const LoopLevel &loop_level) override
Halide::Internal::GeneratorBase::check_min_phase
void check_min_phase(Phase expected_phase) const
Halide::Internal::GeneratorBase::post_schedule
void post_schedule()
Halide::Internal::GeneratorBase::realize
void realize(Realization r)
Definition: Generator.h:3213
Halide::Internal::GeneratorBase::post_generate
void post_generate()
Halide::Internal::GeneratorBase::Created
enum Halide::Internal::GeneratorBase::Phase Created
Halide::Internal::GeneratorBase::set_generator_names
void set_generator_names(const std::string &registered_name, const std::string &stub_name)
Halide::Internal::GeneratorBase::Phase
Phase
Definition: Generator.h:3504
Halide::Internal::GeneratorBase::GenerateCalled
@ GenerateCalled
Definition: Generator.h:3518
Halide::Internal::GeneratorBase::ConfigureCalled
@ ConfigureCalled
Definition: Generator.h:3511
Halide::Internal::GeneratorBase::InputsSet
@ InputsSet
Definition: Generator.h:3515
Halide::Internal::GeneratorBase::Created
@ Created
Definition: Generator.h:3506
Halide::Internal::GeneratorBase::ScheduleCalled
@ ScheduleCalled
Definition: Generator.h:3521
Halide::Internal::GeneratorBase::realize
Realization realize(std::vector< int32_t > sizes)
Definition: Generator.h:3200
Halide::Internal::GeneratorBase::add_input
GeneratorInput< T > * add_input(const std::string &name, int dimensions)
Definition: Generator.h:3264
Halide::Internal::GeneratorBase::arginfos
std::vector< ArgInfo > arginfos() override
Return a list of all the ArgInfos for this generator.
Halide::Internal::GeneratorBase::call_configure
virtual void call_configure()=0
Halide::Internal::GeneratorBase::trace_pipeline
void trace_pipeline()
Definition: Generator.h:3417
Halide::Internal::GeneratorBase::add_input
GeneratorInput< T > * add_input(const std::string &name, const Type &type)
Definition: Generator.h:3305
Halide::Internal::GeneratorBase::set_generatorparam_value
void set_generatorparam_value(const std::string &name, const std::string &value) override
Set the value for a specific GeneratorParam for an AbstractGenerator instance.
Halide::Internal::GeneratorBase::GeneratorBase
GeneratorBase(GeneratorBase &&that)=delete
Halide::Internal::GeneratorBase::add_output
GeneratorOutput< T > * add_output(const std::string &name, int dimensions)
Definition: Generator.h:3360
Halide::Internal::GeneratorBase::using_autoscheduler
bool using_autoscheduler() const
Definition: Generator.h:3533
Halide::Internal::GeneratorBase::GeneratorParamBase
friend class GeneratorParamBase
Definition: Generator.h:3543
Halide::Internal::GeneratorBase::emit_cpp_stub
bool emit_cpp_stub(const std::string &stub_file_path) override
Emit a Generator Stub (.stub.h) file to the given path.
Halide::Internal::GeneratorBase::GeneratorParamInfo
friend class GeneratorParamInfo
Definition: Generator.h:3547
Halide::Internal::GeneratorBase::pre_build
void pre_build()
Halide::Internal::GeneratorBase::add_output
GeneratorOutput< T > * add_output(const std::string &name, const std::vector< Type > &t, int dimensions)
Definition: Generator.h:3319
Halide::Internal::GeneratorBase::post_build
void post_build()
Halide::Internal::GeneratorBase::GIOBase
friend class GIOBase
Definition: Generator.h:3544
Halide::Internal::GeneratorBase::add_output
GeneratorOutput< T > * add_output(const std::string &name, const std::vector< Type > &t)
Definition: Generator.h:3374
Halide::Internal::GeneratorBase::operator=
GeneratorBase & operator=(const GeneratorBase &)=delete
Halide::Internal::GeneratorBase::operator=
GeneratorBase & operator=(GeneratorBase &&that)=delete
Halide::Internal::GeneratorBase::pre_configure
void pre_configure()
Halide::Internal::GeneratorBase::set_inputs
void set_inputs(const Args &...args)
set_inputs is a variadic wrapper around set_inputs_vector, which makes usage much simpler in many cas...
Definition: Generator.h:3191
Halide::Internal::GeneratorBase::autoscheduler_
GeneratorParam_AutoSchedulerParams autoscheduler_
Definition: Generator.h:3539
Halide::Internal::GeneratorBase::add_requirement
HALIDE_NO_USER_CODE_INLINE void add_requirement(const Expr &condition, Args &&...error_args)
Definition: Generator.h:3411
Halide::Internal::GeneratorBase::add_input
GeneratorInput< T > * add_input(const std::string &name, const Type &t, int dimensions)
Definition: Generator.h:3236
Halide::Internal::GeneratorBase::add_requirement
void add_requirement(const Expr &condition, const std::vector< Expr > &error_args)
Halide::Internal::GeneratorBase::natural_vector_size
int natural_vector_size(Halide::Type t) const
Given a data type, return an estimate of the "natural" vector size for that data type when compiling ...
Definition: Generator.h:3169
Halide::Internal::GeneratorBase::advance_phase
void advance_phase(Phase new_phase)
Halide::Internal::GeneratorBase::add_output
GeneratorOutput< T > * add_output(const std::string &name, const Type &t, int dimensions)
Definition: Generator.h:3331
Halide::Internal::GeneratorBase::GeneratorOutputBase
friend class GeneratorOutputBase
Definition: Generator.h:3546
Halide::Internal::GeneratorFactoryProvider
GeneratorFactoryProvider provides a way to customize the Generators that are visible to generate_filt...
Definition: Generator.h:330
Halide::Internal::GeneratorFactoryProvider::create
virtual AbstractGeneratorPtr create(const std::string &name, const Halide::GeneratorContext &context) const =0
Create an instance of the Generator that is registered under the given name.
Halide::Internal::GeneratorFactoryProvider::GeneratorFactoryProvider
GeneratorFactoryProvider(const GeneratorFactoryProvider &)=delete
Halide::Internal::GeneratorFactoryProvider::GeneratorFactoryProvider
GeneratorFactoryProvider()=default
Halide::Internal::GeneratorFactoryProvider::operator=
GeneratorFactoryProvider & operator=(GeneratorFactoryProvider &&)=delete
Halide::Internal::GeneratorFactoryProvider::GeneratorFactoryProvider
GeneratorFactoryProvider(GeneratorFactoryProvider &&)=delete
Halide::Internal::GeneratorFactoryProvider::operator=
GeneratorFactoryProvider & operator=(const GeneratorFactoryProvider &)=delete
Halide::Internal::GeneratorFactoryProvider::enumerate
virtual std::vector< std::string > enumerate() const =0
Return a list of all registered Generators that are available for use with the create() method.
Halide::Internal::GeneratorFactoryProvider::~GeneratorFactoryProvider
virtual ~GeneratorFactoryProvider()=default
Halide::Internal::GeneratorInput_Arithmetic
Definition: Generator.h:2102
Halide::Internal::GeneratorInput_Arithmetic::GeneratorInput_Arithmetic
GeneratorInput_Arithmetic(size_t array_size, const std::string &name)
Definition: Generator.h:2136
Halide::Internal::GeneratorInput_Arithmetic::GeneratorInput_Arithmetic
GeneratorInput_Arithmetic(const std::string &name, const TBase &def, const TBase &min, const TBase &max)
Definition: Generator.h:2147
Halide::Internal::GeneratorInput_Arithmetic::set_def_min_max
void set_def_min_max() override
Definition: Generator.h:2111
Halide::Internal::GeneratorInput_Arithmetic::max_
const Expr max_
Definition: Generator.h:2109
Halide::Internal::GeneratorInput_Arithmetic::GeneratorInput_Arithmetic
GeneratorInput_Arithmetic(size_t array_size, const std::string &name, const TBase &def)
Definition: Generator.h:2141
Halide::Internal::GeneratorInput_Arithmetic::min_
const Expr min_
Definition: Generator.h:2109
Halide::Internal::GeneratorInput_Arithmetic::GeneratorInput_Arithmetic
GeneratorInput_Arithmetic(const std::string &name)
Definition: Generator.h:2127
Halide::Internal::GeneratorInput_Arithmetic::GeneratorInput_Arithmetic
GeneratorInput_Arithmetic(size_t array_size, const std::string &name, const TBase &def, const TBase &min, const TBase &max)
Definition: Generator.h:2154
Halide::Internal::GeneratorInput_Arithmetic::GeneratorInput_Arithmetic
GeneratorInput_Arithmetic(const std::string &name, const TBase &def)
Definition: Generator.h:2131
Halide::Internal::GeneratorInput_Buffer
Definition: Generator.h:1665
Halide::Internal::GeneratorInput_Buffer::in
Func in(const Func &other)
Definition: Generator.h:1759
Halide::Internal::GeneratorInput_Buffer::get_c_type
std::string get_c_type() const override
Definition: Generator.h:1675
Halide::Internal::GeneratorInput_Buffer::set_estimate
GeneratorInput_Buffer< T > & set_estimate(Var var, Expr min, Expr extent)
Definition: Generator.h:1742
Halide::Internal::GeneratorInput_Buffer::GeneratorInput_Buffer
GeneratorInput_Buffer(const std::string &name, const Type &t)
Definition: Generator.h:1703
Halide::Internal::GeneratorInput_Buffer::GeneratorInput_Buffer
GeneratorInput_Buffer(const std::string &name)
Definition: Generator.h:1691
Halide::Internal::GeneratorInput_Buffer::GeneratorInput_Buffer
GeneratorInput_Buffer(const std::string &name, const Type &t, int d)
Definition: Generator.h:1697
Halide::Internal::GeneratorInput_Buffer::end
std::vector< ImageParam >::const_iterator end() const
Definition: Generator.h:1800
Halide::Internal::GeneratorInput_Buffer::operator()
Expr operator()(std::vector< Expr > args) const
Definition: Generator.h:1721
Halide::Internal::GeneratorInput_Buffer::begin
std::vector< ImageParam >::const_iterator begin() const
Definition: Generator.h:1794
Halide::Internal::GeneratorInput_Buffer::operator()
Expr operator()(Args &&...args) const
Definition: Generator.h:1716
Halide::Internal::GeneratorInput_Buffer::size
size_t size() const
Definition: Generator.h:1776
Halide::Internal::GeneratorInput_Buffer::as
T2 as() const
Definition: Generator.h:1686
Halide::Internal::GeneratorInput_Buffer::in
Func in(const std::vector< Func > &others)
Definition: Generator.h:1764
Halide::Internal::GeneratorInput_Buffer::set_estimates
GeneratorInput_Buffer< T > & set_estimates(const Region &estimates)
Definition: Generator.h:1748
Halide::Internal::GeneratorInput_Buffer::operator[]
ImageParam operator[](size_t i) const
Definition: Generator.h:1782
Halide::Internal::GeneratorInput_Buffer::at
ImageParam at(size_t i) const
Definition: Generator.h:1788
Halide::Internal::GeneratorInput_Buffer::TBase
typename Super::TBase TBase
Definition: Generator.h:1670
Halide::Internal::GeneratorInput_Buffer::in
Func in()
Definition: Generator.h:1754
Halide::Internal::GeneratorInput_Buffer::GeneratorInput_Buffer
GeneratorInput_Buffer(const std::string &name, int d)
Definition: Generator.h:1708
Halide::Internal::GeneratorInput_DynamicScalar
Definition: Generator.h:1951
Halide::Internal::GeneratorInput_DynamicScalar::get_c_type
std::string get_c_type() const override
Definition: Generator.h:1958
Halide::Internal::GeneratorInput_DynamicScalar::type
Type type() const
Definition: Generator.h:1989
Halide::Internal::GeneratorInput_DynamicScalar::GeneratorInput_DynamicScalar
GeneratorInput_DynamicScalar(const std::string &name)
Definition: Generator.h:1963
Halide::Internal::GeneratorInput_DynamicScalar::set_estimate
void set_estimate(const Expr &value)
Definition: Generator.h:1982
Halide::Internal::GeneratorInput_Func
Definition: Generator.h:1827
Halide::Internal::GeneratorInput_Func::GeneratorInput_Func
GeneratorInput_Func(size_t array_size, const std::string &name, int d)
Definition: Generator.h:1868
Halide::Internal::GeneratorInput_Func::operator()
Expr operator()(Args &&...args) const
Definition: Generator.h:1883
Halide::Internal::GeneratorInput_Func::in
Func in(const std::vector< Func > &others)
Definition: Generator.h:1925
Halide::Internal::GeneratorInput_Func::set_estimates
GeneratorInput_Func< T > & set_estimates(const Region &estimates)
Definition: Generator.h:1909
Halide::Internal::GeneratorInput_Func::set_estimate
GeneratorInput_Func< T > & set_estimate(Var var, Expr min, Expr extent)
Definition: Generator.h:1903
Halide::Internal::GeneratorInput_Func::GeneratorInput_Func
GeneratorInput_Func(size_t array_size, const std::string &name, const Type &t, int d)
Definition: Generator.h:1863
Halide::Internal::GeneratorInput_Func::GeneratorInput_Func
GeneratorInput_Func(const std::string &name, int d)
Definition: Generator.h:1849
Halide::Internal::GeneratorInput_Func::GeneratorInput_Func
GeneratorInput_Func(const std::string &name, const Type &t)
Definition: Generator.h:1854
Halide::Internal::GeneratorInput_Func::GeneratorInput_Func
GeneratorInput_Func(size_t array_size, const std::string &name, const Type &t)
Definition: Generator.h:1873
Halide::Internal::GeneratorInput_Func::as
T2 as() const
Definition: Generator.h:1839
Halide::Internal::GeneratorInput_Func::TBase
typename Super::TBase TBase
Definition: Generator.h:1832
Halide::Internal::GeneratorInput_Func::operator()
Expr operator()(const std::vector< Expr > &args) const
Definition: Generator.h:1888
Halide::Internal::GeneratorInput_Func::in
Func in(const Func &other)
Definition: Generator.h:1920
Halide::Internal::GeneratorInput_Func::get_c_type
std::string get_c_type() const override
Definition: Generator.h:1834
Halide::Internal::GeneratorInput_Func::in
Func in()
Definition: Generator.h:1915
Halide::Internal::GeneratorInput_Func::GeneratorInput_Func
GeneratorInput_Func(const std::string &name, const Type &t, int d)
Definition: Generator.h:1844
Halide::Internal::GeneratorInput_Func::GeneratorInput_Func
GeneratorInput_Func(const std::string &name)
Definition: Generator.h:1859
Halide::Internal::GeneratorInput_Func::GeneratorInput_Func
GeneratorInput_Func(size_t array_size, const std::string &name)
Definition: Generator.h:1878
Halide::Internal::GeneratorInput_Scalar
Definition: Generator.h:1995
Halide::Internal::GeneratorInput_Scalar::GeneratorInput_Scalar
GeneratorInput_Scalar(size_t array_size, const std::string &name)
Definition: Generator.h:2039
Halide::Internal::GeneratorInput_Scalar::TBaseToExpr
static Expr TBaseToExpr(const TBase2 &value)
Definition: Generator.h:2020
Halide::Internal::GeneratorInput_Scalar::set_estimate
void set_estimate(const TBase &value)
Definition: Generator.h:2065
Halide::Internal::GeneratorInput_Scalar::type
Type type() const
Definition: Generator.h:2096
Halide::Internal::GeneratorInput_Scalar::set_def_min_max
void set_def_min_max() override
Definition: Generator.h:2005
Halide::Internal::GeneratorInput_Scalar::set_estimate
void set_estimate(size_t index, const TBase &value)
Definition: Generator.h:2087
Halide::Internal::GeneratorInput_Scalar::TBase
typename Super::TBase TBase
Definition: Generator.h:2000
Halide::Internal::GeneratorInput_Scalar::GeneratorInput_Scalar
GeneratorInput_Scalar(size_t array_size, const std::string &name, const TBase &def)
Definition: Generator.h:2044
Halide::Internal::GeneratorInput_Scalar::GeneratorInput_Scalar
GeneratorInput_Scalar(const std::string &name)
Definition: Generator.h:2031
Halide::Internal::GeneratorInput_Scalar::GeneratorInput_Scalar
GeneratorInput_Scalar(const std::string &name, const TBase &def)
Definition: Generator.h:2035
Halide::Internal::GeneratorInput_Scalar::def_expr_
const Expr def_expr_
Definition: Generator.h:2003
Halide::Internal::GeneratorInput_Scalar::get_c_type
std::string get_c_type() const override
Definition: Generator.h:2013
Halide::Internal::GeneratorInput_Scalar::def_
const TBase def_
Definition: Generator.h:2002
Halide::Internal::GeneratorInputBase
Definition: Generator.h:1539
Halide::Internal::GeneratorInputBase::verify_internals
void verify_internals() override
Halide::Internal::GeneratorInputBase::StubEmitter
friend class StubEmitter
Definition: Generator.h:1564
Halide::Internal::GeneratorInputBase::set_inputs
void set_inputs(const std::vector< StubInput > &inputs)
Halide::Internal::GeneratorInputBase::get_c_type
virtual std::string get_c_type() const =0
Halide::Internal::GeneratorInputBase::set_estimate_impl
void set_estimate_impl(const Var &var, const Expr &min, const Expr &extent)
Halide::Internal::GeneratorInputBase::inputs_set
bool inputs_set
Definition: Generator.h:1558
Halide::Internal::GeneratorInputBase::parameters_
std::vector< Parameter > parameters_
Definition: Generator.h:1552
Halide::Internal::GeneratorInputBase::init_internals
void init_internals()
Halide::Internal::GeneratorInputBase::input_or_output
const char * input_or_output() const override
Definition: Generator.h:1570
Halide::Internal::GeneratorInputBase::GeneratorInputBase
GeneratorInputBase(const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
Halide::Internal::GeneratorInputBase::~GeneratorInputBase
~GeneratorInputBase() override
Halide::Internal::GeneratorInputBase::parameter
Parameter parameter() const
Halide::Internal::GeneratorInputBase::set_estimates_impl
void set_estimates_impl(const Region &estimates)
Halide::Internal::GeneratorInputBase::check_value_writable
void check_value_writable() const override
Halide::Internal::GeneratorInputBase::set_def_min_max
virtual void set_def_min_max()
Halide::Internal::GeneratorInputBase::GeneratorInputBase
GeneratorInputBase(size_t array_size, const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
Halide::Internal::GeneratorInputImpl
Definition: Generator.h:1582
Halide::Internal::GeneratorInputImpl::is_array
bool is_array() const override
Definition: Generator.h:1586
Halide::Internal::GeneratorInputImpl::TBase
std::remove_all_extents_t< T > TBase
Definition: Generator.h:1584
Halide::Internal::GeneratorInputImpl::operator[]
const ValueType & operator[](size_t i) const
Definition: Generator.h:1619
Halide::Internal::GeneratorInputImpl::GeneratorInputImpl
GeneratorInputImpl(const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
Definition: Generator.h:1593
Halide::Internal::GeneratorInputImpl::at
const ValueType & at(size_t i) const
Definition: Generator.h:1625
Halide::Internal::GeneratorInputImpl::end
std::vector< ValueType >::const_iterator end() const
Definition: Generator.h:1637
Halide::Internal::GeneratorInputImpl::size
size_t size() const
Definition: Generator.h:1613
Halide::Internal::GeneratorInputImpl::begin
std::vector< ValueType >::const_iterator begin() const
Definition: Generator.h:1631
Halide::Internal::GeneratorOutput_Arithmetic
Definition: Generator.h:2775
Halide::Internal::GeneratorOutput_Arithmetic::GeneratorOutput_Arithmetic
GeneratorOutput_Arithmetic(const std::string &name)
Definition: Generator.h:2782
Halide::Internal::GeneratorOutput_Arithmetic::GeneratorOutput_Arithmetic
GeneratorOutput_Arithmetic(size_t array_size, const std::string &name)
Definition: Generator.h:2786
Halide::Internal::GeneratorOutput_Buffer
Definition: Generator.h:2478
Halide::Internal::GeneratorOutput_Buffer::GeneratorOutput_Buffer
GeneratorOutput_Buffer(const std::string &name, int d)
Definition: Generator.h:2545
Halide::Internal::GeneratorOutput_Buffer::GeneratorOutput_Buffer
GeneratorOutput_Buffer(size_t array_size, const std::string &name)
Definition: Generator.h:2553
Halide::Internal::GeneratorOutput_Buffer::GeneratorOutput_Buffer
GeneratorOutput_Buffer(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
Definition: Generator.h:2559
Halide::Internal::GeneratorOutput_Buffer::operator=
GeneratorOutput_Buffer< T > & operator=(const StubOutputBuffer< T2 > &stub_output_buffer)
Definition: Generator.h:2632
Halide::Internal::GeneratorOutput_Buffer::GeneratorOutput_Buffer
GeneratorOutput_Buffer(const std::string &name)
Definition: Generator.h:2525
Halide::Internal::GeneratorOutput_Buffer::get_c_type
HALIDE_NO_USER_CODE_INLINE std::string get_c_type() const override
Definition: Generator.h:2581
Halide::Internal::GeneratorOutput_Buffer::set_estimates
GeneratorOutput_Buffer< T > & set_estimates(const Region &estimates)
Definition: Generator.h:2656
Halide::Internal::GeneratorOutput_Buffer::as
HALIDE_NO_USER_CODE_INLINE T2 as() const
Definition: Generator.h:2592
Halide::Internal::GeneratorOutput_Buffer::GeneratorOutput_Buffer
GeneratorOutput_Buffer(const std::string &name, const std::vector< Type > &t)
Definition: Generator.h:2539
Halide::Internal::GeneratorOutput_Buffer::GeneratorOutput_Buffer
GeneratorOutput_Buffer(size_t array_size, const std::string &name, int d)
Definition: Generator.h:2573
Halide::Internal::GeneratorOutput_Buffer::operator=
GeneratorOutput_Buffer< T > & operator=(const Func &f)
Definition: Generator.h:2641
Halide::Internal::GeneratorOutput_Buffer::operator=
HALIDE_NO_USER_CODE_INLINE GeneratorOutput_Buffer< T > & operator=(Buffer< T2, D2 > &buffer)
Definition: Generator.h:2604
Halide::Internal::GeneratorOutput_Buffer::operator[]
const Func & operator[](size_t i) const
Definition: Generator.h:2664
Halide::Internal::GeneratorOutput_Buffer::GeneratorOutput_Buffer
GeneratorOutput_Buffer(size_t array_size, const std::string &name, const std::vector< Type > &t)
Definition: Generator.h:2567
Halide::Internal::GeneratorOutput_Buffer::GeneratorOutput_Buffer
GeneratorOutput_Buffer(const std::string &name, const std::vector< Type > &t, int d)
Definition: Generator.h:2531
Halide::Internal::GeneratorOutput_Buffer::operator[]
Func operator[](size_t i)
Definition: Generator.h:2671
Halide::Internal::GeneratorOutput_Func
Definition: Generator.h:2695
Halide::Internal::GeneratorOutput_Func::operator[]
const Func & operator[](size_t i) const
Definition: Generator.h:2750
Halide::Internal::GeneratorOutput_Func::GeneratorOutput_Func
GeneratorOutput_Func(const std::string &name)
Definition: Generator.h:2707
Halide::Internal::GeneratorOutput_Func::operator=
GeneratorOutput_Func< T > & operator=(const Func &f)
Definition: Generator.h:2730
Halide::Internal::GeneratorOutput_Func::GeneratorOutput_Func
GeneratorOutput_Func(const std::string &name, const std::vector< Type > &t, int d)
Definition: Generator.h:2711
Halide::Internal::GeneratorOutput_Func::GeneratorOutput_Func
GeneratorOutput_Func(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
Definition: Generator.h:2723
Halide::Internal::GeneratorOutput_Func::GeneratorOutput_Func
GeneratorOutput_Func(const std::string &name, int d)
Definition: Generator.h:2719
Halide::Internal::GeneratorOutput_Func::set_estimate
GeneratorOutput_Func< T > & set_estimate(const Var &var, const Expr &min, const Expr &extent)
Definition: Generator.h:2755
Halide::Internal::GeneratorOutput_Func::operator[]
Func & operator[](size_t i)
Definition: Generator.h:2742
Halide::Internal::GeneratorOutput_Func::GeneratorOutput_Func
GeneratorOutput_Func(const std::string &name, const std::vector< Type > &t)
Definition: Generator.h:2715
Halide::Internal::GeneratorOutput_Func::set_estimates
GeneratorOutput_Func< T > & set_estimates(const Region &estimates)
Definition: Generator.h:2764
Halide::Internal::GeneratorOutputBase
Definition: Generator.h:2264
Halide::Internal::GeneratorOutputBase::set_type
void set_type(const std::vector< Type > &types)
Set types dynamically for tuple outputs.
Halide::Internal::GeneratorOutputBase::StubEmitter
friend class StubEmitter
Definition: Generator.h:2363
Halide::Internal::GeneratorOutputBase::input_or_output
const char * input_or_output() const override
Definition: Generator.h:2374
Halide::Internal::GeneratorOutputBase::~GeneratorOutputBase
~GeneratorOutputBase() override
Halide::Internal::GeneratorOutputBase::GeneratorOutputBase
GeneratorOutputBase(const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
Halide::Internal::GeneratorOutputBase::get_c_type
virtual std::string get_c_type() const
Definition: Generator.h:2368
Halide::Internal::GeneratorOutputBase::as
HALIDE_NO_USER_CODE_INLINE T2 as() const
Definition: Generator.h:2267
Halide::Internal::GeneratorOutputBase::init_internals
void init_internals()
Halide::Internal::GeneratorOutputBase::check_value_writable
void check_value_writable() const override
Halide::Internal::GeneratorOutputBase::resize
void resize(size_t size)
Halide::Internal::GeneratorOutputBase::GeneratorOutputBase
GeneratorOutputBase(size_t array_size, const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
Halide::Internal::GeneratorOutputImpl
Definition: Generator.h:2383
Halide::Internal::GeneratorOutputImpl::end
std::vector< ValueType >::const_iterator end() const
Definition: Generator.h:2463
Halide::Internal::GeneratorOutputImpl::operator[]
const ValueType & operator[](size_t i) const
Definition: Generator.h:2445
Halide::Internal::GeneratorOutputImpl::GeneratorOutputImpl
GeneratorOutputImpl(const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
Definition: Generator.h:2395
Halide::Internal::GeneratorOutputImpl::size
size_t size() const
Definition: Generator.h:2439
Halide::Internal::GeneratorOutputImpl::at
const ValueType & at(size_t i) const
Definition: Generator.h:2451
Halide::Internal::GeneratorOutputImpl::begin
std::vector< ValueType >::const_iterator begin() const
Definition: Generator.h:2457
Halide::Internal::GeneratorOutputImpl::is_array
bool is_array() const override
Definition: Generator.h:2388
Halide::Internal::GeneratorOutputImpl::resize
void resize(size_t size)
Definition: Generator.h:2471
Halide::Internal::GeneratorOutputImpl::TBase
std::remove_all_extents_t< T > TBase
Definition: Generator.h:2385
Halide::Internal::GeneratorOutputImpl::operator()
FuncRef operator()(std::vector< ExprOrVar > args) const
Definition: Generator.h:2421
Halide::Internal::GeneratorOutputImpl::operator()
FuncRef operator()(Args &&...args) const
Definition: Generator.h:2415
Halide::Internal::GeneratorParam_Arithmetic
Definition: Generator.h:726
Halide::Internal::GeneratorParam_Arithmetic::set_from_string
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:742
Halide::Internal::GeneratorParam_Arithmetic::get_c_type
std::string get_c_type() const override
Definition: Generator.h:779
Halide::Internal::GeneratorParam_Arithmetic::GeneratorParam_Arithmetic
GeneratorParam_Arithmetic(const std::string &name, const T &value, const T &min=std::numeric_limits< T >::lowest(), const T &max=std::numeric_limits< T >::max())
Definition: Generator.h:728
Halide::Internal::GeneratorParam_Arithmetic::get_default_value
std::string get_default_value() const override
Definition: Generator.h:759
Halide::Internal::GeneratorParam_Arithmetic::call_to_string
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:773
Halide::Internal::GeneratorParam_Arithmetic::set_impl
void set_impl(const T &new_value) override
Definition: Generator.h:737
Halide::Internal::GeneratorParam_AutoSchedulerParams
Definition: Generator.h:636
Halide::Internal::GeneratorParam_AutoSchedulerParams::GeneratorParam_AutoSchedulerParams
GeneratorParam_AutoSchedulerParams()
Halide::Internal::GeneratorParam_AutoSchedulerParams::get_c_type
std::string get_c_type() const override
Halide::Internal::GeneratorParam_AutoSchedulerParams::set_from_string
void set_from_string(const std::string &new_value_string) override
Halide::Internal::GeneratorParam_AutoSchedulerParams::get_default_value
std::string get_default_value() const override
Halide::Internal::GeneratorParam_AutoSchedulerParams::call_to_string
std::string call_to_string(const std::string &v) const override
Halide::Internal::GeneratorParam_Bool
Definition: Generator.h:802
Halide::Internal::GeneratorParam_Bool::set_from_string
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:808
Halide::Internal::GeneratorParam_Bool::get_default_value
std::string get_default_value() const override
Definition: Generator.h:820
Halide::Internal::GeneratorParam_Bool::call_to_string
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:824
Halide::Internal::GeneratorParam_Bool::GeneratorParam_Bool
GeneratorParam_Bool(const std::string &name, const T &value)
Definition: Generator.h:804
Halide::Internal::GeneratorParam_Bool::get_c_type
std::string get_c_type() const override
Definition: Generator.h:830
Halide::Internal::GeneratorParam_Enum
Definition: Generator.h:836
Halide::Internal::GeneratorParam_Enum::call_to_string
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:856
Halide::Internal::GeneratorParam_Enum::set
void set(const T &e)
Definition: Generator.h:846
Halide::Internal::GeneratorParam_Enum::get_default_value
std::string get_default_value() const override
Definition: Generator.h:864
Halide::Internal::GeneratorParam_Enum::GeneratorParam_Enum
GeneratorParam_Enum(const std::string &name, const T &value, const std::map< std::string, T > &enum_map)
Definition: Generator.h:838
Halide::Internal::GeneratorParam_Enum::set_from_string
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:850
Halide::Internal::GeneratorParam_Enum::get_c_type
std::string get_c_type() const override
Definition: Generator.h:860
Halide::Internal::GeneratorParam_Enum::get_type_decls
std::string get_type_decls() const override
Definition: Generator.h:868
Halide::Internal::GeneratorParam_LoopLevel
Definition: Generator.h:651
Halide::Internal::GeneratorParam_LoopLevel::GeneratorParam_LoopLevel
GeneratorParam_LoopLevel(const std::string &name, const LoopLevel &value)
Definition: Generator.h:653
Halide::Internal::GeneratorParam_LoopLevel::get_c_type
std::string get_c_type() const override
Definition: Generator.h:716
Halide::Internal::GeneratorParam_LoopLevel::call_to_string
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:711
Halide::Internal::GeneratorParam_LoopLevel::is_looplevel_param
bool is_looplevel_param() const override
Definition: Generator.h:720
Halide::Internal::GeneratorParam_LoopLevel::set
void set(const LoopLevel &value) override
Definition: Generator.h:659
Halide::Internal::GeneratorParam_LoopLevel::set_from_string
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:679
Halide::Internal::GeneratorParam_LoopLevel::get_default_value
std::string get_default_value() const override
Definition: Generator.h:689
Halide::Internal::GeneratorParam_String
Definition: Generator.h:919
Halide::Internal::GeneratorParam_String::GeneratorParam_String
GeneratorParam_String(const std::string &name, const std::string &value)
Definition: Generator.h:921
Halide::Internal::GeneratorParam_String::get_c_type
std::string get_c_type() const override
Definition: Generator.h:936
Halide::Internal::GeneratorParam_String::set_from_string
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:924
Halide::Internal::GeneratorParam_String::get_default_value
std::string get_default_value() const override
Definition: Generator.h:928
Halide::Internal::GeneratorParam_String::call_to_string
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:932
Halide::Internal::GeneratorParam_Synthetic
Definition: Generator.h:2905
Halide::Internal::GeneratorParam_Synthetic::is_synthetic_param
bool is_synthetic_param() const override
Definition: Generator.h:2931
Halide::Internal::GeneratorParam_Synthetic::call_to_string
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:2921
Halide::Internal::GeneratorParam_Synthetic::set_from_string
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:2907
Halide::Internal::GeneratorParam_Synthetic::get_default_value
std::string get_default_value() const override
Definition: Generator.h:2916
Halide::Internal::GeneratorParam_Synthetic::get_c_type
std::string get_c_type() const override
Definition: Generator.h:2926
Halide::Internal::GeneratorParam_Target
Definition: Generator.h:611
Halide::Internal::GeneratorParam_Target::set_from_string
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:617
Halide::Internal::GeneratorParam_Target::GeneratorParam_Target
GeneratorParam_Target(const std::string &name, const T &value)
Definition: Generator.h:613
Halide::Internal::GeneratorParam_Target::get_c_type
std::string get_c_type() const override
Definition: Generator.h:631
Halide::Internal::GeneratorParam_Target::get_default_value
std::string get_default_value() const override
Definition: Generator.h:621
Halide::Internal::GeneratorParam_Target::call_to_string
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:625
Halide::Internal::GeneratorParam_Type
Definition: Generator.h:895
Halide::Internal::GeneratorParam_Type::get_type_decls
std::string get_type_decls() const override
Definition: Generator.h:913
Halide::Internal::GeneratorParam_Type::get_c_type
std::string get_c_type() const override
Definition: Generator.h:905
Halide::Internal::GeneratorParam_Type::call_to_string
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:901
Halide::Internal::GeneratorParam_Type::get_default_value
std::string get_default_value() const override
Definition: Generator.h:909
Halide::Internal::GeneratorParam_Type::GeneratorParam_Type
GeneratorParam_Type(const std::string &name, const T &value)
Definition: Generator.h:897
Halide::Internal::GeneratorParamBase
Definition: Generator.h:398
Halide::Internal::GeneratorParamBase::StubEmitter
friend class StubEmitter
Definition: Generator.h:447
Halide::Internal::GeneratorParamBase::check_value_readable
void check_value_readable() const
Halide::Internal::GeneratorParamBase::is_synthetic_param
virtual bool is_synthetic_param() const
Definition: Generator.h:464
Halide::Internal::GeneratorParamBase::GeneratorParamBase
GeneratorParamBase(GeneratorParamBase &&)=delete
Halide::Internal::GeneratorParamBase::call_to_string
virtual std::string call_to_string(const std::string &v) const =0
Halide::Internal::GeneratorParamBase::fail_wrong_type
void fail_wrong_type(const char *type)
Halide::Internal::GeneratorParamBase::~GeneratorParamBase
virtual ~GeneratorParamBase()
Halide::Internal::GeneratorParamBase::get_type_decls
virtual std::string get_type_decls() const
Definition: Generator.h:458
Halide::Internal::GeneratorParamBase::GeneratorParamBase
GeneratorParamBase(const std::string &name)
Halide::Internal::GeneratorParamBase::get_default_value
virtual std::string get_default_value() const =0
Halide::Internal::GeneratorParamBase::set
void set(const std::string &new_value)
Definition: Generator.h:437
Halide::Internal::GeneratorParamBase::GeneratorParamBase
GeneratorParamBase(const GeneratorParamBase &)=delete
Halide::Internal::GeneratorParamBase::get_c_type
virtual std::string get_c_type() const =0
Halide::Internal::GeneratorParamBase::is_looplevel_param
virtual bool is_looplevel_param() const
Definition: Generator.h:468
Halide::Internal::GeneratorParamBase::set_from_string
virtual void set_from_string(const std::string &value_string)=0
Halide::Internal::GeneratorParamBase::check_value_writable
void check_value_writable() const
Halide::Internal::GeneratorParamBase::operator=
GeneratorParamBase & operator=(GeneratorParamBase &&)=delete
Halide::Internal::GeneratorParamBase::name
const std::string & name() const
Definition: Generator.h:403
Halide::Internal::GeneratorParamBase::operator=
GeneratorParamBase & operator=(const GeneratorParamBase &)=delete
Halide::Internal::GeneratorParamBase::set
void set(const char *new_value)
Definition: Generator.h:440
Halide::Internal::GeneratorParamImpl
Definition: Generator.h:506
Halide::Internal::GeneratorParamImpl::set
void set(const std::string &new_value)
Definition: Generator.h:551
Halide::Internal::GeneratorParamImpl::value
T value() const
Definition: Generator.h:514
Halide::Internal::GeneratorParamImpl::GeneratorParamImpl
GeneratorParamImpl(const std::string &name, const T &value)
Definition: Generator.h:510
Halide::Internal::GeneratorParamImpl::type
T type
Definition: Generator.h:508
Halide::Internal::GeneratorParamImpl::set_impl
virtual void set_impl(const T &new_value)
Definition: Generator.h:557
Halide::Internal::GeneratorParamImpl::value_
T value_
Definition: Generator.h:563
Halide::Internal::GeneratorParamInfo
Definition: Generator.h:3126
Halide::Internal::GeneratorParamInfo::inputs
const std::vector< Internal::GeneratorInputBase * > & inputs() const
Definition: Generator.h:3155
Halide::Internal::GeneratorParamInfo::generator_params
const std::vector< Internal::GeneratorParamBase * > & generator_params() const
Definition: Generator.h:3152
Halide::Internal::GeneratorParamInfo::GeneratorParamInfo
GeneratorParamInfo(GeneratorBase *generator, size_t size)
Halide::Internal::GeneratorParamInfo::outputs
const std::vector< Internal::GeneratorOutputBase * > & outputs() const
Definition: Generator.h:3158
Halide::Internal::GeneratorRegistry
Definition: Generator.h:3770
Halide::Internal::GeneratorRegistry::GeneratorRegistry
GeneratorRegistry(const GeneratorRegistry &)=delete
Halide::Internal::GeneratorRegistry::create
static AbstractGeneratorPtr create(const std::string &name, const Halide::GeneratorContext &context)
Halide::Internal::GeneratorRegistry::operator=
GeneratorRegistry & operator=(GeneratorRegistry &&that)=delete
Halide::Internal::GeneratorRegistry::GeneratorRegistry
GeneratorRegistry(GeneratorRegistry &&that)=delete
Halide::Internal::GeneratorRegistry::operator=
GeneratorRegistry & operator=(const GeneratorRegistry &)=delete
Halide::Internal::GeneratorRegistry::register_factory
static void register_factory(const std::string &name, GeneratorFactory generator_factory)
Halide::Internal::GeneratorRegistry::enumerate
static std::vector< std::string > enumerate()
Halide::Internal::GeneratorRegistry::unregister_factory
static void unregister_factory(const std::string &name)
Halide::Internal::RegisterGenerator
Definition: Generator.h:3950
Halide::Internal::RegisterGenerator::RegisterGenerator
RegisterGenerator(const char *registered_name, GeneratorFactory generator_factory)
Halide::Internal::StubInputBuffer
StubInputBuffer is the placeholder that a Stub uses when it requires a Buffer for an input (rather th...
Definition: Generator.h:1265
Halide::Internal::StubInputBuffer::to_parameter_vector
static std::vector< Parameter > to_parameter_vector(const StubInputBuffer< T2 > &t)
Definition: Generator.h:1305
Halide::Internal::StubInputBuffer::StubInputBuffer
StubInputBuffer(const Buffer< T2, D2 > &b)
Definition: Generator.h:1300
Halide::Internal::StubInputBuffer::StubInputBuffer
StubInputBuffer()=default
Halide::Internal::StubInputBuffer::to_parameter_vector
static std::vector< Parameter > to_parameter_vector(const std::vector< StubInputBuffer< T2 > > &v)
Definition: Generator.h:1310
Halide::Internal::StubInputBuffer::StubInputBuffer
friend class StubInputBuffer
Definition: Generator.h:1270
Halide::Internal::StubInput
Definition: Generator.h:1383
Halide::Internal::StubInput::kind
ArgInfoKind kind() const
Definition: Generator.h:1406
Halide::Internal::StubInput::StubInput
StubInput(const StubInputBuffer< T2 > &b)
Definition: Generator.h:1393
Halide::Internal::StubInput::StubInput
StubInput(const Parameter &p)
Definition: Generator.h:1396
Halide::Internal::StubInput::parameter
Parameter parameter() const
Definition: Generator.h:1410
Halide::Internal::StubInput::func
Func func() const
Definition: Generator.h:1415
Halide::Internal::StubInput::expr
Expr expr() const
Definition: Generator.h:1420
Halide::Internal::StubInput::StubInput
StubInput(const Expr &e)
Definition: Generator.h:1402
Halide::Internal::StubInput::StubInput
StubInput(const Func &f)
Definition: Generator.h:1399
Halide::Internal::StubOutputBufferBase
Definition: Generator.h:1322
Halide::Internal::StubOutputBufferBase::get_target
Target get_target() const
Halide::Internal::StubOutputBufferBase::f
Func f
Definition: Generator.h:1324
Halide::Internal::StubOutputBufferBase::generator
std::shared_ptr< AbstractGenerator > generator
Definition: Generator.h:1325
Halide::Internal::StubOutputBufferBase::realize
Realization realize(Args &&...args)
Definition: Generator.h:1336
Halide::Internal::StubOutputBufferBase::StubOutputBufferBase
StubOutputBufferBase(const Func &f, const std::shared_ptr< AbstractGenerator > &generator)
Halide::Internal::StubOutputBufferBase::realize
void realize(Dst dst)
Definition: Generator.h:1341
Halide::Internal::StubOutputBufferBase::realize
Realization realize(std::vector< int32_t > sizes)
Halide::Internal::StubOutputBufferBase::StubOutputBufferBase
StubOutputBufferBase()
Halide::Internal::StubOutputBuffer
StubOutputBuffer is the placeholder that a Stub uses when it requires a Buffer for an output (rather ...
Definition: Generator.h:1359
Halide::Internal::StubOutputBuffer::StubOutputBuffer
StubOutputBuffer()=default
Halide::Internal::StubOutputBuffer::to_output_buffers
static std::vector< StubOutputBuffer< T > > to_output_buffers(const std::vector< Func > &v, const std::shared_ptr< AbstractGenerator > &gen)
Definition: Generator.h:1369
Halide::LoopLevel
A reference to a site in a Halide statement at the top of the body of a particular for loop.
Definition: Schedule.h:203
Halide::LoopLevel::root
static LoopLevel root()
Construct a special LoopLevel value which represents the location outside of all for loops.
Halide::LoopLevel::inlined
static LoopLevel inlined()
Construct a special LoopLevel value that implies that a function should be inlined away.
Halide::LoopLevel::set
void set(const LoopLevel &other)
Mutate our contents to match the contents of 'other'.
Halide::LoopLevel::is_root
bool is_root() const
Halide::LoopLevel::is_inlined
bool is_inlined() const
Halide::LoopLevel::lock
LoopLevel & lock()
Halide::NamesInterface
Definition: Generator.h:3055
Halide::NamesInterface::Target
Halide::Target Target
Definition: Generator.h:3075
Halide::NamesInterface::Bool
static Type Bool(int lanes=1)
Definition: Generator.h:3092
Halide::NamesInterface::cast
static Expr cast(Expr e)
Definition: Generator.h:3080
Halide::NamesInterface::cast
static Expr cast(Halide::Type t, Expr e)
Definition: Generator.h:3083
Halide::NamesInterface::Expr
Halide::Expr Expr
Definition: Generator.h:3060
Halide::NamesInterface::UInt
static Type UInt(int bits, int lanes=1)
Definition: Generator.h:3101
Halide::NamesInterface::Int
static Type Int(int bits, int lanes=1)
Definition: Generator.h:3098
Halide::NamesInterface::Float
static Type Float(int bits, int lanes=1)
Definition: Generator.h:3095
Halide::NamesInterface::Func
Halide::Func Func
Definition: Generator.h:3063
Halide::NamesInterface::Pipeline
Halide::Pipeline Pipeline
Definition: Generator.h:3070
Halide::OutputImageParam
A handle on the output buffer of a pipeline.
Definition: OutputImageParam.h:19
Halide::Param
A scalar parameter to a halide pipeline.
Definition: Param.h:22
Halide::Parameter
A reference-counted handle to a parameter to a halide pipeline.
Definition: Parameter.h:40
Halide::Parameter::set_default_value
void set_default_value(const Expr &e)
Get and set the default values for scalar parameters.
Halide::Parameter::dimensions
int dimensions() const
Get the dimensionality of this parameter.
Halide::Parameter::set_max_value
void set_max_value(const Expr &e)
Halide::Parameter::set_buffer
void set_buffer(const Buffer< void > &b)
If the parameter is a buffer parameter, set its current value.
Halide::Parameter::set_min_value
void set_min_value(const Expr &e)
Get and set constraints for scalar parameters.
Halide::Parameter::set_estimate
void set_estimate(Expr e)
Halide::Parameter::type
Type type() const
Get the type of this parameter.
Halide::Pipeline
A class representing a Halide pipeline.
Definition: Pipeline.h:107
Halide::Pipeline::trace_pipeline
void trace_pipeline()
Generate begin_pipeline and end_pipeline tracing calls for this pipeline.
Halide::Pipeline::realize
Realization realize(std::vector< int32_t > sizes={}, const Target &target=Target())
See Func::realize.
Halide::RDom
A multi-dimensional domain over which to iterate.
Definition: RDom.h:193
Halide::RVar
A reduction variable represents a single dimension of a reduction domain (RDom).
Definition: RDom.h:29
Halide::Realization
A Realization is a vector of references to existing Buffer objects.
Definition: Realization.h:19
Halide::Stage
A single definition of a Func.
Definition: Func.h:70
Halide::Tuple
Create a small array of Exprs for defining and calling functions with multiple outputs.
Definition: Tuple.h:18
Halide::Var
A Halide variable, to be used when defining functions.
Definition: Var.h:19
Halide::Internal::GeneratorMinMax::max_forward
auto max_forward(const Other &a, const GeneratorParam< T > &b) -> decltype(max(a,(T) b))
Definition: Generator.h:1207
Halide::Internal::GeneratorMinMax::min_forward
auto min_forward(const Other &a, const GeneratorParam< T > &b) -> decltype(min(a,(T) b))
Definition: Generator.h:1198
Halide::Internal::ArgInfoKind
ArgInfoKind
Definition: AbstractGenerator.h:26
Halide::Internal::ArgInfoKind::Buffer
@ Buffer
Halide::Internal::ArgInfoKind::Function
@ Function
Halide::Internal::ArgInfoKind::Scalar
@ Scalar
Halide::Internal::GeneratorFactory
std::function< AbstractGeneratorPtr(const GeneratorContext &context)> GeneratorFactory
Definition: Generator.h:3124
Halide::Internal::generate_filter_main
int generate_filter_main(int argc, char **argv)
generate_filter_main() is a convenient wrapper for GeneratorRegistry::create() + compile_to_files(); ...
Halide::Internal::halide_type_to_enum_string
std::string halide_type_to_enum_string(const Type &t)
Definition: Generator.h:315
Halide::Internal::has_static_halide_type_method_v
constexpr bool has_static_halide_type_method_v
Definition: Generator.h:2173
Halide::Internal::type_sink_t
void type_sink_t
Definition: Generator.h:2164
Halide::Internal::min
ConstantInterval min(const ConstantInterval &a, const ConstantInterval &b)
Halide::Internal::SyntheticParamType
SyntheticParamType
Definition: Generator.h:2898
Halide::Internal::SyntheticParamType::ArraySize
@ ArraySize
Halide::Internal::SyntheticParamType::Dim
@ Dim
Halide::Internal::SyntheticParamType::Type
@ Type
Halide::Internal::parameter_constraints
std::vector< Expr > parameter_constraints(const Parameter &p)
Halide::Internal::select_type_t
typename select_type< Args... >::type select_type_t
Definition: Generator.h:394
Halide::Internal::no_realizations_v
constexpr bool no_realizations_v
Definition: Generator.h:3120
Halide::Internal::make_const
Expr make_const(Type t, int64_t val)
Construct an immediate of the given type from any numeric C++ type.
Halide::Internal::halide_type_to_c_source
std::string halide_type_to_c_source(const Type &t)
Halide::Internal::GeneratorOutputImplBase
select_type_t< cond< has_static_halide_type_method_v< TBase >, GeneratorOutput_Buffer< T > >, cond< std::is_same_v< TBase, Func >, GeneratorOutput_Func< T > >, cond< std::is_arithmetic_v< TBase >, GeneratorOutput_Arithmetic< T > > > GeneratorOutputImplBase
Definition: Generator.h:2796
Halide::Internal::max
ConstantInterval max(const ConstantInterval &a, const ConstantInterval &b)
Halide::Internal::GeneratorInputImplBase
select_type_t< cond< has_static_halide_type_method_v< TBase >, GeneratorInput_Buffer< T > >, cond< std::is_same_v< TBase, Func >, GeneratorInput_Func< T > >, cond< std::is_arithmetic_v< TBase >, GeneratorInput_Arithmetic< T > >, cond< std::is_scalar_v< TBase >, GeneratorInput_Scalar< T > >, cond< std::is_same_v< TBase, Expr >, GeneratorInput_DynamicScalar< T > > > GeneratorInputImplBase
Definition: Generator.h:2182
Halide::Internal::GeneratorParamImplBase
select_type_t< cond< std::is_same_v< T, Target >, GeneratorParam_Target< T > >, cond< std::is_same_v< T, LoopLevel >, GeneratorParam_LoopLevel >, cond< std::is_same_v< T, std::string >, GeneratorParam_String< T > >, cond< std::is_same_v< T, Type >, GeneratorParam_Type< T > >, cond< std::is_same_v< T, bool >, GeneratorParam_Bool< T > >, cond< std::is_arithmetic_v< T >, GeneratorParam_Arithmetic< T > >, cond< std::is_enum_v< T >, GeneratorParam_Enum< T > > > GeneratorParamImplBase
Definition: Generator.h:950
Halide::Internal::enum_to_string
HALIDE_NO_USER_CODE_INLINE std::string enum_to_string(const std::map< std::string, T > &enum_map, const T &t)
Definition: Generator.h:297
Halide::Internal::parse_halide_type_list
std::vector< Type > parse_halide_type_list(const std::string &types)
Halide::Internal::halide_type_to_c_type
std::string halide_type_to_c_type(const Type &t)
Halide::Internal::print_loop_nest
std::string print_loop_nest(const std::vector< Function > &output_funcs)
Emit some simple pseudocode that shows the structure of the loop nest specified by this pipeline's sc...
Halide::Internal::all_are_printable_args_v
constexpr bool all_are_printable_args_v
Definition: IROperator.h:353
Halide::Internal::AbstractGeneratorPtr
std::unique_ptr< AbstractGenerator > AbstractGeneratorPtr
Definition: AbstractGenerator.h:244
Halide::Internal::generator_test
void generator_test()
Halide::Internal::execute_generator
void execute_generator(const ExecuteGeneratorArgs &args)
Execute a Generator for AOT compilation – this provides the implementation of the command-line Genera...
Halide::Internal::collect_print_args
HALIDE_NO_USER_CODE_INLINE void collect_print_args(std::vector< Expr > &args)
Definition: IROperator.h:356
Halide::Internal::get_registered_generators
const GeneratorFactoryProvider & get_registered_generators()
Return a GeneratorFactoryProvider that knows about all the currently-registered C++ Generators.
Halide::Internal::ArgInfoDirection
ArgInfoDirection
Definition: AbstractGenerator.h:30
Halide::Internal::parse_scalar
T parse_scalar(const std::string &value)
Definition: Generator.h:2888
Halide::Internal::get_halide_type_enum_map
const std::map< std::string, Halide::Type > & get_halide_type_enum_map()
Halide::Internal::enum_from_string
T enum_from_string(const std::map< std::string, T > &enum_map, const std::string &s)
Definition: Generator.h:308
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AbstractGenerator.h:19
Halide::operator>=
auto operator>=(const Other &a, const GeneratorParam< T > &b) -> decltype(a >=(T) b)
Greater than or equal comparison between GeneratorParam<T> and any type that supports operator>= with...
Definition: Generator.h:1105
Halide::UInt
Type UInt(int bits, int lanes=1)
Constructing an unsigned integer type.
Definition: Type.h:544
Halide::reinterpret
Expr reinterpret(Type t, Expr e)
Reinterpret the bits of one value as another type.
Halide::Float
Type Float(int bits, int lanes=1)
Construct a floating-point type.
Definition: Type.h:549
Halide::operator==
auto operator==(const Other &a, const GeneratorParam< T > &b) -> decltype(a==(T) b)
Equality comparison between GeneratorParam<T> and any type that supports operator== with T.
Definition: Generator.h:1131
Halide::LinkageType::Internal
@ Internal
Not visible externally, similar to 'static' linkage in C.
Halide::operator<
auto operator<(const Other &a, const GeneratorParam< T > &b) -> decltype(a<(T) b)
Less than comparison between GeneratorParam<T> and any type that supports operator< with T.
Definition: Generator.h:1092
Halide::GeneratorParamsMap
std::map< std::string, std::string > GeneratorParamsMap
Definition: AbstractGenerator.h:22
Halide::operator*
auto operator*(const Other &a, const GeneratorParam< T > &b) -> decltype(a *(T) b)
Multiplication between GeneratorParam<T> and any type that supports operator* with T.
Definition: Generator.h:1040
Halide::operator||
auto operator||(const Other &a, const GeneratorParam< T > &b) -> decltype(a||(T) b)
Logical or between between GeneratorParam<T> and any type that supports operator|| with T.
Definition: Generator.h:1174
Halide::PrefetchBoundStrategy
PrefetchBoundStrategy
Different ways to handle accesses outside the original extents in a prefetch.
Definition: PrefetchDirective.h:16
Halide::min
auto min(const GeneratorParam< T > &a, const Other &b) -> decltype(Internal::GeneratorMinMax::min_forward(a, b))
Definition: Generator.h:1226
Halide::operator-
auto operator-(const Other &a, const GeneratorParam< T > &b) -> decltype(a -(T) b)
Subtraction between GeneratorParam<T> and any type that supports operator- with T.
Definition: Generator.h:1027
Halide::operator!
auto operator!(const GeneratorParam< T > &a) -> decltype(!(T) a)
Not operator for GeneratorParam.
Definition: Generator.h:1246
Halide::TailStrategy
TailStrategy
Different ways to handle a tail case in a split when the factor does not provably divide the extent.
Definition: Schedule.h:33
Halide::CompilerLoggerFactory
std::function< std::unique_ptr< Internal::CompilerLogger >(const std::string &fn_name, const Target &target)> CompilerLoggerFactory
Definition: Module.h:243
Halide::Int
Type Int(int bits, int lanes=1)
Constructing a signed integer type.
Definition: Type.h:539
Halide::OutputFileType::schedule
@ schedule
Halide::operator+
auto operator+(const Other &a, const GeneratorParam< T > &b) -> decltype(a+(T) b)
Addition between GeneratorParam<T> and any type that supports operator+ with T.
Definition: Generator.h:1014
Halide::create_callable_from_generator
Callable create_callable_from_generator(const GeneratorContext &context, const std::string &name, const GeneratorParamsMap &generator_params={})
Create a Generator from the currently-registered Generators, use it to create a Callable.
Halide::min
Expr min(const FuncRef &a, const FuncRef &b)
Explicit overloads of min and max for FuncRef.
Definition: Func.h:625
Halide::operator&&
auto operator&&(const Other &a, const GeneratorParam< T > &b) -> decltype(a &&(T) b)
Logical and between between GeneratorParam<T> and any type that supports operator&& with T.
Definition: Generator.h:1157
Halide::operator%
auto operator%(const Other &a, const GeneratorParam< T > &b) -> decltype(a %(T) b)
Modulo between GeneratorParam<T> and any type that supports operator% with T.
Definition: Generator.h:1066
Halide::NameMangling
NameMangling
An enum to specify calling convention for extern stages.
Definition: Function.h:26
Halide::operator<=
auto operator<=(const Other &a, const GeneratorParam< T > &b) -> decltype(a<=(T) b)
Less than or equal comparison between GeneratorParam<T> and any type that supports operator<= with T.
Definition: Generator.h:1118
Halide::operator>
auto operator>(const Other &a, const GeneratorParam< T > &b) -> decltype(a >(T) b)
Greater than comparison between GeneratorParam<T> and any type that supports operator> with T.
Definition: Generator.h:1079
Halide::AnyDims
constexpr int AnyDims
Definition: Buffer.h:11
Halide::operator!=
auto operator!=(const Other &a, const GeneratorParam< T > &b) -> decltype(a !=(T) b)
Inequality comparison between between GeneratorParam<T> and any type that supports operator!...
Definition: Generator.h:1144
Halide::cast
Internal::ConstantInterval cast(Type t, const Internal::ConstantInterval &a)
Cast operators for ConstantIntervals.
Halide::Bool
Type Bool(int lanes=1)
Construct a boolean type.
Definition: Type.h:559
Halide::Region
std::vector< Range > Region
A multi-dimensional box.
Definition: Expr.h:350
Halide::operator/
auto operator/(const Other &a, const GeneratorParam< T > &b) -> decltype(a/(T) b)
Division between GeneratorParam<T> and any type that supports operator/ with T.
Definition: Generator.h:1053
Halide::max
Expr max(const FuncRef &a, const FuncRef &b)
Definition: Func.h:628
Halide::max
auto max(const GeneratorParam< T > &a, const Other &b) -> decltype(Internal::GeneratorMinMax::max_forward(a, b))
Definition: Generator.h:1239
Halide::MemoryType
MemoryType
An enum describing different address spaces to be used with Func::store_in.
Definition: Expr.h:353
Halide::Partition
Partition
Different ways to handle loops with a potentially optimizable boundary conditions.
Definition: LoopPartitioningDirective.h:16
halide_register_generator
Definition: Generator.h:4054
uint64_t
unsigned __INT64_TYPE__ uint64_t
Definition: runtime_internal.h:23
int64_t
signed __INT64_TYPE__ int64_t
Definition: runtime_internal.h:22
int32_t
signed __INT32_TYPE__ int32_t
Definition: runtime_internal.h:24
uint8_t
unsigned __INT8_TYPE__ uint8_t
Definition: runtime_internal.h:29
uint16_t
unsigned __INT16_TYPE__ uint16_t
Definition: runtime_internal.h:27
uint32_t
unsigned __INT32_TYPE__ uint32_t
Definition: runtime_internal.h:25
int16_t
signed __INT16_TYPE__ int16_t
Definition: runtime_internal.h:26
int8_t
signed __INT8_TYPE__ int8_t
Definition: runtime_internal.h:28
Halide::AutoschedulerParams
Special the Autoscheduler to be used (if any), along with arbitrary additional arguments specific to ...
Definition: Pipeline.h:48
Halide::AutoschedulerParams::name
std::string name
Definition: Pipeline.h:49
Halide::Expr
A fragment of Halide syntax.
Definition: Expr.h:258
Halide::Expr::type
HALIDE_ALWAYS_INLINE Type type() const
Get the type of this expression node.
Definition: Expr.h:327
Halide::ExternFuncArgument
An argument to an extern-defined Func.
Definition: ExternFuncArgument.h:17
Halide::Internal::Convert
Definition: Generator.h:493
Halide::Internal::Convert::value
static TO2 value(const FROM &from)
Definition: Generator.h:495
Halide::Internal::Dim
The Dim struct represents one loop in the schedule's representation of a loop nest.
Definition: Schedule.h:439
Halide::Internal::ExecuteGeneratorArgs
ExecuteGeneratorArgs is the set of arguments to execute_generator().
Definition: Generator.h:3959
Halide::Internal::ExecuteGeneratorArgs::compiler_logger_factory
CompilerLoggerFactory compiler_logger_factory
Definition: Generator.h:4020
Halide::Internal::ExecuteGeneratorArgs::function_name
std::string function_name
Definition: Generator.h:3982
Halide::Internal::ExecuteGeneratorArgs::output_dir
std::string output_dir
Definition: Generator.h:3961
Halide::Internal::ExecuteGeneratorArgs::build_mode
enum Halide::Internal::ExecuteGeneratorArgs::BuildMode build_mode
Halide::Internal::ExecuteGeneratorArgs::BuildMode
BuildMode
Definition: Generator.h:3996
Halide::Internal::ExecuteGeneratorArgs::Default
@ Default
Definition: Generator.h:3998
Halide::Internal::ExecuteGeneratorArgs::Gradient
@ Gradient
Definition: Generator.h:4001
Halide::Internal::ExecuteGeneratorArgs::file_base_name
std::string file_base_name
Definition: Generator.h:3986
Halide::Internal::ExecuteGeneratorArgs::create_generator
CreateGeneratorFn create_generator
Definition: Generator.h:4010
Halide::Internal::ExecuteGeneratorArgs::generator_name
std::string generator_name
Definition: Generator.h:3978
Halide::Internal::ExecuteGeneratorArgs::runtime_name
std::string runtime_name
Definition: Generator.h:3993
Halide::Internal::ExecuteGeneratorArgs::output_types
std::set< OutputFileType > output_types
Definition: Generator.h:3964
Halide::Internal::ExecuteGeneratorArgs::suffixes
std::vector< std::string > suffixes
Definition: Generator.h:3974
Halide::Internal::ExecuteGeneratorArgs::targets
std::vector< Target > targets
Definition: Generator.h:3968
Halide::Internal::ExecuteGeneratorArgs::generator_params
GeneratorParamsMap generator_params
Definition: Generator.h:4017
Halide::Internal::ExecuteGeneratorArgs::log_outputs
bool log_outputs
Definition: Generator.h:4023
Halide::Internal::ExecuteGeneratorArgs::CreateGeneratorFn
std::function< AbstractGeneratorPtr(const std::string &name, const GeneratorContext &context)> CreateGeneratorFn
Definition: Generator.h:4009
Halide::Internal::IntrusivePtr::defined
HALIDE_ALWAYS_INLINE bool defined() const
Definition: IntrusivePtr.h:164
Halide::Internal::NoRealizations<>
Definition: Generator.h:3112
Halide::Internal::NoRealizations
Definition: Generator.h:3109
Halide::Internal::cond
Definition: Generator.h:380
Halide::Internal::cond::value
static constexpr bool value
Definition: Generator.h:381
Halide::Internal::cond::type
T type
Definition: Generator.h:382
Halide::Internal::has_static_halide_type_method
Definition: Generator.h:2167
Halide::Internal::select_type< First >::type
std::conditional_t< First::value, typename First::type, void > type
Definition: Generator.h:390
Halide::Internal::select_type
Definition: Generator.h:386
Halide::Target
A struct representing a target machine and os to generate code for.
Definition: Target.h:19
Halide::Target::natural_vector_size
int natural_vector_size(const Halide::Type &t) const
Given a data type, return an estimate of the "natural" vector size for that data type when compiling ...
Halide::Type
Types in the halide type system.
Definition: Type.h:281