On 10/4/19 7:09 PM, Richard Sandiford wrote:
> Bernd Edlinger <bernd.edlin...@hotmail.de> writes:
>>
>> Actually I wanted to do it with a template, and invoke it using 
>> __typeof(RTX).
>>
>> BUT with that I ran into a lmitation of the template vs. block statements
>> See PR#91803:  We cannot instantiate a template on the
>> type of a statement expression, only when the expression is completely
>> written down without statement expressions.
>>
>> So even if we remove that limitation, it will be impossible to use
>> templates dependent on __typeof(statement-expressions) as we need
>> to bootstrap from rather old gcc versions.
>>
>> However if we are able to replace all statement-expressions in
>> rtl.h then it will probably be possible to use a template here,
>> without that type cast.
>>
>> I still need a const and a non-const version of that function because
>> otherwise the -Werror=cast-qual warning will kill me.
>>
>>
>>> #define GET_CODE(RTX) ((rtx_code) static_cast<const_rtx> (RTX)->code)
>>>
>>> (Wonder how much code that will break :-))
>>>
>>> And if we do use templates instead of const_rtx/rtx variants,
>>> it might be simpler to keep the checking and assert together:
>>>
>>> #define RTL_FLAG_CHECK(NAME, RTX, ...)                              \
>>>   (rtl_flag_check<__VA_ARGS__> (NAME, RTX, __FILE__, __LINE__,      \
>>>                             __FUNCTION__))
>>>
>>> template<rtx_code C1, typename T>
>>> inline T
>>> rtl_flag_check (const char *name, T rtl, const char *file, int line,
>>>             const char *func)
>>> { 
>>>   if (GET_CODE (rtl) != C1)
>>>     rtl_check_failed_flag (name, rtl, file, line, func);
>>>   return rtl;
>>> }
>>>
>>> ...etc...
>>>
>>
>> I somehow expected the typename T need to be given int the template arguments
>> like rtl_flag_check<__typeof(RTX), __VA_ARGS__> (NAME, RTX,
>>
>> Could be that there is way to make that work without __typeof ?
> 
> Yeah, the typename will be deduced automatically in the example above.
> I don't think we need __typeof here.
> 

Yes, indeed it works.

The updated patch uses only one template function for rtl_flag_check.

It also fixes the --enable-checking=rtl issue.  I wonder if that can
also be simplified into one template, unlike the rtl_flag_check the
result is either a const or a non-const object but not the same
type as the rtvec probably you'll have
immediately an idea here?


Thanks
Bernd.
2019-10-04  Bernd Edlinger  <bernd.edlin...@hotmail.de>

	* rtl.h (RTL_CHECK1, RTL_CHECK2, RTL_CHECKC1, RTL_CHECKC2
	RTVEC_ELT): Reimplement with inline functions.
	(RTL_FLAG_CHECK): New variadic macro.
	(RTL_FLAG_CHECK1-6): Use RTL_FLAG_CHECK.
	(RTL_FLAG_CHECK7): Remove.
	(rtl_check, rtvec_check): New helper functions.
	(check_rtl_bounds, check_rtl_code,
	rtl_flag_check): New helper templates.

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	(revision 276589)
+++ gcc/rtl.h	(working copy)
@@ -1070,43 +1070,21 @@
 #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
 /* The bit with a star outside the statement expr and an & inside is
    so that N can be evaluated only once.  */
-#define RTL_CHECK1(RTX, N, C1) __extension__				\
-(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
-     const enum rtx_code _code = GET_CODE (_rtx);			\
-     if (_n < 0 || _n >= GET_RTX_LENGTH (_code))			\
-       rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__,		\
-				__FUNCTION__);				\
-     if (GET_RTX_FORMAT (_code)[_n] != C1)				\
-       rtl_check_failed_type1 (_rtx, _n, C1, __FILE__, __LINE__,	\
-			       __FUNCTION__);				\
-     &_rtx->u.fld[_n]; }))
+#define RTL_CHECK1(RTX, N, C1)						\
+  rtl_check (check_rtl_bounds<C1>,					\
+	     RTX, N, __FILE__, __LINE__, __FUNCTION__)
 
-#define RTL_CHECK2(RTX, N, C1, C2) __extension__			\
-(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
-     const enum rtx_code _code = GET_CODE (_rtx);			\
-     if (_n < 0 || _n >= GET_RTX_LENGTH (_code))			\
-       rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__,		\
-				__FUNCTION__);				\
-     if (GET_RTX_FORMAT (_code)[_n] != C1				\
-	 && GET_RTX_FORMAT (_code)[_n] != C2)				\
-       rtl_check_failed_type2 (_rtx, _n, C1, C2, __FILE__, __LINE__,	\
-			       __FUNCTION__);				\
-     &_rtx->u.fld[_n]; }))
+#define RTL_CHECK2(RTX, N, C1, C2)					\
+  rtl_check (check_rtl_bounds<C1, C2>,					\
+	     RTX, N, __FILE__, __LINE__, __FUNCTION__)
 
