#ifndef HALIDE_PARAMETER_H
#define HALIDE_PARAMETER_H
/** \file
* Defines the internal representation of parameters to halide piplines
*/
#include "Expr.h"
#include "Buffer.h"
namespace Halide {
class OutputImageParam;
namespace Internal {
class Constrainable;
struct ParameterContents;
/** A reference-counted handle to a parameter to a halide
* pipeline. May be a scalar parameter or a buffer */
class Parameter {
IntrusivePtr<ParameterContents> contents;
void check_defined() const;
void check_is_buffer() const;
void check_is_scalar() const;
void check_dim_ok(int dim) const;
public:
/** Construct a new undefined handle */
EXPORT Parameter();
/** Construct a new parameter of the given type. If the second
* argument is true, this is a buffer parameter of the given
* dimensionality, otherwise, it is a scalar parameter (and the
* dimensionality should be zero). The parameter will be given a
* unique auto-generated name. */
EXPORT Parameter(Type t, bool is_buffer, int dimensions);
/** Construct a new parameter of the given type with name given by
* the third argument. If the second argument is true, this is a
* buffer parameter, otherwise, it is a scalar parameter. The
* third argument gives the dimensionality of the buffer
* parameter. It should be zero for scalar parameters. If the
* fifth argument is true, the the name being passed in was
* explicitly specified (as opposed to autogenerated). If the
* sixth argument is true, the Parameter is registered in the global
* ObjectInstanceRegistry. */
EXPORT Parameter(Type t, bool is_buffer, int dimensions,
const std::string &name, bool is_explicit_name = false,
bool register_instance = true, bool is_bound_before_lowering = false);
/** Copy ctor, operator=, and dtor, needed for ObjectRegistry accounting. */
EXPORT Parameter(const Parameter&);
EXPORT Parameter& operator=(const Parameter&);
EXPORT ~Parameter();
/** Get the type of this parameter */
EXPORT Type type() const;
/** Get the dimensionality of this parameter. Zero for scalars. */
EXPORT int dimensions() const;
/** Get the name of this parameter */
EXPORT const std::string &name() const;
/** Return true iff the name was explicitly specified */
EXPORT bool is_explicit_name() const;
/** Return true iff this Parameter is expected to be replaced with a
* constant at the start of lowering, and thus should not be used to
* infer arguments */
EXPORT bool is_bound_before_lowering() const;
/** Does this parameter refer to a buffer/image? */
EXPORT bool is_buffer() const;
/** If the parameter is a scalar parameter, get its currently
* bound value. Only relevant when jitting */
template<typename T>
NO_INLINE T get_scalar() const {
// Allow get_scalar<uint64_t>() for all Handle types
user_assert(type() == type_of<T>() || (type().is_handle() && type_of<T>() == UInt(64)))
<< "Can't get Param<" << type()
<< "> as scalar of type " << type_of<T>() << "\n";
return *((const T *)(get_scalar_address()));
}
/** This returns the current value of get_scalar<type()>()
* as an Expr. */
EXPORT Expr get_scalar_expr() const;
/** If the parameter is a scalar parameter, set its current
* value. Only relevant when jitting */
template<typename T>
NO_INLINE void set_scalar(T val) {
// Allow set_scalar<uint64_t>() for all Handle types
user_assert(type() == type_of<T>() || (type().is_handle() && type_of<T>() == UInt(64)))
<< "Can't set Param<" << type()
<< "> to scalar of type " << type_of<T>() << "\n";
*((T *)(get_scalar_address())) = val;
}
/** If the parameter is a buffer parameter, get its currently
* bound buffer. Only relevant when jitting */
EXPORT Buffer<> get_buffer() const;
/** If the parameter is a buffer parameter, set its current
* value. Only relevant when jitting */
EXPORT void set_buffer(Buffer<> b);
/** Get the pointer to the current value of the scalar
* parameter. For a given parameter, this address will never
* change. Only relevant when jitting. */
EXPORT void *get_scalar_address() const;
/** Tests if this handle is the same as another handle */
EXPORT bool same_as(const Parameter &other) const;
/** Tests if this handle is non-nullptr */
EXPORT bool defined() const;
/** Get and set constraints for the min, extent, and stride (see
* ImageParam::set_extent) */
//@{
EXPORT void set_min_constraint(int dim, Expr e);
EXPORT void set_extent_constraint(int dim, Expr e);
EXPORT void set_stride_constraint(int dim, Expr e);
EXPORT void set_host_alignment(int bytes);
EXPORT Expr min_constraint(int dim) const;
EXPORT Expr extent_constraint(int dim) const;
EXPORT Expr stride_constraint(int dim) const;
EXPORT int host_alignment() const;
//@}
/** Get and set constraints for scalar parameters. These are used
* directly by Param, so they must be exported. */
// @{
EXPORT void set_min_value(Expr e);
EXPORT Expr get_min_value() const;
EXPORT void set_max_value(Expr e);
EXPORT Expr get_max_value() const;
// @}
};
class Dimension {
public:
/** Get an expression representing the minimum coordinates of this image
* parameter in the given dimension. */
EXPORT Expr min() const;
/** Get an expression representing the extent of this image
* parameter in the given dimension */
EXPORT Expr extent() const;
/** Get an expression representing the maximum coordinates of
* this image parameter in the given dimension. */
EXPORT Expr max() const;
/** Get an expression representing the stride of this image in the
* given dimension */
EXPORT Expr stride() const;
/** Set the min in a given dimension to equal the given
* expression. Setting the mins to zero may simplify some
* addressing math. */
EXPORT Dimension set_min(Expr e);
/** Set the extent in a given dimension to equal the given
* expression. Images passed in that fail this check will generate
* a runtime error. Returns a reference to the ImageParam so that
* these calls may be chained.
*
* This may help the compiler generate better
* code. E.g:
\code
im.dim(0).set_extent(100);
\endcode
* tells the compiler that dimension zero must be of extent 100,
* which may result in simplification of boundary checks. The
* value can be an arbitrary expression:
\code
im.dim(0).set_extent(im.dim(1).extent());
\endcode
* declares that im is a square image (of unknown size), whereas:
\code
im.dim(0).set_extent((im.dim(0).extent()/32)*32);
\endcode
* tells the compiler that the extent is a multiple of 32. */
EXPORT Dimension set_extent(Expr e);
/** Set the stride in a given dimension to equal the given
* value. This is particularly helpful to set when
* vectorizing. Known strides for the vectorized dimension
* generate better code. */
EXPORT Dimension set_stride(Expr e);
/** Set the min and extent in one call. */
EXPORT Dimension set_bounds(Expr min, Expr extent);
/** Get a different dimension of the same buffer */
// @{
EXPORT Dimension dim(int i);
EXPORT const Dimension dim(int i) const;
// @}
private:
friend class ::Halide::OutputImageParam;
friend class Constrainable;
/** Construct a Dimension representing dimension d of some
* Internal::Parameter p. Only friends may construct
* these. */
EXPORT Dimension(const Internal::Parameter &p, int d);
/** Only friends may copy these, too. This prevents
* users removing constness by making a non-const copy. */
Dimension(const Dimension &) = default;
Parameter param;
int d;
};
/** Validate arguments to a call to a func, image or imageparam. */
void check_call_arg_types(const std::string &name, std::vector<Expr> *args, int dims);
}
}
#endif