On Fri, 2016-12-09 at 12:56 +0000, Richard Sandiford wrote:
> This patch adds a scalar_float_mode class, which wraps a mode enum
> that is known to satisfy SCALAR_FLOAT_MODE_P. Things like "SFmode"
> now give a scalar_float_mode object instead of a machine_mode.
> This in turn needs a change to the real.h format_helper, so that
> it can accept both machine_modes and scalar_float_modes.
[...]
> diff --git a/gcc/machmode.h b/gcc/machmode.h
> index 44a8ad4..996f991 100644
> --- a/gcc/machmode.h
> +++ b/gcc/machmode.h
> @@ -29,6 +29,16 @@ extern const unsigned short
> mode_unit_precision[NUM_MACHINE_MODES];
> extern const unsigned char mode_wider[NUM_MACHINE_MODES];
> extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
>
> +/* Allow direct conversion of enums to specific mode classes only
> + when USE_ENUM_MODES is defined. This is only intended for use
> + by gencondmd, so that it can tell more easily when .md conditions
> + are always false. */
> +#ifdef USE_ENUM_MODES
> +#define PROTECT_ENUM_CONVERSION public
> +#else
> +#define PROTECT_ENUM_CONVERSION protected
> +#endif
> +
> /* Get the name of mode MODE as a string. */
>
> extern const char * const mode_name[NUM_MACHINE_MODES];
> @@ -237,6 +247,85 @@ opt_mode<T>::exists (U *mode) const
> return false;
> }
>
> +/* Return true if mode M has type T. */
> +
> +template<typename T>
> +inline bool
> +is_a (machine_mode_enum m)
> +{
> + return T::includes_p (m);
> +}
> +
> +/* Assert that mode M has type T, and return it in that form. */
> +
> +template<typename T>
> +inline T
> +as_a (machine_mode_enum m)
> +{
> + gcc_checking_assert (T::includes_p (m));
> + return T::from_int (m);
> +}
> +
> +/* Convert M to an opt_mode<T>. */
> +
> +template<typename T>
> +inline opt_mode<T>
> +dyn_cast (machine_mode_enum m)
> +{
> + if (T::includes_p (m))
> + return T::from_int (m);
> + return opt_mode<T> ();
> +}
> +
> +/* Return true if mode M has type T, storing it as a T in *RESULT
> + if so. */
> +
> +template<typename T, typename U>
> +inline bool
> +is_a (machine_mode_enum m, U *result)
> +{
> + if (T::includes_p (m))
> + {
> + *result = T::from_int (m);
> + return true;
> + }
> + return false;
> +}
> +
> +/* Represents a machine mode that is known to be a
> SCALAR_FLOAT_MODE_P. */
> +class scalar_float_mode
Should this be a subclass of machine_mode? Or does this lead to name
clashes? (e.g. for "from_int")
(Similar questions for the other more specialized wrapper classes; it
looks like you have a set of independent wrapper classes around the
machine_mode_enum, without using inheritance, with a trip through the
enum needed to convert between wrappers)
> +{
> +public:
> + ALWAYS_INLINE scalar_float_mode () {}
> + ALWAYS_INLINE operator machine_mode_enum () const { return m_mode;
> }
> +
> + static bool includes_p (machine_mode_enum);
> + static scalar_float_mode from_int (int i);
> +
> +PROTECT_ENUM_CONVERSION:
> + ALWAYS_INLINE scalar_float_mode (machine_mode_enum m) : m_mode (m)
> {}
Should this ctor have some kind of:
gcc_checking_assert (SCALAR_FLOAT_MODE_P (m));
or somesuch? (or does that slow down the debug build too much?)
> +
> +protected:
> + machine_mode_enum m_mode;
> +};
> +
> +/* Return true if M is a scalar_float_mode. */
> +
> +inline bool
> +scalar_float_mode::includes_p (machine_mode_enum m)
> +{
> + return SCALAR_FLOAT_MODE_P (m);
> +}
> +
> +/* Return M as a scalar_float_mode. This function should only be
> used by
> + utility functions; general code should use as_a<T> instead. */
> +
> +ALWAYS_INLINE scalar_float_mode
> +scalar_float_mode::from_int (int i)
> +{
> + return machine_mode_enum (i);
> +}
...or put an assertion in here? (I *think* it's the only public
function that can (implicitly) call the ctor without checking the
invariant)
[...]
Hope this is constructive
Dave