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  * or ScheduleParams), which affect code generation.
153  *
154  * GeneratorParams, ScheduleParams, 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  * ScheduleParam(s)
160  * Input<Func>(s)
161  * Input<non-Func>(s)
162  * Output<Func>(s)
163  * \endcode
164  *
165  * Note that the Inputs and Outputs will appear in the C function call in the order
166  * they are declared. All Input<Func> and Output<Func> are represented as buffer_t;
167  * all other Input<> are the appropriate C++ scalar type. (GeneratorParams are
168  * always referenced by name, not position, so their order is irrelevant.)
169  *
170  * All Inputs and Outputs must have explicit names, and all such names must match
171  * the regex [A-Za-z][A-Za-z_0-9]* (i.e., essentially a C/C++ variable name, with
172  * some extra restrictions on underscore use). By convention, the name should match
173  * the member-variable name.
174  *
175  *
176  * All Generators have three GeneratorParams that are implicitly provided
177  * by the base class:
178  *
179  * GeneratorParam<Target> target{"target", Target()};
180  * GeneratorParam<bool> auto_schedule{"auto_schedule", false};
181  * GeneratorParam<MachineParams> machine_params{"machine_params", MachineParams::generic()};
182  *
183  * - 'target' is the Halide::Target for which the Generator is producing code.
184  * It is read-only during the Generator's lifetime, and must not be modified;
185  * its value should always be filled in by the calling code: either the Halide
186  * build system (for ahead-of-time compilation), or ordinary C++ code
187  * (for JIT compilation).
188  * - 'auto_schedule' indicates whether the auto-scheduler should be run for this
189  * Generator:
190  * - if 'false', the Generator should schedule its Funcs as it sees fit.
191  * - if 'true', the Generator should only provide estimate()s for its Funcs,
192  * and not call any other scheduling methods.
193  * - 'machine_params' is only used if auto_schedule is true; it is ignored
194  * if auto_schedule is false. It provides details about the machine architecture
195  * being targeted which may be used to enhance the automatically-generated
196  * schedule.
197  *
198  * Generators are added to a global registry to simplify AOT build mechanics; this
199  * is done by simply using the HALIDE_REGISTER_GENERATOR macro at global scope:
200  *
201  * \code
202  * HALIDE_REGISTER_GENERATOR(ExampleGen, jit_example)
203  * \endcode
204  *
205  * The registered name of the Generator is provided must match the same rules as
206  * Input names, above.
207  *
208  * Note that the class name of the generated Stub class will match the registered
209  * name by default; if you want to vary it (typically, to include namespaces),
210  * you can add it as an optional third argument:
211  *
212  * \code
213  * HALIDE_REGISTER_GENERATOR(ExampleGen, jit_example, SomeNamespace::JitExampleStub)
214  * \endcode
215  *
216  * Note that a Generator is always executed with a specific Target assigned to it,
217  * that you can access via the get_target() method. (You should *not* use the
218  * global get_target_from_environment(), etc. methods provided in Target.h)
219  *
220  * (Note that there are older variations of Generator that differ from what's
221  * documented above; these are still supported but not described here. See
222  * https://github.com/halide/Halide/wiki/Old-Generator-Documentation for
223  * more information.)
224  */
225 
226 #include <algorithm>
227 #include <iterator>
228 #include <limits>
229 #include <memory>
230 #include <mutex>
231 #include <sstream>
232 #include <string>
233 #include <type_traits>
234 #include <vector>
235 
236 #include "Func.h"
237 #include "ExternalCode.h"
238 #include "ImageParam.h"
239 #include "Introspection.h"
240 #include "ObjectInstanceRegistry.h"
241 #include "ScheduleParam.h"
242 #include "Target.h"
243 
244 namespace Halide {
245 
246 template<typename T> class Buffer;
247 
248 namespace Internal {
249 
250 EXPORT void generator_test();
251 
252 /**
253  * ValueTracker is an internal utility class that attempts to track and flag certain
254  * obvious Stub-related errors at Halide compile time: it tracks the constraints set
255  * on any Parameter-based argument (i.e., Input<Buffer> and Output<Buffer>) to
256  * ensure that incompatible values aren't set.
257  *
258  * e.g.: if a Generator A requires stride[0] == 1,
259  * and Generator B uses Generator A via stub, but requires stride[0] == 4,
260  * we should be able to detect this at Halide compilation time, and fail immediately,
261  * rather than producing code that fails at runtime and/or runs slowly due to
262  * vectorization being unavailable.
263  *
264  * We do this by tracking the active values at entrance and exit to all user-provided
265  * Generator methods (build()/generate()/schedule()); if we ever find more than two unique
266  * values active, we know we have a potential conflict. ("two" here because the first
267  * value is the default value for a given constraint.)
268  *
269  * Note that this won't catch all cases:
270  * -- JIT compilation has no way to check for conflicts at the top-level
271  * -- constraints that match the default value (e.g. if dim(0).set_stride(1) is the
272  * first value seen by the tracker) will be ignored, so an explicit requirement set
273  * this way can be missed
274  *
275  * Nevertheless, this is likely to be much better than nothing when composing multiple
276  * layers of Stubs in a single fused result.
277  */
279 private:
280  std::map<std::string, std::vector<std::vector<Expr>>> values_history;
281  const size_t max_unique_values;
282 public:
283  explicit ValueTracker(size_t max_unique_values = 2) : max_unique_values(max_unique_values) {}
284  EXPORT void track_values(const std::string &name, const std::vector<Expr> &values);
285 };
286 
287 EXPORT std::vector<Expr> parameter_constraints(const Parameter &p);
288 
289 template <typename T>
290 NO_INLINE std::string enum_to_string(const std::map<std::string, T> &enum_map, const T& t) {
291  for (auto key_value : enum_map) {
292  if (t == key_value.second) {
293  return key_value.first;
294  }
295  }
296  user_error << "Enumeration value not found.\n";
297  return "";
298 }
299 
300 template <typename T>
301 T enum_from_string(const std::map<std::string, T> &enum_map, const std::string& s) {
302  auto it = enum_map.find(s);
303  user_assert(it != enum_map.end()) << "Enumeration value not found: " << s << "\n";
304  return it->second;
305 }
306 
307 EXPORT extern const std::map<std::string, Halide::Type> &get_halide_type_enum_map();
308 inline std::string halide_type_to_enum_string(const Type &t) {
310 }
311 
312 EXPORT extern const std::map<std::string, Halide::LoopLevel> &get_halide_looplevel_enum_map();
313 inline std::string halide_looplevel_to_enum_string(const LoopLevel &loop_level){
314  return enum_to_string(get_halide_looplevel_enum_map(), loop_level);
315 }
316 
317 // Convert a Halide Type into a string representation of its C source.
318 // e.g., Int(32) -> "Halide::Int(32)"
319 EXPORT std::string halide_type_to_c_source(const Type &t);
320 
321 // Convert a Halide Type into a string representation of its C Source.
322 // e.g., Int(32) -> "int32_t"
323 EXPORT std::string halide_type_to_c_type(const Type &t);
324 
325 /** generate_filter_main() is a convenient wrapper for GeneratorRegistry::create() +
326  * compile_to_files(); it can be trivially wrapped by a "real" main() to produce a
327  * command-line utility for ahead-of-time filter compilation. */
328 EXPORT int generate_filter_main(int argc, char **argv, std::ostream &cerr);
329 
330 // select_type<> is to std::conditional as switch is to if:
331 // it allows a multiway compile-time type definition via the form
332 //
333 // select_type<cond<condition1, type1>,
334 // cond<condition2, type2>,
335 // ....
336 // cond<conditionN, typeN>>::type
337 //
338 // Note that the conditions are evaluated in order; the first evaluating to true
339 // is chosen.
340 //
341 // Note that if no conditions evaluate to true, the resulting type is illegal
342 // and will produce a compilation error. (You can provide a default by simply
343 // using cond<true, SomeType> as the final entry.)
344 template<bool B, typename T>
345 struct cond {
346  static constexpr bool value = B;
347  using type = T;
348 };
349 
350 template <typename First, typename... Rest>
351 struct select_type : std::conditional<First::value, typename First::type, typename select_type<Rest...>::type> { };
352 
353 template<typename First>
354 struct select_type<First> { using type = typename std::conditional<First::value, typename First::type, void>::type; };
355 
356 class GeneratorBase;
357 
359 public:
360  EXPORT explicit GeneratorParamBase(const std::string &name);
361  EXPORT virtual ~GeneratorParamBase();
362 
363  const std::string name;
364 
365  // overload the set() function to call the right virtual method based on type.
366  // This allows us to attempt to set a GeneratorParam via a
367  // plain C++ type, even if we don't know the specific templated
368  // subclass. Attempting to set the wrong type will assert.
369  // Notice that there is no typed setter for Enums, for obvious reasons;
370  // setting enums in an unknown type must fallback to using set_from_string.
371  //
372  // It's always a bit iffy to use macros for this, but IMHO it clarifies the situation here.
373 #define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
374  virtual void set(const TYPE &new_value) = 0;
375 
390 
391 #undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
392 
393  // Add overloads for string and char*
394  void set(const std::string &new_value) { set_from_string(new_value); }
395  void set(const char *new_value) { set_from_string(std::string(new_value)); }
396 
397 protected:
398  friend class GeneratorBase;
399  friend class StubEmitter;
400 
401  EXPORT void check_value_readable() const;
402  EXPORT void check_value_writable() const;
403 
404  // All GeneratorParams are settable from string.
405  virtual void set_from_string(const std::string &value_string) = 0;
406 
407  virtual std::string to_string() const = 0;
408  virtual std::string call_to_string(const std::string &v) const = 0;
409  virtual std::string get_c_type() const = 0;
410 
411  virtual std::string get_type_decls() const {
412  return "";
413  }
414 
415  virtual std::string get_default_value() const {
416  return to_string();
417  }
418 
419  virtual std::string get_template_type() const {
420  return get_c_type();
421  }
422 
423  virtual std::string get_template_value() const {
424  return get_default_value();
425  }
426 
427  virtual bool is_synthetic_param() const {
428  return false;
429  }
430 
431  EXPORT void fail_wrong_type(const char *type);
432 
433 private:
434  explicit GeneratorParamBase(const GeneratorParamBase &) = delete;
435  void operator=(const GeneratorParamBase &) = delete;
436 
437  // Generator which owns this GeneratorParam. Note that this will be null
438  // initially; the GeneratorBase itself will set this field when it initially
439  // builds its info about params. However, since it (generally) isn't
440  // appropriate for GeneratorParam<> to be declared outside of a Generator,
441  // all reasonable non-testing code should expect this to be non-null.
442  GeneratorBase *generator{nullptr};
443 };
444 
445 template<typename T>
446 class GeneratorParamImpl : public GeneratorParamBase {
447 public:
448  using type = T;
449 
450  GeneratorParamImpl(const std::string &name, const T &value) : GeneratorParamBase(name), value_(value) {}
451 
452  T value() const { check_value_readable(); return value_; }
453 
454  operator T() const { return this->value(); }
455 
456  operator Expr() const { return make_const(type_of<T>(), this->value()); }
457 
458 #define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
459  void set(const TYPE &new_value) override { typed_setter_impl<TYPE>(new_value, #TYPE); }
460 
475 
476 #undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
477 
478 protected:
479  virtual void set_impl(const T &new_value) { check_value_writable(); value_ = new_value; }
480 
481 private:
482  T value_;
483 
484  template <typename T2, typename std::enable_if<std::is_convertible<T2, T>::value &&
485  !std::is_same<T2, MachineParams>::value>::type * = nullptr>
486  HALIDE_ALWAYS_INLINE void typed_setter_impl(const T2 &value, const char * msg) {
487  check_value_writable();
488  // Arithmetic types must roundtrip losslessly.
489  if (!std::is_same<T, T2>::value &&
490  std::is_arithmetic<T>::value &&
491  std::is_arithmetic<T2>::value) {
492  const T t = Convert<T2, T>::value(value);
493  const T2 t2 = Convert<T, T2>::value(t);
494  if (t2 != value) {
495  fail_wrong_type(msg);
496  }
497  }
498  value_ = Convert<T2, T>::value(value);
499  }
500 
501  template <typename T2, typename std::enable_if<!std::is_convertible<T2, T>::value>::type * = nullptr>
502  HALIDE_ALWAYS_INLINE void typed_setter_impl(const T2 &, const char *msg) {
503  fail_wrong_type(msg);
504  }
505 
506  template <typename T2, typename std::enable_if<std::is_same<T2, MachineParams>::value &&
507  std::is_same<T, MachineParams>::value>::type * = nullptr>
508  HALIDE_ALWAYS_INLINE void typed_setter_impl(const T2 &value, const char *msg) {
509  value_ = value;
510  }
511 };
512 
513 // Stubs for type-specific implementations of GeneratorParam, to avoid
514 // many complex enable_if<> statements that were formerly spread through the
515 // implementation. Note that not all of these need to be templated classes,
516 // (e.g. for GeneratorParam_Target, T == Target always), but are declared
517 // that way for symmetry of declaration.
518 template<typename T>
520 public:
521  GeneratorParam_Target(const std::string &name, const T &value) : GeneratorParamImpl<T>(name, value) {}
522 
523  void set_from_string(const std::string &new_value_string) override {
524  this->set(Target(new_value_string));
525  }
526 
527  std::string to_string() const override {
528  return this->value().to_string();
529  }
530 
531  std::string call_to_string(const std::string &v) const override {
532  std::ostringstream oss;
533  oss << v << ".to_string()";
534  return oss.str();
535  }
536 
537  std::string get_c_type() const override {
538  return "Target";
539  }
540 };
541 
542 template<typename T>
544 public:
545  GeneratorParam_MachineParams(const std::string &name, const T &value) : GeneratorParamImpl<T>(name, value) {}
546 
547  void set_from_string(const std::string &new_value_string) override {
548  this->set(MachineParams(new_value_string));
549  }
550 
551  std::string to_string() const override {
552  return this->value().to_string();
553  }
554 
555  std::string call_to_string(const std::string &v) const override {
556  std::ostringstream oss;
557  oss << v << ".to_string()";
558  return oss.str();
559  }
560 
561  std::string get_c_type() const override {
562  return "MachineParams";
563  }
564 };
565 
566 template<typename T>
568 public:
569  GeneratorParam_Arithmetic(const std::string &name,
570  const T &value,
571  const T &min = std::numeric_limits<T>::lowest(),
572  const T &max = std::numeric_limits<T>::max())
573  : GeneratorParamImpl<T>(name, value), min(min), max(max) {
574  // call set() to ensure value is clamped to min/max
575  this->set(value);
576  }
577 
578  void set_impl(const T &new_value) override {
579  user_assert(new_value >= min && new_value <= max) << "Value out of range: " << new_value;
581  }
582 
583  void set_from_string(const std::string &new_value_string) override {
584  std::istringstream iss(new_value_string);
585  T t;
586  iss >> t;
587  user_assert(!iss.fail() && iss.get() == EOF) << "Unable to parse: " << new_value_string;
588  this->set(t);
589  }
590 
591  std::string to_string() const override {
592  std::ostringstream oss;
593  oss << this->value();
594  if (std::is_same<T, float>::value) {
595  // If the constant has no decimal point ("1")
596  // we must append one before appending "f"
597  if (oss.str().find(".") == std::string::npos) {
598  oss << ".";
599  }
600  oss << "f";
601  }
602  return oss.str();
603  }
604 
605  std::string call_to_string(const std::string &v) const override {
606  std::ostringstream oss;
607  oss << "std::to_string(" << v << ")";
608  return oss.str();
609  }
610 
611  std::string get_c_type() const override {
612  std::ostringstream oss;
613  if (std::is_same<T, float>::value) {
614  return "float";
615  } else if (std::is_same<T, double>::value) {
616  return "double";
617  } else if (std::is_integral<T>::value) {
618  if (std::is_unsigned<T>::value) oss << 'u';
619  oss << "int" << (sizeof(T) * 8) << "_t";
620  return oss.str();
621  } else {
622  user_error << "Unknown arithmetic type\n";
623  return "";
624  }
625  }
626 
627 private:
628  const T min, max;
629 };
630 
631 template<typename T>
633 public:
634  GeneratorParam_Bool(const std::string &name, const T &value) : GeneratorParam_Arithmetic<T>(name, value) {}
635 
636  void set_from_string(const std::string &new_value_string) override {
637  bool v = false;
638  if (new_value_string == "true") {
639  v = true;
640  } else if (new_value_string == "false") {
641  v = false;
642  } else {
643  user_assert(false) << "Unable to parse bool: " << new_value_string;
644  }
645  this->set(v);
646  }
647 
648  std::string to_string() const override {
649  return this->value() ? "true" : "false";
650  }
651 
652  std::string call_to_string(const std::string &v) const override {
653  std::ostringstream oss;
654  oss << "(" << v << ") ? \"true\" : \"false\"";
655  return oss.str();
656  }
657 
658  std::string get_c_type() const override {
659  return "bool";
660  }
661 };
662 
663 template<typename T>
665 public:
666  GeneratorParam_Enum(const std::string &name, const T &value, const std::map<std::string, T> &enum_map)
667  : GeneratorParamImpl<T>(name, value), enum_map(enum_map) {}
668 
669  // define a "set" that takes our specific enum (but don't hide the inherited virtual functions)
671 
672  template <typename T2 = T, typename std::enable_if<!std::is_same<T2, Type>::value>::type * = nullptr>
673  void set(const T &e) {
674  this->set_impl(e);
675  }
676 
677  void set_from_string(const std::string &new_value_string) override {
678  auto it = enum_map.find(new_value_string);
679  user_assert(it != enum_map.end()) << "Enumeration value not found: " << new_value_string;
680  this->set_impl(it->second);
681  }
682 
683  std::string to_string() const override {
684  return enum_to_string(enum_map, this->value());
685  }
686 
687  std::string call_to_string(const std::string &v) const override {
688  return "Enum_" + this->name + "_map().at(" + v + ")";
689  }
690 
691  std::string get_c_type() const override {
692  return "Enum_" + this->name;
693  }
694 
695  std::string get_default_value() const override {
696  return "Enum_" + this->name + "::" + enum_to_string(enum_map, this->value());
697  }
698 
699  std::string get_type_decls() const override {
700  std::ostringstream oss;
701  oss << "enum class Enum_" << this->name << " {\n";
702  for (auto key_value : enum_map) {
703  oss << " " << key_value.first << ",\n";
704  }
705  oss << "};\n";
706  oss << "\n";
707 
708  // TODO: since we generate the enums, we could probably just use a vector (or array!) rather than a map,
709  // since we can ensure that the enum values are a nice tight range.
710  oss << "inline NO_INLINE const std::map<Enum_" << this->name << ", std::string>& Enum_" << this->name << "_map() {\n";
711  oss << " static const std::map<Enum_" << this->name << ", std::string> m = {\n";
712  for (auto key_value : enum_map) {
713  oss << " { Enum_" << this->name << "::" << key_value.first << ", \"" << key_value.first << "\"},\n";
714  }
715  oss << " };\n";
716  oss << " return m;\n";
717  oss << "};\n";
718  return oss.str();
719  }
720 
721 private:
722  const std::map<std::string, T> enum_map;
723 };
724 
725 template<typename T>
727 public:
728  GeneratorParam_Type(const std::string &name, const T &value)
729  : GeneratorParam_Enum<T>(name, value, get_halide_type_enum_map()) {}
730 
731  std::string call_to_string(const std::string &v) const override {
732  return "Halide::Internal::halide_type_to_enum_string(" + v + ")";
733  }
734 
735  std::string get_c_type() const override {
736  return "Type";
737  }
738 
739  std::string get_template_type() const override {
740  return "typename";
741  }
742 
743  std::string get_template_value() const override {
744  return halide_type_to_c_type(this->value());
745  }
746 
747  std::string get_default_value() const override {
748  return halide_type_to_c_source(this->value());
749  }
750 
751  std::string get_type_decls() const override {
752  return "";
753  }
754 };
755 
756 template<typename T>
758  typename select_type<
765  >::type;
766 
767 } // namespace Internal
768 
769 /** GeneratorParam is a templated class that can be used to modify the behavior
770  * of the Generator at code-generation time. GeneratorParams are commonly
771  * specified in build files (e.g. Makefile) to customize the behavior of
772  * a given Generator, thus they have a very constrained set of types to allow
773  * for efficient specification via command-line flags. A GeneratorParam can be:
774  * - any float or int type.
775  * - bool
776  * - enum
777  * - Halide::Target
778  * - Halide::Type
779  * All GeneratorParams have a default value. Arithmetic types can also
780  * optionally specify min and max. Enum types must specify a string-to-value
781  * map.
782  *
783  * Halide::Type is treated as though it were an enum, with the mappings:
784  *
785  * "int8" Halide::Int(8)
786  * "int16" Halide::Int(16)
787  * "int32" Halide::Int(32)
788  * "uint8" Halide::UInt(8)
789  * "uint16" Halide::UInt(16)
790  * "uint32" Halide::UInt(32)
791  * "float32" Halide::Float(32)
792  * "float64" Halide::Float(64)
793  *
794  * No vector Types are currently supported by this mapping.
795  *
796  */
797 template <typename T>
799 public:
800  GeneratorParam(const std::string &name, const T &value)
801  : Internal::GeneratorParamImplBase<T>(name, value) {}
802 
803  GeneratorParam(const std::string &name, const T &value, const T &min, const T &max)
804  : Internal::GeneratorParamImplBase<T>(name, value, min, max) {}
805 
806  GeneratorParam(const std::string &name, const T &value, const std::map<std::string, T> &enum_map)
807  : Internal::GeneratorParamImplBase<T>(name, value, enum_map) {}
808 
809  GeneratorParam(const std::string &name, const std::string &value)
810  : Internal::GeneratorParamImplBase<T>(name, value) {}
811 };
812 
813 
814 /** Addition between GeneratorParam<T> and any type that supports operator+ with T.
815  * Returns type of underlying operator+. */
816 // @{
817 template <typename Other, typename T>
818 decltype((Other)0 + (T)0) operator+(const Other &a, const GeneratorParam<T> &b) { return a + (T)b; }
819 template <typename Other, typename T>
820 decltype((T)0 + (Other)0) operator+(const GeneratorParam<T> &a, const Other & b) { return (T)a + b; }
821 // @}
822 
823 /** Subtraction between GeneratorParam<T> and any type that supports operator- with T.
824  * Returns type of underlying operator-. */
825 // @{
826 template <typename Other, typename T>
827 decltype((Other)0 - (T)0) operator-(const Other & a, const GeneratorParam<T> &b) { return a - (T)b; }
828 template <typename Other, typename T>
829 decltype((T)0 - (Other)0) operator-(const GeneratorParam<T> &a, const Other & b) { return (T)a - b; }
830 // @}
831 
832 /** Multiplication between GeneratorParam<T> and any type that supports operator* with T.
833  * Returns type of underlying operator*. */
834 // @{
835 template <typename Other, typename T>
836 decltype((Other)0 * (T)0) operator*(const Other &a, const GeneratorParam<T> &b) { return a * (T)b; }
837 template <typename Other, typename T>
838 decltype((Other)0 * (T)0) operator*(const GeneratorParam<T> &a, const Other &b) { return (T)a * b; }
839 // @}
840 
841 /** Division between GeneratorParam<T> and any type that supports operator/ with T.
842  * Returns type of underlying operator/. */
843 // @{
844 template <typename Other, typename T>
845 decltype((Other)0 / (T)1) operator/(const Other &a, const GeneratorParam<T> &b) { return a / (T)b; }
846 template <typename Other, typename T>
847 decltype((T)0 / (Other)1) operator/(const GeneratorParam<T> &a, const Other &b) { return (T)a / b; }
848 // @}
849 
850 /** Modulo between GeneratorParam<T> and any type that supports operator% with T.
851  * Returns type of underlying operator%. */
852 // @{
853 template <typename Other, typename T>
854 decltype((Other)0 % (T)1) operator%(const Other &a, const GeneratorParam<T> &b) { return a % (T)b; }
855 template <typename Other, typename T>
856 decltype((T)0 % (Other)1) operator%(const GeneratorParam<T> &a, const Other &b) { return (T)a % b; }
857 // @}
858 
859 /** Greater than comparison between GeneratorParam<T> and any type that supports operator> with T.
860  * Returns type of underlying operator>. */
861 // @{
862 template <typename Other, typename T>
863 decltype((Other)0 > (T)1) operator>(const Other &a, const GeneratorParam<T> &b) { return a > (T)b; }
864 template <typename Other, typename T>
865 decltype((T)0 > (Other)1) operator>(const GeneratorParam<T> &a, const Other &b) { return (T)a > b; }
866 // @}
867 
868 /** Less than comparison between GeneratorParam<T> and any type that supports operator< with T.
869  * Returns type of underlying operator<. */
870 // @{
871 template <typename Other, typename T>
872 decltype((Other)0 < (T)1) operator<(const Other &a, const GeneratorParam<T> &b) { return a < (T)b; }
873 template <typename Other, typename T>
874 decltype((T)0 < (Other)1) operator<(const GeneratorParam<T> &a, const Other &b) { return (T)a < b; }
875 // @}
876 
877 /** Greater than or equal comparison between GeneratorParam<T> and any type that supports operator>= with T.
878  * Returns type of underlying operator>=. */
879 // @{
880 template <typename Other, typename T>
881 decltype((Other)0 >= (T)1) operator>=(const Other &a, const GeneratorParam<T> &b) { return a >= (T)b; }
882 template <typename Other, typename T>
883 decltype((T)0 >= (Other)1) operator>=(const GeneratorParam<T> &a, const Other &b) { return (T)a >= b; }
884 // @}
885 
886 /** Less than or equal comparison between GeneratorParam<T> and any type that supports operator<= with T.
887  * Returns type of underlying operator<=. */
888 // @{
889 template <typename Other, typename T>
890 decltype((Other)0 <= (T)1) operator<=(const Other &a, const GeneratorParam<T> &b) { return a <= (T)b; }
891 template <typename Other, typename T>
892 decltype((T)0 <= (Other)1) operator<=(const GeneratorParam<T> &a, const Other &b) { return (T)a <= b; }
893 // @}
894 
895 /** Equality comparison between GeneratorParam<T> and any type that supports operator== with T.
896  * Returns type of underlying operator==. */
897 // @{
898 template <typename Other, typename T>
899 decltype((Other)0 == (T)1) operator==(const Other &a, const GeneratorParam<T> &b) { return a == (T)b; }
900 template <typename Other, typename T>
901 decltype((T)0 == (Other)1) operator==(const GeneratorParam<T> &a, const Other &b) { return (T)a == b; }
902 // @}
903 
904 /** Inequality comparison between between GeneratorParam<T> and any type that supports operator!= with T.
905  * Returns type of underlying operator!=. */
906 // @{
907 template <typename Other, typename T>
908 decltype((Other)0 != (T)1) operator!=(const Other &a, const GeneratorParam<T> &b) { return a != (T)b; }
909 template <typename Other, typename T>
910 decltype((T)0 != (Other)1) operator!=(const GeneratorParam<T> &a, const Other &b) { return (T)a != b; }
911 // @}
912 
913 /** Logical and between between GeneratorParam<T> and any type that supports operator&& with T.
914  * Returns type of underlying operator&&. */
915 // @{
916 template <typename Other, typename T>
917 decltype((Other)0 && (T)1) operator&&(const Other &a, const GeneratorParam<T> &b) { return a && (T)b; }
918 template <typename Other, typename T>
919 decltype((T)0 && (Other)1) operator&&(const GeneratorParam<T> &a, const Other &b) { return (T)a && b; }
920 // @}
921 
922 /** Logical or between between GeneratorParam<T> and any type that supports operator&& with T.
923  * Returns type of underlying operator||. */
924 // @{
925 template <typename Other, typename T>
926 decltype((Other)0 || (T)1) operator||(const Other &a, const GeneratorParam<T> &b) { return a || (T)b; }
927 template <typename Other, typename T>
928 decltype((T)0 || (Other)1) operator||(const GeneratorParam<T> &a, const Other &b) { return (T)a || b; }
929 // @}
930 
931 /* min and max are tricky as the language support for these is in the std
932  * namespace. In order to make this work, forwarding functions are used that
933  * are declared in a namespace that has std::min and std::max in scope.
934  */
935 namespace Internal { namespace GeneratorMinMax {
936 
937 using std::max;
938 using std::min;
939 
940 template <typename Other, typename T>
941 decltype(min((Other)0, (T)1)) min_forward(const Other &a, const GeneratorParam<T> &b) { return min(a, (T)b); }
942 template <typename Other, typename T>
943 decltype(min((T)0, (Other)1)) min_forward(const GeneratorParam<T> &a, const Other &b) { return min((T)a, b); }
944 
945 template <typename Other, typename T>
946 decltype(max((Other)0, (T)1)) max_forward(const Other &a, const GeneratorParam<T> &b) { return max(a, (T)b); }
947 template <typename Other, typename T>
948 decltype(max((T)0, (Other)1)) max_forward(const GeneratorParam<T> &a, const Other &b) { return max((T)a, b); }
949 
950 }}
951 
952 /** Compute minimum between GeneratorParam<T> and any type that supports min with T.
953  * Will automatically import std::min. Returns type of underlying min call. */
954 // @{
955 template <typename Other, typename T>
956 auto min(const Other &a, const GeneratorParam<T> &b) -> decltype(Internal::GeneratorMinMax::min_forward(a, b)) {
958 }
959 template <typename Other, typename T>
960 auto min(const GeneratorParam<T> &a, const Other &b) -> decltype(Internal::GeneratorMinMax::min_forward(a, b)) {
962 }
963 // @}
964 
965 /** Compute the maximum value between GeneratorParam<T> and any type that supports max with T.
966  * Will automatically import std::max. Returns type of underlying max call. */
967 // @{
968 template <typename Other, typename T>
969 auto max(const Other &a, const GeneratorParam<T> &b) -> decltype(Internal::GeneratorMinMax::max_forward(a, b)) {
971 }
972 template <typename Other, typename T>
973 auto max(const GeneratorParam<T> &a, const Other &b) -> decltype(Internal::GeneratorMinMax::max_forward(a, b)) {
975 }
976 // @}
977 
978 /** Not operator for GeneratorParam */
979 template <typename T>
980 decltype(!(T)0) operator!(const GeneratorParam<T> &a) { return !(T)a; }
981 
982 namespace Internal {
983 
984 template<typename T2> class GeneratorInput_Buffer;
985 
986 enum class IOKind { Scalar, Function, Buffer };
987 
988 /**
989  * StubInputBuffer is the placeholder that a Stub uses when it requires
990  * a Buffer for an input (rather than merely a Func or Expr). It is constructed
991  * to allow only two possible sorts of input:
992  * -- Assignment of an Input<Buffer<>>, with compatible type and dimensions,
993  * essentially allowing us to pipe a parameter from an enclosing Generator to an internal Stub.
994  * -- Assignment of a Buffer<>, with compatible type and dimensions,
995  * causing the Input<Buffer<>> to become a precompiled buffer in the generated code.
996  */
997 template<typename T = void>
999  friend class StubInput;
1000  template<typename T2> friend class GeneratorInput_Buffer;
1001 
1002  Parameter parameter_;
1003 
1004  NO_INLINE explicit StubInputBuffer(const Parameter &p) : parameter_(p) {
1005  // Create an empty 1-element buffer with the right runtime typing and dimensions,
1006  // which we'll use only to pass to can_convert_from() to verify this
1007  // Parameter is compatible with our constraints.
1008  Buffer<> other(p.type(), nullptr, std::vector<int>(p.dimensions(), 1));
1010  }
1011 
1012  template<typename T2>
1013  NO_INLINE static Parameter parameter_from_buffer(const Buffer<T2> &b) {
1015  Parameter p(b.type(), true, b.dimensions());
1016  p.set_buffer(b);
1017  return p;
1018  }
1019 
1020 public:
1022 
1023  // *not* explicit -- this ctor should only be used when you want
1024  // to pass a literal Buffer<> for a Stub Input; this Buffer<> will be
1025  // compiled into the Generator's product, rather than becoming
1026  // a runtime Parameter.
1027  template<typename T2>
1028  StubInputBuffer(const Buffer<T2> &b) : parameter_(parameter_from_buffer(b)) {}
1029 };
1030 
1032 protected:
1034  std::shared_ptr<GeneratorBase> generator;
1035 
1036  EXPORT void check_scheduled(const char* m) const;
1037  EXPORT Target get_target() const;
1038 
1039  explicit StubOutputBufferBase(const Func &f, std::shared_ptr<GeneratorBase> generator) : f(f), generator(generator) {}
1041 
1042 public:
1043  Realization realize(std::vector<int32_t> sizes) {
1044  check_scheduled("realize");
1045  return f.realize(sizes, get_target());
1046  }
1047 
1048  template <typename... Args>
1049  Realization realize(Args&&... args) {
1050  check_scheduled("realize");
1051  return f.realize(std::forward<Args>(args)..., get_target());
1052  }
1053 
1054  template<typename Dst>
1055  void realize(Dst dst) {
1056  check_scheduled("realize");
1057  f.realize(dst, get_target());
1058  }
1059 };
1060 
1061 /**
1062  * StubOutputBuffer is the placeholder that a Stub uses when it requires
1063  * a Buffer for an output (rather than merely a Func). It is constructed
1064  * to allow only two possible sorts of things:
1065  * -- Assignment to an Output<Buffer<>>, with compatible type and dimensions,
1066  * essentially allowing us to pipe a parameter from the result of a Stub to an
1067  * enclosing Generator
1068  * -- Realization into a Buffer<>; this is useful only in JIT compilation modes
1069  * (and shouldn't be usable otherwise)
1070  *
1071  * It is deliberate that StubOutputBuffer is not (easily) convertible to Func.
1072  */
1073 template<typename T = void>
1075  template<typename T2> friend class GeneratorOutput_Buffer;
1076  friend class GeneratorStub;
1077  explicit StubOutputBuffer(const Func &f, std::shared_ptr<GeneratorBase> generator) : StubOutputBufferBase(f, generator) {}
1078 public:
1080 };
1081 
1082 // This is a union-like class that allows for convenient initialization of Stub Inputs
1083 // via C++11 initializer-list syntax; it is only used in situations where the
1084 // downstream consumer will be able to explicitly check that each value is
1085 // of the expected/required kind.
1086 class StubInput {
1087  const IOKind kind_;
1088  // Exactly one of the following fields should be defined:
1089  const Parameter parameter_;
1090  const Func func_;
1091  const Expr expr_;
1092 public:
1093  // *not* explicit.
1094  template<typename T2>
1095  StubInput(const StubInputBuffer<T2> &b) : kind_(IOKind::Buffer), parameter_(b.parameter_) {}
1096  StubInput(const Func &f) : kind_(IOKind::Function), func_(f) {}
1097  StubInput(const Expr &e) : kind_(IOKind::Scalar), expr_(e) {}
1098 
1099 private:
1100  friend class GeneratorInputBase;
1101 
1102  IOKind kind() const {
1103  return kind_;
1104  }
1105 
1106  Parameter parameter() const {
1107  internal_assert(kind_ == IOKind::Buffer);
1108  return parameter_;
1109  }
1110 
1111  Func func() const {
1113  return func_;
1114  }
1115 
1116  Expr expr() const {
1117  internal_assert(kind_ == IOKind::Scalar);
1118  return expr_;
1119  }
1120 };
1121 
1122 /** GIOBase is the base class for all GeneratorInput<> and GeneratorOutput<>
1123  * instantiations; it is not part of the public API and should never be
1124  * used directly by user code.
1125  *
1126  * Every GIOBase instance can be either a single value or an array-of-values;
1127  * each of these values can be an Expr or a Func. (Note that for an
1128  * array-of-values, the types/dimensions of all values in the array must match.)
1129  *
1130  * A GIOBase can have multiple Types, in which case it represents a Tuple.
1131  * (Note that Tuples are currently only supported for GeneratorOutput, but
1132  * it is likely that GeneratorInput will be extended to support Tuple as well.)
1133  *
1134  * The array-size, type(s), and dimensions can all be left "unspecified" at
1135  * creation time, in which case they may assume values provided by a Stub.
1136  * (It is important to note that attempting to use a GIOBase with unspecified
1137  * values will assert-fail; you must ensure that all unspecified values are
1138  * filled in prior to use.)
1139  */
1140 class GIOBase {
1141 public:
1142  EXPORT bool array_size_defined() const;
1143  EXPORT size_t array_size() const;
1144  EXPORT virtual bool is_array() const;
1145 
1146  EXPORT const std::string &name() const;
1147  EXPORT IOKind kind() const;
1148 
1149  EXPORT bool types_defined() const;
1150  EXPORT const std::vector<Type> &types() const;
1151  EXPORT Type type() const;
1152 
1153  EXPORT bool dims_defined() const;
1154  EXPORT int dims() const;
1155 
1156  EXPORT const std::vector<Func> &funcs() const;
1157  EXPORT const std::vector<Expr> &exprs() const;
1158 
1159 protected:
1160  EXPORT GIOBase(size_t array_size,
1161  const std::string &name,
1162  IOKind kind,
1163  const std::vector<Type> &types,
1164  int dims);
1165  EXPORT virtual ~GIOBase();
1166 
1167  friend class GeneratorBase;
1168 
1169  int array_size_; // always 1 if is_array() == false.
1170  // -1 if is_array() == true but unspecified.
1171 
1172  const std::string name_;
1173  const IOKind kind_;
1174  std::vector<Type> types_; // empty if type is unspecified
1175  int dims_; // -1 if dim is unspecified
1176 
1177  // Exactly one of these will have nonzero length
1178  std::vector<Func> funcs_;
1179  std::vector<Expr> exprs_;
1180 
1181  // Generator which owns this Input or Output. Note that this will be null
1182  // initially; the GeneratorBase itself will set this field when it initially
1183  // builds its info about params. However, since it isn't
1184  // appropriate for Input<> or Output<> to be declared outside of a Generator,
1185  // all reasonable non-testing code should expect this to be non-null.
1186  GeneratorBase *generator{nullptr};
1187 
1188  EXPORT std::string array_name(size_t i) const;
1189 
1190  EXPORT virtual void verify_internals() const;
1191 
1192  EXPORT void check_matching_array_size(size_t size);
1193  EXPORT void check_matching_type_and_dim(const std::vector<Type> &t, int d);
1194 
1195  template<typename ElemType>
1196  const std::vector<ElemType> &get_values() const;
1197 
1198  virtual void check_value_writable() const = 0;
1199 
1200 private:
1201  template<typename T> friend class GeneratorParam_Synthetic;
1202 
1203  explicit GIOBase(const GIOBase &) = delete;
1204  void operator=(const GIOBase &) = delete;
1205 };
1206 
1207 template<>
1208 inline const std::vector<Expr> &GIOBase::get_values<Expr>() const {
1209  return exprs();
1210 }
1211 
1212 template<>
1213 inline const std::vector<Func> &GIOBase::get_values<Func>() const {
1214  return funcs();
1215 }
1216 
1217 class GeneratorInputBase : public GIOBase {
1218 protected:
1219  EXPORT GeneratorInputBase(size_t array_size,
1220  const std::string &name,
1221  IOKind kind,
1222  const std::vector<Type> &t,
1223  int d);
1224 
1225  EXPORT GeneratorInputBase(const std::string &name, IOKind kind, const std::vector<Type> &t, int d);
1226 
1227  EXPORT ~GeneratorInputBase() override;
1228 
1229  friend class GeneratorBase;
1230 
1231  std::vector<Parameter> parameters_;
1232 
1233  EXPORT Parameter parameter() const;
1234 
1235  EXPORT void init_internals();
1236  EXPORT void set_inputs(const std::vector<StubInput> &inputs);
1237 
1238  EXPORT virtual void set_def_min_max();
1239 
1240  EXPORT void verify_internals() const override;
1241 
1242  friend class StubEmitter;
1243 
1244  virtual std::string get_c_type() const = 0;
1245 
1246  EXPORT void check_value_writable() const override;
1247 
1248  EXPORT void estimate_impl(Var var, Expr min, Expr extent);
1249 };
1250 
1251 
1252 template<typename T, typename ValueType>
1254 protected:
1255  using TBase = typename std::remove_all_extents<T>::type;
1256 
1257  bool is_array() const override {
1258  return std::is_array<T>::value;
1259  }
1260 
1261  template <typename T2 = T, typename std::enable_if<
1262  // Only allow T2 not-an-array
1263  !std::is_array<T2>::value
1264  >::type * = nullptr>
1265  GeneratorInputImpl(const std::string &name, IOKind kind, const std::vector<Type> &t, int d)
1266  : GeneratorInputBase(name, kind, t, d) {
1267  }
1268 
1269  template <typename T2 = T, typename std::enable_if<
1270  // Only allow T2[kSomeConst]
1271  std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)
1272  >::type * = nullptr>
1273  GeneratorInputImpl(const std::string &name, IOKind kind, const std::vector<Type> &t, int d)
1274  : GeneratorInputBase(std::extent<T2, 0>::value, name, kind, t, d) {
1275  }
1276 
1277  template <typename T2 = T, typename std::enable_if<
1278  // Only allow T2[]
1279  std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0
1280  >::type * = nullptr>
1281  GeneratorInputImpl(const std::string &name, IOKind kind, const std::vector<Type> &t, int d)
1282  : GeneratorInputBase(-1, name, kind, t, d) {
1283  }
1284 
1285 public:
1286  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1287  size_t size() const {
1288  return get_values<ValueType>().size();
1289  }
1290 
1291  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1292  const ValueType &operator[](size_t i) const {
1293  return get_values<ValueType>()[i];
1294  }
1295 
1296  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1297  const ValueType &at(size_t i) const {
1298  return get_values<ValueType>().at(i);
1299  }
1300 
1301  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1302  typename std::vector<ValueType>::const_iterator begin() const {
1303  return get_values<ValueType>().begin();
1304  }
1305 
1306  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1307  typename std::vector<ValueType>::const_iterator end() const {
1308  return get_values<ValueType>().end();
1309  }
1310 };
1311 
1312 template<typename T>
1313 class GeneratorInput_Buffer : public GeneratorInputImpl<T, Func> {
1314 private:
1315  using Super = GeneratorInputImpl<T, Func>;
1316 
1317 protected:
1318  using TBase = typename Super::TBase;
1319 
1320  friend class ::Halide::Func;
1321  friend class ::Halide::Stage;
1322 
1323  std::string get_c_type() const override {
1324  if (TBase::has_static_halide_type) {
1325  return "Halide::Internal::StubInputBuffer<" +
1326  halide_type_to_c_type(TBase::static_halide_type()) +
1327  ">";
1328  } else {
1329  return "Halide::Internal::StubInputBuffer<>";
1330  }
1331  }
1332 
1333  static_assert(!std::is_array<T>::value, "Input<Buffer<>[]> is not a legal construct.");
1334 
1335 public:
1336  GeneratorInput_Buffer(const std::string &name)
1337  : Super(name, IOKind::Buffer,
1338  TBase::has_static_halide_type ? std::vector<Type>{ TBase::static_halide_type() } : std::vector<Type>{},
1339  -1) {
1340  }
1341 
1342  GeneratorInput_Buffer(const std::string &name, const Type &t, int d = -1)
1343  : Super(name, IOKind::Buffer, {t}, d) {
1344  static_assert(!TBase::has_static_halide_type, "Cannot use pass a Type argument for a Buffer with a non-void static type");
1345  }
1346 
1347  GeneratorInput_Buffer(const std::string &name, int d)
1348  : Super(name, IOKind::Buffer, TBase::has_static_halide_type ? std::vector<Type>{ TBase::static_halide_type() } : std::vector<Type>{}, d) {
1349  }
1350 
1351 
1352  template <typename... Args>
1353  Expr operator()(Args&&... args) const {
1354  return Func(*this)(std::forward<Args>(args)...);
1355  }
1356 
1357  Expr operator()(std::vector<Expr> args) const {
1358  return Func(*this)(args);
1359  }
1360 
1361  template<typename T2>
1362  operator StubInputBuffer<T2>() const {
1363  return StubInputBuffer<T2>(this->parameter());
1364  }
1365 
1366  operator Func() const {
1367  return this->funcs().at(0);
1368  }
1369 
1370  operator ExternFuncArgument() const {
1371  return ExternFuncArgument(this->parameters_.at(0));
1372  }
1373 
1375  this->estimate_impl(var, min, extent);
1376  return *this;
1377  }
1378 
1379  Func in() {
1380  return Func(*this).in();
1381  }
1382 
1383  Func in(Func other) {
1384  return Func(*this).in(other);
1385  }
1386 
1387  Func in(const std::vector<Func> &others) {
1388  return Func(*this).in(others);
1389  }
1390 
1391  operator ImageParam() const {
1392  return ImageParam(this->parameter(), Func(*this));
1393  }
1394 
1395 #define HALIDE_INPUT_FORWARD(method) \
1396  template<typename ...Args> \
1397  inline auto method(Args&&... args) -> \
1398  decltype(std::declval<ImageParam>().method(std::forward<Args>(args)...)) {\
1399  return ((ImageParam) *this).method(std::forward<Args>(args)...); \
1400  }
1401 
1402 #define HALIDE_INPUT_FORWARD_CONST(method) \
1403  template<typename ...Args> \
1404  inline auto method(Args&&... args) const -> \
1405  decltype(std::declval<ImageParam>().method(std::forward<Args>(args)...)) {\
1406  return ((ImageParam) *this).method(std::forward<Args>(args)...); \
1407  }
1408 
1409  /** Forward methods to the ImageParam. */
1410  // @{
1413  HALIDE_INPUT_FORWARD_CONST(host_alignment)
1414  HALIDE_INPUT_FORWARD(set_host_alignment)
1415  HALIDE_INPUT_FORWARD_CONST(dimensions)
1422  HALIDE_INPUT_FORWARD_CONST(channels)
1423  // }@
1424 
1425 #undef HALIDE_INPUT_FORWARD
1426 #undef HALIDE_INPUT_FORWARD_CONST
1427 };
1428 
1429 
1430 template<typename T>
1431 class GeneratorInput_Func : public GeneratorInputImpl<T, Func> {
1432 private:
1434 
1435 protected:
1436  using TBase = typename Super::TBase;
1437 
1438  std::string get_c_type() const override {
1439  return "Func";
1440  }
1441 
1442 public:
1443  GeneratorInput_Func(const std::string &name, const Type &t, int d)
1444  : Super(name, IOKind::Function, {t}, d) {
1445  }
1446 
1447  // unspecified type
1448  GeneratorInput_Func(const std::string &name, int d)
1449  : Super(name, IOKind::Function, {}, d) {
1450  }
1451 
1452  // unspecified dimension
1453  GeneratorInput_Func(const std::string &name, const Type &t)
1454  : Super(name, IOKind::Function, {t}, -1) {
1455  }
1456 
1457  // unspecified type & dimension
1458  GeneratorInput_Func(const std::string &name)
1459  : Super(name, IOKind::Function, {}, -1) {
1460  }
1461 
1462  GeneratorInput_Func(size_t array_size, const std::string &name, const Type &t, int d)
1463  : Super(array_size, name, IOKind::Function, {t}, d) {
1464  }
1465 
1466  // unspecified type
1467  GeneratorInput_Func(size_t array_size, const std::string &name, int d)
1468  : Super(array_size, name, IOKind::Function, {}, d) {
1469  }
1470 
1471  // unspecified dimension
1472  GeneratorInput_Func(size_t array_size, const std::string &name, const Type &t)
1473  : Super(array_size, name, IOKind::Function, {t}, -1) {
1474  }
1475 
1476  // unspecified type & dimension
1477  GeneratorInput_Func(size_t array_size, const std::string &name)
1478  : Super(array_size, name, IOKind::Function, {}, -1) {
1479  }
1480 
1481  template <typename... Args>
1482  Expr operator()(Args&&... args) const {
1483  return this->funcs().at(0)(std::forward<Args>(args)...);
1484  }
1485 
1486  Expr operator()(std::vector<Expr> args) const {
1487  return this->funcs().at(0)(args);
1488  }
1489 
1490  operator Func() const {
1491  return this->funcs().at(0);
1492  }
1493 
1494  operator ExternFuncArgument() const {
1495  return ExternFuncArgument(this->parameters_.at(0));
1496  }
1497 
1499  this->estimate_impl(var, min, extent);
1500  return *this;
1501  }
1502 
1503  Func in() {
1504  return Func(*this).in();
1505  }
1506 
1507  Func in(Func other) {
1508  return Func(*this).in(other);
1509  }
1510 
1511  Func in(const std::vector<Func> &others) {
1512  return Func(*this).in(others);
1513  }
1514 
1515 #define HALIDE_INPUT_FORWARD_CONST(method) \
1516  template<typename ...Args> \
1517  inline auto method(Args&&... args) const -> \
1518  decltype(std::declval<Func>().method(std::forward<Args>(args)...)) { \
1519  user_assert(this->funcs().size() == 1) << "Use operator[] to access the Func you want"; \
1520  return Func(*this).method(std::forward<Args>(args)...); \
1521  }
1522 
1523  /** Forward const methods to the underlying Func. (Non-const methods
1524  * aren't available for Input<Func>.) */
1525  // @{
1528  HALIDE_INPUT_FORWARD_CONST(has_update_definition)
1529  HALIDE_INPUT_FORWARD_CONST(num_update_definitions)
1530  HALIDE_INPUT_FORWARD_CONST(output_types)
1533  HALIDE_INPUT_FORWARD_CONST(update_args)
1534  HALIDE_INPUT_FORWARD_CONST(update_value)
1535  HALIDE_INPUT_FORWARD_CONST(update_values)
1538  // }@
1539 
1540 #undef HALIDE_INPUT_FORWARD
1541 #undef HALIDE_INPUT_FORWARD_CONST
1542 };
1543 
1544 
1545 template<typename T>
1547 private:
1549 protected:
1550  using TBase = typename Super::TBase;
1551 
1552  const TBase def_{TBase()};
1553 
1554 protected:
1555  void set_def_min_max() override {
1556  for (Parameter &p : this->parameters_) {
1557  p.set_scalar<TBase>(def_);
1558  }
1559  }
1560 
1561  std::string get_c_type() const override {
1562  return "Expr";
1563  }
1564 
1565 public:
1566  explicit GeneratorInput_Scalar(const std::string &name,
1567  const TBase &def = static_cast<TBase>(0))
1568  : Super(name, IOKind::Scalar, {type_of<TBase>()}, 0), def_(def) {
1569  }
1570 
1571  GeneratorInput_Scalar(size_t array_size,
1572  const std::string &name,
1573  const TBase &def = static_cast<TBase>(0))
1574  : Super(array_size, name, IOKind::Scalar, {type_of<TBase>()}, 0), def_(def) {
1575  }
1576 
1577  /** You can use this Input as an expression in a halide
1578  * function definition */
1579  operator Expr() const {
1580  return this->exprs().at(0);
1581  }
1582 
1583  /** Using an Input as the argument to an external stage treats it
1584  * as an Expr */
1585  operator ExternFuncArgument() const {
1586  return ExternFuncArgument(this->exprs().at(0));
1587  }
1588 
1589  void set_estimate(const T &value) {
1590  for (Parameter &p : this->parameters_) {
1591  p.set_estimate(Expr(value));
1592  }
1593  }
1594 };
1595 
1596 template<typename T>
1598 private:
1600 protected:
1601  using TBase = typename Super::TBase;
1602 
1603  const Expr min_, max_;
1604 
1605 protected:
1606  void set_def_min_max() override {
1608  // Don't set min/max for bool
1609  if (!std::is_same<TBase, bool>::value) {
1610  for (Parameter &p : this->parameters_) {
1611  if (min_.defined()) p.set_min_value(min_);
1612  if (max_.defined()) p.set_max_value(max_);
1613  }
1614  }
1615  }
1616 
1617 public:
1618  explicit GeneratorInput_Arithmetic(const std::string &name,
1619  const TBase &def = static_cast<TBase>(0))
1620  : Super(name, def), min_(Expr()), max_(Expr()) {
1621  }
1622 
1623  GeneratorInput_Arithmetic(size_t array_size,
1624  const std::string &name,
1625  const TBase &def = static_cast<TBase>(0))
1626  : Super(array_size, name, def), min_(Expr()), max_(Expr()) {
1627  }
1628 
1629  GeneratorInput_Arithmetic(const std::string &name,
1630  const TBase &def,
1631  const TBase &min,
1632  const TBase &max)
1633  : Super(name, def), min_(min), max_(max) {
1634  }
1635 
1636  GeneratorInput_Arithmetic(size_t array_size,
1637  const std::string &name,
1638  const TBase &def,
1639  const TBase &min,
1640  const TBase &max)
1641  : Super(array_size, name, def), min_(min), max_(max) {
1642  }
1643 };
1644 
1645 template<typename>
1646 struct type_sink { typedef void type; };
1647 
1648 template<typename T2, typename = void>
1649 struct has_static_halide_type_method : std::false_type {};
1650 
1651 template<typename T2>
1652 struct has_static_halide_type_method<T2, typename type_sink<decltype(T2::static_halide_type())>::type> : std::true_type {};
1653 
1654 template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
1655 using GeneratorInputImplBase =
1656  typename select_type<
1661  >::type;
1662 
1663 } // namespace Internal
1664 
1665 template <typename T>
1667 private:
1669 protected:
1670  using TBase = typename Super::TBase;
1671 
1672  // Trick to avoid ambiguous ctor between Func-with-dim and int-with-default-value;
1673  // since we can't use std::enable_if on ctors, define the argument to be one that
1674  // can only be properly resolved for TBase=Func.
1675  struct Unused;
1676  using IntIfNonScalar =
1677  typename Internal::select_type<
1681  >::type;
1682 
1683 public:
1684  explicit GeneratorInput(const std::string &name)
1685  : Super(name) {
1686  }
1687 
1688  GeneratorInput(const std::string &name, const TBase &def)
1689  : Super(name, def) {
1690  }
1691 
1692  GeneratorInput(size_t array_size, const std::string &name, const TBase &def)
1693  : Super(array_size, name, def) {
1694  }
1695 
1696  GeneratorInput(const std::string &name,
1697  const TBase &def, const TBase &min, const TBase &max)
1698  : Super(name, def, min, max) {
1699  }
1700 
1701  GeneratorInput(size_t array_size, const std::string &name,
1702  const TBase &def, const TBase &min, const TBase &max)
1703  : Super(array_size, name, def, min, max) {
1704  }
1705 
1706  GeneratorInput(const std::string &name, const Type &t, int d)
1707  : Super(name, t, d) {
1708  }
1709 
1710  GeneratorInput(const std::string &name, const Type &t)
1711  : Super(name, t) {
1712  }
1713 
1714  // Avoid ambiguity between Func-with-dim and int-with-default
1715  GeneratorInput(const std::string &name, IntIfNonScalar d)
1716  : Super(name, d) {
1717  }
1718 
1719  GeneratorInput(size_t array_size, const std::string &name, const Type &t, int d)
1720  : Super(array_size, name, t, d) {
1721  }
1722 
1723  GeneratorInput(size_t array_size, const std::string &name, const Type &t)
1724  : Super(array_size, name, t) {
1725  }
1726 
1727  // Avoid ambiguity between Func-with-dim and int-with-default
1728  //template <typename T2 = T, typename std::enable_if<std::is_same<TBase, Func>::value>::type * = nullptr>
1729  GeneratorInput(size_t array_size, const std::string &name, IntIfNonScalar d)
1730  : Super(array_size, name, d) {
1731  }
1732 
1733  GeneratorInput(size_t array_size, const std::string &name)
1734  : Super(array_size, name) {
1735  }
1736 };
1737 
1738 namespace Internal {
1739 
1740 
1742 public:
1743 #define HALIDE_OUTPUT_FORWARD(method) \
1744  template<typename ...Args> \
1745  inline auto method(Args&&... args) -> \
1746  decltype(std::declval<Func>().method(std::forward<Args>(args)...)) {\
1747  return get_func_ref().method(std::forward<Args>(args)...); \
1748  }
1749 
1750 #define HALIDE_OUTPUT_FORWARD_CONST(method) \
1751  template<typename ...Args> \
1752  inline auto method(Args&&... args) const -> \
1753  decltype(std::declval<Func>().method(std::forward<Args>(args)...)) {\
1754  return get_func_ref().method(std::forward<Args>(args)...); \
1755  }
1756 
1757  /** Forward schedule-related methods to the underlying Func. */
1758  // @{
1759  HALIDE_OUTPUT_FORWARD(align_bounds)
1760  HALIDE_OUTPUT_FORWARD(align_storage)
1762  HALIDE_OUTPUT_FORWARD(bound)
1763  HALIDE_OUTPUT_FORWARD(bound_extent)
1764  HALIDE_OUTPUT_FORWARD(compute_at)
1765  HALIDE_OUTPUT_FORWARD(compute_inline)
1766  HALIDE_OUTPUT_FORWARD(compute_root)
1767  HALIDE_OUTPUT_FORWARD(define_extern)
1769  HALIDE_OUTPUT_FORWARD(estimate)
1770  HALIDE_OUTPUT_FORWARD(fold_storage)
1771  HALIDE_OUTPUT_FORWARD(fuse)
1772  HALIDE_OUTPUT_FORWARD(glsl)
1774  HALIDE_OUTPUT_FORWARD(gpu_blocks)
1775  HALIDE_OUTPUT_FORWARD(gpu_single_thread)
1776  HALIDE_OUTPUT_FORWARD(gpu_threads)
1777  HALIDE_OUTPUT_FORWARD(gpu_tile)
1778  HALIDE_OUTPUT_FORWARD_CONST(has_update_definition)
1779  HALIDE_OUTPUT_FORWARD(hexagon)
1781  HALIDE_OUTPUT_FORWARD(memoize)
1782  HALIDE_OUTPUT_FORWARD_CONST(num_update_definitions)
1783  HALIDE_OUTPUT_FORWARD_CONST(output_types)
1785  HALIDE_OUTPUT_FORWARD(parallel)
1786  HALIDE_OUTPUT_FORWARD(prefetch)
1788  HALIDE_OUTPUT_FORWARD(rename)
1789  HALIDE_OUTPUT_FORWARD(reorder)
1790  HALIDE_OUTPUT_FORWARD(reorder_storage)
1792  HALIDE_OUTPUT_FORWARD(serial)
1793  HALIDE_OUTPUT_FORWARD(shader)
1794  HALIDE_OUTPUT_FORWARD(specialize)
1795  HALIDE_OUTPUT_FORWARD(specialize_fail)
1796  HALIDE_OUTPUT_FORWARD(split)
1797  HALIDE_OUTPUT_FORWARD(store_at)
1798  HALIDE_OUTPUT_FORWARD(store_root)
1799  HALIDE_OUTPUT_FORWARD(tile)
1800  HALIDE_OUTPUT_FORWARD(trace_stores)
1801  HALIDE_OUTPUT_FORWARD(unroll)
1802  HALIDE_OUTPUT_FORWARD(update)
1803  HALIDE_OUTPUT_FORWARD_CONST(update_args)
1804  HALIDE_OUTPUT_FORWARD_CONST(update_value)
1805  HALIDE_OUTPUT_FORWARD_CONST(update_values)
1808  HALIDE_OUTPUT_FORWARD(vectorize)
1809  // }@
1810 
1811 #undef HALIDE_OUTPUT_FORWARD
1812 #undef HALIDE_OUTPUT_FORWARD_CONST
1813 
1814 protected:
1815  EXPORT GeneratorOutputBase(size_t array_size,
1816  const std::string &name,
1817  IOKind kind,
1818  const std::vector<Type> &t,
1819  int d);
1820 
1821  EXPORT GeneratorOutputBase(const std::string &name,
1822  IOKind kind,
1823  const std::vector<Type> &t,
1824  int d);
1825 
1826  EXPORT ~GeneratorOutputBase() override;
1827 
1828  friend class GeneratorBase;
1829  friend class StubEmitter;
1830 
1831  EXPORT Parameter parameter() const;
1832 
1833  EXPORT void init_internals();
1834  EXPORT void resize(size_t size);
1835 
1836  virtual std::string get_c_type() const {
1837  return "Func";
1838  }
1839 
1840  EXPORT void check_value_writable() const override;
1841 
1843  internal_assert(kind() != IOKind::Scalar);
1844  internal_assert(exprs_.empty());
1845  user_assert(funcs_.size() == 1) << "Use [] to access individual Funcs in Output<Func[]>";
1846  return funcs_[0];
1847  }
1848 
1849  NO_INLINE const Func &get_func_ref() const {
1850  internal_assert(kind() != IOKind::Scalar);
1851  internal_assert(exprs_.empty());
1852  user_assert(funcs_.size() == 1) << "Use [] to access individual Funcs in Output<Func[]>";
1853  return funcs_[0];
1854  }
1855 };
1856 
1857 template<typename T>
1859 protected:
1860  using TBase = typename std::remove_all_extents<T>::type;
1861  using ValueType = Func;
1862 
1863  bool is_array() const override {
1864  return std::is_array<T>::value;
1865  }
1866 
1867  template <typename T2 = T, typename std::enable_if<
1868  // Only allow T2 not-an-array
1869  !std::is_array<T2>::value
1870  >::type * = nullptr>
1871  GeneratorOutputImpl(const std::string &name, IOKind kind, const std::vector<Type> &t, int d)
1872  : GeneratorOutputBase(name, kind, t, d) {
1873  }
1874 
1875  template <typename T2 = T, typename std::enable_if<
1876  // Only allow T2[kSomeConst]
1877  std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)
1878  >::type * = nullptr>
1879  GeneratorOutputImpl(const std::string &name, IOKind kind, const std::vector<Type> &t, int d)
1880  : GeneratorOutputBase(std::extent<T2, 0>::value, name, kind, t, d) {
1881  }
1882 
1883  template <typename T2 = T, typename std::enable_if<
1884  // Only allow T2[]
1885  std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0
1886  >::type * = nullptr>
1887  GeneratorOutputImpl(const std::string &name, IOKind kind, const std::vector<Type> &t, int d)
1888  : GeneratorOutputBase(-1, name, kind, t, d) {
1889  }
1890 
1891 public:
1892  template <typename... Args, typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * = nullptr>
1893  FuncRef operator()(Args&&... args) const {
1894  return get_values<ValueType>().at(0)(std::forward<Args>(args)...);
1895  }
1896 
1897  template <typename ExprOrVar, typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * = nullptr>
1898  FuncRef operator()(std::vector<ExprOrVar> args) const {
1899  return get_values<ValueType>().at(0)(args);
1900  }
1901 
1902  template <typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * = nullptr>
1903  operator Func() const {
1904  return get_values<ValueType>().at(0);
1905  }
1906 
1907  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1908  size_t size() const {
1909  return get_values<ValueType>().size();
1910  }
1911 
1912  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1913  const ValueType &operator[](size_t i) const {
1914  return get_values<ValueType>()[i];
1915  }
1916 
1917  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1918  const ValueType &at(size_t i) const {
1919  return get_values<ValueType>().at(i);
1920  }
1921 
1922  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1923  typename std::vector<ValueType>::const_iterator begin() const {
1924  return get_values<ValueType>().begin();
1925  }
1926 
1927  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
1928  typename std::vector<ValueType>::const_iterator end() const {
1929  return get_values<ValueType>().end();
1930  }
1931 
1932  template <typename T2 = T, typename std::enable_if<
1933  // Only allow T2[]
1934  std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0
1935  >::type * = nullptr>
1936  void resize(size_t size) {
1938  }
1939 };
1940 
1941 template<typename T>
1943 private:
1944  using Super = GeneratorOutputImpl<T>;
1945 
1946  NO_INLINE void assign_from_func(const Func &f) {
1947  this->check_value_writable();
1948 
1949  internal_assert(f.defined());
1950 
1951  const auto &output_types = f.output_types();
1952  user_assert(output_types.size() == 1)
1953  << "Output should have size=1 but saw size=" << output_types.size() << "\n";
1954 
1955  Buffer<> other(output_types.at(0), nullptr, std::vector<int>(f.dimensions(), 1));
1956  user_assert(T::can_convert_from(other))
1957  << "Cannot assign to the Output \"" << this->name()
1958  << "\": the expression is not convertible to the same Buffer type and/or dimensions.\n";
1959 
1960  if (this->types_defined()) {
1961  user_assert(output_types.at(0) == this->type())
1962  << "Output should have type=" << this->type() << " but saw type=" << output_types.at(0) << "\n";
1963  }
1964  if (this->dims_defined()) {
1965  user_assert(f.dimensions() == this->dims())
1966  << "Output should have dim=" << this->dims() << " but saw dim=" << f.dimensions() << "\n";
1967  }
1968 
1969  internal_assert(this->exprs_.empty() && this->funcs_.size() == 1);
1970  user_assert(!this->funcs_.at(0).defined());
1971  this->funcs_[0] = f;
1972  }
1973 
1974 protected:
1975  using TBase = typename Super::TBase;
1976 
1977  static_assert(!std::is_array<T>::value, "Output<Buffer<>[]> is not a legal construct.");
1978 
1979 protected:
1980  GeneratorOutput_Buffer(const std::string &name)
1981  : Super(name, IOKind::Buffer,
1982  TBase::has_static_halide_type ? std::vector<Type>{ TBase::static_halide_type() } : std::vector<Type>{},
1983  -1) {
1984  }
1985 
1986  GeneratorOutput_Buffer(const std::string &name, const std::vector<Type> &t, int d = -1)
1987  : Super(name, IOKind::Buffer,
1988  TBase::has_static_halide_type ? std::vector<Type>{ TBase::static_halide_type() } : t,
1989  d) {
1990  if (TBase::has_static_halide_type) {
1991  user_assert(t.empty()) << "Cannot use pass a Type argument for a Buffer with a non-void static type\n";
1992  } else {
1993  user_assert(t.size() <= 1) << "Output<Buffer<>>(" << name << ") requires at most one Type, but has " << t.size() << "\n";
1994  }
1995  }
1996 
1997  GeneratorOutput_Buffer(const std::string &name, int d)
1998  : Super(name, IOKind::Buffer, std::vector<Type>{ TBase::static_halide_type() }, d) {
1999  static_assert(TBase::has_static_halide_type, "Must pass a Type argument for a Buffer with a static type of void");
2000  }
2001 
2002  NO_INLINE std::string get_c_type() const override {
2003  if (TBase::has_static_halide_type) {
2004  return "Halide::Internal::StubOutputBuffer<" +
2005  halide_type_to_c_type(TBase::static_halide_type()) +
2006  ">";
2007  } else {
2008  return "Halide::Internal::StubOutputBuffer<>";
2009  }
2010  }
2011 
2012 public:
2013 
2014  // Allow assignment from a Buffer<> to an Output<Buffer<>>;
2015  // this allows us to use a statically-compiled buffer inside a Generator
2016  // to assign to an output.
2017  // TODO: This used to take the buffer as a const ref. This no longer works as
2018  // using it in a Pipeline might change the dev field so it is currently
2019  // not considered const. We should consider how this really ought to work.
2020  template<typename T2>
2022  this->check_value_writable();
2023 
2024  user_assert(T::can_convert_from(buffer))
2025  << "Cannot assign to the Output \"" << this->name()
2026  << "\": the expression is not convertible to the same Buffer type and/or dimensions.\n";
2027 
2028  if (this->types_defined()) {
2029  user_assert(Type(buffer.type()) == this->type())
2030  << "Output should have type=" << this->type() << " but saw type=" << Type(buffer.type()) << "\n";
2031  }
2032  if (this->dims_defined()) {
2033  user_assert(buffer.dimensions() == this->dims())
2034  << "Output should have dim=" << this->dims() << " but saw dim=" << buffer.dimensions() << "\n";
2035  }
2036 
2037  internal_assert(this->exprs_.empty() && this->funcs_.size() == 1);
2038  user_assert(!this->funcs_.at(0).defined());
2039  this->funcs_.at(0)(_) = buffer(_);
2040 
2041  return *this;
2042  }
2043 
2044  // Allow assignment from a StubOutputBuffer to an Output<Buffer>;
2045  // this allows us to pipeline the results of a Stub to the results
2046  // of the enclosing Generator.
2047  template<typename T2>
2049  assign_from_func(stub_output_buffer.f);
2050  return *this;
2051  }
2052 
2053  // Allow assignment from a Func to an Output<Buffer>;
2054  // this allows us to use helper functions that return a plain Func
2055  // to simply set the output(s) without needing a wrapper Func.
2057  assign_from_func(f);
2058  return *this;
2059  }
2060 
2061  operator OutputImageParam() const {
2062  internal_assert(this->exprs_.empty() && this->funcs_.size() == 1);
2063  return this->funcs_.at(0).output_buffer();
2064  }
2065 
2066 #define HALIDE_OUTPUT_FORWARD(method) \
2067  template<typename ...Args> \
2068  inline auto method(Args&&... args) -> \
2069  decltype(std::declval<OutputImageParam>().method(std::forward<Args>(args)...)) {\
2070  return ((OutputImageParam) *this).method(std::forward<Args>(args)...); \
2071  }
2072 
2073 #define HALIDE_OUTPUT_FORWARD_CONST(method) \
2074  template<typename ...Args> \
2075  inline auto method(Args&&... args) const -> \
2076  decltype(std::declval<OutputImageParam>().method(std::forward<Args>(args)...)) {\
2077  return ((OutputImageParam) *this).method(std::forward<Args>(args)...); \
2078  }
2079 
2080  /** Forward methods to the OutputImageParam. */
2081  // @{
2084  HALIDE_OUTPUT_FORWARD_CONST(host_alignment)
2085  HALIDE_OUTPUT_FORWARD(set_host_alignment)
2086  HALIDE_OUTPUT_FORWARD_CONST(dimensions)
2093  HALIDE_OUTPUT_FORWARD_CONST(channels)
2094  // }@
2095 
2096 #undef HALIDE_OUTPUT_FORWARD
2097 #undef HALIDE_OUTPUT_FORWARD_CONST
2098 };
2099 
2100 
2101 template<typename T>
2103 private:
2104  using Super = GeneratorOutputImpl<T>;
2105 
2106  NO_INLINE Func &get_assignable_func_ref(size_t i) {
2107  internal_assert(this->exprs_.empty() && this->funcs_.size() > i);
2108  return this->funcs_.at(i);
2109  }
2110 
2111 protected:
2112  using TBase = typename Super::TBase;
2113 
2114 protected:
2115  GeneratorOutput_Func(const std::string &name)
2116  : Super(name, IOKind::Function, std::vector<Type>{}, -1) {
2117  }
2118 
2119  GeneratorOutput_Func(const std::string &name, const std::vector<Type> &t, int d = -1)
2120  : Super(name, IOKind::Function, t, d) {
2121  }
2122 
2123  GeneratorOutput_Func(size_t array_size, const std::string &name, const std::vector<Type> &t, int d)
2124  : Super(array_size, name, IOKind::Function, t, d) {
2125  }
2126 
2127 public:
2128  // Allow Output<Func> = Func
2129  template <typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * = nullptr>
2131  this->check_value_writable();
2132 
2133  // Don't bother verifying the Func type, dimensions, etc., here:
2134  // That's done later, when we produce the pipeline.
2135  get_assignable_func_ref(0) = f;
2136  return *this;
2137  }
2138 
2139  // Allow Output<Func[]> = Func
2140  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
2141  Func &operator[](size_t i) {
2142  this->check_value_writable();
2143  return get_assignable_func_ref(i);
2144  }
2145 
2146  // Allow Func = Output<Func[]>
2147  template <typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * = nullptr>
2148  const Func &operator[](size_t i) const {
2149  return Super::operator[](i);
2150  }
2151 
2153  internal_assert(this->exprs_.empty() && this->funcs_.size() > 0);
2154  for (Func &f : this->funcs_) {
2155  f.estimate(var, min, extent);
2156  }
2157  return *this;
2158  }
2159 };
2160 
2161 
2162 template<typename T>
2164 private:
2165  using Super = GeneratorOutputImpl<T>;
2166 protected:
2167  using TBase = typename Super::TBase;
2168 
2169 protected:
2170  explicit GeneratorOutput_Arithmetic(const std::string &name)
2171  : Super(name, IOKind::Function, {type_of<TBase>()}, 0) {
2172  }
2173 
2174  GeneratorOutput_Arithmetic(size_t array_size, const std::string &name)
2175  : Super(array_size, name, IOKind::Function, {type_of<TBase>()}, 0) {
2176  }
2177 };
2178 
2179 template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
2181  typename select_type<
2185  >::type;
2186 
2187 } // namespace Internal
2188 
2189 template <typename T>
2191 private:
2193 protected:
2194  using TBase = typename Super::TBase;
2195 
2196 public:
2197  explicit GeneratorOutput(const std::string &name)
2198  : Super(name) {
2199  }
2200 
2201  explicit GeneratorOutput(const char *name)
2202  : GeneratorOutput(std::string(name)) {
2203  }
2204 
2205  GeneratorOutput(size_t array_size, const std::string &name)
2206  : Super(array_size, name) {
2207  }
2208 
2209  GeneratorOutput(const std::string &name, int d)
2210  : Super(name, {}, d) {
2211  }
2212 
2213  GeneratorOutput(const std::string &name, const Type &t, int d)
2214  : Super(name, {t}, d) {
2215  }
2216 
2217  GeneratorOutput(const std::string &name, const std::vector<Type> &t, int d)
2218  : Super(name, t, d) {
2219  }
2220 
2221  GeneratorOutput(size_t array_size, const std::string &name, int d)
2222  : Super(array_size, name, {}, d) {
2223  }
2224 
2225  GeneratorOutput(size_t array_size, const std::string &name, const Type &t, int d)
2226  : Super(array_size, name, {t}, d) {
2227  }
2228 
2229  GeneratorOutput(size_t array_size, const std::string &name, const std::vector<Type> &t, int d)
2230  : Super(array_size, name, t, d) {
2231  }
2232 
2233  // TODO: This used to take the buffer as a const ref. This no longer works as
2234  // using it in a Pipeline might change the dev field so it is currently
2235  // not considered const. We should consider how this really ought to work.
2236  template <typename T2>
2238  Super::operator=(buffer);
2239  return *this;
2240  }
2241 
2242  template <typename T2>
2244  Super::operator=(stub_output_buffer);
2245  return *this;
2246  }
2247 
2249  Super::operator=(f);
2250  return *this;
2251  }
2252 };
2253 
2254 namespace Internal {
2255 
2256 template<typename T>
2257 T parse_scalar(const std::string &value) {
2258  std::istringstream iss(value);
2259  T t;
2260  iss >> t;
2261  user_assert(!iss.fail() && iss.get() == EOF) << "Unable to parse: " << value;
2262  return t;
2263 }
2264 
2265 EXPORT std::vector<Type> parse_halide_type_list(const std::string &types);
2266 
2267 // This is a type of GeneratorParam used internally to create 'synthetic' params
2268 // (e.g. image.type, image.dim); it is not possible for user code to instantiate it.
2269 template<typename T>
2271 public:
2272  void set_from_string(const std::string &new_value_string) override {
2273  set_from_string_impl<T>(new_value_string);
2274  }
2275 
2276  std::string to_string() const override {
2278  return std::string();
2279  }
2280 
2281  std::string call_to_string(const std::string &v) const override {
2283  return std::string();
2284  }
2285 
2286  std::string get_c_type() const override {
2288  return std::string();
2289  }
2290 
2291  bool is_synthetic_param() const override {
2292  return true;
2293  }
2294 
2295 private:
2296  friend class GeneratorBase;
2297 
2298  enum Which { Type, Dim, ArraySize };
2299  GeneratorParam_Synthetic(const std::string &name, GIOBase &gio, Which which) : GeneratorParamImpl<T>(name, T()), gio(gio), which(which) {}
2300 
2301  template <typename T2 = T, typename std::enable_if<std::is_same<T2, ::Halide::Type>::value>::type * = nullptr>
2302  void set_from_string_impl(const std::string &new_value_string) {
2303  internal_assert(which == Type);
2304  gio.types_ = parse_halide_type_list(new_value_string);
2305  }
2306 
2307  template <typename T2 = T, typename std::enable_if<std::is_integral<T2>::value>::type * = nullptr>
2308  void set_from_string_impl(const std::string &new_value_string) {
2309  if (which == Dim) {
2310  gio.dims_ = parse_scalar<T2>(new_value_string);
2311  } else if (which == ArraySize) {
2312  gio.array_size_ = parse_scalar<T2>(new_value_string);
2313  } else {
2315  }
2316  }
2317 
2318  GIOBase &gio;
2319  const Which which;
2320 };
2321 
2322 
2323 class GeneratorStub;
2324 
2325 } // namespace Internal
2326 
2327 /** GeneratorContext is a base class that is used when using Generators (or Stubs) directly;
2328  * it is used to allow the outer context (typically, either a Generator or "top-level" code)
2329  * to specify certain information to the inner context to ensure that inner and outer
2330  * Generators are compiled in a compatible way.
2331  *
2332  * If you are using this at "top level" (e.g. with the JIT), you can construct a GeneratorContext
2333  * with a Target:
2334  * \code
2335  * auto my_stub = MyStub(
2336  * GeneratorContext(get_target_from_environment()),
2337  * // inputs
2338  * { ... },
2339  * // generator params
2340  * { ... }
2341  * );
2342  * \endcode
2343  *
2344  * Note that all Generators inherit from GeneratorContext, so if you are using a Stub
2345  * from within a Generator, you can just pass 'this' for the GeneratorContext:
2346  * \code
2347  * struct SomeGen : Generator<SomeGen> {
2348  * void generate() {
2349  * ...
2350  * auto my_stub = MyStub(
2351  * this, // GeneratorContext
2352  * // inputs
2353  * { ... },
2354  * // generator params
2355  * { ... }
2356  * );
2357  * ...
2358  * }
2359  * };
2360  * \endcode
2361  */
2363 public:
2364  using ExternsMap = std::map<std::string, ExternalCode>;
2365 
2366  explicit GeneratorContext(const Target &t,
2367  bool auto_schedule = false,
2368  const MachineParams &machine_params = MachineParams::generic()) :
2369  target("target", t),
2370  auto_schedule("auto_schedule", auto_schedule),
2371  machine_params("machine_params", machine_params),
2372  externs_map(std::make_shared<ExternsMap>()),
2373  value_tracker(std::make_shared<Internal::ValueTracker>()) {}
2374  virtual ~GeneratorContext() {}
2375 
2376  inline Target get_target() const { return target; }
2377  inline bool get_auto_schedule() const { return auto_schedule; }
2378  inline MachineParams get_machine_params() const { return machine_params; }
2379 
2380  /** Generators can register ExternalCode objects onto
2381  * themselves. The Generator infrastructure will arrange to have
2382  * this ExternalCode appended to the Module that is finally
2383  * compiled using the Generator. This allows encapsulating
2384  * functionality that depends on external libraries or handwritten
2385  * code for various targets. The name argument should match the
2386  * name of the ExternalCode block and is used to ensure the same
2387  * code block is not duplicated in the output. Halide does not do
2388  * anything other than to compare names for equality. To guarantee
2389  * uniqueness in public code, we suggest using a Java style
2390  * inverted domain name followed by organization specific
2391  * naming. E.g.:
2392  * com.yoyodyne.overthruster.0719acd19b66df2a9d8d628a8fefba911a0ab2b7
2393  *
2394  * See test/generator/external_code_generator.cpp for example use. */
2395  inline std::shared_ptr<ExternsMap> get_externs_map() const {
2396  return externs_map;
2397  }
2398 
2399  template <typename T>
2400  inline std::unique_ptr<T> create() const {
2401  return T::create(*this);
2402  }
2403 
2404  template <typename T, typename... Args>
2405  inline std::unique_ptr<T> apply(const Args &...args) const {
2406  auto t = this->create<T>();
2407  t->apply(args...);
2408  return t;
2409  }
2410 
2411 protected:
2415  std::shared_ptr<ExternsMap> externs_map;
2416  std::shared_ptr<Internal::ValueTracker> value_tracker;
2417 
2419 
2420  inline void init_from_context(const Halide::GeneratorContext &context) {
2421  target.set(context.get_target());
2422  auto_schedule.set(context.get_auto_schedule());
2423  machine_params.set(context.get_machine_params());
2424  value_tracker = context.get_value_tracker();
2425  externs_map = context.get_externs_map();
2426  }
2427 
2428  inline std::shared_ptr<Internal::ValueTracker> get_value_tracker() const {
2429  return value_tracker;
2430  }
2431 
2432  // No copy
2433  GeneratorContext(const GeneratorContext &) = delete;
2434  void operator=(const GeneratorContext &) = delete;
2435  // No move
2436  GeneratorContext(GeneratorContext&&) = delete;
2437  void operator=(GeneratorContext&&) = delete;
2438 };
2439 
2441  // Names in this class are only intended for use in derived classes.
2442 protected:
2443  // Import a consistent list of Halide names that can be used in
2444  // Halide generators without qualification.
2457  using Var = Halide::Var;
2459  template <typename T> static Expr cast(Expr e) { return Halide::cast<T>(e); }
2460  static inline Expr cast(Halide::Type t, Expr e) { return Halide::cast(t, e); }
2461  template <typename T> using GeneratorParam = Halide::GeneratorParam<T>;
2462  template <typename T> using ScheduleParam = Halide::ScheduleParam<T>;
2463  template <typename T = void> using Buffer = Halide::Buffer<T>;
2464  template <typename T> using Param = Halide::Param<T>;
2465  static inline Type Bool(int lanes = 1) { return Halide::Bool(lanes); }
2466  static inline Type Float(int bits, int lanes = 1) { return Halide::Float(bits, lanes); }
2467  static inline Type Int(int bits, int lanes = 1) { return Halide::Int(bits, lanes); }
2468  static inline Type UInt(int bits, int lanes = 1) { return Halide::UInt(bits, lanes); }
2469 };
2470 
2471 namespace Internal {
2472 
2473 template<typename ...Args>
2474 struct NoRealizations : std::false_type {};
2475 
2476 template<>
2477 struct NoRealizations<> : std::true_type {};
2478 
2479 template<typename T, typename ...Args>
2480 struct NoRealizations<T, Args...> {
2481  static const bool value = !std::is_convertible<T, Realization>::value && NoRealizations<Args...>::value;
2482 };
2483 
2484 class GeneratorStub;
2485 class SimpleGeneratorFactory;
2486 
2487 // Note that these functions must never return null:
2488 // if they cannot return a valid Generator, they must assert-fail.
2489 using GeneratorFactory = std::function<std::unique_ptr<GeneratorBase>(const GeneratorContext&)>;
2490 
2492 public:
2493  struct EmitOptions {
2494  bool emit_o{false};
2495  bool emit_h{true};
2496  bool emit_cpp{false};
2497  bool emit_assembly{false};
2498  bool emit_bitcode{false};
2499  bool emit_stmt{false};
2500  bool emit_stmt_html{false};
2501  bool emit_static_library{true};
2502  bool emit_cpp_stub{false};
2503  bool emit_schedule{false};
2504  // This is an optional map used to replace the default extensions generated for
2505  // a file: if an key matches an output extension, emit those files with the
2506  // corresponding value instead (e.g., ".s" -> ".assembly_text"). This is
2507  // empty by default; it's mainly useful in build environments where the default
2508  // extensions are problematic, and avoids the need to rename output files
2509  // after the fact.
2510  std::map<std::string, std::string> substitutions;
2511  };
2512 
2513  EXPORT virtual ~GeneratorBase();
2514 
2515  EXPORT void set_generator_param(const std::string &name, const std::string &value);
2516  EXPORT void set_generator_and_schedule_param_values(const std::map<std::string, std::string> &params);
2517 
2518  template<typename T>
2519  GeneratorBase &set_generator_param(const std::string &name, const T &value) {
2520  find_generator_param_by_name(name).set(value);
2521  return *this;
2522  }
2523 
2524  template<typename T>
2525  GeneratorBase &set_schedule_param(const std::string &name, const T &value) {
2526  find_schedule_param_by_name(name).set(value);
2527  return *this;
2528  }
2529 
2530  /** Given a data type, return an estimate of the "natural" vector size
2531  * for that data type when compiling for the current target. */
2533  return get_target().natural_vector_size(t);
2534  }
2535 
2536  /** Given a data type, return an estimate of the "natural" vector size
2537  * for that data type when compiling for the current target. */
2538  template <typename data_t>
2539  int natural_vector_size() const {
2540  return get_target().natural_vector_size<data_t>();
2541  }
2542 
2543  EXPORT void emit_cpp_stub(const std::string &stub_file_path);
2544 
2545  // Call build() and produce a Module for the result.
2546  // If function_name is empty, generator_name() will be used for the function.
2547  EXPORT Module build_module(const std::string &function_name = "",
2549 
2550  /**
2551  * set_inputs is a variadic wrapper around set_inputs_vector, which makes usage much simpler
2552  * in many cases, as it constructs the relevant entries for the vector for you, which
2553  * is often a bit unintuitive at present. The arguments are passed in Input<>-declaration-order,
2554  * and the types must be compatible. Array inputs are passed as std::vector<> of the relevant type.
2555  *
2556  * Note: at present, scalar input types must match *exactly*, i.e., for Input<uint8_t>, you
2557  * must pass an argument that is actually uint8_t; an argument that is int-that-will-fit-in-uint8
2558  * will assert-fail at Halide compile time.
2559  */
2560  template <typename... Args>
2561  void set_inputs(const Args &...args) {
2562  // set_inputs_vector() checks this too, but checking it here allows build_inputs() to avoid out-of-range checks.
2563  ParamInfo &pi = param_info();
2564  user_assert(sizeof...(args) == pi.filter_inputs.size())
2565  << "Expected exactly " << pi.filter_inputs.size()
2566  << " inputs but got " << sizeof...(args) << "\n";
2567  set_inputs_vector(build_inputs(std::forward_as_tuple<const Args &...>(args...), make_index_sequence<sizeof...(Args)>{}));
2568  }
2569 
2570  Realization realize(std::vector<int32_t> sizes) {
2571  check_scheduled("realize");
2572  return get_pipeline().realize(sizes, get_target());
2573  }
2574 
2575  // Only enable if none of the args are Realization; otherwise we can incorrectly
2576  // select this method instead of the Realization-as-outparam variant
2577  template <typename... Args, typename std::enable_if<NoRealizations<Args...>::value>::type * = nullptr>
2578  Realization realize(Args&&... args) {
2579  check_scheduled("realize");
2580  return get_pipeline().realize(std::forward<Args>(args)..., get_target());
2581  }
2582 
2584  check_scheduled("realize");
2585  get_pipeline().realize(r, get_target());
2586  }
2587 
2588  // Return the Pipeline that has been built by the generate() method.
2589  // This method can only be used from a Generator that has a generate()
2590  // method (vs a build() method), and currently can only be called from
2591  // the schedule() method. (This may be relaxed in the future to allow
2592  // calling from generate() as long as all Outputs have been defined.)
2593  EXPORT Pipeline get_pipeline();
2594 
2595 protected:
2596  EXPORT GeneratorBase(size_t size, const void *introspection_helper);
2597  EXPORT void set_generator_names(const std::string &registered_name, const std::string &stub_name);
2598 
2599  EXPORT virtual Pipeline build_pipeline() = 0;
2600  EXPORT virtual void call_generate() = 0;
2601  EXPORT virtual void call_schedule() = 0;
2602 
2603  EXPORT void track_parameter_values(bool include_outputs);
2604 
2605  EXPORT void pre_build();
2606  EXPORT void post_build();
2607  EXPORT void pre_generate();
2608  EXPORT void post_generate();
2609  EXPORT void pre_schedule();
2610  EXPORT void post_schedule();
2611 
2612  template<typename T>
2614 
2615  template<typename T>
2617 
2618  template<typename T>
2620 
2621  // A Generator's creation and usage must go in a certain phase to ensure correctness;
2622  // the state machine here is advanced and checked at various points to ensure
2623  // this is the case.
2624  enum Phase {
2625  // Generator has just come into being.
2627 
2628  // All Input<>/Param<> fields have been set. (Applicable only in JIT mode;
2629  // in AOT mode, this can be skipped, going Created->GenerateCalled directly.)
2631 
2632  // Generator has had its generate() method called. (For Generators with
2633  // a build() method instead of generate(), this phase will be skipped
2634  // and will advance directly to ScheduleCalled.)
2636 
2637  // Generator has had its schedule() method (if any) called.
2639  } phase{Created};
2640 
2641  void check_exact_phase(Phase expected_phase) const;
2642  void check_min_phase(Phase expected_phase) const;
2643  void advance_phase(Phase new_phase);
2644 
2645 private:
2647  friend class GeneratorParamBase;
2648  friend class GeneratorInputBase;
2649  friend class GeneratorOutputBase;
2650  friend class GeneratorStub;
2652  friend class StubOutputBufferBase;
2653 
2654  struct ParamInfo {
2655  EXPORT ParamInfo(GeneratorBase *generator, const size_t size);
2656 
2657  // Ordered-list of non-null ptrs to GeneratorParam<> fields.
2658  std::vector<Internal::GeneratorParamBase *> generator_params;
2659 
2660  // Ordered-list of non-null ptrs to ScheduleParam<> fields.
2661  std::vector<Internal::ScheduleParamBase *> schedule_params;
2662 
2663  // Ordered-list of non-null ptrs to Input<> fields.
2664  // Only one of filter_inputs and filter_params may be nonempty.
2665  std::vector<Internal::GeneratorInputBase *> filter_inputs;
2666 
2667  // Ordered-list of non-null ptrs to Param<> or ImageParam<> fields.
2668  // Must be empty if the Generator has a build() method rather than generate()/schedule().
2669  // Only one of filter_inputs and filter_params may be nonempty.
2670  std::vector<Internal::Parameter *> filter_params;
2671 
2672  // Ordered-list of non-null ptrs to Output<> fields; empty if old-style Generator.
2673  std::vector<Internal::GeneratorOutputBase *> filter_outputs;
2674 
2675  // Convenience structure to look up GP by name.
2676  std::map<std::string, Internal::GeneratorParamBase *> generator_params_by_name;
2677 
2678  // Convenience structure to look up SP by name.
2679  std::map<std::string, Internal::ScheduleParamBase *> schedule_params_by_name;
2680 
2681  private:
2682  // list of synthetic GP's that we dynamically created; this list only exists to simplify
2683  // lifetime management, and shouldn't be accessed directly outside of our ctor/dtor,
2684  // regardless of friend access.
2685  std::vector<std::unique_ptr<Internal::GeneratorParamBase>> owned_synthetic_params;
2686  };
2687 
2688  const size_t size;
2689  // Lazily-allocated-and-inited struct with info about our various Params.
2690  // Do not access directly: use the param_info() getter to lazy-init.
2691  std::unique_ptr<ParamInfo> param_info_ptr;
2692 
2693  mutable std::shared_ptr<ExternsMap> externs_map;
2694 
2695  bool inputs_set{false};
2696  std::string generator_registered_name, generator_stub_name;
2697  Pipeline pipeline;
2698 
2699  // Return our ParamInfo (lazy-initing as needed).
2700  EXPORT ParamInfo &param_info();
2701 
2702  EXPORT Internal::GeneratorParamBase &find_generator_param_by_name(const std::string &name);
2703  EXPORT Internal::ScheduleParamBase &find_schedule_param_by_name(const std::string &name);
2704 
2705  EXPORT void check_scheduled(const char* m) const;
2706 
2707  EXPORT void build_params(bool force = false);
2708 
2709  // Provide private, unimplemented, wrong-result-type methods here
2710  // so that Generators don't attempt to call the global methods
2711  // of the same name by accident: use the get_target() method instead.
2712  void get_host_target();
2715 
2716  EXPORT Func get_first_output();
2717  EXPORT Func get_output(const std::string &n);
2718  EXPORT std::vector<Func> get_output_vector(const std::string &n);
2719 
2720  EXPORT void set_inputs_vector(const std::vector<std::vector<StubInput>> &inputs);
2721 
2722  EXPORT static void check_input_is_singular(Internal::GeneratorInputBase *in);
2723  EXPORT static void check_input_is_array(Internal::GeneratorInputBase *in);
2724  EXPORT static void check_input_kind(Internal::GeneratorInputBase *in, Internal::IOKind kind);
2725 
2726  // Allow Buffer<> if:
2727  // -- we are assigning it to an Input<Buffer<>> (with compatible type and dimensions),
2728  // causing the Input<Buffer<>> to become a precompiled buffer in the generated code.
2729  // -- we are assigningit to an Input<Func>, in which case we just Func-wrap the Buffer<>.
2730  template<typename T>
2731  std::vector<StubInput> build_input(size_t i, const Buffer<T> &arg) {
2732  auto *in = param_info().filter_inputs.at(i);
2733  check_input_is_singular(in);
2734  const auto k = in->kind();
2735  if (k == Internal::IOKind::Buffer) {
2736  Halide::Buffer<> b = arg;
2737  StubInputBuffer<> sib(b);
2738  StubInput si(sib);
2739  return {si};
2740  } else if (k == Internal::IOKind::Function) {
2741  Halide::Func f(arg.name() + "_im");
2742  f(Halide::_) = arg(Halide::_);
2743  StubInput si(f);
2744  return {si};
2745  } else {
2746  check_input_kind(in, Internal::IOKind::Buffer); // just to trigger assertion
2747  return {};
2748  }
2749  }
2750 
2751  // Allow Input<Buffer<>> if:
2752  // -- we are assigning it to another Input<Buffer<>> (with compatible type and dimensions),
2753  // allowing us to simply pipe a parameter from an enclosing Generator to the Invoker.
2754  // -- we are assigningit to an Input<Func>, in which case we just Func-wrap the Input<Buffer<>>.
2755  template<typename T>
2756  std::vector<StubInput> build_input(size_t i, const GeneratorInput<Buffer<T>> &arg) {
2757  auto *in = param_info().filter_inputs.at(i);
2758  check_input_is_singular(in);
2759  const auto k = in->kind();
2760  if (k == Internal::IOKind::Buffer) {
2761  StubInputBuffer<> sib = arg;
2762  StubInput si(sib);
2763  return {si};
2764  } else if (k == Internal::IOKind::Function) {
2765  Halide::Func f = arg.funcs().at(0);
2766  StubInput si(f);
2767  return {si};
2768  } else {
2769  check_input_kind(in, Internal::IOKind::Buffer); // just to trigger assertion
2770  return {};
2771  }
2772  }
2773 
2774  // Allow Func iff we are assigning it to an Input<Func> (with compatible type and dimensions).
2775  std::vector<StubInput> build_input(size_t i, const Func &arg) {
2776  auto *in = param_info().filter_inputs.at(i);
2777  check_input_kind(in, Internal::IOKind::Function);
2778  check_input_is_singular(in);
2779  Halide::Func f = arg;
2780  StubInput si(f);
2781  return {si};
2782  }
2783 
2784  // Allow vector<Func> iff we are assigning it to an Input<Func[]> (with compatible type and dimensions).
2785  std::vector<StubInput> build_input(size_t i, const std::vector<Func> &arg) {
2786  auto *in = param_info().filter_inputs.at(i);
2787  check_input_kind(in, Internal::IOKind::Function);
2788  check_input_is_array(in);
2789  // My kingdom for a list comprehension...
2790  std::vector<StubInput> siv;
2791  siv.reserve(arg.size());
2792  for (const auto &f : arg) {
2793  siv.emplace_back(f);
2794  }
2795  return siv;
2796  }
2797 
2798  // Expr must be Input<Scalar>.
2799  std::vector<StubInput> build_input(size_t i, const Expr &arg) {
2800  auto *in = param_info().filter_inputs.at(i);
2801  check_input_kind(in, Internal::IOKind::Scalar);
2802  check_input_is_singular(in);
2803  StubInput si(arg);
2804  return {si};
2805  }
2806 
2807  // (Array form)
2808  std::vector<StubInput> build_input(size_t i, const std::vector<Expr> &arg) {
2809  auto *in = param_info().filter_inputs.at(i);
2810  check_input_kind(in, Internal::IOKind::Scalar);
2811  check_input_is_array(in);
2812  std::vector<StubInput> siv;
2813  siv.reserve(arg.size());
2814  for (const auto &value : arg) {
2815  siv.emplace_back(value);
2816  }
2817  return siv;
2818  }
2819 
2820  // Any other type must be convertible to Expr and must be associated with an Input<Scalar>.
2821  // Use is_arithmetic since some Expr conversions are explicit.
2822  template<typename T,
2823  typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
2824  std::vector<StubInput> build_input(size_t i, const T &arg) {
2825  auto *in = param_info().filter_inputs.at(i);
2826  check_input_kind(in, Internal::IOKind::Scalar);
2827  check_input_is_singular(in);
2828  // We must use an explicit Expr() ctor to preserve the type
2829  Expr e(arg);
2830  StubInput si(e);
2831  return {si};
2832  }
2833 
2834  // (Array form)
2835  template<typename T,
2836  typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
2837  std::vector<StubInput> build_input(size_t i, const std::vector<T> &arg) {
2838  auto *in = param_info().filter_inputs.at(i);
2839  check_input_kind(in, Internal::IOKind::Scalar);
2840  check_input_is_array(in);
2841  std::vector<StubInput> siv;
2842  siv.reserve(arg.size());
2843  for (const auto &value : arg) {
2844  // We must use an explicit Expr() ctor to preserve the type;
2845  // otherwise, implicit conversions can downgrade (e.g.) float -> int
2846  Expr e(value);
2847  siv.emplace_back(e);
2848  }
2849  return siv;
2850  }
2851 
2852  template<typename... Args, size_t... Indices>
2853  std::vector<std::vector<StubInput>> build_inputs(const std::tuple<const Args &...>& t, index_sequence<Indices...>) {
2854  return {build_input(Indices, std::get<Indices>(t))...};
2855  }
2856 
2857  // No copy
2858  GeneratorBase(const GeneratorBase &) = delete;
2859  void operator=(const GeneratorBase &) = delete;
2860  // No move
2861  GeneratorBase(GeneratorBase&& that) = delete;
2862  void operator=(GeneratorBase&& that) = delete;
2863 };
2864 
2866 public:
2867  EXPORT static void register_factory(const std::string &name, GeneratorFactory generator_factory);
2868  EXPORT static void unregister_factory(const std::string &name);
2869  EXPORT static std::vector<std::string> enumerate();
2870  // Note that this method will never return null:
2871  // if it cannot return a valid Generator, it should assert-fail.
2872  EXPORT static std::unique_ptr<GeneratorBase> create(const std::string &name,
2873  const GeneratorContext &context);
2874 
2875 private:
2876  using GeneratorFactoryMap = std::map<const std::string, GeneratorFactory>;
2877 
2878  GeneratorFactoryMap factories;
2879  std::mutex mutex;
2880 
2881  EXPORT static GeneratorRegistry &get_registry();
2882 
2883  GeneratorRegistry() {}
2884  GeneratorRegistry(const GeneratorRegistry &) = delete;
2885  void operator=(const GeneratorRegistry &) = delete;
2886 };
2887 
2888 } // namespace Internal
2889 
2890 template <class T>
2892 protected:
2893 
2894  // TODO: This causes problems for existing code that declares helper
2895  // methods (that use ImageParam, etc as arguments) outside the class body,
2896  // as there is an ambiguity between Halide::ImageParam and Generator<T>::ImageParam.
2897  //
2898  // Consider re-enabling this at some point in the future when the likelihood of
2899  // collision with existing code is much smaller.
2900  //
2901  // // Add wrapper types here that exists just to allow us to tag
2902  // // ImageParam/Param-used-inside-Generator with HALIDE_ATTRIBUTE_DEPRECATED.
2903  // // (This won't catch code that uses "Halide::Param" or "Halide::ImageParam"
2904  // // but those are somewhat uncommon cases.)
2905 
2906  // template<typename T2>
2907  // class Param : public ::Halide::Param<T2> {
2908  // public:
2909  // template <typename... Args>
2910  // HALIDE_ATTRIBUTE_DEPRECATED("Using Param<> in Generators is deprecated; please use Input<> instead.")
2911  // explicit Param(const Args &...args) : ::Halide::Param<T2>(args...) { }
2912  // };
2913 
2914  // class ImageParam : public ::Halide::ImageParam {
2915  // public:
2916  // template <typename... Args>
2917  // HALIDE_ATTRIBUTE_DEPRECATED("Using ImageParam<> in Generators is deprecated; please use Input<Buffer<>> instead.")
2918  // explicit ImageParam(const Args &...args) : ::Halide::ImageParam(args...) { }
2919  // };
2920 
2921 protected:
2923  Internal::GeneratorBase(sizeof(T),
2924  Internal::Introspection::get_introspection_helper<T>()) {}
2925 
2926 public:
2927  static std::unique_ptr<T> create(const Halide::GeneratorContext &context) {
2928  // We must have an object of type T (not merely GeneratorBase) to call a protected method,
2929  // because CRTP is a weird beast.
2930  auto g = std::unique_ptr<T>(new T());
2931  g->init_from_context(context);
2932  return g;
2933  }
2934 
2935  // This is public but intended only for use by the HALIDE_REGISTER_GENERATOR() macro.
2936  static std::unique_ptr<T> create(const Halide::GeneratorContext &context,
2937  const std::string &registered_name,
2938  const std::string &stub_name) {
2939  auto g = create(context);
2940  g->set_generator_names(registered_name, stub_name);
2941  return g;
2942  }
2943 
2946 
2947  template <typename... Args>
2948  void apply(const Args &...args) {
2949  static_assert(has_generate_method<T>::value && has_schedule_method<T>::value,
2950  "apply() is not supported for old-style Generators.");
2951  set_inputs(args...);
2952  call_generate();
2953  call_schedule();
2954  }
2955 
2956 private:
2957 
2958  // std::is_member_function_pointer will fail if there is no member of that name,
2959  // so we use a little SFINAE to detect if there are method-shaped members.
2960  template<typename>
2961  struct type_sink { typedef void type; };
2962 
2963  template<typename T2, typename = void>
2964  struct has_generate_method : std::false_type {};
2965 
2966  template<typename T2>
2967  struct has_generate_method<T2, typename type_sink<decltype(std::declval<T2>().generate())>::type> : std::true_type {};
2968 
2969  template<typename T2, typename = void>
2970  struct has_schedule_method : std::false_type {};
2971 
2972  template<typename T2>
2973  struct has_schedule_method<T2, typename type_sink<decltype(std::declval<T2>().schedule())>::type> : std::true_type {};
2974 
2975  template <typename T2 = T,
2976  typename std::enable_if<!has_generate_method<T2>::value>::type * = nullptr>
2977 
2978  // Implementations for build_pipeline_impl(), specialized on whether we
2979  // have build() or generate()/schedule() methods.
2980 
2981  // MSVC apparently has some weirdness with the usual sfinae tricks
2982  // for detecting method-shaped things, so we can't actually use
2983  // the helpers above outside of static_assert. Instead we make as
2984  // many overloads as we can exist, and then use C++'s preference
2985  // for treating a 0 as an int rather than a double to choose one
2986  // of them.
2987  Pipeline build_pipeline_impl(double) {
2988  static_assert(!has_schedule_method<T2>::value, "The schedule() method is ignored if you define a build() method; use generate() instead.");
2989  pre_build();
2990  Pipeline p = ((T *)this)->build();
2991  post_build();
2992  return p;
2993  }
2994 
2995  template <typename T2 = T,
2996  typename = decltype(std::declval<T2>().generate())>
2997  Pipeline build_pipeline_impl(int) {
2998  ((T *)this)->call_generate_impl(0);
2999  ((T *)this)->call_schedule_impl(0, 0);
3000  return get_pipeline();
3001  }
3002 
3003  // Implementations for call_generate_impl(), specialized on whether we
3004  // have build() or generate()/schedule() methods.
3005 
3006  void call_generate_impl(double) {
3007  user_error << "Unimplemented";
3008  }
3009 
3010  template <typename T2 = T,
3011  typename = decltype(std::declval<T2>().generate())>
3012  void call_generate_impl(int) {
3013  T *t = (T*)this;
3014  static_assert(std::is_void<decltype(t->generate())>::value, "generate() must return void");
3015  pre_generate();
3016  t->generate();
3017  post_generate();
3018  }
3019 
3020  // Implementations for call_schedule_impl(), specialized on whether we
3021  // have build() or generate()/schedule() methods.
3022 
3023  void call_schedule_impl(double, double) {
3024  user_error << "Unimplemented";
3025  }
3026 
3027  template<typename T2 = T,
3028  typename = decltype(std::declval<T2>().generate())>
3029  void call_schedule_impl(double, int) {
3030  // Generator has a generate() method but no schedule() method. This is ok. Just advance the phase.
3031  pre_schedule();
3032  post_schedule();
3033  }
3034 
3035  template<typename T2 = T,
3036  typename = decltype(std::declval<T2>().generate()),
3037  typename = decltype(std::declval<T2>().schedule())>
3038  void call_schedule_impl(int, int) {
3039  T *t = (T*)this;
3040  static_assert(std::is_void<decltype(t->schedule())>::value, "schedule() must return void");
3041  pre_schedule();
3042  t->schedule();
3043  post_schedule();
3044  }
3045 
3046 protected:
3048  return this->build_pipeline_impl(0);
3049  }
3050 
3051  void call_generate() override {
3052  this->call_generate_impl(0);
3053  }
3054 
3055  void call_schedule() override {
3056  this->call_schedule_impl(0, 0);
3057  }
3058 
3059 private:
3061  friend class Internal::SimpleGeneratorFactory;
3063  friend class ::Halide::GeneratorContext;
3064 
3065  // No copy
3066  Generator(const Generator &) = delete;
3067  void operator=(const Generator &) = delete;
3068  // No move
3069  Generator(Generator&& that) = delete;
3070  void operator=(Generator&& that) = delete;
3071 };
3072 
3073 namespace Internal {
3074 
3076 public:
3077  RegisterGenerator(const char* registered_name, GeneratorFactory generator_factory) {
3078  Internal::GeneratorRegistry::register_factory(registered_name, generator_factory);
3079  }
3080 };
3081 
3083 public:
3084  // default ctor
3085  GeneratorStub() = default;
3086 
3087  // move constructor
3088  GeneratorStub(GeneratorStub&& that) : generator(std::move(that.generator)) {}
3089 
3090  // move assignment operator
3092  generator = std::move(that.generator);
3093  return *this;
3094  }
3095 
3096  Target get_target() const { return generator->get_target(); }
3097 
3098  template<typename T>
3099  GeneratorStub &set_schedule_param(const std::string &name, const T &value) {
3100  generator->set_schedule_param(name, value);
3101  return *this;
3102  }
3103 
3105  generator->call_schedule();
3106  return *this;
3107  }
3108 
3109  // Overloads for first output
3110  operator Func() const {
3111  return get_first_output();
3112  }
3113 
3114  template <typename... Args>
3115  FuncRef operator()(Args&&... args) const {
3116  return get_first_output()(std::forward<Args>(args)...);
3117  }
3118 
3119  template <typename ExprOrVar>
3120  FuncRef operator()(std::vector<ExprOrVar> args) const {
3121  return get_first_output()(args);
3122  }
3123 
3124  Realization realize(std::vector<int32_t> sizes) {
3125  return generator->realize(sizes);
3126  }
3127 
3128  // Only enable if none of the args are Realization; otherwise we can incorrectly
3129  // select this method instead of the Realization-as-outparam variant
3130  template <typename... Args, typename std::enable_if<NoRealizations<Args...>::value>::type * = nullptr>
3131  Realization realize(Args&&... args) {
3132  return generator->realize(std::forward<Args>(args)...);
3133  }
3134 
3136  generator->realize(r);
3137  }
3138 
3139  virtual ~GeneratorStub() {}
3140 
3141 protected:
3142  EXPORT GeneratorStub(const GeneratorContext &context,
3143  GeneratorFactory generator_factory,
3144  const std::map<std::string, std::string> &generator_params,
3145  const std::vector<std::vector<Internal::StubInput>> &inputs);
3146 
3147  ScheduleParamBase &get_schedule_param(const std::string &n) const {
3148  return generator->find_schedule_param_by_name(n);
3149  }
3150 
3151  // Output(s)
3152  // TODO: identify vars used
3153  Func get_output(const std::string &n) const {
3154  return generator->get_output(n);
3155  }
3156 
3157  template<typename T2>
3158  T2 get_output_buffer(const std::string &n) const {
3159  return T2(get_output(n), generator);
3160  }
3161 
3162  std::vector<Func> get_output_vector(const std::string &n) const {
3163  return generator->get_output_vector(n);
3164  }
3165 
3166  bool has_generator() const {
3167  return generator != nullptr;
3168  }
3169 
3170  static std::vector<StubInput> to_stub_input_vector(const Expr &e) {
3171  return { StubInput(e) };
3172  }
3173 
3174  static std::vector<StubInput> to_stub_input_vector(const Func &f) {
3175  return { StubInput(f) };
3176  }
3177 
3178  template<typename T = void>
3179  static std::vector<StubInput> to_stub_input_vector(const StubInputBuffer<T> &b) {
3180  return { StubInput(b) };
3181  }
3182 
3183  template <typename T>
3184  static std::vector<StubInput> to_stub_input_vector(const std::vector<T> &v) {
3185  std::vector<StubInput> r;
3186  std::copy(v.begin(), v.end(), std::back_inserter(r));
3187  return r;
3188  }
3189 
3190  EXPORT void verify_same_funcs(const Func &a, const Func &b);
3191  EXPORT void verify_same_funcs(const std::vector<Func>& a, const std::vector<Func>& b);
3192 
3193  template<typename T2>
3195  verify_same_funcs(a.f, b.f);
3196  }
3197 
3198 private:
3199  std::shared_ptr<GeneratorBase> generator;
3200 
3201  Func get_first_output() const {
3202  return generator->get_first_output();
3203  }
3204  explicit GeneratorStub(const GeneratorStub &) = delete;
3205  GeneratorStub &operator=(const GeneratorStub &) = delete;
3206  explicit GeneratorStub(const GeneratorStub &&) = delete;
3207  GeneratorStub &operator=(const GeneratorStub &&) = delete;
3208 };
3209 
3210 } // namespace Internal
3211 
3212 
3213 } // namespace Halide
3214 
3215 // Define this namespace at global scope so that anonymous namespaces won't
3216 // defeat our static_assert check; define a dummy type inside so we can
3217 // check for type aliasing injected by anonymous namespace usage
3219  struct halide_global_ns;
3220 };
3221 
3222 #define _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
3223  namespace halide_register_generator { \
3224  struct halide_global_ns; \
3225  namespace GEN_REGISTRY_NAME##_ns { \
3226  std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext& context) { \
3227  return GEN_CLASS_NAME::create(context, #GEN_REGISTRY_NAME, #FULLY_QUALIFIED_STUB_NAME); \
3228  } \
3229  } \
3230  static auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
3231  } \
3232  static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
3233  "HALIDE_REGISTER_GENERATOR must be used at global scope");
3234 
3235 #define _HALIDE_REGISTER_GENERATOR2(GEN_CLASS_NAME, GEN_REGISTRY_NAME) \
3236  _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME)
3237 
3238 #define _HALIDE_REGISTER_GENERATOR3(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
3239  _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)
3240 
3241 // MSVC has a broken implementation of variadic macros: it expands __VA_ARGS__
3242 // as a single token in argument lists (rather than multiple tokens).
3243 // Jump through some hoops to work around this.
3244 #define __HALIDE_REGISTER_ARGCOUNT_IMPL(_1, _2, _3, COUNT, ...) \
3245  COUNT
3246 
3247 #define _HALIDE_REGISTER_ARGCOUNT_IMPL(ARGS) \
3248  __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS
3249 
3250 #define _HALIDE_REGISTER_ARGCOUNT(...) \
3251  _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0))
3252 
3253 #define ___HALIDE_REGISTER_CHOOSER(COUNT) \
3254  _HALIDE_REGISTER_GENERATOR##COUNT
3255 
3256 #define __HALIDE_REGISTER_CHOOSER(COUNT) \
3257  ___HALIDE_REGISTER_CHOOSER(COUNT)
3258 
3259 #define _HALIDE_REGISTER_CHOOSER(COUNT) \
3260  __HALIDE_REGISTER_CHOOSER(COUNT)
3261 
3262 #define _HALIDE_REGISTER_GENERATOR_PASTE(A, B) \
3263  A B
3264 
3265 #define HALIDE_REGISTER_GENERATOR(...) \
3266  _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__))
3267 
3268 #endif // HALIDE_GENERATOR_H_
GeneratorOutput(const std::string &name, const Type &t, int d)
Definition: Generator.h:2213
void init_from_context(const Halide::GeneratorContext &context)
Definition: Generator.h:2420
EXPORT int dimensions() const
The dimensionality (number of arguments) of this function.
EXPORT IOKind kind() const
Create a small array of Exprs for defining and calling functions with multiple outputs.
Definition: Tuple.h:19
GeneratorOutput_Arithmetic(const std::string &name)
Definition: Generator.h:2170
static std::vector< StubInput > to_stub_input_vector(const Expr &e)
Definition: Generator.h:3170
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:2561
EXPORT void generator_test()
#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE)
Definition: Generator.h:458
std::string get_c_type() const override
Definition: Generator.h:2286
A reference to a site in a Halide statement at the top of the body of a particular for loop...
Definition: Schedule.h:98
std::string get_c_type() const override
Definition: Generator.h:561
std::string to_string() const override
Definition: Generator.h:527
GeneratorOutput_Func< T > & estimate(Var var, Expr min, Expr extent)
Definition: Generator.h:2152
Func in(const std::vector< Func > &others)
Definition: Generator.h:1387
const std::string name_
Definition: Generator.h:1172
Type type() const
Does the same thing as the equivalent Halide::Runtime::Buffer method.
Definition: Buffer.h:388
GeneratorContext is a base class that is used when using Generators (or Stubs) directly; it is used t...
Definition: Generator.h:2362
A fragment of Halide syntax.
Definition: Expr.h:276
NO_INLINE std::string get_c_type() const override
Forward schedule-related methods to the underlying Func.
Definition: Generator.h:2002
std::string to_string() const override
Definition: Generator.h:648
StubOutputBuffer is the placeholder that a Stub uses when it requires a Buffer for an output (rather ...
Definition: Generator.h:1074
decltype((Other) 0||(T) 1) operator||(const Other &a, const GeneratorParam< T > &b)
Logical or between between GeneratorParam<T> and any type that supports operator&& with T...
Definition: Generator.h:926
std::string get_c_type() const override
Definition: Generator.h:537
std::shared_ptr< ExternsMap > get_externs_map() const
Generators can register ExternalCode objects onto themselves.
Definition: Generator.h:2395
NO_INLINE Func & get_func_ref()
Forward schedule-related methods to the underlying Func.
Definition: Generator.h:1842
std::string get_default_value() const override
Definition: Generator.h:747
Expr operator()(Args &&... args) const
Definition: Generator.h:1353
static std::vector< StubInput > to_stub_input_vector(const Func &f)
Definition: Generator.h:3174
A class representing a Halide pipeline.
Definition: Pipeline.h:58
GeneratorOutput_Func(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
Definition: Generator.h:2123
EXPORT Func & estimate(Var var, Expr min, Expr extent)
Statically declare the range over which the function will be evaluated in the general case...
GeneratorInput_Scalar(const std::string &name, const TBase &def=static_cast< TBase >(0))
Definition: Generator.h:1566
std::vector< ValueType >::const_iterator begin() const
Definition: Generator.h:1302
GeneratorStub(GeneratorStub &&that)
Definition: Generator.h:3088
decltype((Other) 0==(T) 1) operator==(const Other &a, const GeneratorParam< T > &b)
Equality comparison between GeneratorParam<T> and any type that supports operator== with T...
Definition: Generator.h:899
EXPORT std::string halide_type_to_c_source(const Type &t)
void call_schedule() override
Definition: Generator.h:3055
static Type Int(int bits, int lanes=1)
Definition: Generator.h:2467
EXPORT Target get_host_target()
Return the target corresponding to the host machine.
GeneratorOutput(size_t array_size, const std::string &name, const Type &t, int d)
Definition: Generator.h:2225
GeneratorOutput_Arithmetic(size_t array_size, const std::string &name)
Definition: Generator.h:2174
EXPORT Func in(const Func &f)
Creates and returns a new identity Func that wraps this Func.
std::vector< Expr > exprs_
Definition: Generator.h:1179
typename select_type< cond< std::is_same< T, Target >::value, GeneratorParam_Target< T > >, cond< std::is_same< T, MachineParams >::value, GeneratorParam_MachineParams< 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:765
static std::vector< StubInput > to_stub_input_vector(const std::vector< T > &v)
Definition: Generator.h:3184
StubInput(const StubInputBuffer< T2 > &b)
Definition: Generator.h:1095
EXPORT int dimensions() const
Get the dimensionality of this parameter.
GeneratorStub & set_schedule_param(const std::string &name, const T &value)
Definition: Generator.h:3099
GeneratorParam(const std::string &name, const T &value)
Definition: Generator.h:800
A Realization is a vector of references to existing Buffer objects.
Definition: Tuple.h:69
A halide function.
Definition: Func.h:502
GeneratorInput(size_t array_size, const std::string &name, const Type &t, int d)
Definition: Generator.h:1719
auto max(const GeneratorParam< T > &a, const Other &b) -> decltype(Internal::GeneratorMinMax::max_forward(a, b))
Compute the maximum value between GeneratorParam<T> and any type that supports max with T...
Definition: Generator.h:973
decltype(min((T) 0,(Other) 1)) min_forward(const GeneratorParam< T > &a, const Other &b)
Definition: Generator.h:943
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:636
GIOBase is the base class for all GeneratorInput<> and GeneratorOutput<> instantiations; it is not pa...
Definition: Generator.h:1140
GeneratorParam_Enum(const std::string &name, const T &value, const std::map< std::string, T > &enum_map)
Definition: Generator.h:666
A struct representing the machine parameters to generate the auto-scheduled code for.
Definition: AutoSchedule.h:16
const ValueType & operator[](size_t i) const
Definition: Generator.h:1292
ValueTracker(size_t max_unique_values=2)
Definition: Generator.h:283
TailStrategy
Different ways to handle a tail case in a split when the factor does not provably divide the extent...
Definition: Schedule.h:29
NO_INLINE std::string enum_to_string(const std::map< std::string, T > &enum_map, const T &t)
Definition: Generator.h:290
GeneratorInput_Func(const std::string &name, int d)
Definition: Generator.h:1448
GeneratorOutput(const char *name)
Definition: Generator.h:2201
GeneratorInput(const std::string &name, IntIfNonScalar d)
Definition: Generator.h:1715
bool get_auto_schedule() const
Definition: Generator.h:2377
std::string to_string() const override
Definition: Generator.h:551
FuncRef operator()(Args &&... args) const
Definition: Generator.h:3115
GeneratorInput_Func(size_t array_size, const std::string &name, const Type &t, int d)
Definition: Generator.h:1462
A struct representing a target machine and os to generate code for.
Definition: Target.h:21
GeneratorInput_Func(const std::string &name)
Definition: Generator.h:1458
Visible externally. Argument metadata and an argv wrapper are also generated.
Definition: Module.h:52
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:531
#define internal_error
Definition: Error.h:135
Realization realize(Args &&... args)
Definition: Generator.h:1049
virtual bool is_synthetic_param() const
Definition: Generator.h:427
Defines methods for introspecting in C++.
std::string get_default_value() const override
Definition: Generator.h:695
A Halide variable, to be used when defining functions.
Definition: Var.h:17
GeneratorOutput(const std::string &name, const std::vector< Type > &t, int d)
Definition: Generator.h:2217
std::map< std::string, ExternalCode > ExternsMap
Definition: Generator.h:2364
GeneratorInput_Arithmetic(size_t array_size, const std::string &name, const TBase &def, const TBase &min, const TBase &max)
Definition: Generator.h:1636
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:569
Func get_output(const std::string &n) const
Definition: Generator.h:3153
auto min(const GeneratorParam< T > &a, const Other &b) -> decltype(Internal::GeneratorMinMax::min_forward(a, b))
Compute minimum between GeneratorParam<T> and any type that supports min with T.
Definition: Generator.h:960
signed __INT8_TYPE__ int8_t
EXPORT const std::map< std::string, Halide::LoopLevel > & get_halide_looplevel_enum_map()
std::vector< Func > get_output_vector(const std::string &n) const
Definition: Generator.h:3162
EXPORT void resize(size_t size)
Forward schedule-related methods to the underlying Func.
STL namespace.
GeneratorOutput(size_t array_size, const std::string &name)
Definition: Generator.h:2205
std::unique_ptr< T > apply(const Args &...args) const
Definition: Generator.h:2405
A fragment of front-end syntax of the form f(x, y, z), where x, y, z are Vars or Exprs.
Definition: Func.h:314
Expr operator()(std::vector< Expr > args) const
Definition: Generator.h:1357
EXPORT Realization realize(std::vector< int32_t > sizes, const Target &target=Target())
Evaluate this function over some rectangular domain and return the resulting buffer or buffers...
GeneratorOutput(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
Definition: Generator.h:2229
void realize(Realization r)
Definition: Generator.h:3135
GeneratorOutput(size_t array_size, const std::string &name, int d)
Definition: Generator.h:2221
const Func & operator[](size_t i) const
Definition: Generator.h:2148
GeneratorBase & set_schedule_param(const std::string &name, const T &value)
Definition: Generator.h:2525
std::shared_ptr< GeneratorBase > generator
Definition: Generator.h:1034
Expr cast(Expr a)
Cast an expression to the halide type corresponding to the C++ type T.
Definition: IROperator.h:205
A Halide::Buffer is a named shared reference to a Halide::Runtime::Buffer.
Definition: Buffer.h:12
std::vector< Parameter > parameters_
Definition: Generator.h:1231
GeneratorInput_Func(size_t array_size, const std::string &name)
Definition: Generator.h:1477
GeneratorOutput_Buffer(const std::string &name)
Definition: Generator.h:1980
std::shared_ptr< Internal::ValueTracker > get_value_tracker() const
Definition: Generator.h:2428
Defines methods for manipulating and analyzing boolean expressions.
Realization realize(Args &&... args)
Definition: Generator.h:3131
EXPORT void set_min_value(Expr e)
Get and set constraints for scalar parameters.
virtual void set_impl(const T &new_value)
Definition: Generator.h:479
virtual std::string get_template_value() const
Definition: Generator.h:423
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&#39;s sc...
std::string get_template_value() const override
Definition: Generator.h:743
decltype((Other) 0+(T) 0) operator+(const Other &a, const GeneratorParam< T > &b)
Addition between GeneratorParam<T> and any type that supports operator+ with T.
Definition: Generator.h:818
T parse_scalar(const std::string &value)
Definition: Generator.h:2257
RegisterGenerator(const char *registered_name, GeneratorFactory generator_factory)
Definition: Generator.h:3077
GeneratorOutputImpl(const std::string &name, IOKind kind, const std::vector< Type > &t, int d)
Definition: Generator.h:1871
GeneratorInput_Buffer(const std::string &name, int d)
Definition: Generator.h:1347
typename std::remove_all_extents< T >::type TBase
Definition: Generator.h:1255
StubInput(const Expr &e)
Definition: Generator.h:1097
std::function< std::unique_ptr< GeneratorBase >(const GeneratorContext &)> GeneratorFactory
Definition: Generator.h:2489
void verify_same_funcs(const StubOutputBuffer< T2 > &a, const StubOutputBuffer< T2 > &b)
Definition: Generator.h:3194
unsigned __INT8_TYPE__ uint8_t
Defines the structure that describes a Halide target.
EXPORT std::vector< Type > parse_halide_type_list(const std::string &types)
std::string to_string() const override
Definition: Generator.h:683
decltype(max((T) 0,(Other) 1)) max_forward(const GeneratorParam< T > &a, const Other &b)
Definition: Generator.h:948
typename std::remove_all_extents< T >::type TBase
Definition: Generator.h:1860
std::shared_ptr< ExternsMap > externs_map
Definition: Generator.h:2415
Expr operator()(Args &&... args) const
Definition: Generator.h:1482
Expr min(FuncRef a, FuncRef b)
Explicit overloads of min and max for FuncRef.
Definition: Func.h:418
GeneratorInput_Arithmetic(const std::string &name, const TBase &def, const TBase &min, const TBase &max)
Definition: Generator.h:1629
typename Super::TBase TBase
Definition: Generator.h:1670
decltype((Other) 0 -(T) 0) operator-(const Other &a, const GeneratorParam< T > &b)
Subtraction between GeneratorParam<T> and any type that supports operator- with T.
Definition: Generator.h:827
std::vector< ValueType >::const_iterator end() const
Definition: Generator.h:1307
Expr operator()(std::vector< Expr > args) const
Definition: Generator.h:1486
NO_INLINE void set_scalar(T val)
If the parameter is a scalar parameter, set its current value.
Definition: Parameter.h:96
EXPORT Target get_jit_target_from_environment()
Return the target that Halide will use for jit-compilation.
std::vector< ValueType >::const_iterator begin() const
Definition: Generator.h:1923
Defines Func - the front-end handle on a halide function, and related classes.
virtual std::string get_c_type() const
Forward schedule-related methods to the underlying Func.
Definition: Generator.h:1836
GeneratorInput_Buffer< T > & estimate(Var var, Expr min, Expr extent)
Definition: Generator.h:1374
ValueTracker is an internal utility class that attempts to track and flag certain obvious Stub-relate...
Definition: Generator.h:278
std::string get_c_type() const override
Definition: Generator.h:611
#define HALIDE_INPUT_FORWARD_CONST(method)
Definition: Generator.h:1515
EXPORT bool defined() const
Does this function have at least a pure definition.
const void * get_introspection_helper()
Return the address of a global with type T *.
Definition: Introspection.h:40
EXPORT std::vector< Expr > parameter_constraints(const Parameter &p)
make_integer_sequence< size_t, N > make_index_sequence
Definition: Util.h:320
#define HALIDE_OUTPUT_FORWARD_CONST(method)
Definition: Generator.h:2073
Func in(const std::vector< Func > &others)
Definition: Generator.h:1511
typename std::conditional< First::value, typename First::type, void >::type type
Definition: Generator.h:354
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:677
Realization realize(std::vector< int32_t > sizes)
Definition: Generator.h:2570
GeneratorInput(size_t array_size, const std::string &name, const TBase &def, const TBase &min, const TBase &max)
Definition: Generator.h:1701
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:555
T2 get_output_buffer(const std::string &n) const
Definition: Generator.h:3158
decltype((Other) 0 !=(T) 1) operator!=(const Other &a, const GeneratorParam< T > &b)
Inequality comparison between between GeneratorParam<T> and any type that supports operator!= with T...
Definition: Generator.h:908
GeneratorParam_MachineParams(const std::string &name, const T &value)
Definition: Generator.h:545
GeneratorOutput< T > & operator=(Buffer< T2 > &buffer)
Definition: Generator.h:2237
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:583
GeneratorInput_Arithmetic(const std::string &name, const TBase &def=static_cast< TBase >(0))
Definition: Generator.h:1618
GeneratorOutput_Buffer(const std::string &name, int d)
Definition: Generator.h:1997
#define NO_INLINE
Definition: Util.h:41
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:652
A halide module.
Definition: Module.h:83
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:731
GeneratorParam(const std::string &name, const std::string &value)
Definition: Generator.h:809
GeneratorOutput_Buffer< T > & operator=(const Func &f)
Definition: Generator.h:2056
std::string get_c_type() const override
Definition: Generator.h:1438
GeneratorOutput_Buffer(const std::string &name, const std::vector< Type > &t, int d=-1)
Definition: Generator.h:1986
GeneratorOutput_Func< T > & operator=(const Func &f)
Definition: Generator.h:2130
static Expr cast(Expr e)
Definition: Generator.h:2459
EXPORT Var _
A placeholder variable for infered arguments.
static std::vector< StubInput > to_stub_input_vector(const StubInputBuffer< T > &b)
Definition: Generator.h:3179
typename Super::TBase TBase
Definition: Generator.h:2194
std::vector< Func > funcs_
Definition: Generator.h:1178
std::unique_ptr< T > create() const
Definition: Generator.h:2400
const ValueType & at(size_t i) const
Definition: Generator.h:1918
#define HALIDE_OUTPUT_FORWARD(method)
Definition: Generator.h:2066
void apply(const Args &...args)
Definition: Generator.h:2948
std::string get_c_type() const override
Definition: Generator.h:735
char * end
Definition: printer.h:30
#define internal_assert(c)
Definition: Error.h:140
A handle on the output buffer of a pipeline.
const ValueType & at(size_t i) const
Definition: Generator.h:1297
GeneratorInput(size_t array_size, const std::string &name)
Definition: Generator.h:1733
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:2272
GeneratorParam< bool > auto_schedule
Definition: Generator.h:2413
std::string halide_type_to_enum_string(const Type &t)
Definition: Generator.h:308
std::string get_c_type() const override
Definition: Generator.h:1561
unsigned __INT32_TYPE__ uint32_t
Classes for declaring scalar parameters to halide pipelines.
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:687
GeneratorInput_Buffer(const std::string &name, const Type &t, int d=-1)
Definition: Generator.h:1342
decltype(max((Other) 0,(T) 1)) max_forward(const Other &a, const GeneratorParam< T > &b)
Definition: Generator.h:946
char * dst
Definition: printer.h:30
const ValueType & operator[](size_t i) const
Definition: Generator.h:1913
virtual std::string get_type_decls() const
Definition: Generator.h:411
GeneratorInput(const std::string &name, const Type &t, int d)
Definition: Generator.h:1706
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:2281
NO_INLINE GeneratorOutput_Buffer< T > & operator=(Buffer< T2 > &buffer)
Definition: Generator.h:2021
std::string get_template_type() const override
Definition: Generator.h:739
EXPORT void set_estimate(Expr e)
Get and set constraints for scalar parameters.
GeneratorParam< MachineParams > machine_params
Definition: Generator.h:2414
#define user_error
Definition: Error.h:136
GeneratorInput(const std::string &name, const Type &t)
Definition: Generator.h:1710
LinkageType
Type of linkage a function can have.
Definition: Module.h:50
GeneratorInput_Arithmetic(size_t array_size, const std::string &name, const TBase &def=static_cast< TBase >(0))
Definition: Generator.h:1623
Provides a single global registry of Generators, GeneratorParams, and Params indexed by this pointer...
signed __INT64_TYPE__ int64_t
static std::unique_ptr< T > create(const Halide::GeneratorContext &context, const std::string &registered_name, const std::string &stub_name)
Definition: Generator.h:2936
EXPORT void set_buffer(Buffer<> b)
If the parameter is a buffer parameter, set its current value.
Type Bool(int lanes=1)
Construct a boolean type.
Definition: Type.h:452
GeneratorInput_Buffer(const std::string &name)
Definition: Generator.h:1336
GeneratorParam_Bool(const std::string &name, const T &value)
Definition: Generator.h:634
NO_INLINE const Func & get_func_ref() const
Forward schedule-related methods to the underlying Func.
Definition: Generator.h:1849
GeneratorBase & set_generator_param(const std::string &name, const T &value)
Definition: Generator.h:2519
EXPORT Type type() const
Get the type of this parameter.
std::string to_string() const override
Definition: Generator.h:2276
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:2539
bool is_array() const override
Definition: Generator.h:1257
GeneratorContext(const Target &t, bool auto_schedule=false, const MachineParams &machine_params=MachineParams::generic())
Definition: Generator.h:2366
GeneratorInput(size_t array_size, const std::string &name, const TBase &def)
Definition: Generator.h:1692
GeneratorOutput< T > & operator=(const Func &f)
Definition: Generator.h:2248
GeneratorInput_Func< T > & estimate(Var var, Expr min, Expr extent)
Definition: Generator.h:1498
GeneratorOutput(const std::string &name)
Definition: Generator.h:2197
#define HALIDE_ALWAYS_INLINE
Definition: HalideRuntime.h:27
bool is_array() const override
Definition: Generator.h:1863
GeneratorOutput(const std::string &name, int d)
Definition: Generator.h:2209
static EXPORT MachineParams generic()
Default machine parameters for generic CPU architecture.
FuncRef operator()(Args &&... args) const
Definition: Generator.h:1893
static EXPORT void register_factory(const std::string &name, GeneratorFactory generator_factory)
decltype(min((Other) 0,(T) 1)) min_forward(const Other &a, const GeneratorParam< T > &b)
Definition: Generator.h:941
GeneratorInput(const std::string &name, const TBase &def)
Definition: Generator.h:1688
decltype((Other) 0 >=(T) 1) operator>=(const Other &a, const GeneratorParam< T > &b)
Greater than or equal comparison between GeneratorParam<T> and any type that supports operator>= with...
Definition: Generator.h:881
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:2532
GeneratorInput_Func(const std::string &name, const Type &t)
Definition: Generator.h:1453
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 > > >::type GeneratorInputImplBase
Definition: Generator.h:1661
Realization realize(std::vector< int32_t > sizes)
Definition: Generator.h:3124
StubOutputBufferBase(const Func &f, std::shared_ptr< GeneratorBase > generator)
Definition: Generator.h:1039
A reference-counted handle to a parameter to a halide pipeline.
Definition: Parameter.h:21
void call_generate() override
Definition: Generator.h:3051
EXPORT const std::vector< Type > & output_types() const
Get the types of the outputs of this Func.
std::string to_string() const override
Definition: Generator.h:591
std::string call_to_string(const std::string &v) const override
Definition: Generator.h:605
decltype((Other) 0 *(T) 0) operator*(const Other &a, const GeneratorParam< T > &b)
Multiplication between GeneratorParam<T> and any type that supports operator* with T...
Definition: Generator.h:836
GeneratorParam_Type(const std::string &name, const T &value)
Definition: Generator.h:728
GeneratorInput_Func(const std::string &name, const Type &t, int d)
Definition: Generator.h:1443
static Type Float(int bits, int lanes=1)
Definition: Generator.h:2466
const std::string & name() const
Buffers are optionally named.
Definition: Buffer.h:271
Type UInt(int bits, int lanes=1)
Constructing an unsigned integer type.
Definition: Type.h:442
A reference-counted handle to Halide&#39;s internal representation of a function.
Definition: Function.h:67
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:547
#define user_assert(c)
Definition: Error.h:141
GeneratorParamImpl(const std::string &name, const T &value)
Definition: Generator.h:450
bool is_synthetic_param() const override
Definition: Generator.h:2291
Realization realize(std::vector< int32_t > sizes)
Definition: Generator.h:1043
GeneratorInputImpl(const std::string &name, IOKind kind, const std::vector< Type > &t, int d)
Definition: Generator.h:1265
EXPORT Target get_target_from_environment()
Return the target that Halide will use.
An Image parameter to a halide pipeline.
Definition: ImageParam.h:20
unsigned __INT16_TYPE__ uint16_t
An argument to an extern-defined Func.
Definition: Function.h:24
Types in the halide type system.
Definition: Type.h:285
Pipeline build_pipeline() override
Definition: Generator.h:3047
EXPORT void track_values(const std::string &name, const std::vector< Expr > &values)
GeneratorOutput_Func(const std::string &name)
Definition: Generator.h:2115
GeneratorParam_Target(const std::string &name, const T &value)
Definition: Generator.h:521
NameMangling
An enum to specify calling convention for extern stages.
Definition: Function.h:54
std::shared_ptr< Internal::ValueTracker > value_tracker
Definition: Generator.h:2416
GeneratorInput_Func(size_t array_size, const std::string &name, int d)
Definition: Generator.h:1467
virtual std::string get_template_type() const
Definition: Generator.h:419
void realize(Realization r)
Definition: Generator.h:2583
EXPORT std::string halide_type_to_c_type(const Type &t)
decltype((Other) 0 &&(T) 1) operator &&(const Other &a, const GeneratorParam< T > &b)
Logical and between between GeneratorParam<T> and any type that supports operator&& with T...
Definition: Generator.h:917
decltype((Other) 0 >(T) 1) operator>(const Other &a, const GeneratorParam< T > &b)
Greater than comparison between GeneratorParam<T> and any type that supports operator> with T...
Definition: Generator.h:863
GeneratorParam(const std::string &name, const T &value, const std::map< std::string, T > &enum_map)
Definition: Generator.h:806
GeneratorParam is a templated class that can be used to modify the behavior of the Generator at code-...
Definition: Generator.h:798
MachineParams get_machine_params() const
Definition: Generator.h:2378
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:1681
GeneratorInput_Func(size_t array_size, const std::string &name, const Type &t)
Definition: Generator.h:1472
A ScheduleParam is a "Param" that can contain a scalar Expr or a LoopLevel; unlike Param<>...
Definition: Schedule.h:17
Target get_target() const
Definition: Generator.h:2376
decltype((Other) 0 %(T) 1) operator%(const Other &a, const GeneratorParam< T > &b)
Modulo between GeneratorParam<T> and any type that supports operator% with T.
Definition: Generator.h:854
#define HALIDE_INPUT_FORWARD(method)
Definition: Generator.h:1395
ScheduleParamBase & get_schedule_param(const std::string &n) const
Definition: Generator.h:3147
FuncRef operator()(std::vector< ExprOrVar > args) const
Definition: Generator.h:3120
EXPORT void set_max_value(Expr e)
Get and set constraints for scalar parameters.
GeneratorOutput< T > & operator=(const Internal::StubOutputBuffer< T2 > &stub_output_buffer)
Definition: Generator.h:2243
T enum_from_string(const std::map< std::string, T > &enum_map, const std::string &s)
Definition: Generator.h:301
GeneratorInput(const std::string &name, const TBase &def, const TBase &min, const TBase &max)
Definition: Generator.h:1696
static TO2 value(const FROM &from)
Definition: ScheduleParam.h:94
#define EXPORT
Definition: Util.h:30
GeneratorParam< Target > target
Definition: Generator.h:2412
A multi-dimensional domain over which to iterate.
Definition: RDom.h:179
std::string get_type_decls() const override
Definition: Generator.h:699
GeneratorInput(size_t array_size, const std::string &name, IntIfNonScalar d)
Definition: Generator.h:1729
A scalar parameter to a halide pipeline.
Definition: Param.h:21
virtual std::string get_default_value() const
Definition: Generator.h:415
std::map< std::string, std::string > substitutions
Definition: Generator.h:2510
StubInputBuffer is the placeholder that a Stub uses when it requires a Buffer for an input (rather th...
Definition: Generator.h:998
Classes for declaring image parameters to halide pipelines.
GeneratorParam(const std::string &name, const T &value, const T &min, const T &max)
Definition: Generator.h:803
GeneratorOutput_Buffer< T > & operator=(const StubOutputBuffer< T2 > &stub_output_buffer)
Definition: Generator.h:2048
void set_from_string(const std::string &new_value_string) override
Definition: Generator.h:523
static Type Bool(int lanes=1)
Definition: Generator.h:2465
static Expr cast(Halide::Type t, Expr e)
Definition: Generator.h:2460
static Type UInt(int bits, int lanes=1)
Definition: Generator.h:2468
std::string get_c_type() const override
Definition: Generator.h:1323
unsigned __INT64_TYPE__ uint64_t
FuncRef operator()(std::vector< ExprOrVar > args) const
Definition: Generator.h:1898
decltype((Other) 0/(T) 1) operator/(const Other &a, const GeneratorParam< T > &b)
Division between GeneratorParam<T> and any type that supports operator/ with T.
Definition: Generator.h:845
GeneratorInput(size_t array_size, const std::string &name, const Type &t)
Definition: Generator.h:1723
std::string get_c_type() const override
Definition: Generator.h:658
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:2185
GeneratorStub & operator=(GeneratorStub &&that)
Definition: Generator.h:3091
GeneratorInput(const std::string &name)
Definition: Generator.h:1684
std::string get_c_type() const override
Definition: Generator.h:691
Realization realize(Args &&... args)
Definition: Generator.h:2578
StubInputBuffer(const Buffer< T2 > &b)
Definition: Generator.h:1028
decltype(!(T) 0) operator!(const GeneratorParam< T > &a)
Not operator for GeneratorParam.
Definition: Generator.h:980
GeneratorInput_Scalar(size_t array_size, const std::string &name, const TBase &def=static_cast< TBase >(0))
Definition: Generator.h:1571
EXPORT int generate_filter_main(int argc, char **argv, std::ostream &cerr)
generate_filter_main() is a convenient wrapper for GeneratorRegistry::create() + compile_to_files(); ...
Expr max(FuncRef a, FuncRef b)
Explicit overloads of min and max for FuncRef.
Definition: Func.h:419
void set_impl(const T &new_value) override
Definition: Generator.h:578
GeneratorStub & schedule()
Definition: Generator.h:3104
signed __INT32_TYPE__ int32_t
std::string halide_looplevel_to_enum_string(const LoopLevel &loop_level)
Definition: Generator.h:313
Type Int(int bits, int lanes=1)
Constructing a signed integer type.
Definition: Type.h:437
signed __INT16_TYPE__ int16_t
StubInput(const Func &f)
Definition: Generator.h:1096
std::vector< ValueType >::const_iterator end() const
Definition: Generator.h:1928
EXPORT const std::map< std::string, Halide::Type > & get_halide_type_enum_map()
std::vector< Type > types_
Definition: Generator.h:1174
std::string get_type_decls() const override
Definition: Generator.h:751
EXPORT Expr make_const(Type t, int64_t val)
Construct an immediate of the given type from any numeric C++ type.
static std::unique_ptr< T > create(const Halide::GeneratorContext &context)
Definition: Generator.h:2927
GeneratorOutput_Func(const std::string &name, const std::vector< Type > &t, int d=-1)
Definition: Generator.h:2119
Type Float(int bits, int lanes=1)
Construct a floating-point type.
Definition: Type.h:447