This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: new __builtin_choose_type (patch) (new builtin_equal_typespatch)
- To: "Joseph S. Myers" <jsm28 at cam dot ac dot uk>
- Subject: Re: new __builtin_choose_type (patch) (new builtin_equal_typespatch)
- From: Aldy Hernandez <aldyh at redhat dot com>
- Date: 07 Oct 2001 22:39:33 -0400
- Cc: Jakub Jelinek <jakub at redhat dot com>, gcc at gcc dot gnu dot org
- References: <Pine.LNX.4.33.0110080059120.24100-100000@kern.srcf.societies.cam.ac.uk>
> * 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 <tgmath.h> 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 <aldyh@redhat.com>
* 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,