-#define RTL_CHECKC1(RTX, N, C) __extension__				\
-(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
-     if (GET_CODE (_rtx) != (C))					\
-       rtl_check_failed_code1 (_rtx, (C), __FILE__, __LINE__,		\
-			       __FUNCTION__);				\
-     &_rtx->u.fld[_n]; }))
+#define RTL_CHECKC1(RTX, N, C1)						\
+  rtl_check (check_rtl_code<C1>,					\
+	     RTX, N, __FILE__, __LINE__, __FUNCTION__)
 
-#define RTL_CHECKC2(RTX, N, C1, C2) __extension__			\
-(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
-     const enum rtx_code _code = GET_CODE (_rtx);			\
-     if (_code != (C1) && _code != (C2))				\
-       rtl_check_failed_code2 (_rtx, (C1), (C2), __FILE__, __LINE__,	\
-			       __FUNCTION__); \
-     &_rtx->u.fld[_n]; }))
+#define RTL_CHECKC2(RTX, N, C1, C2)					\
+  rtl_check (check_rtl_code<C1, C2>,					\
+	     RTX, N, __FILE__, __LINE__, __FUNCTION__)
 
 #define RTL_CHECKC3(RTX, N, C1, C2, C3) __extension__			\
 (*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
@@ -1116,12 +1094,8 @@
 			       __LINE__, __FUNCTION__);			\
      &_rtx->u.fld[_n]; }))
 
-#define RTVEC_ELT(RTVEC, I) __extension__				\
-(*({ __typeof (RTVEC) const _rtvec = (RTVEC); const int _i = (I);	\
-     if (_i < 0 || _i >= GET_NUM_ELEM (_rtvec))				\
-       rtvec_check_failed_bounds (_rtvec, _i, __FILE__, __LINE__,	\
-				  __FUNCTION__);			\
-     &_rtvec->elem[_i]; }))
+#define RTVEC_ELT(RTVEC, I)						\
+  rtvec_check (RTVEC, I, __FILE__, __LINE__, __FUNCTION__)
 
 #define XWINT(RTX, N) __extension__					\
 (*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N);		\
@@ -1222,6 +1196,84 @@
 				       const char *)
     ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
 
+static inline rtx const&
+rtvec_check (const_rtvec vec, int i,
+	     const char *file, int line, const char *func)
+{
+  if (i < 0 || i >= GET_NUM_ELEM (vec))
+    rtvec_check_failed_bounds (vec, i, file, line, func);
+  return vec->elem[i];
+}
+
+static inline rtx&
+rtvec_check (rtvec vec, int i,
+	     const char *file, int line, const char *func)
+{
+  if (i < 0 || i >= GET_NUM_ELEM (vec))
+    rtvec_check_failed_bounds (vec, i, file, line, func);
+  return vec->elem[i];
+}
+
+static inline const rtunion&
+rtl_check (void (*check) (const_rtx, int, const char *, int, const char *),
+	   const_rtx rtl, int n, const char *file, int line, const char *func)
+{
+  check (rtl, n, file, line, func);
+  return rtl->u.fld[n];
+}
+
+static inline rtunion&
+rtl_check (void (*check) (const_rtx, int, const char *, int, const char *),
+	   rtx rtl, int n, const char *file, int line, const char *func)
+{
+  check (rtl, n, file, line, func);
+  return rtl->u.fld[n];
+}
+
+template<char C1>
+void
+check_rtl_bounds (const_rtx rtl, int n,
+		  const char *file, int line, const char *function)
+{
+   const enum rtx_code code = GET_CODE (rtl);
+   if (n < 0 || n >= GET_RTX_LENGTH (code))
+     rtl_check_failed_bounds (rtl, n, file, line, function);
+   if (GET_RTX_FORMAT (code)[n] != C1)
+     rtl_check_failed_type1 (rtl, n, C1, file, line, function);
+}
+
+template<char C1, char C2>
+void
+check_rtl_bounds (const_rtx rtl, int n,
+		  const char *file, int line, const char *function)
+{
+   const enum rtx_code code = GET_CODE (rtl);
+   if (n < 0 || n >= GET_RTX_LENGTH (code))
+     rtl_check_failed_bounds (rtl, n, file, line, function);
+   if (GET_RTX_FORMAT (code)[n] != C1
+       && GET_RTX_FORMAT (code)[n] != C2)
+     rtl_check_failed_type2 (rtl, n, C1, C2, file, line, function);
+}
+
+template<RTX_CODE C1>
+void
+check_rtl_code (const_rtx rtl, int n ATTRIBUTE_UNUSED,
+		const char *file, int line, const char *function)
+{
+  if (GET_CODE (rtl) != C1)
+    rtl_check_failed_code1 (rtl, C1, file, line, function);
+}
+
+template<RTX_CODE C1, RTX_CODE C2>
+void
+check_rtl_code (const_rtx rtl, int n ATTRIBUTE_UNUSED,
+		const char *file, int line, const char *function)
+{
+  if (GET_CODE (rtl) != C1
+      && GET_CODE (rtl) != C2)
+    rtl_check_failed_code2 (rtl, C1, C2, file, line, function);
+}
+
 #else   /* not ENABLE_RTL_CHECKING */
 
 #define RTL_CHECK1(RTX, N, C1)      ((RTX)->u.fld[N])
