#ifndef HALIDE_TYPE_H
#define HALIDE_TYPE_H
#include <stdint.h>
#include "runtime/HalideRuntime.h"
#include "Error.h"
#include "Util.h"
#include "Float16.h"
struct halide_cplusplus_type_name {
enum CPPTypeType {
Simple,
Struct,
Class,
Union,
Enum,
} cpp_type_type;
std::string name;
halide_cplusplus_type_name(CPPTypeType cpp_type_type, const std::string &name)
: cpp_type_type(cpp_type_type), name(name) {
}
bool operator==(const halide_cplusplus_type_name &rhs) const {
return cpp_type_type == rhs.cpp_type_type &&
name == rhs.name;
}
bool operator!=(const halide_cplusplus_type_name &rhs) const {
return !(*this == rhs);
}
bool operator<(const halide_cplusplus_type_name &rhs) const {
return cpp_type_type < rhs.cpp_type_type ||
(cpp_type_type == rhs.cpp_type_type &&
name < rhs.name);
}
};
struct halide_handle_cplusplus_type {
halide_cplusplus_type_name inner_name;
std::vector<std::string> namespaces;
std::vector<halide_cplusplus_type_name> enclosing_types;
enum Modifier : uint8_t {
Const = 1 << 0,
Volatile = 1 << 1,
Restrict = 1 << 2,
Pointer = 1 << 3,
};
std::vector<uint8_t> cpp_type_modifiers;
enum ReferenceType : uint8_t {
NotReference = 0,
LValueReference = 1,
RValueReference = 2,
};
ReferenceType reference_type;
halide_handle_cplusplus_type(const halide_cplusplus_type_name &inner_name,
const std::vector<std::string> &namespaces = { },
const std::vector<halide_cplusplus_type_name> &enclosing_types = { },
const std::vector<uint8_t> &modifiers = { },
ReferenceType reference_type = NotReference)
: inner_name(inner_name),
namespaces(namespaces),
enclosing_types(enclosing_types),
cpp_type_modifiers(modifiers),
reference_type(reference_type) {}
};
template<typename T>
struct halide_c_type_to_name {
static const bool known_type = false;
};
#define HALIDE_DECLARE_EXTERN_TYPE(TypeType, Type) \
template<> struct halide_c_type_to_name<Type> { \
static const bool known_type = true; \
static halide_cplusplus_type_name name() { \
return { halide_cplusplus_type_name::TypeType, #Type}; \
} \
}
#define HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(T) HALIDE_DECLARE_EXTERN_TYPE(Simple, T)
#define HALIDE_DECLARE_EXTERN_STRUCT_TYPE(T) HALIDE_DECLARE_EXTERN_TYPE(Struct, T)
#define HALIDE_DECLARE_EXTERN_CLASS_TYPE(T) HALIDE_DECLARE_EXTERN_TYPE(Class, T)
#define HALIDE_DECLARE_EXTERN_UNION_TYPE(T) HALIDE_DECLARE_EXTERN_TYPE(Union, T)
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(bool);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(int8_t);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(uint8_t);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(int16_t);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(uint16_t);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(int32_t);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(uint32_t);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(int64_t);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(uint64_t);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(float);
HALIDE_DECLARE_EXTERN_SIMPLE_TYPE(double);
HALIDE_DECLARE_EXTERN_STRUCT_TYPE(buffer_t);
HALIDE_DECLARE_EXTERN_STRUCT_TYPE(halide_buffer_t);
HALIDE_DECLARE_EXTERN_STRUCT_TYPE(halide_dimension_t);
HALIDE_DECLARE_EXTERN_STRUCT_TYPE(halide_device_interface_t);
HALIDE_DECLARE_EXTERN_STRUCT_TYPE(halide_filter_metadata_t);
template<typename T, bool KnownType>
struct halide_internal_handle_traits {
static const halide_handle_cplusplus_type *type_info(bool is_ptr,
halide_handle_cplusplus_type::ReferenceType ref_type) {
static_assert(!KnownType, "Only unknown types handled here");
internal_assert(is_ptr) << "Unknown types must be pointers";
internal_assert(ref_type == halide_handle_cplusplus_type::NotReference) << "Unknown types must not be references";
static const halide_handle_cplusplus_type the_info{
{halide_cplusplus_type_name::Simple, "void"},
{},
{},
{
(uint8_t)(halide_handle_cplusplus_type::Pointer |
(std::is_const<T>::value ? halide_handle_cplusplus_type::Const : 0) |
(std::is_volatile<T>::value ? halide_handle_cplusplus_type::Volatile : 0))
},
halide_handle_cplusplus_type::NotReference
};
return &the_info;
}
};
template<typename T>
struct halide_internal_handle_traits<T, true> {
static const halide_handle_cplusplus_type make_info(bool is_ptr,
halide_handle_cplusplus_type::ReferenceType ref_type) {
halide_handle_cplusplus_type the_info = {
halide_c_type_to_name<typename std::remove_cv<T>::type>::name(),
{},
{},
{
(uint8_t)((is_ptr ? halide_handle_cplusplus_type::Pointer : 0) |
(std::is_const<T>::value ? halide_handle_cplusplus_type::Const : 0) |
(std::is_volatile<T>::value ? halide_handle_cplusplus_type::Volatile : 0))
},
ref_type
};
the_info.inner_name.name =
Halide::Internal::extract_namespaces(the_info.inner_name.name,
the_info.namespaces);
return the_info;
}
static const halide_handle_cplusplus_type *type_info(bool is_ptr,
halide_handle_cplusplus_type::ReferenceType ref_type) {
static const halide_handle_cplusplus_type the_info = make_info(is_ptr, ref_type);
return &the_info;
}
};
template<typename T>
struct halide_handle_traits {
inline static const halide_handle_cplusplus_type *type_info() { return nullptr; }
};
template<typename T>
struct halide_handle_traits<T *> {
inline static const halide_handle_cplusplus_type *type_info() {
return halide_internal_handle_traits<T, halide_c_type_to_name<typename std::remove_cv<T>::type>::known_type>::type_info(true, halide_handle_cplusplus_type::NotReference);
}
};
template<typename T>
struct halide_handle_traits<T &> {
inline static const halide_handle_cplusplus_type *type_info() {
return halide_internal_handle_traits<T, halide_c_type_to_name<typename std::remove_cv<T>::type>::known_type>::type_info(false, halide_handle_cplusplus_type::LValueReference);
}
};
template<typename T>
struct halide_handle_traits<T &&> {
inline static const halide_handle_cplusplus_type *type_info() {
return halide_internal_handle_traits<T, halide_c_type_to_name<typename std::remove_cv<T>::type>::known_type>::type_info(false, halide_handle_cplusplus_type::RValueReference);
}
};
template<>
struct halide_handle_traits<const char *> {
inline static const halide_handle_cplusplus_type *type_info() {
static const halide_handle_cplusplus_type the_info{
halide_cplusplus_type_name(halide_cplusplus_type_name::Simple, "char"),
{}, {}, { halide_handle_cplusplus_type::Pointer |
halide_handle_cplusplus_type::Const}};
return &the_info;
}
};
namespace Halide {
struct Expr;
struct Type {
private:
halide_type_t type;
public:
static const halide_type_code_t Int = halide_type_int;
static const halide_type_code_t UInt = halide_type_uint;
static const halide_type_code_t Float = halide_type_float;
static const halide_type_code_t Handle = halide_type_handle;
int bytes() const {return (bits() + 7) / 8;}
Type() : type(Handle, 0, 0), handle_type(nullptr) {}
Type(halide_type_code_t code, int bits, int lanes, const halide_handle_cplusplus_type *handle_type = nullptr)
: type(code, (uint8_t)bits, (uint16_t)lanes), handle_type(handle_type) {
}
Type(const Type &that) = default;
Type(const halide_type_t &that, const halide_handle_cplusplus_type *handle_type = nullptr)
: type(that), handle_type(handle_type) {}
operator halide_type_t() const { return type; }
halide_type_code_t code() const { return (halide_type_code_t)type.code; }
int bits() const { return type.bits; }
int lanes() const { return type.lanes; }
Type with_code(halide_type_code_t new_code) const {
return Type(new_code, bits(), lanes(),
(new_code == code()) ? handle_type : nullptr);
}
Type with_bits(int new_bits) const {
return Type(code(), new_bits, lanes(),
(new_bits == bits()) ? handle_type : nullptr);
}
Type with_lanes(int new_lanes) const {
return Type(code(), bits(), new_lanes, handle_type);
}
const halide_handle_cplusplus_type *handle_type;
bool is_bool() const {return code() == UInt && bits() == 1;}
bool is_vector() const {return lanes() != 1;}
bool is_scalar() const {return lanes() == 1;}
bool is_float() const {return code() == Float;}
bool is_int() const {return code() == Int;}
bool is_uint() const {return code() == UInt;}
bool is_handle() const {return code() == Handle;}
EXPORT bool same_handle_type(const Type &other) const;
bool operator==(const Type &other) const {
return code() == other.code() && bits() == other.bits() && lanes() == other.lanes() &&
(code() != Handle || same_handle_type(other));
}
bool operator!=(const Type &other) const {
return code() != other.code() || bits() != other.bits() || lanes() != other.lanes() ||
(code() == Handle && !same_handle_type(other));
}
Type element_of() const {
return with_lanes(1);
}
EXPORT bool can_represent(Type other) const;
EXPORT bool can_represent(double x) const;
EXPORT bool can_represent(int64_t x) const;
EXPORT bool can_represent(uint64_t x) const;
EXPORT bool is_max(uint64_t) const;
EXPORT bool is_max(int64_t) const;
EXPORT bool is_min(uint64_t) const;
EXPORT bool is_min(int64_t) const;
EXPORT Expr max() const;
EXPORT Expr min() const;
};
inline Type Int(int bits, int lanes = 1) {
return Type(Type::Int, bits, lanes);
}
inline Type UInt(int bits, int lanes = 1) {
return Type(Type::UInt, bits, lanes);
}
inline Type Float(int bits, int lanes = 1) {
return Type(Type::Float, bits, lanes);
}
inline Type Bool(int lanes = 1) {
return UInt(1, lanes);
}
inline Type Handle(int lanes = 1, const halide_handle_cplusplus_type *handle_type = nullptr) {
return Type(Type::Handle, 64, lanes, handle_type);
}
template<typename T>
inline Type type_of() {
return Type(halide_type_of<T>(), halide_handle_traits<T>::type_info());
}
}
#endif