From mboxrd@z Thu Jan 1 00:00:00 1970 From: Aldy Hernandez To: "Joseph S. Myers" Cc: Jakub Jelinek , gcc@gcc.gnu.org Subject: Re: new __builtin_choose_type (patch) (new builtin_equal_typespatch) Date: Sun, 07 Oct 2001 19:36:00 -0000 Message-id: <1002508773.3159.70.camel@culebra.cygnus.com> References: X-SW-Source: 2001-10/msg00527.html > * C is an *integer constant expression*, not necessarily a literal > constant. (For example, it might be the return value of > __builtin_types_compatible_p.) fixed > > * An implementation for C++ is also needed. will wait for new front end like suggested. [when's that?] > * To use this for type-generic functions, the __builtin_choose_expr > goes together with __builtin_types_compatible_p which needs > implementing as well. done. see patch below. > * The actual patch submitted for inclusion in GCC should come with a > corresponding patch to glibc's that makes it a lot simpler uhhh, will have to work on this. i hate tgmath.h :) without further ado, here are the patches for both __builtin_choose_expr and __builtin_types_compatible_p, test cases and docs. i hope this one makes everone happy. as a side note... i'm not a big fan of these big huge builtin names. it'll make tgmath.h horrendous to write (specially when combining __builtin_types_compatible_p and __builtin_choose_expr in one line). please comment... cheers aldy -- Aldy Hernandez E-mail: aldyh@redhat.com Professional Gypsy on a [broken] Motorcycle Red Hat, Inc. 2001-10-07 Aldy Hernandez * testsuite/gcc.c-torture/execute/builtin-types-compatible-p.c: New. * testsuite/gcc.c-torture/execute/builtin-choose-expr.c: New. * c-common.h (rid): Add RID_CHOOSE_EXPR and RID_TYPES_COMPATIBLE_P. * c-parse.in (reswords): Add __builtin_choose_expr. Add __builtin_types_compatible_p. Add CHOOSE_EXPR token. Add TYPES_COMPATIBLE_P token. Add production for CHOOSE_EXPR. Add production for TYPES_COMPATIBLE_P. * doc/extend.texi (__builtin_choose_expr): New. (__builtin_types_compatible_p): New. Index: doc/extend.texi =================================================================== RCS file: /cvs/gcc/egcs/gcc/doc/extend.texi,v retrieving revision 1.27 diff -c -p -r1.27 extend.texi *** extend.texi 2001/10/02 23:15:55 1.27 --- extend.texi 2001/10/08 02:28:35 *************** the same names as the standard macros ( *** 4342,4347 **** --- 4342,4403 ---- prefixed. We intend for a library implementor to be able to simply @code{#define} each standard macro to its built-in equivalent. + @deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, + @var{type2}) + + You can use the builtin function @code{__builtin_types_compatible_p} to + determine whether two types are the same. This builtin ignores top + level qualifiers (e.g. const, static). If the types are the same, this + builtin returns the integer constant 1. Otherwise, 0 is returned. + + You would typically use this function in code whose execution varies + depending on the arguments' types. For example: + + @smallexample + #define foo(x) \ + ({ \ + typeof (x) tmp; \ + if (__builtin_types_compatible_p (typeof (x), long double)) \ + tmp = foo_long_double (tmp); \ + else if (__builtin_types_compatible_p (typeof (x), double)) \ + tmp = foo_double (tmp); \ + else if (__builtin_types_compatible_p (typeof (x), float)) \ + tmp = foo_float (tmp); \ + else \ + abort (); \ + tmp; \ + }) + @end smallexample + + @end deftypefn + + @deftypefn {Built-in Function} int __builtin_choose_expr (@var{const_exp}, + @var{exp1}, @var{exp2}) + + You can use the builtin function @code{__builtin_choose_expr} to + evaluate code depending on the value of a constant expression. This + builtin returns exp1 if the constant expression const_exp is non zero. + Otherwise it returns 0. + + If exp1 is returned, the return type is the same as exp1's type. The + expression returned has its type unaltered by promotion rules. + Similarly, if exp2 is returned, its return type is the same as exp2. + + Example: + + @smallexample + #define foo(x) \ + __builtin_choose_expr (__builtin_types_compatible_p (typeof (x), double), \ + foo_double (x), \ + __builtin_choose_expr (__builtin_types_compatible_p (typeof (x), float), \ + foo_float (x), \ + /* The void expression results in a compile-time error \ + when assigning the result to something. */ \ + (void)0)) + @end smallexample + + @end deftypefn + @deftypefn {Built-in Function} int __builtin_constant_p (@var{exp}) You can use the built-in function @code{__builtin_constant_p} to determine if a value is known to be constant at compile-time and hence Index: testsuite/gcc.c-torture/execute/builtin-types-compatible-p.c =================================================================== RCS file: builtin-types-compatible-p.c diff -N builtin-types-compatible-p.c *** /dev/null Tue May 5 13:32:27 1998 --- builtin-types-compatible-p.c Sun Oct 7 19:28:35 2001 *************** *** 0 **** --- 1,15 ---- + int i; + double d; + + main () + { + if (__builtin_types_compatible_p (typeof (i), typeof (d))) + exit (1); + if (!__builtin_types_compatible_p (int, const int)) + exit (1); + if (__builtin_types_compatible_p (char, int)) + exit (1); + if (__builtin_types_compatible_p (long double, double)) + exit (1); + exit (0); + } Index: testsuite/gcc.c-torture/execute/builtin-choose-expr.c =================================================================== RCS file: builtin-choose-expr.c diff -N builtin-choose-expr.c *** /dev/null Tue May 5 13:32:27 1998 --- builtin-choose-expr.c Sun Oct 7 19:28:35 2001 *************** *** 0 **** --- 1,10 ---- + main () + { + if (__builtin_choose_expr (45, 0, 22)) + exit (1); + if (__builtin_choose_expr (0, 12, 0)) + exit (1); + if (!__builtin_choose_expr (45, 3, 0)) + exit (1); + exit (0); + } Index: c-common.h =================================================================== RCS file: /cvs/gcc/egcs/gcc/c-common.h,v retrieving revision 1.85 diff -c -p -r1.85 c-common.h *** c-common.h 2001/09/22 13:14:34 1.85 --- c-common.h 2001/10/08 02:28:35 *************** enum rid *** 74,80 **** /* C extensions */ RID_ASM, RID_TYPEOF, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG, RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_PTRBASE, ! RID_PTREXTENT, RID_PTRVALUE, /* Too many ways of getting the name of a function as a string */ RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME, --- 74,80 ---- /* C extensions */ RID_ASM, RID_TYPEOF, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG, RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_PTRBASE, ! RID_PTREXTENT, RID_PTRVALUE, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, /* Too many ways of getting the name of a function as a string */ RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME, Index: c-parse.in =================================================================== RCS file: /cvs/gcc/egcs/gcc/c-parse.in,v retrieving revision 1.106 diff -c -p -r1.106 c-parse.in *** c-parse.in 2001/09/21 01:26:52 1.106 --- c-parse.in 2001/10/08 02:28:35 *************** end ifc *** 121,127 **** %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF %token ATTRIBUTE EXTENSION LABEL ! %token REALPART IMAGPART VA_ARG %token PTR_VALUE PTR_BASE PTR_EXTENT /* function name can be a string const or a var decl. */ --- 121,127 ---- %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF %token ATTRIBUTE EXTENSION LABEL ! %token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P %token PTR_VALUE PTR_BASE PTR_EXTENT /* function name can be a string const or a var decl. */ *************** primary: *** 710,715 **** --- 710,734 ---- { $$ = build_function_call ($1, $3); } | VA_ARG '(' expr_no_commas ',' typename ')' { $$ = build_va_arg ($3, groktypename ($5)); } + | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ',' expr_no_commas ')' + { + tree c; + + c = fold ($3); + STRIP_NOPS (c); + if (TREE_CODE (c) != INTEGER_CST) + error ("first argument to __builtin_choose_expr not a constant"); + $$ = integer_zerop (c) ? $7 : $5; + } + | TYPES_COMPATIBLE_P '(' typename ',' typename ')' + { + tree e1, e2; + + e1 = TYPE_MAIN_VARIANT (groktypename ($3)); + e2 = TYPE_MAIN_VARIANT (groktypename ($5)); + + $$ = e1 == e2 ? build_int_2 (1, 0) : build_int_2 (0, 0); + } | primary '[' expr ']' %prec '.' { $$ = build_array_ref ($1, $3); } | primary '.' identifier *************** static const struct resword reswords[] = *** 3290,3295 **** --- 3309,3316 ---- { "__attribute__", RID_ATTRIBUTE, 0 }, { "__bounded", RID_BOUNDED, 0 }, { "__bounded__", RID_BOUNDED, 0 }, + { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 }, + { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 }, { "__builtin_va_arg", RID_VA_ARG, 0 }, { "__complex", RID_COMPLEX, 0 }, { "__complex__", RID_COMPLEX, 0 }, *************** static const short rid_to_yy[RID_MAX] = *** 3461,3466 **** --- 3482,3489 ---- /* RID_PTRBASE */ PTR_BASE, /* RID_PTREXTENT */ PTR_EXTENT, /* RID_PTRVALUE */ PTR_VALUE, + /* RID_CHOOSE_EXPR */ CHOOSE_EXPR, + /* RID_TYPES_COMPATIBLE_P */ TYPES_COMPATIBLE_P, /* RID_FUNCTION_NAME */ STRING_FUNC_NAME, /* RID_PRETTY_FUNCTION_NAME */ STRING_FUNC_NAME,