This is the mail archive of the gcc-patches@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]
Other format: [Raw text]

[PATCH] Generalize builtin_mathfn_code


The following patch generalizes the middle-end's builtin_mathfn_code
function to most (all?) of GCC's builtin functions.  As pointed out
by Kaveh, the current scheme suffers from the dual drawbacks that it
duplicates/hard-codes the builtin function's type (as already encoded
in builtins.def), and it isn't easily extensible to the large number
of mathematical builtins recently added to GCC.

The builtin_mathfn_code function is used within the middle-end to
determine that a given CALL_EXPR tree is actually a call to a standard
GCC builtin, with the correct number arguments with appropriate types.
Indeed historically the original name of this function was
builtin_mathfn_p, but it was decided under review to change it to
builtin_mathfn_code reflecting that upon success the program would return
BUILT_IN_SQRT, BUILT_IN_SIN or BUILT_IN_COS if the call was a valid
invocation to the resulting mathematical function.  Indeed, this saved
the need for a series of predicates such as builtin_sqrt_call_p (), etc...
by factoring them into a single function and checking the return value.

An important role of this function was checking that the call's argument
list was a tree list containing a single expression of REAL_TYPE_P.
In C, it's possible to do some very wierd stuff that needs to be
defended against such as the following (see PR optimization/12085):

double pow(double, double);

double foo(double x, double y, int z)
{
  return pow(x,y) * ((double(*)(double))pow)(x);
}


Most of the code to expand builtins as RTL defends against this abuse
by calling the function validate_arglist and generating a call to the
library function if arguments don't match their expected type classes.
In fold-const.c and elsewhere, the task of checking arguments is
handed off to builtin_mathfn_code.  This dramatically simplifies this
code as once the constant folder as the "enum built_in_function"
result, it may index and dereference the call's argument list without
fear or NULL pointers or error_mark_nodes.


The problem is that the utility of this function has become its own
downfall.  Where originally it handled just the common math builtins
that took a single floating point type and returned a floating point
type, it has since been extended to handle pow, powf, powl, atan2,
atan2f and atan2l which take two reals and return a real.  And with
Kaveh's recent excellent work to support the remaining C90, C99 and
BSD mathematical builtins, there is now a need to support many more
function "shapes".

In hindsight the solution is so obvious as to be painful.  Rather
than re-encode the types of each builtin via explicit checks in a
switch statement, the entire process may be generalized by simply
comparing the call's argument list against the builtin fndecl's
tree type, using the approximate middle-end notion of type matching,
i.e. that checks for compatible type classes, as is already used
in validate_arglist.  This is exactly what the patch below does.

By calling this function at the beginning of expand_builtin and
fold_builtin, it should be possible to eliminate almost all of
the calls to validate_arglist in builtins.c.  This also has the
added benefit of catching any remaining builtin function expanders
or folders that don't currently validate their argument lists (such
as expand_builtin_trap for example :).


The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all languages except treelang, and regression tested
with a top-level "make -k check" with no new failures.  Many thanks to
Kaveh for motivating this patch and his patience whilst I was developing
and testing it.

Ok for mainline?


2003-09-11  Roger Sayle  <roger@eyesopen.com>

	* builtins.c (builtin_mathfn_code): Generalize to check whether
	the call is to any built-in function by comparing the call's
	argument list against the builtin decl's function type.


Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.251
diff -c -3 -p -r1.251 builtins.c
*** builtins.c	9 Sep 2003 22:10:29 -0000	1.251
--- builtins.c	12 Sep 2003 00:48:34 -0000
*************** expand_builtin (tree exp, rtx target, rt
*** 5391,5405 ****
  }

  /* Determine whether a tree node represents a call to a built-in
!    math function.  If the tree T is a call to a built-in function
!    taking a single real argument, then the return value is the
!    DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.  Otherwise
!    the return value is END_BUILTINS.  */

  enum built_in_function
  builtin_mathfn_code (tree t)
  {
!   tree fndecl, arglist;

    if (TREE_CODE (t) != CALL_EXPR
        || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
--- 5391,5406 ----
  }

  /* Determine whether a tree node represents a call to a built-in
!    function.  If the tree T is a call to a built-in function with
!    the right number of arguments of the appropriate types, return
!    the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
!    Otherwise the return value is END_BUILTINS.  */

  enum built_in_function
  builtin_mathfn_code (tree t)
  {
!   tree fndecl, arglist, parmlist;
!   tree argtype, parmtype;

    if (TREE_CODE (t) != CALL_EXPR
        || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
*************** builtin_mathfn_code (tree t)
*** 5407,5442 ****

    fndecl = get_callee_fndecl (t);
    if (fndecl == NULL_TREE
        || ! DECL_BUILT_IN (fndecl)
        || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
      return END_BUILTINS;

    arglist = TREE_OPERAND (t, 1);
!   if (! arglist
!       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
!     return END_BUILTINS;
!
!   arglist = TREE_CHAIN (arglist);
!   switch (DECL_FUNCTION_CODE (fndecl))
      {
!     case BUILT_IN_POW:
!     case BUILT_IN_POWF:
!     case BUILT_IN_POWL:
!     case BUILT_IN_ATAN2:
!     case BUILT_IN_ATAN2F:
!     case BUILT_IN_ATAN2L:
!       if (! arglist
! 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE
! 	  || TREE_CHAIN (arglist))
  	return END_BUILTINS;
-       break;

!     default:
!       if (arglist)
  	return END_BUILTINS;
!       break;
      }

    return DECL_FUNCTION_CODE (fndecl);
  }

--- 5408,5464 ----

    fndecl = get_callee_fndecl (t);
    if (fndecl == NULL_TREE
+       || TREE_CODE (fndecl) != FUNCTION_DECL
        || ! DECL_BUILT_IN (fndecl)
        || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
      return END_BUILTINS;

    arglist = TREE_OPERAND (t, 1);
!   parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
!   for (; parmlist; parmlist = TREE_CHAIN (parmlist))
      {
!       /* If a function doesn't take a variable number of arguments,
! 	 the last element in the list will have type `void'.  */
!       parmtype = TREE_VALUE (parmlist);
!       if (VOID_TYPE_P (parmtype))
! 	{
! 	  if (arglist)
! 	    return END_BUILTINS;
! 	  return DECL_FUNCTION_CODE (fndecl);
! 	}
!
!       if (! arglist)
  	return END_BUILTINS;

!       argtype = TREE_TYPE (TREE_VALUE (arglist));
!
!       if (SCALAR_FLOAT_TYPE_P (parmtype))
! 	{
! 	  if (! SCALAR_FLOAT_TYPE_P (argtype))
! 	    return END_BUILTINS;
! 	}
!       else if (COMPLEX_FLOAT_TYPE_P (parmtype))
! 	{
! 	  if (! COMPLEX_FLOAT_TYPE_P (argtype))
! 	    return END_BUILTINS;
! 	}
!       else if (POINTER_TYPE_P (parmtype))
! 	{
! 	  if (! POINTER_TYPE_P (argtype))
! 	    return END_BUILTINS;
! 	}
!       else if (INTEGRAL_TYPE_P (parmtype))
! 	{
! 	  if (! INTEGRAL_TYPE_P (argtype))
! 	    return END_BUILTINS;
! 	}
!       else
  	return END_BUILTINS;
!
!       arglist = TREE_CHAIN (arglist);
      }

+   /* Variable-length argument list.  */
    return DECL_FUNCTION_CODE (fndecl);
  }


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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