@@ -1249,66 +1301,17 @@
 #define RTX_FLAG(RTX, FLAG)	((RTX)->FLAG)
 
 #if defined ENABLE_RTL_FLAG_CHECKING && (GCC_VERSION >= 2007)
-#define RTL_FLAG_CHECK1(NAME, RTX, C1) __extension__			\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1)						\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
+#define RTL_FLAG_CHECK(NAME, RTX, ...)					\
+  rtl_flag_check<__VA_ARGS__> (NAME, RTX, __FILE__, __LINE__,		\
+					__FUNCTION__)
 
-#define RTL_FLAG_CHECK2(NAME, RTX, C1, C2) __extension__		\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE(_rtx) != C2)			\
-     rtl_check_failed_flag  (NAME,_rtx, __FILE__, __LINE__,		\
-			      __FUNCTION__);				\
-   _rtx; })
+#define RTL_FLAG_CHECK1 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK2 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK3 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK4 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK5 RTL_FLAG_CHECK
+#define RTL_FLAG_CHECK6 RTL_FLAG_CHECK
 
-#define RTL_FLAG_CHECK3(NAME, RTX, C1, C2, C3) __extension__		\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE(_rtx) != C2			\
-       && GET_CODE (_rtx) != C3)					\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
-
-#define RTL_FLAG_CHECK4(NAME, RTX, C1, C2, C3, C4) __extension__	\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE(_rtx) != C2			\
-       && GET_CODE (_rtx) != C3 && GET_CODE(_rtx) != C4)		\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			      __FUNCTION__);				\
-   _rtx; })
-
-#define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5) __extension__	\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2			\
-       && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4		\
-       && GET_CODE (_rtx) != C5)					\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
-
-#define RTL_FLAG_CHECK6(NAME, RTX, C1, C2, C3, C4, C5, C6)		\
-  __extension__								\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2			\
-       && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4		\
-       && GET_CODE (_rtx) != C5 && GET_CODE (_rtx) != C6)		\
-     rtl_check_failed_flag  (NAME,_rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
-
-#define RTL_FLAG_CHECK7(NAME, RTX, C1, C2, C3, C4, C5, C6, C7)		\
-  __extension__								\
-({ __typeof (RTX) const _rtx = (RTX);					\
-   if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2			\
-       && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4		\
-       && GET_CODE (_rtx) != C5 && GET_CODE (_rtx) != C6		\
-       && GET_CODE (_rtx) != C7)					\
-     rtl_check_failed_flag  (NAME, _rtx, __FILE__, __LINE__,		\
-			     __FUNCTION__);				\
-   _rtx; })
-
 #define RTL_INSN_CHAIN_FLAG_CHECK(NAME, RTX) 				\
   __extension__								\
 ({ __typeof (RTX) const _rtx = (RTX);					\
@@ -1322,6 +1325,75 @@
     ATTRIBUTE_NORETURN ATTRIBUTE_COLD
     ;
 
+template<RTX_CODE C1, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3,
+	 RTX_CODE C4, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3 && GET_CODE (rtl) != C4)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3,
+	 RTX_CODE C4, RTX_CODE C5, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3 && GET_CODE (rtl) != C4
+      && GET_CODE (rtl) != C5)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
+template<RTX_CODE C1, RTX_CODE C2, RTX_CODE C3,
+	 RTX_CODE C4, RTX_CODE C5, RTX_CODE C6, typename T>
+inline T
+rtl_flag_check (const char *name, T rtl,
+		const char *file, int line, const char *func)
+{
+  if (GET_CODE (rtl) != C1 && GET_CODE (rtl) != C2
+      && GET_CODE (rtl) != C3 && GET_CODE (rtl) != C4
+      && GET_CODE (rtl) != C5 && GET_CODE (rtl) != C6)
+    rtl_check_failed_flag (name, rtl, file, line, func);
+  return rtl;
+}
+
 #else	/* not ENABLE_RTL_FLAG_CHECKING */
 
 #define RTL_FLAG_CHECK1(NAME, RTX, C1)					(RTX)
@@ -1330,7 +1402,6 @@
 #define RTL_FLAG_CHECK4(NAME, RTX, C1, C2, C3, C4)			(RTX)
 #define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5)			(RTX)
 #define RTL_FLAG_CHECK6(NAME, RTX, C1, C2, C3, C4, C5, C6)		(RTX)
-#define RTL_FLAG_CHECK7(NAME, RTX, C1, C2, C3, C4, C5, C6, C7)		(RTX)
 #define RTL_INSN_CHAIN_FLAG_CHECK(NAME, RTX) 				(RTX)
 #endif
 

Reply via email to