1#ifndef HALIDE_GENERATOR_H_
2#define HALIDE_GENERATOR_H_
270#include <type_traits>
280#if !(__cplusplus >= 201703L || _MSVC_LANG >= 201703L)
281#error "Halide requires C++17 or later; please upgrade your compiler."
298 for (
const auto &key_value : enum_map) {
299 if (t == key_value.second) {
300 return key_value.first;
303 user_error <<
"Enumeration value not found.\n";
309 auto it = enum_map.find(s);
310 user_assert(it != enum_map.end()) <<
"Enumeration value not found: " << s <<
"\n";
379template<
bool B,
typename T>
385template<
typename First,
typename... Rest>
386struct select_type : std::conditional<First::value, typename First::type, typename select_type<Rest...>::type> {};
388template<
typename First>
390 using type =
typename std::conditional<First::value, typename First::type, void>::type;
400 const std::string &
name()
const {
412#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
413 virtual void set(const TYPE &new_value) = 0;
431#undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
434 void set(
const std::string &new_value) {
437 void set(
const char *new_value) {
472 const std::string name_;
489template<
typename FROM,
typename TO>
491 template<typename TO2 = TO, typename std::enable_if<!std::is_same<TO2, bool>::value>::type * =
nullptr>
492 static TO2
value(
const FROM &from) {
493 return static_cast<TO2
>(from);
496 template<typename TO2 = TO, typename std::enable_if<std::is_same<TO2, bool>::value>::type * =
nullptr>
497 static TO2
value(
const FROM &from) {
517 return this->
value();
524#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE) \
525 void set(const TYPE &new_value) override { \
526 typed_setter_impl<TYPE>(new_value, #TYPE); \
545#undef HALIDE_GENERATOR_PARAM_TYPED_SETTER
548 void set(
const std::string &new_value) {
564 template<
typename FROM,
typename std::enable_if<
565 !std::is_convertible<FROM, T>::value>
::type * =
nullptr>
571 template<
typename FROM,
typename std::enable_if<
572 std::is_same<FROM, T>::value>
::type * =
nullptr>
579 template<
typename FROM,
typename std::enable_if<
580 !std::is_same<FROM, T>::value &&
581 std::is_convertible<FROM, T>::value &&
582 std::is_convertible<T, FROM>::value>
::type * =
nullptr>
587 if (value2 !=
value) {
594 template<
typename FROM,
typename std::enable_if<
595 !std::is_same<FROM, T>::value &&
596 std::is_convertible<FROM, T>::value &&
597 !std::is_convertible<T, FROM>::value>
::type * =
nullptr>
621 return this->
value().to_string();
625 std::ostringstream oss;
626 oss << v <<
".to_string()";
647 bool try_set(
const std::string &key,
const std::string &
value);
679 if (new_value_string ==
"root") {
681 }
else if (new_value_string ==
"inlined") {
684 user_error <<
"Unable to parse " << this->
name() <<
": " << new_value_string;
701 return "LoopLevel::inlined()";
703 return "LoopLevel::root()";
712 return std::string();
729 const T &min = std::numeric_limits<T>::lowest(),
730 const T &max = std::numeric_limits<T>::max())
737 user_assert(new_value >= min && new_value <= max) <<
"Value out of range: " << new_value;
742 std::istringstream iss(new_value_string);
747 if (
sizeof(T) ==
sizeof(
char) && !std::is_same<T, bool>::value) {
754 user_assert(!iss.fail() && iss.get() == EOF) <<
"Unable to parse: " << new_value_string;
759 std::ostringstream oss;
760 oss << this->
value();
761 if (std::is_same<T, float>::value) {
764 if (oss.str().find(
'.') == std::string::npos) {
773 std::ostringstream oss;
774 oss <<
"std::to_string(" << v <<
")";
779 std::ostringstream oss;
780 if (std::is_same<T, float>::value) {
782 }
else if (std::is_same<T, double>::value) {
784 }
else if (std::is_integral<T>::value) {
785 if (std::is_unsigned<T>::value) {
788 oss <<
"int" << (
sizeof(T) * 8) <<
"_t";
809 if (new_value_string ==
"true" || new_value_string ==
"True") {
811 }
else if (new_value_string ==
"false" || new_value_string ==
"False") {
814 user_assert(
false) <<
"Unable to parse bool: " << new_value_string;
820 return this->
value() ?
"true" :
"false";
824 std::ostringstream oss;
825 oss <<
"std::string((" << v <<
") ? \"true\" : \"false\")";
844 template<typename T2 = T, typename std::enable_if<!std::is_same<T2, Type>::value>
::type * =
nullptr>
850 auto it = enum_map.find(new_value_string);
851 user_assert(it != enum_map.end()) <<
"Enumeration value not found: " << new_value_string;
856 return "Enum_" + this->
name() +
"_map().at(" + v +
")";
860 return "Enum_" + this->
name();
868 std::ostringstream oss;
869 oss <<
"enum class Enum_" << this->
name() <<
" {\n";
870 for (
auto key_value : enum_map) {
871 oss <<
" " << key_value.first <<
",\n";
878 oss <<
"inline HALIDE_NO_USER_CODE_INLINE const std::map<Enum_" << this->
name() <<
", std::string>& Enum_" << this->
name() <<
"_map() {\n";
879 oss <<
" static const std::map<Enum_" << this->
name() <<
", std::string> m = {\n";
880 for (
auto key_value : enum_map) {
881 oss <<
" { Enum_" << this->
name() <<
"::" << key_value.first <<
", \"" << key_value.first <<
"\"},\n";
884 oss <<
" return m;\n";
890 const std::map<std::string, T> enum_map;
901 return "Halide::Internal::halide_type_to_enum_string(" + v +
")";
924 this->
set(new_value_string);
928 return "\"" + this->
value() +
"\"";
936 return "std::string";
991 template<typename T2 = T, typename std::enable_if<!std::is_same<T2, std::string>::value>::type * =
nullptr>
993 :
Internal::GeneratorParamImplBase<T>(name, value) {
1000 GeneratorParam(
const std::string &name,
const T &value,
const std::map<std::string, T> &enum_map)
1001 :
Internal::GeneratorParamImplBase<T>(name, value, enum_map) {
1005 :
Internal::GeneratorParamImplBase<T>(name, value) {
1012template<
typename Other,
typename T>
1016template<
typename Other,
typename T>
1025template<
typename Other,
typename T>
1029template<
typename Other,
typename T>
1038template<
typename Other,
typename T>
1042template<
typename Other,
typename T>
1051template<
typename Other,
typename T>
1055template<
typename Other,
typename T>
1064template<
typename Other,
typename T>
1068template<
typename Other,
typename T>
1077template<
typename Other,
typename T>
1081template<
typename Other,
typename T>
1090template<
typename Other,
typename T>
1094template<
typename Other,
typename T>
1103template<
typename Other,
typename T>
1107template<
typename Other,
typename T>
1116template<
typename Other,
typename T>
1120template<
typename Other,
typename T>
1129template<
typename Other,
typename T>
1133template<
typename Other,
typename T>
1142template<
typename Other,
typename T>
1146template<
typename Other,
typename T>
1155template<
typename Other,
typename T>
1159template<
typename Other,
typename T>
1165 return (T)a && (T)b;
1172template<
typename Other,
typename T>
1176template<
typename Other,
typename T>
1182 return (T)a || (T)b;
1196template<
typename Other,
typename T>
1198 return min(a, (T)b);
1200template<
typename Other,
typename T>
1202 return min((T)a, b);
1205template<
typename Other,
typename T>
1207 return max(a, (T)b);
1209template<
typename Other,
typename T>
1211 return max((T)a, b);
1220template<
typename Other,
typename T>
1224template<
typename Other,
typename T>
1233template<
typename Other,
typename T>
1237template<
typename Other,
typename T>
1251template<
typename T2>
1252class GeneratorInput_Buffer;
1263template<typename T = void, int Dims = Buffer<>::AnyDims>
1266 template<
typename T2>
1268 template<
typename T2,
int D2>
1282 template<
typename T2,
int D2>
1298 template<
typename T2,
int D2>
1300 : parameter_(parameter_from_buffer(b)) {
1303 template<
typename T2>
1305 return {t.parameter_};
1308 template<
typename T2>
1310 std::vector<Parameter> r;
1311 r.reserve(v.size());
1312 for (
const auto &s : v) {
1313 r.push_back(s.parameter_);
1319class AbstractGenerator;
1334 template<
typename... Args>
1336 return f.realize(std::forward<Args>(args)...,
get_target());
1339 template<
typename Dst>
1357template<
typename T =
void>
1359 template<
typename T2>
1369 const std::shared_ptr<AbstractGenerator> &gen) {
1370 std::vector<StubOutputBuffer<T>> result;
1371 for (
const Func &
f : v) {
1372 result.push_back(StubOutputBuffer<T>(
f, gen));
1391 template<
typename T2>
1472 const std::string &
name,
1474 const std::vector<Type> &types,
1507 template<
typename ElemType>
1517 template<
typename T>
1541 const std::string &
name,
1543 const std::vector<Type> &t,
1580template<
typename T,
typename ValueType>
1583 using TBase =
typename std::remove_all_extents<T>::type;
1586 return std::is_array<T>::value;
1589 template<
typename T2 = T,
typename std::enable_if<
1591 !std::is_array<T2>::value>::type * =
nullptr>
1596 template<
typename T2 = T,
typename std::enable_if<
1598 std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)>::type * =
nullptr>
1603 template<
typename T2 = T,
typename std::enable_if<
1605 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>::type * =
nullptr>
1611 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1617 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1623 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1624 const ValueType &
at(
size_t i)
const {
1629 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1630 typename std::vector<ValueType>::const_iterator
begin()
const {
1635 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1636 typename std::vector<ValueType>::const_iterator
end()
const {
1650#define HALIDE_FORWARD_METHOD(Class, Method) \
1651 template<typename... Args> \
1652 inline auto Method(Args &&...args) -> typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
1653 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1656#define HALIDE_FORWARD_METHOD_CONST(Class, Method) \
1657 template<typename... Args> \
1658 inline auto Method(Args &&...args) const -> \
1659 typename std::remove_reference<decltype(std::declval<Class>().Method(std::forward<Args>(args)...))>::type { \
1660 this->check_gio_access(); \
1661 return this->template as<Class>().Method(std::forward<Args>(args)...); \
1665class GeneratorInput_Buffer :
public GeneratorInputImpl<T, Func> {
1667 using Super = GeneratorInputImpl<T, Func>;
1672 friend class ::Halide::Func;
1673 friend class ::Halide::Stage;
1676 if (TBase::has_static_halide_type) {
1677 return "Halide::Internal::StubInputBuffer<" +
1681 return "Halide::Internal::StubInputBuffer<>";
1685 template<
typename T2>
1693 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
1694 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
1699 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Input<Buffer<T>> if T is void or omitted.");
1700 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Input<Buffer<T, D>> if D is -1 or omitted.");
1705 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Input<Buffer<T>> if T is void or omitted.");
1710 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
1712 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Input<Buffer<T, D>> if D is -1 or omitted.");
1715 template<
typename... Args>
1718 return Func(*
this)(std::forward<Args>(args)...);
1723 return Func(*
this)(std::move(args));
1726 template<
typename T2>
1728 user_assert(!this->
is_array()) <<
"Cannot assign an array type to a non-array type for Input " << this->
name();
1734 return this->
funcs().at(0);
1756 return Func(*this).in();
1761 return Func(*this).in(other);
1766 return Func(*this).in(others);
1771 user_assert(!this->
is_array()) <<
"Cannot convert an Input<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->
name();
1775 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1781 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1787 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1793 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1794 typename std::vector<ImageParam>::const_iterator
begin()
const {
1795 user_error <<
"Input<Buffer<>>::begin() is not supported.";
1799 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
1800 typename std::vector<ImageParam>::const_iterator
end()
const {
1801 user_error <<
"Input<Buffer<>>::end() is not supported.";
1838 template<
typename T2>
1882 template<
typename... Args>
1885 return this->
funcs().at(0)(std::forward<Args>(args)...);
1890 return this->
funcs().at(0)(args);
1895 return this->
funcs().at(0);
1922 return Func(*this).
in(other);
1927 return Func(*this).
in(others);
1955 static_assert(std::is_same<typename std::remove_all_extents<T>::type,
Expr>::value,
"GeneratorInput_DynamicScalar is only legal to use with T=Expr for now");
1965 user_assert(!std::is_array<T>::value) <<
"Input<Expr[]> is not allowed";
1972 return this->
exprs().at(0);
2019 template<typename TBase2 = TBase, typename std::enable_if<!std::is_pointer<TBase2>::value>::type * =
nullptr>
2024 template<typename TBase2 = TBase, typename std::enable_if<std::is_pointer<TBase2>::value>::type * =
nullptr>
2026 user_assert(value == 0) <<
"Zero is the only legal default value for Inputs which are pointer types.\n";
2040 const std::string &
name)
2045 const std::string &
name,
2054 return this->
exprs().at(0);
2064 template<typename T2 = T, typename std::enable_if<std::is_pointer<T2>::value>::type * =
nullptr>
2067 user_assert(value ==
nullptr) <<
"nullptr is the only valid estimate for Input<PointerType>";
2074 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value && !std::is_pointer<T2>::value>::type * =
nullptr>
2078 if (std::is_same<T2, bool>::value) {
2086 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2090 if (std::is_same<T2, bool>::value) {
2114 if (!std::is_same<TBase, bool>::value) {
2116 if (
min_.defined()) {
2119 if (
max_.defined()) {
2137 const std::string &
name)
2142 const std::string &
name,
2155 const std::string &
name,
2168template<
typename T2,
typename =
void>
2171template<
typename T2>
2174template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
2212 : Super(name, def) {
2216 : Super(array_size, name, def) {
2221 : Super(name, def,
min,
max) {
2226 : Super(array_size, name, def,
min,
max) {
2230 : Super(name, t, d) {
2243 : Super(array_size, name, t, d) {
2247 : Super(array_size, name, t) {
2253 : Super(array_size, name, d) {
2257 : Super(array_size, name) {
2265 template<typename T2, typename std::enable_if<std::is_same<T2, Func>::value>::type * =
nullptr>
2267 static_assert(std::is_same<T2, Func>::value,
"Only Func allowed here");
2271 user_assert(
funcs_.size() == 1) <<
"Use [] to access individual Funcs in Output<Func[]>";
2341#undef HALIDE_OUTPUT_FORWARD
2342#undef HALIDE_OUTPUT_FORWARD_CONST
2346 const std::string &
name,
2348 const std::vector<Type> &t,
2353 const std::vector<Type> &t,
2379 using TBase =
typename std::remove_all_extents<T>::type;
2383 return std::is_array<T>::value;
2386 template<
typename T2 = T,
typename std::enable_if<
2388 !std::is_array<T2>::value>::type * =
nullptr>
2393 template<
typename T2 = T,
typename std::enable_if<
2395 std::is_array<T2>::value && std::rank<T2>::value == 1 && (std::extent<T2, 0>::value > 0)>::type * =
nullptr>
2400 template<
typename T2 = T,
typename std::enable_if<
2402 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>::type * =
nullptr>
2408 template<
typename... Args,
typename T2 = T,
typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2414 template<typename ExprOrVar, typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2420 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2426 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2432 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2438 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2444 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2450 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2451 typename std::vector<ValueType>::const_iterator
begin()
const {
2456 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2457 typename std::vector<ValueType>::const_iterator
end()
const {
2462 template<
typename T2 = T,
typename std::enable_if<
2464 std::is_array<T2>::value && std::rank<T2>::value == 1 && std::extent<T2, 0>::value == 0>::type * =
nullptr>
2482 const auto &my_types = this->
gio_types();
2484 <<
"Cannot assign Func \"" << f.
name()
2485 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2486 <<
"Output " << this->
name()
2487 <<
" is declared to have " << my_types.size() <<
" tuple elements"
2488 <<
" but Func " << f.
name()
2489 <<
" has " << f.
types().size() <<
" tuple elements.\n";
2490 for (
size_t i = 0; i < my_types.size(); i++) {
2492 <<
"Cannot assign Func \"" << f.
name()
2493 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2494 << (my_types.size() > 1 ?
"In tuple element " + std::to_string(i) +
", " :
"")
2495 <<
"Output " << this->
name()
2496 <<
" has declared type " << my_types[i]
2497 <<
" but Func " << f.
name()
2498 <<
" has type " << f.
types().at(i) <<
"\n";
2503 <<
"Cannot assign Func \"" << f.
name()
2504 <<
"\" to Output \"" << this->
name() <<
"\"\n"
2505 <<
"Output " << this->
name()
2506 <<
" has declared dimensionality " << this->
dims()
2507 <<
" but Func " << f.
name()
2508 <<
" has dimensionality " << f.
dimensions() <<
"\n";
2521 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2522 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
2529 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2530 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2536 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2541 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2544 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2549 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2550 TBase::has_static_dimensions ? TBase::static_dimensions() : -1) {
2557 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2558 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2564 static_assert(!TBase::has_static_halide_type,
"You can only specify a Type argument for Output<Buffer<T, D>> if T is void or omitted.");
2569 TBase::has_static_halide_type ? std::vector<
Type>{TBase::static_halide_type()} : std::vector<Type>{},
2572 static_assert(!TBase::has_static_dimensions,
"You can only specify a dimension argument for Output<Buffer<T, D>> if D is -1 or omitted.");
2576 if (TBase::has_static_halide_type) {
2577 return "Halide::Internal::StubOutputBuffer<" +
2581 return "Halide::Internal::StubOutputBuffer<>";
2585 template<typename T2, typename std::enable_if<!std::is_same<T2, Func>::value>::type * =
nullptr>
2597 template<
typename T2,
int D2>
2603 <<
"Cannot assign to the Output \"" << this->
name()
2604 <<
"\": the expression is not convertible to the same Buffer type and/or dimensions.\n";
2608 <<
"Output " << this->
name() <<
" should have type=" << this->
gio_type() <<
" but saw type=" <<
Type(buffer.
type()) <<
"\n";
2612 <<
"Output " << this->
name() <<
" should have dim=" << this->
dims() <<
" but saw dim=" << buffer.dimensions() <<
"\n";
2617 this->
funcs_.at(0)(_) = buffer(_);
2625 template<
typename T2>
2628 assign_from_func(stub_output_buffer.
f);
2637 assign_from_func(f);
2643 user_assert(!this->
is_array()) <<
"Cannot convert an Output<Buffer<>[]> to an ImageParam; use an explicit subscript operator: " << this->
name();
2645 return this->
funcs_.at(0).output_buffer();
2651 user_assert(!this->
is_array()) <<
"Cannot call set_estimates() on an array Output; use an explicit subscript operator: " << this->
name();
2653 this->
funcs_.at(0).set_estimates(estimates);
2657 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2664 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2695 return this->
funcs_.at(i);
2723 template<typename T2 = T, typename std::enable_if<!std::is_array<T2>::value>::type * =
nullptr>
2730 get_assignable_func_ref(0) = f;
2735 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2739 return get_assignable_func_ref(i);
2743 template<typename T2 = T, typename std::enable_if<std::is_array<T2>::value>::type * =
nullptr>
2753 f.set_estimate(var,
min, extent);
2762 f.set_estimates(estimates);
2785template<typename T, typename TBase = typename std::remove_all_extents<T>::type>
2815 : Super(array_size, name) {
2823 : Super(name, {t}) {
2831 : Super(name, {t}, d) {
2835 : Super(name, t, d) {
2839 : Super(array_size, name, d) {
2843 : Super(array_size, name, {t}) {
2846 explicit GeneratorOutput(
size_t array_size,
const std::string &name,
const std::vector<Type> &t)
2847 : Super(array_size, name, t) {
2851 : Super(array_size, name, {t}, d) {
2854 explicit GeneratorOutput(
size_t array_size,
const std::string &name,
const std::vector<Type> &t,
int d)
2855 : Super(array_size, name, t, d) {
2861 template<
typename T2,
int D2>
2863 Super::operator=(buffer);
2867 template<
typename T2>
2869 Super::operator=(stub_output_buffer);
2874 Super::operator=(f);
2883 std::istringstream iss(value);
2886 user_assert(!iss.fail() && iss.get() == EOF) <<
"Unable to parse: " << value;
2904 if (!error_msg.empty()) {
2907 set_from_string_impl<T>(new_value_string);
2912 return std::string();
2917 return std::string();
2922 return std::string();
2932 static std::unique_ptr<Internal::GeneratorParamBase> make(
2934 const std::string &generator_name,
2935 const std::string &gpname,
2939 std::string error_msg = defined ?
"Cannot set the GeneratorParam " + gpname +
" for " + generator_name +
" because the value is explicitly specified in the C++ source." :
"";
2940 return std::unique_ptr<GeneratorParam_Synthetic<T>>(
2941 new GeneratorParam_Synthetic<T>(gpname, gio, which, error_msg));
2948 template<typename T2 = T, typename std::enable_if<std::is_same<T2, ::Halide::Type>::value>::type * =
nullptr>
2949 void set_from_string_impl(
const std::string &new_value_string) {
2951 gio.types_ = parse_halide_type_list(new_value_string);
2954 template<typename T2 = T, typename std::enable_if<std::is_integral<T2>::value>::type * =
nullptr>
2955 void set_from_string_impl(
const std::string &new_value_string) {
2956 if (which == SyntheticParamType::Dim) {
2957 gio.dims_ = parse_scalar<T2>(new_value_string);
2958 }
else if (which == SyntheticParamType::ArraySize) {
2959 gio.array_size_ = parse_scalar<T2>(new_value_string);
2967 const std::string error_msg;
3025 return autoscheduler_params_;
3033 template<
typename T>
3035 return T::create(*
this);
3037 template<
typename T,
typename... Args>
3038 std::unique_ptr<T>
apply(
const Args &...args)
const {
3073 template<
typename T>
3080 template<
typename T>
3082 template<
typename T = void,
int D = -1>
3084 template<
typename T>
3102template<
typename... Args>
3108template<
typename T,
typename... Args>
3119 std::set<std::string> names;
3122 std::vector<Internal::GeneratorParamBase *> filter_generator_params;
3125 std::vector<Internal::GeneratorInputBase *> filter_inputs;
3128 std::vector<Internal::GeneratorOutputBase *> filter_outputs;
3133 std::vector<std::unique_ptr<Internal::GeneratorParamBase>> owned_synthetic_params;
3136 std::vector<std::unique_ptr<Internal::GIOBase>> owned_extras;
3144 return filter_generator_params;
3146 const std::vector<Internal::GeneratorInputBase *> &
inputs()
const {
3147 return filter_inputs;
3149 const std::vector<Internal::GeneratorOutputBase *> &
outputs()
const {
3150 return filter_outputs;
3166 template<
typename data_t>
3168 return get_target().natural_vector_size<data_t>();
3181 template<
typename... Args>
3186 <<
"Expected exactly " << pi.
inputs().size()
3187 <<
" inputs but got " <<
sizeof...(args) <<
"\n";
3188 set_inputs_vector(build_inputs(std::forward_as_tuple<const Args &...>(args...), std::make_index_sequence<
sizeof...(Args)>{}));
3192 this->check_scheduled(
"realize");
3198 template<
typename... Args,
typename std::enable_if<
NoRealizations<Args...>::value>::type * =
nullptr>
3200 this->check_scheduled(
"realize");
3205 this->check_scheduled(
"realize");
3216 template<
typename T,
3217 typename std::enable_if<std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3221 p->generator =
this;
3222 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3223 param_info_ptr->filter_inputs.push_back(p);
3228 template<
typename T,
3229 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3231 static_assert(!T::has_static_halide_type,
"You can only call this version of add_input() for a Buffer<T, D> where T is void or omitted .");
3232 static_assert(!T::has_static_dimensions,
"You can only call this version of add_input() for a Buffer<T, D> where D is -1 or omitted.");
3235 p->generator =
this;
3236 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3237 param_info_ptr->filter_inputs.push_back(p);
3242 template<
typename T,
3243 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3245 static_assert(T::has_static_halide_type,
"You can only call this version of add_input() for a Buffer<T, D> where T is not void.");
3246 static_assert(!T::has_static_dimensions,
"You can only call this version of add_input() for a Buffer<T, D> where D is -1 or omitted.");
3249 p->generator =
this;
3250 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3251 param_info_ptr->filter_inputs.push_back(p);
3256 template<
typename T,
3257 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3259 static_assert(T::has_static_halide_type,
"You can only call this version of add_input() for a Buffer<T, D> where T is not void.");
3260 static_assert(T::has_static_dimensions,
"You can only call this version of add_input() for a Buffer<T, D> where D is not -1.");
3263 p->generator =
this;
3264 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3265 param_info_ptr->filter_inputs.push_back(p);
3269 template<
typename T,
3270 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3274 p->generator =
this;
3275 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3276 param_info_ptr->filter_inputs.push_back(p);
3280 template<
typename T,
3281 typename std::enable_if<std::is_same<T, Expr>::value>::type * =
nullptr>
3285 p->generator =
this;
3287 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3288 param_info_ptr->filter_inputs.push_back(p);
3293 template<
typename T,
3294 typename std::enable_if<std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3298 p->generator =
this;
3299 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3300 param_info_ptr->filter_outputs.push_back(p);
3305 template<
typename T,
3306 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3308 static_assert(!T::has_static_halide_type,
"You can only call this version of add_output() for a Buffer<T, D> where T is void or omitted .");
3309 static_assert(!T::has_static_dimensions,
"You can only call this version of add_output() for a Buffer<T, D> where D is -1 or omitted.");
3312 p->generator =
this;
3313 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3314 param_info_ptr->filter_outputs.push_back(p);
3319 template<
typename T,
3320 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3322 static_assert(T::has_static_halide_type,
"You can only call this version of add_output() for a Buffer<T, D> where T is not void.");
3323 static_assert(!T::has_static_dimensions,
"You can only call this version of add_output() for a Buffer<T, D> where D is -1 or omitted.");
3326 p->generator =
this;
3327 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3328 param_info_ptr->filter_outputs.push_back(p);
3333 template<
typename T,
3334 typename std::enable_if<!std::is_arithmetic<T>::value && !std::is_same<T, Halide::Func>::value>::type * =
nullptr>
3336 static_assert(T::has_static_halide_type,
"You can only call this version of add_output() for a Buffer<T, D> where T is not void.");
3337 static_assert(T::has_static_dimensions,
"You can only call this version of add_output() for a Buffer<T, D> where D is not -1.");
3340 p->generator =
this;
3341 param_info_ptr->owned_extras.push_back(std::unique_ptr<Internal::GIOBase>(p));
3342 param_info_ptr->filter_outputs.push_back(p);
3348 template<
typename... Args,
3351 std::vector<Expr> collected_args;
3434 template<
typename T>
3437 template<
typename T>
3481 friend void ::Halide::Internal::generator_test();
3493 std::unique_ptr<GeneratorParamInfo> param_info_ptr;
3495 std::string generator_registered_name, generator_stub_name;
3498 struct Requirement {
3500 std::vector<Expr> error_args;
3502 std::vector<Requirement> requirements;
3507 template<
typename T>
3508 T *find_by_name(
const std::string &name,
const std::vector<T *> &v) {
3510 if (t->name() == name) {
3517 Internal::GeneratorInputBase *find_input_by_name(
const std::string &name);
3518 Internal::GeneratorOutputBase *find_output_by_name(
const std::string &name);
3520 void check_scheduled(
const char *m)
const;
3522 void build_params(
bool force =
false);
3531 void set_inputs_vector(
const std::vector<std::vector<StubInput>> &inputs);
3533 static void check_input_is_singular(Internal::GeneratorInputBase *in);
3534 static void check_input_is_array(Internal::GeneratorInputBase *in);
3535 static void check_input_kind(Internal::GeneratorInputBase *in, Internal::ArgInfoKind kind);
3541 template<
typename T,
int Dims>
3542 std::vector<StubInput> build_input(
size_t i,
const Buffer<T, Dims> &arg) {
3543 auto *in = param_info().inputs().at(i);
3544 check_input_is_singular(in);
3545 const auto k = in->kind();
3546 if (k == Internal::ArgInfoKind::Buffer) {
3547 Halide::Buffer<> b = arg;
3548 StubInputBuffer<> sib(b);
3551 }
else if (k == Internal::ArgInfoKind::Function) {
3552 Halide::Func f(arg.name() +
"_im");
3553 f(Halide::_) = arg(Halide::_);
3557 check_input_kind(in, Internal::ArgInfoKind::Buffer);
3566 template<
typename T,
int Dims>
3567 std::vector<StubInput> build_input(
size_t i,
const GeneratorInput<Buffer<T, Dims>> &arg) {
3568 auto *in = param_info().inputs().at(i);
3569 check_input_is_singular(in);
3570 const auto k = in->kind();
3571 if (k == Internal::ArgInfoKind::Buffer) {
3572 StubInputBuffer<> sib = arg;
3575 }
else if (k == Internal::ArgInfoKind::Function) {
3576 Halide::Func f = arg.funcs().at(0);
3580 check_input_kind(in, Internal::ArgInfoKind::Buffer);
3586 std::vector<StubInput> build_input(
size_t i,
const Func &arg) {
3587 auto *in = param_info().inputs().at(i);
3588 check_input_kind(in, Internal::ArgInfoKind::Function);
3589 check_input_is_singular(in);
3590 const Halide::Func &f = arg;
3596 std::vector<StubInput> build_input(
size_t i,
const std::vector<Func> &arg) {
3597 auto *in = param_info().inputs().at(i);
3598 check_input_kind(in, Internal::ArgInfoKind::Function);
3599 check_input_is_array(in);
3601 std::vector<StubInput> siv;
3602 siv.reserve(arg.size());
3603 for (
const auto &f : arg) {
3604 siv.emplace_back(f);
3610 std::vector<StubInput> build_input(
size_t i,
const Expr &arg) {
3611 auto *in = param_info().inputs().at(i);
3612 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3613 check_input_is_singular(in);
3619 std::vector<StubInput> build_input(
size_t i,
const std::vector<Expr> &arg) {
3620 auto *in = param_info().inputs().at(i);
3621 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3622 check_input_is_array(in);
3623 std::vector<StubInput> siv;
3624 siv.reserve(arg.size());
3625 for (
const auto &value : arg) {
3626 siv.emplace_back(value);
3633 template<
typename T,
3634 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3635 std::vector<StubInput> build_input(
size_t i,
const T &arg) {
3636 auto *in = param_info().inputs().at(i);
3637 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3638 check_input_is_singular(in);
3646 template<
typename T,
3647 typename std::enable_if<std::is_arithmetic<T>::value>::type * =
nullptr>
3648 std::vector<StubInput> build_input(
size_t i,
const std::vector<T> &arg) {
3649 auto *in = param_info().inputs().at(i);
3650 check_input_kind(in, Internal::ArgInfoKind::Scalar);
3651 check_input_is_array(in);
3652 std::vector<StubInput> siv;
3653 siv.reserve(arg.size());
3654 for (
const auto &value : arg) {
3658 siv.emplace_back(e);
3663 template<
typename... Args,
size_t... Indices>
3664 std::vector<std::vector<StubInput>> build_inputs(
const std::tuple<const Args &...> &t, std::index_sequence<Indices...>) {
3665 return {build_input(Indices, std::get<Indices>(t))...};
3670 template<
typename T>
3671 static void get_arguments(std::vector<AbstractGenerator::ArgInfo> &args, ArgInfoDirection dir,
const T &t) {
3673 args.push_back({e->name(),
3676 e->gio_types_defined() ? e->gio_types() : std::vector<Type>{},
3677 e->dims_defined() ? e->dims() : 0});
3710class GeneratorRegistry {
3721 using GeneratorFactoryMap = std::map<const std::string, GeneratorFactory>;
3723 GeneratorFactoryMap factories;
3726 static GeneratorRegistry &get_registry();
3728 GeneratorRegistry() =
default;
3732 GeneratorRegistry &
operator=(
const GeneratorRegistry &) =
delete;
3734 GeneratorRegistry &
operator=(GeneratorRegistry &&that) =
delete;
3750 auto g = std::make_unique<T>();
3751 g->init_from_context(
context);
3757 const std::string ®istered_name,
3758 const std::string &stub_name) {
3760 g->set_generator_names(registered_name, stub_name);
3764 template<
typename... Args>
3772 template<
typename T2>
3777 template<
typename T2,
typename... Args>
3778 std::unique_ptr<T2>
apply(
const Args &...args)
const {
3792 template<
typename T2,
typename =
void>
3793 struct has_configure_method : std::false_type {};
3795 template<
typename T2>
3796 struct has_configure_method<T2, typename type_sink<decltype(std::declval<T2>().configure())>::type> : std::true_type {};
3798 template<
typename T2,
typename =
void>
3799 struct has_generate_method : std::false_type {};
3801 template<
typename T2>
3802 struct has_generate_method<T2, typename type_sink<decltype(std::declval<T2>().generate())>::type> : std::true_type {};
3804 template<
typename T2,
typename =
void>
3805 struct has_schedule_method : std::false_type {};
3807 template<
typename T2>
3808 struct has_schedule_method<T2, typename type_sink<decltype(std::declval<T2>().
schedule())>::type> : std::true_type {};
3810 Pipeline build_pipeline_impl() {
3817 t->call_generate_impl();
3818 t->call_schedule_impl();
3819 return get_pipeline();
3822 void call_configure_impl() {
3824 if constexpr (has_configure_method<T>::value) {
3826 static_assert(std::is_void<
decltype(t->configure())>::value,
"configure() must return void");
3832 void call_generate_impl() {
3834 static_assert(has_generate_method<T>::value,
"Expected a generate() method here.");
3836 static_assert(std::is_void<
decltype(t->generate())>::value,
"generate() must return void");
3841 void call_schedule_impl() {
3843 if constexpr (has_schedule_method<T>::value) {
3845 static_assert(std::is_void<
decltype(t->schedule())>::value,
"schedule() must return void");
3854 return this->build_pipeline_impl();
3858 this->call_configure_impl();
3862 this->call_generate_impl();
3866 this->call_schedule_impl();
3870 friend void ::Halide::Internal::generator_test();
3871 friend void ::Halide::Internal::generator_test();
3872 friend class ::Halide::GeneratorContext;
3975 const std::string &name,
3978 const std::string &name,
3988struct halide_global_ns;
3991#define _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
3992 namespace halide_register_generator { \
3993 struct halide_global_ns; \
3994 namespace GEN_REGISTRY_NAME##_ns { \
3995 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
3996 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
3997 using GenType = std::remove_pointer<decltype(new GEN_CLASS_NAME)>::type; \
3998 return GenType::create(context, #GEN_REGISTRY_NAME, #FULLY_QUALIFIED_STUB_NAME); \
4002 auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
4005 static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
4006 "HALIDE_REGISTER_GENERATOR must be used at global scope");
4008#define _HALIDE_REGISTER_GENERATOR2(GEN_CLASS_NAME, GEN_REGISTRY_NAME) \
4009 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, GEN_REGISTRY_NAME)
4011#define _HALIDE_REGISTER_GENERATOR3(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME) \
4012 _HALIDE_REGISTER_GENERATOR_IMPL(GEN_CLASS_NAME, GEN_REGISTRY_NAME, FULLY_QUALIFIED_STUB_NAME)
4017#define __HALIDE_REGISTER_ARGCOUNT_IMPL(_1, _2, _3, COUNT, ...) \
4020#define _HALIDE_REGISTER_ARGCOUNT_IMPL(ARGS) \
4021 __HALIDE_REGISTER_ARGCOUNT_IMPL ARGS
4023#define _HALIDE_REGISTER_ARGCOUNT(...) \
4024 _HALIDE_REGISTER_ARGCOUNT_IMPL((__VA_ARGS__, 3, 2, 1, 0))
4026#define ___HALIDE_REGISTER_CHOOSER(COUNT) \
4027 _HALIDE_REGISTER_GENERATOR##COUNT
4029#define __HALIDE_REGISTER_CHOOSER(COUNT) \
4030 ___HALIDE_REGISTER_CHOOSER(COUNT)
4032#define _HALIDE_REGISTER_CHOOSER(COUNT) \
4033 __HALIDE_REGISTER_CHOOSER(COUNT)
4035#define _HALIDE_REGISTER_GENERATOR_PASTE(A, B) \
4038#define HALIDE_REGISTER_GENERATOR(...) \
4039 _HALIDE_REGISTER_GENERATOR_PASTE(_HALIDE_REGISTER_CHOOSER(_HALIDE_REGISTER_ARGCOUNT(__VA_ARGS__)), (__VA_ARGS__))
4055#define HALIDE_REGISTER_GENERATOR_ALIAS(GEN_REGISTRY_NAME, ORIGINAL_REGISTRY_NAME, ...) \
4056 namespace halide_register_generator { \
4057 struct halide_global_ns; \
4058 namespace ORIGINAL_REGISTRY_NAME##_ns { \
4059 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4061 namespace GEN_REGISTRY_NAME##_ns { \
4062 std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context) { \
4063 auto g = ORIGINAL_REGISTRY_NAME##_ns::factory(context); \
4064 const Halide::GeneratorParamsMap m = __VA_ARGS__; \
4065 g->set_generatorparam_values(m); \
4070 auto reg_##GEN_REGISTRY_NAME = Halide::Internal::RegisterGenerator(#GEN_REGISTRY_NAME, GEN_REGISTRY_NAME##_ns::factory); \
4073 static_assert(std::is_same<::halide_register_generator::halide_global_ns, halide_register_generator::halide_global_ns>::value, \
4074 "HALIDE_REGISTER_GENERATOR_ALIAS must be used at global scope");
4079#define HALIDE_GENERATOR_PYSTUB(GEN_REGISTRY_NAME, MODULE_NAME) \
4080 static_assert(PY_MAJOR_VERSION >= 3, "Python bindings for Halide require Python 3+"); \
4081 extern "C" PyObject *_halide_pystub_impl(const char *module_name, const Halide::Internal::GeneratorFactory &factory); \
4082 namespace halide_register_generator::GEN_REGISTRY_NAME##_ns { \
4083 extern std::unique_ptr<Halide::Internal::AbstractGenerator> factory(const Halide::GeneratorContext &context); \
4085 extern "C" HALIDE_EXPORT_SYMBOL PyObject *PyInit_##MODULE_NAME() { \
4086 const auto factory = halide_register_generator::GEN_REGISTRY_NAME##_ns::factory; \
4087 return _halide_pystub_impl(#MODULE_NAME, factory); \
#define internal_assert(c)
Defines Func - the front-end handle on a halide function, and related classes.
#define HALIDE_GENERATOR_PARAM_TYPED_SETTER(TYPE)
#define HALIDE_FORWARD_METHOD(Class, Method)
#define HALIDE_FORWARD_METHOD_CONST(Class, Method)
#define HALIDE_ALWAYS_INLINE
Classes for declaring image parameters to halide pipelines.
Provides a single global registry of Generators, GeneratorParams, and Params indexed by this pointer.
Defines the structure that describes a Halide target.
#define HALIDE_NO_USER_CODE_INLINE
bool defined() const
Check if this Buffer refers to an existing Buffer.
static bool can_convert_from(const Buffer< T2, D2 > &other)
Helper class for identifying purpose of an Expr passed to memoize.
bool defined() const
Does this function have at least a pure definition.
int dimensions() const
The dimensionality (number of arguments) of this function.
const std::vector< Type > & types() const
const std::string & name() const
The name of this function, either given during construction, or automatically generated.
Func in(const Func &f)
Creates and returns a new identity Func that wraps this Func.
A fragment of front-end syntax of the form f(x, y, z), where x, y, z are Vars or Exprs.
GeneratorContext is a class that is used when using Generators (or Stubs) directly; it is used to all...
GeneratorContext with_target(const Target &t) const
GeneratorContext(const Target &t)
std::unique_ptr< T > apply(const Args &...args) const
std::unique_ptr< T > create() const
GeneratorContext & operator=(GeneratorContext &&)=default
GeneratorContext & operator=(const GeneratorContext &)=default
const Target & target() const
GeneratorContext(const Target &t, const AutoschedulerParams &autoscheduler_params)
GeneratorContext()=default
GeneratorContext(const GeneratorContext &)=default
const AutoschedulerParams & autoscheduler_params() const
GeneratorContext(GeneratorContext &&)=default
void call_generate() override
Generator(Generator &&that)=delete
static std::unique_ptr< T > create(const Halide::GeneratorContext &context, const std::string ®istered_name, const std::string &stub_name)
void call_schedule() override
std::unique_ptr< T2 > apply(const Args &...args) const
static std::unique_ptr< T > create(const Halide::GeneratorContext &context)
Generator & operator=(Generator &&that)=delete
Generator & operator=(const Generator &)=delete
void apply(const Args &...args)
void call_configure() override
std::unique_ptr< T2 > create() const
Pipeline build_pipeline() override
Build and return the Pipeline for this AbstractGenerator.
Generator(const Generator &)=delete
typename Super::TBase TBase
GeneratorOutput(const std::string &name)
GeneratorOutput(const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput< T > & operator=(const Internal::StubOutputBuffer< T2 > &stub_output_buffer)
GeneratorOutput(const char *name)
GeneratorOutput(const std::string &name, const std::vector< Type > &t)
GeneratorOutput(size_t array_size, const std::string &name, int d)
GeneratorOutput(size_t array_size, const std::string &name, const Type &t, int d)
GeneratorOutput(const std::string &name, const Type &t, int d)
GeneratorOutput< T > & operator=(Buffer< T2, D2 > &buffer)
GeneratorOutput(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput(const std::string &name, int d)
GeneratorOutput(size_t array_size, const std::string &name)
GeneratorOutput(const std::string &name, const Type &t)
GeneratorOutput(size_t array_size, const std::string &name, const std::vector< Type > &t)
GeneratorOutput(size_t array_size, const std::string &name, const Type &t)
GeneratorOutput< T > & operator=(const Func &f)
GeneratorParam is a templated class that can be used to modify the behavior of the Generator at code-...
GeneratorParam(const std::string &name, const std::string &value)
GeneratorParam(const std::string &name, const T &value, const T &min, const T &max)
GeneratorParam(const std::string &name, const T &value)
GeneratorParam(const std::string &name, const T &value, const std::map< std::string, T > &enum_map)
An Image parameter to a halide pipeline.
AbstractGenerator is an ABC that defines the API a Generator must provide to work with the existing G...
A reference-counted handle to Halide's internal representation of a function.
GIOBase is the base class for all GeneratorInput<> and GeneratorOutput<> instantiations; it is not pa...
const std::string & name() const
GIOBase & operator=(const GIOBase &)=delete
size_t array_size() const
virtual const char * input_or_output() const =0
GIOBase(size_t array_size, const std::string &name, ArgInfoKind kind, const std::vector< Type > &types, int dims)
void check_matching_dims(int d) const
friend class GeneratorBase
bool array_size_defined() const
const std::vector< Type > & gio_types() const
bool dims_defined() const
GIOBase & operator=(GIOBase &&)=delete
const std::vector< Func > & funcs() const
std::vector< Type > types_
void check_matching_types(const std::vector< Type > &t) const
std::string array_name(size_t i) const
virtual void check_value_writable() const =0
GIOBase(const GIOBase &)=delete
void check_matching_array_size(size_t size) const
friend class GeneratorStub
GIOBase(GIOBase &&)=delete
void check_gio_access() const
void set_dimensions(int dims)
void set_array_size(int size)
std::vector< Func > funcs_
friend class GeneratorParamInfo
virtual bool is_array() const
virtual void verify_internals()
virtual ~GIOBase()=default
friend class GeneratorParam_Synthetic
std::vector< Expr > exprs_
void set_type(const Type &type)
bool gio_types_defined() const
GeneratorBase * generator
const std::vector< Expr > & exprs() const
const std::vector< ElemType > & get_values() const
GeneratorContext context() const override
Return the Target and autoscheduler info that this Generator was created with.
void ensure_configure_has_been_called()
std::string name() override
Return the name of this Generator.
friend class StubOutputBufferBase
virtual void call_schedule()=0
bool allow_out_of_order_inputs_and_outputs() const override
By default, a Generator must declare all Inputs before all Outputs.
GeneratorParam< Target > target
void bind_input(const std::string &name, const std::vector< Parameter > &v) override
Rebind a specified Input to refer to the given piece of IR, replacing the default ImageParam / Param ...
GeneratorInput< T > * add_input(const std::string &name)
std::vector< Func > output_func(const std::string &name) override
Given the name of an output, return the Func(s) for that output.
std::vector< Parameter > input_parameter(const std::string &name) override
Given the name of an input, return the Parameter(s) for that input.
void bind_input(const std::string &name, const std::vector< Func > &v) override
void bind_input(const std::string &name, const std::vector< Expr > &v) override
bool emit_hlpipe(const std::string &hlpipe_file_path) override
Emit a Serialized Halide Pipeline (.hlpipe) file to the given path.
Realization realize(Args &&...args)
GeneratorBase(const GeneratorBase &)=delete
virtual void call_generate()=0
GeneratorOutput< T > * add_output(const std::string &name)
GeneratorBase(size_t size)
GeneratorOutput< T > Output
int natural_vector_size() const
Given a data type, return an estimate of the "natural" vector size for that data type when compiling ...
friend class GeneratorInputBase
Target get_target() const
~GeneratorBase() override
virtual void init_from_context(const Halide::GeneratorContext &context)
void check_exact_phase(Phase expected_phase) const
void set_generatorparam_value(const std::string &name, const LoopLevel &loop_level) override
void check_min_phase(Phase expected_phase) const
void realize(Realization r)
enum Halide::Internal::GeneratorBase::Phase Created
void set_generator_names(const std::string ®istered_name, const std::string &stub_name)
Realization realize(std::vector< int32_t > sizes)
GeneratorInput< T > * add_input(const std::string &name, int dimensions)
std::vector< ArgInfo > arginfos() override
Return a list of all the ArgInfos for this generator.
virtual void call_configure()=0
GeneratorInput< T > * add_input(const std::string &name, const Type &type)
void set_generatorparam_value(const std::string &name, const std::string &value) override
Set the value for a specific GeneratorParam for an AbstractGenerator instance.
GeneratorBase(GeneratorBase &&that)=delete
GeneratorOutput< T > * add_output(const std::string &name, int dimensions)
bool using_autoscheduler() const
friend class GeneratorParamBase
bool emit_cpp_stub(const std::string &stub_file_path) override
Emit a Generator Stub (.stub.h) file to the given path.
friend class GeneratorParamInfo
GeneratorInput< T > Input
GeneratorBase & operator=(const GeneratorBase &)=delete
GeneratorBase & operator=(GeneratorBase &&that)=delete
void set_inputs(const Args &...args)
set_inputs is a variadic wrapper around set_inputs_vector, which makes usage much simpler in many cas...
GeneratorParam_AutoSchedulerParams autoscheduler_
HALIDE_NO_USER_CODE_INLINE void add_requirement(const Expr &condition, Args &&...error_args)
GeneratorInput< T > * add_input(const std::string &name, const Type &t, int dimensions)
void add_requirement(const Expr &condition, const std::vector< Expr > &error_args)
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 ...
void advance_phase(Phase new_phase)
GeneratorOutput< T > * add_output(const std::string &name, const Type &t, int dimensions)
friend class GeneratorOutputBase
GeneratorFactoryProvider provides a way to customize the Generators that are visible to generate_filt...
virtual AbstractGeneratorPtr create(const std::string &name, const Halide::GeneratorContext &context) const =0
Create an instance of the Generator that is registered under the given name.
GeneratorFactoryProvider(const GeneratorFactoryProvider &)=delete
GeneratorFactoryProvider()=default
GeneratorFactoryProvider & operator=(GeneratorFactoryProvider &&)=delete
GeneratorFactoryProvider(GeneratorFactoryProvider &&)=delete
GeneratorFactoryProvider & operator=(const GeneratorFactoryProvider &)=delete
virtual std::vector< std::string > enumerate() const =0
Return a list of all registered Generators that are available for use with the create() method.
virtual ~GeneratorFactoryProvider()=default
GeneratorOutput_Arithmetic(const std::string &name)
GeneratorOutput_Arithmetic(size_t array_size, const std::string &name)
typename Super::TBase TBase
GeneratorOutput_Buffer(const std::string &name, int d)
GeneratorOutput_Buffer(size_t array_size, const std::string &name)
typename Super::TBase TBase
GeneratorOutput_Buffer(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput_Buffer< T > & operator=(const StubOutputBuffer< T2 > &stub_output_buffer)
GeneratorOutput_Buffer(const std::string &name)
HALIDE_NO_USER_CODE_INLINE std::string get_c_type() const override
GeneratorOutput_Buffer< T > & set_estimates(const Region &estimates)
HALIDE_NO_USER_CODE_INLINE T2 as() const
GeneratorOutput_Buffer(const std::string &name, const std::vector< Type > &t)
GeneratorOutput_Buffer(size_t array_size, const std::string &name, int d)
GeneratorOutput_Buffer< T > & operator=(const Func &f)
HALIDE_NO_USER_CODE_INLINE GeneratorOutput_Buffer< T > & operator=(Buffer< T2, D2 > &buffer)
const Func & operator[](size_t i) const
GeneratorOutput_Buffer(size_t array_size, const std::string &name, const std::vector< Type > &t)
GeneratorOutput_Buffer(const std::string &name, const std::vector< Type > &t, int d)
Func operator[](size_t i)
const Func & operator[](size_t i) const
GeneratorOutput_Func(const std::string &name)
typename Super::TBase TBase
GeneratorOutput_Func< T > & operator=(const Func &f)
GeneratorOutput_Func(const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput_Func(size_t array_size, const std::string &name, const std::vector< Type > &t, int d)
GeneratorOutput_Func(const std::string &name, int d)
GeneratorOutput_Func< T > & set_estimate(const Var &var, const Expr &min, const Expr &extent)
Func & operator[](size_t i)
GeneratorOutput_Func(const std::string &name, const std::vector< Type > &t)
GeneratorOutput_Func< T > & set_estimates(const Region &estimates)
const char * input_or_output() const override
~GeneratorOutputBase() override
friend class GeneratorBase
GeneratorOutputBase(const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
virtual std::string get_c_type() const
HALIDE_NO_USER_CODE_INLINE T2 as() const
void check_value_writable() const override
GeneratorOutputBase(size_t array_size, const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
Forward schedule-related methods to the underlying Func.
std::vector< ValueType >::const_iterator end() const
const ValueType & operator[](size_t i) const
GeneratorOutputImpl(const std::string &name, ArgInfoKind kind, const std::vector< Type > &t, int d)
const ValueType & at(size_t i) const
std::vector< ValueType >::const_iterator begin() const
bool is_array() const override
FuncRef operator()(std::vector< ExprOrVar > args) const
typename std::remove_all_extents< T >::type TBase
FuncRef operator()(Args &&...args) const
void set_from_string(const std::string &new_value_string) override
std::string get_c_type() const override
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())
std::string get_default_value() const override
std::string call_to_string(const std::string &v) const override
void set_impl(const T &new_value) override
GeneratorParam_AutoSchedulerParams()
std::string get_c_type() const override
friend class GeneratorBase
void set_from_string(const std::string &new_value_string) override
std::string get_default_value() const override
std::string call_to_string(const std::string &v) const override
void set_from_string(const std::string &new_value_string) override
std::string get_default_value() const override
std::string call_to_string(const std::string &v) const override
GeneratorParam_Bool(const std::string &name, const T &value)
std::string get_c_type() const override
std::string call_to_string(const std::string &v) const override
std::string get_default_value() const override
GeneratorParam_Enum(const std::string &name, const T &value, const std::map< std::string, T > &enum_map)
void set_from_string(const std::string &new_value_string) override
std::string get_c_type() const override
std::string get_type_decls() const override
GeneratorParam_LoopLevel(const std::string &name, const LoopLevel &value)
std::string get_c_type() const override
std::string call_to_string(const std::string &v) const override
bool is_looplevel_param() const override
void set(const LoopLevel &value) override
void set_from_string(const std::string &new_value_string) override
std::string get_default_value() const override
GeneratorParam_String(const std::string &name, const std::string &value)
std::string get_c_type() const override
void set_from_string(const std::string &new_value_string) override
std::string get_default_value() const override
std::string call_to_string(const std::string &v) const override
bool is_synthetic_param() const override
std::string call_to_string(const std::string &v) const override
void set_from_string(const std::string &new_value_string) override
friend class GeneratorParamInfo
std::string get_default_value() const override
std::string get_c_type() const override
void set_from_string(const std::string &new_value_string) override
GeneratorParam_Target(const std::string &name, const T &value)
std::string get_c_type() const override
std::string get_default_value() const override
std::string call_to_string(const std::string &v) const override
std::string get_type_decls() const override
std::string get_c_type() const override
std::string call_to_string(const std::string &v) const override
std::string get_default_value() const override
GeneratorParam_Type(const std::string &name, const T &value)
void check_value_readable() const
virtual bool is_synthetic_param() const
GeneratorParamBase(GeneratorParamBase &&)=delete
friend class GeneratorBase
virtual std::string call_to_string(const std::string &v) const =0
void fail_wrong_type(const char *type)
virtual ~GeneratorParamBase()
virtual std::string get_type_decls() const
GeneratorParamBase(const std::string &name)
virtual std::string get_default_value() const =0
void set(const std::string &new_value)
GeneratorParamBase(const GeneratorParamBase &)=delete
virtual std::string get_c_type() const =0
virtual bool is_looplevel_param() const
virtual void set_from_string(const std::string &value_string)=0
void check_value_writable() const
GeneratorParamBase & operator=(GeneratorParamBase &&)=delete
const std::string & name() const
friend class GeneratorParamInfo
GeneratorParamBase & operator=(const GeneratorParamBase &)=delete
void set(const char *new_value)
void set(const std::string &new_value)
GeneratorParamImpl(const std::string &name, const T &value)
virtual void set_impl(const T &new_value)
const std::vector< Internal::GeneratorInputBase * > & inputs() const
friend class GeneratorBase
const std::vector< Internal::GeneratorParamBase * > & generator_params() const
GeneratorParamInfo(GeneratorBase *generator, size_t size)
const std::vector< Internal::GeneratorOutputBase * > & outputs() const
GeneratorRegistry(const GeneratorRegistry &)=delete
static AbstractGeneratorPtr create(const std::string &name, const Halide::GeneratorContext &context)
GeneratorRegistry & operator=(GeneratorRegistry &&that)=delete
GeneratorRegistry(GeneratorRegistry &&that)=delete
GeneratorRegistry & operator=(const GeneratorRegistry &)=delete
static void register_factory(const std::string &name, GeneratorFactory generator_factory)
static std::vector< std::string > enumerate()
static void unregister_factory(const std::string &name)
RegisterGenerator(const char *registered_name, GeneratorFactory generator_factory)
Target get_target() const
std::shared_ptr< AbstractGenerator > generator
Realization realize(Args &&...args)
StubOutputBufferBase(const Func &f, const std::shared_ptr< AbstractGenerator > &generator)
Realization realize(std::vector< int32_t > sizes)
StubOutputBuffer is the placeholder that a Stub uses when it requires a Buffer for an output (rather ...
StubOutputBuffer()=default
static std::vector< StubOutputBuffer< T > > to_output_buffers(const std::vector< Func > &v, const std::shared_ptr< AbstractGenerator > &gen)
friend class GeneratorOutput_Buffer
A reference to a site in a Halide statement at the top of the body of a particular for loop.
static LoopLevel root()
Construct a special LoopLevel value which represents the location outside of all for loops.
static LoopLevel inlined()
Construct a special LoopLevel value that implies that a function should be inlined away.
void set(const LoopLevel &other)
Mutate our contents to match the contents of 'other'.
Halide::GeneratorParam< T > GeneratorParam
Halide::MemoryType MemoryType
static Type Bool(int lanes=1)
Halide::ImageParam ImageParam
Halide::ExternFuncArgument ExternFuncArgument
static Expr cast(Halide::Type t, Expr e)
Halide::GeneratorContext GeneratorContext
Halide::NameMangling NameMangling
Halide::TailStrategy TailStrategy
static Type UInt(int bits, int lanes=1)
Halide::LoopLevel LoopLevel
Halide::EvictionKey EvictionKey
Halide::Partition Partition
static Type Int(int bits, int lanes=1)
static Type Float(int bits, int lanes=1)
Halide::PrefetchBoundStrategy PrefetchBoundStrategy
Halide::Buffer< T, D > Buffer
Halide::Pipeline Pipeline
A handle on the output buffer of a pipeline.
A scalar parameter to a halide pipeline.
A reference-counted handle to a parameter to a halide pipeline.
void set_default_value(const Expr &e)
Get and set the default values for scalar parameters.
int dimensions() const
Get the dimensionality of this parameter.
void set_max_value(const Expr &e)
void set_buffer(const Buffer< void > &b)
If the parameter is a buffer parameter, set its current value.
void set_min_value(const Expr &e)
Get and set constraints for scalar parameters.
void set_estimate(Expr e)
Type type() const
Get the type of this parameter.
A class representing a Halide pipeline.
A multi-dimensional domain over which to iterate.
A reduction variable represents a single dimension of a reduction domain (RDom).
A Realization is a vector of references to existing Buffer objects.
A single definition of a Func.
Create a small array of Exprs for defining and calling functions with multiple outputs.
A Halide variable, to be used when defining functions.
auto max_forward(const Other &a, const GeneratorParam< T > &b) -> decltype(max(a,(T) b))
auto min_forward(const Other &a, const GeneratorParam< T > &b) -> decltype(min(a,(T) b))
typename select_type< cond< has_static_halide_type_method< TBase >::value, GeneratorInput_Buffer< T > >, cond< std::is_same< TBase, Func >::value, GeneratorInput_Func< T > >, cond< std::is_arithmetic< TBase >::value, GeneratorInput_Arithmetic< T > >, cond< std::is_scalar< TBase >::value, GeneratorInput_Scalar< T > >, cond< std::is_same< TBase, Expr >::value, GeneratorInput_DynamicScalar< T > > >::type GeneratorInputImplBase
int generate_filter_main(int argc, char **argv)
generate_filter_main() is a convenient wrapper for GeneratorRegistry::create() + compile_to_files(); ...
std::string halide_type_to_enum_string(const Type &t)
ConstantInterval min(const ConstantInterval &a, const ConstantInterval &b)
std::vector< Expr > parameter_constraints(const Parameter &p)
Expr make_const(Type t, int64_t val)
Construct an immediate of the given type from any numeric C++ type.
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
std::string halide_type_to_c_source(const Type &t)
std::function< AbstractGeneratorPtr(const GeneratorContext &context)> GeneratorFactory
ConstantInterval max(const ConstantInterval &a, const ConstantInterval &b)
HALIDE_NO_USER_CODE_INLINE std::string enum_to_string(const std::map< std::string, T > &enum_map, const T &t)
std::vector< Type > parse_halide_type_list(const std::string &types)
std::string halide_type_to_c_type(const Type &t)
std::string print_loop_nest(const std::vector< Function > &output_funcs)
Emit some simple pseudocode that shows the structure of the loop nest specified by this pipeline's sc...
void execute_generator(const ExecuteGeneratorArgs &args)
Execute a Generator for AOT compilation – this provides the implementation of the command-line Genera...
std::unique_ptr< AbstractGenerator > AbstractGeneratorPtr
HALIDE_NO_USER_CODE_INLINE void collect_print_args(std::vector< Expr > &args)
const GeneratorFactoryProvider & get_registered_generators()
Return a GeneratorFactoryProvider that knows about all the currently-registered C++ Generators.
typename select_type< cond< std::is_same< T, Target >::value, GeneratorParam_Target< T > >, cond< std::is_same< T, LoopLevel >::value, GeneratorParam_LoopLevel >, cond< std::is_same< T, std::string >::value, GeneratorParam_String< T > >, cond< std::is_same< T, Type >::value, GeneratorParam_Type< T > >, cond< std::is_same< T, bool >::value, GeneratorParam_Bool< T > >, cond< std::is_arithmetic< T >::value, GeneratorParam_Arithmetic< T > >, cond< std::is_enum< T >::value, GeneratorParam_Enum< T > > >::type GeneratorParamImplBase
T parse_scalar(const std::string &value)
const std::map< std::string, Halide::Type > & get_halide_type_enum_map()
T enum_from_string(const std::map< std::string, T > &enum_map, const std::string &s)
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
auto operator>=(const Other &a, const GeneratorParam< T > &b) -> decltype(a >=(T) b)
Greater than or equal comparison between GeneratorParam<T> and any type that supports operator>= with...
Target get_host_target()
Return the target corresponding to the host machine.
Type UInt(int bits, int lanes=1)
Constructing an unsigned integer type.
Expr reinterpret(Type t, Expr e)
Reinterpret the bits of one value as another type.
Type Float(int bits, int lanes=1)
Construct a floating-point type.
std::function< std::unique_ptr< Internal::CompilerLogger >(const std::string &fn_name, const Target &target)> CompilerLoggerFactory
auto operator==(const Other &a, const GeneratorParam< T > &b) -> decltype(a==(T) b)
Equality comparison between GeneratorParam<T> and any type that supports operator== with T.
auto operator<(const Other &a, const GeneratorParam< T > &b) -> decltype(a<(T) b)
Less than comparison between GeneratorParam<T> and any type that supports operator< with T.
Type type_of()
Construct the halide equivalent of a C type.
auto operator*(const Other &a, const GeneratorParam< T > &b) -> decltype(a *(T) b)
Multiplication between GeneratorParam<T> and any type that supports operator* with T.
auto operator||(const Other &a, const GeneratorParam< T > &b) -> decltype(a||(T) b)
Logical or between between GeneratorParam<T> and any type that supports operator|| with T.
PrefetchBoundStrategy
Different ways to handle accesses outside the original extents in a prefetch.
auto operator-(const Other &a, const GeneratorParam< T > &b) -> decltype(a -(T) b)
Subtraction between GeneratorParam<T> and any type that supports operator- with T.
auto operator!(const GeneratorParam< T > &a) -> decltype(!(T) a)
Not operator for GeneratorParam.
TailStrategy
Different ways to handle a tail case in a split when the factor does not provably divide the extent.
Type Int(int bits, int lanes=1)
Constructing a signed integer type.
auto operator+(const Other &a, const GeneratorParam< T > &b) -> decltype(a+(T) b)
Addition between GeneratorParam<T> and any type that supports operator+ with T.
Callable create_callable_from_generator(const GeneratorContext &context, const std::string &name, const GeneratorParamsMap &generator_params={})
Create a Generator from the currently-registered Generators, use it to create a Callable.
Expr min(const FuncRef &a, const FuncRef &b)
Explicit overloads of min and max for FuncRef.
auto operator&&(const Other &a, const GeneratorParam< T > &b) -> decltype(a &&(T) b)
Logical and between between GeneratorParam<T> and any type that supports operator&& with T.
auto operator%(const Other &a, const GeneratorParam< T > &b) -> decltype(a %(T) b)
Modulo between GeneratorParam<T> and any type that supports operator% with T.
NameMangling
An enum to specify calling convention for extern stages.
@ Default
Match whatever is specified in the Target.
Target get_jit_target_from_environment()
Return the target that Halide will use for jit-compilation.
std::map< std::string, std::string > GeneratorParamsMap
auto operator<=(const Other &a, const GeneratorParam< T > &b) -> decltype(a<=(T) b)
Less than or equal comparison between GeneratorParam<T> and any type that supports operator<= with T.
Target get_target_from_environment()
Return the target that Halide will use.
auto operator>(const Other &a, const GeneratorParam< T > &b) -> decltype(a >(T) b)
Greater than comparison between GeneratorParam<T> and any type that supports operator> with T.
auto operator!=(const Other &a, const GeneratorParam< T > &b) -> decltype(a !=(T) b)
Inequality comparison between between GeneratorParam<T> and any type that supports operator!...
Internal::ConstantInterval cast(Type t, const Internal::ConstantInterval &a)
Cast operators for ConstantIntervals.
Type Bool(int lanes=1)
Construct a boolean type.
std::vector< Range > Region
A multi-dimensional box.
auto operator/(const Other &a, const GeneratorParam< T > &b) -> decltype(a/(T) b)
Division between GeneratorParam<T> and any type that supports operator/ with T.
Expr max(const FuncRef &a, const FuncRef &b)
MemoryType
An enum describing different address spaces to be used with Func::store_in.
Partition
Different ways to handle loops with a potentially optimizable boundary conditions.
unsigned __INT64_TYPE__ uint64_t
signed __INT64_TYPE__ int64_t
signed __INT32_TYPE__ int32_t
unsigned __INT8_TYPE__ uint8_t
unsigned __INT16_TYPE__ uint16_t
unsigned __INT32_TYPE__ uint32_t
signed __INT16_TYPE__ int16_t
signed __INT8_TYPE__ int8_t
Special the Autoscheduler to be used (if any), along with arbitrary additional arguments specific to ...
A fragment of Halide syntax.
HALIDE_ALWAYS_INLINE Type type() const
Get the type of this expression node.
An argument to an extern-defined Func.
static TO2 value(const FROM &from)
The Dim struct represents one loop in the schedule's representation of a loop nest.
ExecuteGeneratorArgs is the set of arguments to execute_generator().
CompilerLoggerFactory compiler_logger_factory
std::string function_name
std::string file_base_name
CreateGeneratorFn create_generator
std::string generator_name
std::set< OutputFileType > output_types
std::vector< std::string > suffixes
std::vector< Target > targets
GeneratorParamsMap generator_params
std::function< AbstractGeneratorPtr(const std::string &name, const GeneratorContext &context)> CreateGeneratorFn
static constexpr bool value
typename std::conditional< First::value, typename First::type, void >::type type
A struct representing a target machine and os to generate code for.
Types in the halide type system.