This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]