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