This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
new __builtin_choose_type (patch)
- To: gcc at gcc dot gnu dot org
- Subject: new __builtin_choose_type (patch)
- From: Aldy Hernandez <aldyh at redhat dot com>
- Date: 02 Oct 2001 14:39:09 -0400
hi guys.
for the altivec enhancements, we need a way to overload functions in C.
for example:
vec_add(foo, bar)
where foo and bar can be of a variety of vector types. so if foo and
bar are of V4SF something happens, and if they are of type V2SI
something else happens.
it was suggested to have a builtin analogous to the ?: operator that
will work as follows:
__builtin_choose_type (exp0, type, exp1, exp2);
if <exp0> is of type <type>, evaluate <exp1> else evaluate <exp2>.
i have a patch for this feature and i'd like some comments.
in the example below, b=10 gets evaluated because float != double, and
the entire builtin's value is 10.
int b;
double a;
float float_type;
foo(){
__builtin_choose_type(a, float_type, b=8, b=10);
}
one problem i have with the patch below, is that if the first argument
is of type "char" it gets promoted to an "int" so there's no way to use
this builtin with a <char>. it really doesn't matter since what i
really want is vector types, but i'd really like to get it working
across all types-- perhaps we can rewrite that <tgmath.h> crap with this
builtin ;-).
comment away.
--
Aldy Hernandez E-mail: aldyh@redhat.com
Professional Gypsy on a Motorcycle
Red Hat, Inc.
2001-10-01 Aldy Hernandez <aldyh@redhat.com>
* builtins.c (expand_builtin_choose_type): New.
(expand_builtin): Add case for BUILT_IN_CHOOSE_TYPE.
* builtins.def (BUILT_IN_CHOOSE_TYPE): New.
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/02 18:34:22
***************
*** 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: 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/02 18:34:33
***************
*** 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: