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