This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: new __builtin_choose_type (patch)
> Since your patch doesn't add documentation or testcases, I don't know what
> it really intends. In a case like this, the documentation and the
i started writing docs for the builtin and noticed that yes, you're
right: docs and test cases do make it clearer.
so here is the patch, the doc, and the testcase.
i hope it's clear why this approach is better than the <tgmath.h>
atrocity. ;-)
btw, i can't get my builtin to return a given object (irregardless of
it's type) because the way builtins work seems to force me to choose a
return value type. i don't want a specific value type. i want
something generic. see code documentation below.
--
Aldy Hernandez E-mail: aldyh@redhat.com
Professional Gypsy on a Motorcycle
Red Hat, Inc.
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/doc/extend.texi,v
retrieving revision 1.27
diff -c -r1.27 extend.texi
*** extend.texi 2001/10/02 23:15:55 1.27
--- extend.texi 2001/10/03 00:59:16
***************
*** 4342,4347 ****
--- 4342,4372 ----
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} __builtin_choose_type (@var{object1},
+ @var{object2}, @var{exp1}, @var{exp2})
+ You can use the builtin function @code{__builtin_choose_type} to execute
+ code, depending on its type. This builtin compares the types of OBJECT1
+ and OBJECT2 (without evaluating them) and executes EXP1 if their types
+ are the same. Otherwise, EXP2 is executed.
+
+ @code{__builtin_choose_type} ignores the values of OBJECT1 and OBJECT2,
+ considering only their data type. This returns either exp1 or exp2.
+
+ You would typically use this function on code whose execution varies
+ depending on the arguments' types. For example:
+
+ @smallexample
+ #define atan(X) \
+ ({float f; \
+ __complex double cd; \
+ __builtin_choose_type (X, cd, atan_complex_double (X), \
+ __builtin_choose_type (X, f, atan_float (X), \
+ /* Assume or convert to double. */ \
+ atan_double ((double) X))); })
+ @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: builtins.def
===================================================================
RCS file: /cvs/gcc/egcs/gcc/builtins.def,v
retrieving revision 1.22
diff -c -r1.22 builtins.def
*** builtins.def 2001/08/22 14:34:42 1.22
--- builtins.def 2001/10/03 00:59:17
***************
*** 336,341 ****
--- 336,344 ----
DEF_GCC_BUILTIN(BUILT_IN_TRAP,
"__builtin_trap",
BT_FN_VOID)
+ DEF_GCC_BUILTIN(BUILT_IN_CHOOSE_TYPE,
+ "__builtin_choose_type",
+ BT_FN_PTR_VAR)
/* Stdio builtins. */
DEF_FALLBACK_BUILTIN(BUILT_IN_PUTCHAR,
Index: testsuite/gcc.c-torture/execute/builtin-choose-type.c
====================================================================
new file
--- testsuite/gcc.c-torture/execute/builtin-choose-type.c
***************
*** 0 ****
--- 1,24 ----
+ int b, i;
+ float f;
+ double d;
+
+ no()
+ {
+ exit(1);
+ }
+
+ main()
+ {
+ int j;
+
+ __builtin_choose_type (f, d, no(), 1);
+ __builtin_choose_type (d, (double)3.0F, 1, no());
+ __builtin_choose_type (b, i, 1, no());
+
+ __builtin_choose_type (i, d, no(), j = 45);
+
+ if (j != 45)
+ exit(1);
+
+ exit(0);
+ }
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/builtins.c,v
retrieving revision 1.121
diff -c -r1.121 builtins.c
*** builtins.c 2001/09/22 08:42:00 1.121
--- builtins.c 2001/10/03 00:59:31
***************
*** 95,100 ****
--- 95,101 ----
static rtx expand_builtin_classify_type PARAMS ((tree));
static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx));
static rtx expand_builtin_constant_p PARAMS ((tree));
+ static rtx expand_builtin_choose_type PARAMS ((tree, rtx));
static rtx expand_builtin_args_info PARAMS ((tree));
static rtx expand_builtin_next_arg PARAMS ((tree));
static rtx expand_builtin_va_start PARAMS ((int, tree));
***************
*** 1316,1321 ****
--- 1317,1384 ----
return tmp;
}
+ /* Expand expression EXP, which is a call to __builtin_choose_type.
+
+ __builtin_type_choose (<exp0>, <type>, <exp1>, <exp2>)
+
+ If <exp0> is of type <type>, evaluate <exp1> else evaluate <exp2>.
+ */
+
+ static rtx
+ expand_builtin_choose_type (exp, target)
+ tree exp;
+ rtx target;
+ {
+ tree arg = TREE_OPERAND (exp, 1);
+ tree chain;
+ enum machine_mode exp0_mode, desired_mode;
+
+ if (arg == 0)
+ return const0_rtx;
+
+ chain = TREE_CHAIN (arg);
+ arg = TREE_VALUE (arg);
+
+ /* Strip off all NOPs. */
+ while (TREE_CODE (arg) == NOP_EXPR
+ || TREE_CODE (arg) == CONVERT_EXPR
+ || TREE_CODE (arg) == NON_LVALUE_EXPR
+ || TREE_CODE (arg) == INDIRECT_REF)
+ arg = TREE_OPERAND (arg, 0);
+
+ /* Get <exp0> type. */
+ exp0_mode = TYPE_MODE (TREE_TYPE (arg));
+
+ /* Get <type> type. */
+ arg = TREE_VALUE (chain);
+ if (!arg)
+ return const0_rtx;
+ /* Strip off all NOPs. */
+ while (TREE_CODE (arg) == NOP_EXPR
+ || TREE_CODE (arg) == CONVERT_EXPR
+ || TREE_CODE (arg) == NON_LVALUE_EXPR
+ || TREE_CODE (arg) == INDIRECT_REF)
+ arg = TREE_OPERAND (arg, 0);
+ desired_mode = TYPE_MODE (TREE_TYPE (arg));
+
+ /* Get exp1. */
+ chain = TREE_CHAIN (chain);
+ if (!chain)
+ error ("missing argument in `__builtin_choose_type'");
+
+ if (exp0_mode == desired_mode)
+ /* Evaluate exp1. */
+ return expand_expr (TREE_VALUE (chain), target, VOIDmode, EXPAND_NORMAL);
+
+ /* Get exp2. */
+ chain = TREE_CHAIN (chain);
+ if (!chain)
+ error ("missing argument in `__builtin_choose_type'");
+
+ /* Evaluate exp2. */
+ return expand_expr (TREE_VALUE (chain), target, VOIDmode, EXPAND_NORMAL);
+ }
+
/* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
Return 0 if a normal call should be emitted rather than expanding the
function in-line. EXP is the expression that is a call to the builtin
***************
*** 3512,3517 ****
--- 3575,3583 ----
case BUILT_IN_CONSTANT_P:
return expand_builtin_constant_p (exp);
+
+ case BUILT_IN_CHOOSE_TYPE:
+ return expand_builtin_choose_type (exp, target);
case BUILT_IN_FRAME_ADDRESS:
case BUILT_IN_RETURN_ADDRESS: