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