12088Ssos/* Expand builtin functions.
25536Ssos   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
32088Ssos   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
42088Ssos
52088SsosThis file is part of GCC.
62088Ssos
72088SsosGCC is free software; you can redistribute it and/or modify it under
82088Ssosthe terms of the GNU General Public License as published by the Free
95994SsosSoftware Foundation; either version 2, or (at your option) any later
105994Ssosversion.
112088Ssos
122088SsosGCC is distributed in the hope that it will be useful, but WITHOUT ANY
132088SsosWARRANTY; without even the implied warranty of MERCHANTABILITY or
142088SsosFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
152088Ssosfor more details.
162088Ssos
172088SsosYou should have received a copy of the GNU General Public License
182088Ssosalong with GCC; see the file COPYING.  If not, write to the Free
192088SsosSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
202088Ssos02110-1301, USA.  */
212088Ssos
222088Ssos#include "config.h"
232088Ssos#include "system.h"
242088Ssos#include "coretypes.h"
252088Ssos#include "tm.h"
262088Ssos#include "machmode.h"
272088Ssos#include "real.h"
282088Ssos#include "rtl.h"
2929603Scharnier#include "tree.h"
3029603Scharnier#include "tree-gimple.h"
3138044Syokota#include "flags.h"
3229603Scharnier#include "regs.h"
3329603Scharnier#include "hard-reg-set.h"
342088Ssos#include "except.h"
3529603Scharnier#include "function.h"
362088Ssos#include "insn-config.h"
3729603Scharnier#include "expr.h"
383864Sswallace#include "optabs.h"
3929603Scharnier#include "libfuncs.h"
402088Ssos#include "recog.h"
412088Ssos#include "output.h"
422088Ssos#include "typeclass.h"
432088Ssos#include "toplev.h"
442088Ssos#include "predict.h"
458857Srgrimes#include "tm_p.h"
462088Ssos#include "target.h"
472088Ssos#include "langhooks.h"
482088Ssos#include "basic-block.h"
492088Ssos#include "tree-mudflap.h"
502088Ssos
5132316Syokota#ifndef PAD_VARARGS_DOWN
5232316Syokota#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
5332316Syokota#endif
5432316Syokota
5532316Syokota/* Define the names of the builtin function types and codes.  */
5632316Syokotaconst char *const built_in_class_names[4]
5732316Syokota  = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
5832316Syokota
5932316Syokota#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM, COND) #X,
6032316Syokotaconst char * built_in_names[(int) END_BUILTINS] =
6132316Syokota{
6232316Syokota#include "builtins.def"
635994Ssos};
645994Ssos#undef DEF_BUILTIN
655994Ssos
665994Ssos/* Setup an array of _DECL trees, make sure each element is
675994Ssos   initialized to NULL_TREE.  */
685994Ssostree built_in_decls[(int) END_BUILTINS];
695994Ssos/* Declarations used when constructing the builtin implicitly in the compiler.
705994Ssos   It may be NULL_TREE when this is invalid (for instance runtime is not
715994Ssos   required to implement the function call in all cases).  */
725994Ssostree implicit_built_in_decls[(int) END_BUILTINS];
735994Ssos
745994Ssosstatic int get_pointer_alignment (tree, unsigned int);
759202Srgrimesstatic const char *c_getstr (tree);
765994Ssosstatic rtx c_readstr (const char *, enum machine_mode);
775994Ssosstatic int target_char_cast (tree, char *);
785994Ssosstatic rtx get_memory_rtx (tree, tree);
799202Srgrimesstatic tree build_string_literal (int, const char *);
805994Ssosstatic int apply_args_size (void);
815994Ssosstatic int apply_result_size (void);
825994Ssos#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
835994Ssosstatic rtx result_vector (int, rtx);
845994Ssos#endif
855994Ssosstatic rtx expand_builtin_setjmp (tree, rtx);
865994Ssosstatic void expand_builtin_update_setjmp_buf (rtx);
875994Ssosstatic void expand_builtin_prefetch (tree);
882088Ssosstatic rtx expand_builtin_apply_args (void);
892088Ssosstatic rtx expand_builtin_apply_args_1 (void);
902088Ssosstatic rtx expand_builtin_apply (rtx, rtx, rtx);
912088Ssosstatic void expand_builtin_return (rtx);
922088Ssosstatic enum type_class type_to_class (tree);
932088Ssosstatic rtx expand_builtin_classify_type (tree);
942088Ssosstatic void expand_errno_check (tree, rtx);
952088Ssosstatic rtx expand_builtin_mathfn (tree, rtx, rtx);
962088Ssosstatic rtx expand_builtin_mathfn_2 (tree, rtx, rtx);
972088Ssosstatic rtx expand_builtin_mathfn_3 (tree, rtx, rtx);
986046Ssosstatic rtx expand_builtin_int_roundingfn (tree, rtx, rtx);
992088Ssosstatic rtx expand_builtin_args_info (tree);
10032316Syokotastatic rtx expand_builtin_next_arg (void);
1012088Ssosstatic rtx expand_builtin_va_start (tree);
10229603Scharnierstatic rtx expand_builtin_va_end (tree);
1032088Ssosstatic rtx expand_builtin_va_copy (tree);
1042088Ssosstatic rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
1052088Ssosstatic rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
1062088Ssosstatic rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
1072088Ssosstatic rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
1082088Ssosstatic rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
10929603Scharnierstatic rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
1102088Ssosstatic rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
1112088Ssosstatic rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
1122088Ssosstatic rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
1132088Ssosstatic rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
1142088Ssosstatic rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
1152088Ssosstatic rtx expand_builtin_bcopy (tree);
1162088Ssosstatic rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
1172088Ssosstatic rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
1185536Ssosstatic rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
1195536Ssosstatic rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
1205536Ssosstatic rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
1212088Ssosstatic rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
1222088Ssosstatic rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree);
1232088Ssosstatic rtx expand_builtin_bzero (tree);
1242088Ssosstatic rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
1252088Ssosstatic rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode);
1262088Ssosstatic rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode);
1272088Ssosstatic rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode);
1282088Ssosstatic rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode);
1292088Ssosstatic rtx expand_builtin_alloca (tree, rtx);
1302088Ssosstatic rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
1312088Ssosstatic rtx expand_builtin_frame_address (tree, tree);
1322088Ssosstatic rtx expand_builtin_fputs (tree, rtx, bool);
1332088Ssosstatic rtx expand_builtin_printf (tree, rtx, enum machine_mode, bool);
1342088Ssosstatic rtx expand_builtin_fprintf (tree, rtx, enum machine_mode, bool);
1352088Ssosstatic rtx expand_builtin_sprintf (tree, rtx, enum machine_mode);
1362088Ssosstatic tree stabilize_va_list (tree, int);
1372088Ssosstatic rtx expand_builtin_expect (tree, rtx);
1382088Ssosstatic tree fold_builtin_constant_p (tree);
1392088Ssosstatic tree fold_builtin_classify_type (tree);
1402088Ssosstatic tree fold_builtin_strlen (tree);
1412088Ssosstatic tree fold_builtin_inf (tree, int);
1422088Ssosstatic tree fold_builtin_nan (tree, tree, int);
1432088Ssosstatic int validate_arglist (tree, ...);
14432316Syokotastatic bool integer_valued_real_p (tree);
1452088Ssosstatic tree fold_trunc_transparent_mathfn (tree, tree);
1462088Ssosstatic bool readonly_data_expr (tree);
1472088Ssosstatic rtx expand_builtin_fabs (tree, rtx, rtx);
1482088Ssosstatic rtx expand_builtin_signbit (tree, rtx);
1492088Ssosstatic tree fold_builtin_cabs (tree, tree);
1502088Ssosstatic tree fold_builtin_sqrt (tree, tree);
1512088Ssosstatic tree fold_builtin_cbrt (tree, tree);
1522088Ssosstatic tree fold_builtin_pow (tree, tree, tree);
1532088Ssosstatic tree fold_builtin_powi (tree, tree, tree);
1542088Ssosstatic tree fold_builtin_sin (tree);
1552088Ssosstatic tree fold_builtin_cos (tree, tree, tree);
1562088Ssosstatic tree fold_builtin_tan (tree);
1572088Ssosstatic tree fold_builtin_atan (tree, tree);
1582088Ssosstatic tree fold_builtin_trunc (tree, tree);
1592088Ssosstatic tree fold_builtin_floor (tree, tree);
1602088Ssosstatic tree fold_builtin_ceil (tree, tree);
1612088Ssosstatic tree fold_builtin_round (tree, tree);
1622088Ssosstatic tree fold_builtin_int_roundingfn (tree, tree);
1632088Ssosstatic tree fold_builtin_bitop (tree, tree);
1642088Ssosstatic tree fold_builtin_memcpy (tree, tree);
1652088Ssosstatic tree fold_builtin_mempcpy (tree, tree, int);
1662088Ssosstatic tree fold_builtin_memmove (tree, tree);
1672088Ssosstatic tree fold_builtin_strchr (tree, tree);
1682088Ssosstatic tree fold_builtin_memcmp (tree);
1692088Ssosstatic tree fold_builtin_strcmp (tree);
1702088Ssosstatic tree fold_builtin_strncmp (tree);
1712088Ssosstatic tree fold_builtin_signbit (tree, tree);
1722088Ssosstatic tree fold_builtin_copysign (tree, tree, tree);
1732088Ssosstatic tree fold_builtin_isascii (tree);
1742088Ssosstatic tree fold_builtin_toascii (tree);
1752088Ssosstatic tree fold_builtin_isdigit (tree);
1762088Ssosstatic tree fold_builtin_fabs (tree, tree);
1772088Ssosstatic tree fold_builtin_abs (tree, tree);
1782088Ssosstatic tree fold_builtin_unordered_cmp (tree, tree, enum tree_code,
1795994Ssos					enum tree_code);
1805994Ssosstatic tree fold_builtin_1 (tree, tree, bool);
18132316Syokota
18232316Syokotastatic tree fold_builtin_strpbrk (tree, tree);
18332316Syokotastatic tree fold_builtin_strstr (tree, tree);
18432316Syokotastatic tree fold_builtin_strrchr (tree, tree);
1852088Ssosstatic tree fold_builtin_strcat (tree);
1862088Ssosstatic tree fold_builtin_strncat (tree);
1872088Ssosstatic tree fold_builtin_strspn (tree);
1882088Ssosstatic tree fold_builtin_strcspn (tree);
1892088Ssosstatic tree fold_builtin_sprintf (tree, int);
1902088Ssos
1912088Ssosstatic rtx expand_builtin_object_size (tree);
1922088Ssosstatic rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
1932088Ssos				      enum built_in_function);
1942088Ssosstatic void maybe_emit_chk_warning (tree, enum built_in_function);
1952088Ssosstatic void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
1962088Ssosstatic tree fold_builtin_object_size (tree);
1972088Ssosstatic tree fold_builtin_strcat_chk (tree, tree);
1982088Ssosstatic tree fold_builtin_strncat_chk (tree, tree);
1992088Ssosstatic tree fold_builtin_sprintf_chk (tree, enum built_in_function);
2002088Ssosstatic tree fold_builtin_printf (tree, tree, bool, enum built_in_function);
2012088Ssosstatic tree fold_builtin_fprintf (tree, tree, bool, enum built_in_function);
2022088Ssosstatic bool init_target_chars (void);
2032088Ssos
2042088Ssosstatic unsigned HOST_WIDE_INT target_newline;
20532316Syokotastatic unsigned HOST_WIDE_INT target_percent;
2062088Ssosstatic unsigned HOST_WIDE_INT target_c;
20732316Syokotastatic unsigned HOST_WIDE_INT target_s;
2082088Ssosstatic char target_percent_c[3];
2092088Ssosstatic char target_percent_s[3];
2102088Ssosstatic char target_percent_s_newline[4];
21132316Syokota
21232316Syokota/* Return true if NODE should be considered for inline expansion regardless
21332316Syokota   of the optimization level.  This means whenever a function is invoked with
21432316Syokota   its "internal" name, which normally contains the prefix "__builtin".  */
21532316Syokota
21632316Syokotastatic bool called_as_built_in (tree node)
21732316Syokota{
21832316Syokota  const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
21932316Syokota  if (strncmp (name, "__builtin_", 10) == 0)
22032316Syokota    return true;
22132316Syokota  if (strncmp (name, "__sync_", 7) == 0)
22232316Syokota    return true;
22332316Syokota  return false;
22432316Syokota}
22532316Syokota
22632316Syokota/* Return the alignment in bits of EXP, a pointer valued expression.
22732316Syokota   But don't return more than MAX_ALIGN no matter what.
22832316Syokota   The alignment returned is, by default, the alignment of the thing that
22932316Syokota   EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
2302088Ssos
23132316Syokota   Otherwise, look at the expression to see if we can do better, i.e., if the
23232316Syokota   expression is actually pointing at an object whose alignment is tighter.  */
23332316Syokota
23432316Syokotastatic int
23532316Syokotaget_pointer_alignment (tree exp, unsigned int max_align)
23632316Syokota{
23732316Syokota  unsigned int align, inner;
23832316Syokota
23932316Syokota  if (! POINTER_TYPE_P (TREE_TYPE (exp)))
24032316Syokota    return 0;
24132316Syokota
24232316Syokota  align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
2432088Ssos  align = MIN (align, max_align);
2442088Ssos
2452088Ssos  while (1)
2462088Ssos    {
2472088Ssos      switch (TREE_CODE (exp))
2482088Ssos	{
2492088Ssos	case NOP_EXPR:
2502088Ssos	case CONVERT_EXPR:
2512088Ssos	case NON_LVALUE_EXPR:
2522088Ssos	  exp = TREE_OPERAND (exp, 0);
2532088Ssos	  if (! POINTER_TYPE_P (TREE_TYPE (exp)))
2542088Ssos	    return align;
2552088Ssos
2562088Ssos	  inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
25732316Syokota	  align = MIN (inner, max_align);
2582088Ssos	  break;
2592088Ssos
26032316Syokota	case PLUS_EXPR:
26132316Syokota	  /* If sum of pointer + int, restrict our maximum alignment to that
2622088Ssos	     imposed by the integer.  If not, we can't do any better than
2632088Ssos	     ALIGN.  */
26432316Syokota	  if (! host_integerp (TREE_OPERAND (exp, 1), 1))
26532316Syokota	    return align;
26632316Syokota
26732316Syokota	  while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
26832316Syokota		  & (max_align / BITS_PER_UNIT - 1))
26932316Syokota		 != 0)
2702088Ssos	    max_align >>= 1;
27132316Syokota
27232316Syokota	  exp = TREE_OPERAND (exp, 0);
27332316Syokota	  break;
27432316Syokota
27532316Syokota	case ADDR_EXPR:
27632316Syokota	  /* See what we are pointing at and look at its alignment.  */
27732316Syokota	  exp = TREE_OPERAND (exp, 0);
27832316Syokota	  inner = max_align;
27932316Syokota	  if (handled_component_p (exp))
28032316Syokota	    {
28132316Syokota	      HOST_WIDE_INT bitsize, bitpos;
28232316Syokota	      tree offset;
28332316Syokota	      enum machine_mode mode;
28432316Syokota	      int unsignedp, volatilep;
28532316Syokota
28632316Syokota	      exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
28732316Syokota					 &mode, &unsignedp, &volatilep, true);
28832316Syokota	      if (bitpos)
28932316Syokota		inner = MIN (inner, (unsigned) (bitpos & -bitpos));
29032316Syokota	      if (offset && TREE_CODE (offset) == PLUS_EXPR
29132316Syokota		  && host_integerp (TREE_OPERAND (offset, 1), 1))
29232316Syokota	        {
29332316Syokota		  /* Any overflow in calculating offset_bits won't change
29432316Syokota		     the alignment.  */
29532316Syokota		  unsigned offset_bits
29632316Syokota		    = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
29732316Syokota		       * BITS_PER_UNIT);
29832316Syokota
29932316Syokota		  if (offset_bits)
30032316Syokota		    inner = MIN (inner, (offset_bits & -offset_bits));
30132316Syokota		  offset = TREE_OPERAND (offset, 0);
30232316Syokota		}
30332316Syokota	      if (offset && TREE_CODE (offset) == MULT_EXPR
30432316Syokota		  && host_integerp (TREE_OPERAND (offset, 1), 1))
30532316Syokota	        {
30632316Syokota		  /* Any overflow in calculating offset_factor won't change
30732316Syokota		     the alignment.  */
30832316Syokota		  unsigned offset_factor
30932316Syokota		    = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
31032316Syokota		       * BITS_PER_UNIT);
31132316Syokota
31232316Syokota		  if (offset_factor)
31332316Syokota		    inner = MIN (inner, (offset_factor & -offset_factor));
31432316Syokota		}
31532316Syokota	      else if (offset)
31632316Syokota		inner = MIN (inner, BITS_PER_UNIT);
31732316Syokota	    }
31832316Syokota	  if (TREE_CODE (exp) == FUNCTION_DECL)
31932316Syokota	    align = FUNCTION_BOUNDARY;
32032316Syokota	  else if (DECL_P (exp))
32132316Syokota	    align = MIN (inner, DECL_ALIGN (exp));
32232316Syokota#ifdef CONSTANT_ALIGNMENT
32332316Syokota	  else if (CONSTANT_CLASS_P (exp))
32432316Syokota	    align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
32529603Scharnier#endif
3262088Ssos	  else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
3272088Ssos		   || TREE_CODE (exp) == INDIRECT_REF)
3282088Ssos	    align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
3292088Ssos	  else
3302088Ssos	    align = MIN (align, inner);
3312088Ssos	  return MIN (align, max_align);
3328857Srgrimes
3332088Ssos	default:
3342088Ssos	  return align;
3352088Ssos	}
3362088Ssos    }
3372088Ssos}
3382088Ssos
3392088Ssos/* Compute the length of a C string.  TREE_STRING_LENGTH is not the right
3402088Ssos   way, because it could contain a zero byte in the middle.
3412088Ssos   TREE_STRING_LENGTH is the size of the character array, not the string.
3422088Ssos
3432088Ssos   ONLY_VALUE should be nonzero if the result is not going to be emitted
3442088Ssos   into the instruction stream and zero if it is going to be expanded.
3452088Ssos   E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is nonzero, constant 3
3462088Ssos   is returned, otherwise NULL, since
3472088Ssos   len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
3482088Ssos   evaluate the side-effects.
3492088Ssos
3502088Ssos   The value returned is of type `ssizetype'.
3512088Ssos
3522088Ssos   Unfortunately, string_constant can't access the values of const char
3532088Ssos   arrays with initializers, so neither can we do so here.  */
3542088Ssos
3552088Ssostree
3562088Ssosc_strlen (tree src, int only_value)
3572088Ssos{
3582088Ssos  tree offset_node;
3592088Ssos  HOST_WIDE_INT offset;
3602088Ssos  int max;
3612088Ssos  const char *ptr;
3622088Ssos
3632088Ssos  STRIP_NOPS (src);
3642088Ssos  if (TREE_CODE (src) == COND_EXPR
3652088Ssos      && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
3662088Ssos    {
3672088Ssos      tree len1, len2;
3682088Ssos
3692088Ssos      len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
3702088Ssos      len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
3712088Ssos      if (tree_int_cst_equal (len1, len2))
3722088Ssos	return len1;
3732088Ssos    }
3742088Ssos
3752088Ssos  if (TREE_CODE (src) == COMPOUND_EXPR
3762088Ssos      && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
3772088Ssos    return c_strlen (TREE_OPERAND (src, 1), only_value);
3782088Ssos
3792088Ssos  src = string_constant (src, &offset_node);
3802088Ssos  if (src == 0)
3812088Ssos    return 0;
38232316Syokota
38332316Syokota  max = TREE_STRING_LENGTH (src) - 1;
38432316Syokota  ptr = TREE_STRING_POINTER (src);
3852088Ssos
3862088Ssos  if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
3878857Srgrimes    {
3882088Ssos      /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
3898857Srgrimes	 compute the offset to the following null if we don't know where to
3902088Ssos	 start searching for it.  */
39132316Syokota      int i;
39232316Syokota
3932088Ssos      for (i = 0; i < max; i++)
3948857Srgrimes	if (ptr[i] == 0)
3952088Ssos	  return 0;
39632316Syokota
3972088Ssos      /* We don't know the starting offset, but we do know that the string
3982088Ssos	 has no internal zero bytes.  We can assume that the offset falls
3992088Ssos	 within the bounds of the string; otherwise, the programmer deserves
4008857Srgrimes	 what he gets.  Subtract the offset from the length of the string,
4012088Ssos	 and return that.  This would perhaps not be valid if we were dealing
4028857Srgrimes	 with named arrays in addition to literal string constants.  */
4039202Srgrimes
4048857Srgrimes      return size_diffop (size_int (max), offset_node);
4052088Ssos    }
4068857Srgrimes
4072088Ssos  /* We have a known offset into the string.  Start searching there for
4088857Srgrimes     a null character if we can represent it as a single HOST_WIDE_INT.  */
4092088Ssos  if (offset_node == 0)
4102088Ssos    offset = 0;
4112088Ssos  else if (! host_integerp (offset_node, 0))
4122088Ssos    offset = -1;
4132088Ssos  else
4142088Ssos    offset = tree_low_cst (offset_node, 0);
4152088Ssos
4162088Ssos  /* If the offset is known to be out of bounds, warn, and call strlen at
41729603Scharnier     runtime.  */
4182088Ssos  if (offset < 0 || offset > max)
4192088Ssos    {
4202088Ssos      warning (0, "offset outside bounds of constant string");
4212088Ssos      return 0;
4222088Ssos    }
4232088Ssos
4242088Ssos  /* Use strlen to search for the first zero byte.  Since any strings
4252088Ssos     constructed with build_string will have nulls appended, we win even
4262088Ssos     if we get handed something like (char[4])"abcd".
4272088Ssos
4282088Ssos     Since OFFSET is our starting index into the string, no further
4292088Ssos     calculation is needed.  */
4308857Srgrimes  return ssize_int (strlen (ptr + offset));
4312088Ssos}
4322088Ssos
4332088Ssos/* Return a char pointer for a C string if it is a string constant
4342088Ssos   or sum of string constant and integer constant.  */
4352088Ssos
4362088Ssosstatic const char *
4372088Ssosc_getstr (tree src)
4382088Ssos{
4392088Ssos  tree offset_node;
4402088Ssos
4412088Ssos  src = string_constant (src, &offset_node);
4422088Ssos  if (src == 0)
4432088Ssos    return 0;
4446046Ssos
4456046Ssos  if (offset_node == 0)
4466046Ssos    return TREE_STRING_POINTER (src);
4478857Srgrimes  else if (!host_integerp (offset_node, 1)
4482088Ssos	   || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
4492088Ssos    return 0;
45032316Syokota
45132316Syokota  return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
45232316Syokota}
45332316Syokota
45432316Syokota/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
4552088Ssos   GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
45632316Syokota
45732316Syokotastatic rtx
45832316Syokotac_readstr (const char *str, enum machine_mode mode)
45932316Syokota{
46032316Syokota  HOST_WIDE_INT c[2];
46132316Syokota  HOST_WIDE_INT ch;
46232316Syokota  unsigned int i, j;
46332316Syokota
46432316Syokota  gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
46532316Syokota
46632316Syokota  c[0] = 0;
46732316Syokota  c[1] = 0;
46832316Syokota  ch = 1;
46932316Syokota  for (i = 0; i < GET_MODE_SIZE (mode); i++)
47032316Syokota    {
47132316Syokota      j = i;
47232316Syokota      if (WORDS_BIG_ENDIAN)
47332316Syokota	j = GET_MODE_SIZE (mode) - i - 1;
47432316Syokota      if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
47532316Syokota	  && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
47632316Syokota	j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
47732316Syokota      j *= BITS_PER_UNIT;
47832316Syokota      gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
47932316Syokota
48032316Syokota      if (ch)
48132316Syokota	ch = (unsigned char) str[i];
48232316Syokota      c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
48332316Syokota    }
48432316Syokota  return immed_double_const (c[0], c[1], mode);
48532316Syokota}
48632316Syokota
48732316Syokota/* Cast a target constant CST to target CHAR and if that value fits into
48832316Syokota   host char type, return zero and put that value into variable pointed to by
48932316Syokota   P.  */
49032316Syokota
4912088Ssosstatic int
49232316Syokotatarget_char_cast (tree cst, char *p)
49332316Syokota{
49432316Syokota  unsigned HOST_WIDE_INT val, hostval;
49532316Syokota
49632316Syokota  if (!host_integerp (cst, 1)
49732316Syokota      || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
49832316Syokota    return 1;
49932316Syokota
50032316Syokota  val = tree_low_cst (cst, 1);
50132316Syokota  if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
50232316Syokota    val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
50332316Syokota
50432316Syokota  hostval = val;
50532316Syokota  if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
50632316Syokota    hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
50732316Syokota
50832316Syokota  if (val != hostval)
50932316Syokota    return 1;
51032316Syokota
51132316Syokota  *p = hostval;
51232316Syokota  return 0;
51332316Syokota}
51432316Syokota
51532316Syokota/* Similar to save_expr, but assumes that arbitrary code is not executed
51632316Syokota   in between the multiple evaluations.  In particular, we assume that a
51732316Syokota   non-addressable local variable will not be modified.  */
51832316Syokota
51932316Syokotastatic tree
52032316Syokotabuiltin_save_expr (tree exp)
52132316Syokota{
52232316Syokota  if (TREE_ADDRESSABLE (exp) == 0
52332316Syokota      && (TREE_CODE (exp) == PARM_DECL
52432316Syokota	  || (TREE_CODE (exp) == VAR_DECL && !TREE_STATIC (exp))))
52532316Syokota    return exp;
52632316Syokota
52732316Syokota  return save_expr (exp);
52832316Syokota}
52932316Syokota
53032316Syokota/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
53132316Syokota   times to get the address of either a higher stack frame, or a return
53232316Syokota   address located within it (depending on FNDECL_CODE).  */
53332316Syokota
53432316Syokotastatic rtx
53532316Syokotaexpand_builtin_return_addr (enum built_in_function fndecl_code, int count)
53632316Syokota{
53732316Syokota  int i;
53832316Syokota
53932316Syokota#ifdef INITIAL_FRAME_ADDRESS_RTX
54032316Syokota  rtx tem = INITIAL_FRAME_ADDRESS_RTX;
54132316Syokota#else
54232316Syokota  rtx tem;
54332316Syokota
54432316Syokota  /* For a zero count, we don't care what frame address we return, so frame
54532316Syokota     pointer elimination is OK, and using the soft frame pointer is OK.
54632316Syokota     For a non-zero count, we require a stable offset from the current frame
54732316Syokota     pointer to the previous one, so we must use the hard frame pointer, and
54832316Syokota     we must disable frame pointer elimination.  */
54932316Syokota  if (count == 0)
55032316Syokota    tem = frame_pointer_rtx;
55132316Syokota  else
55232316Syokota    {
55332316Syokota      tem = hard_frame_pointer_rtx;
55432316Syokota
55532486Syokota      /* Tell reload not to eliminate the frame pointer.  */
55632316Syokota      current_function_accesses_prior_frames = 1;
55732316Syokota    }
55832316Syokota#endif
55932316Syokota
56032316Syokota  /* Some machines need special handling before we can access
56132316Syokota     arbitrary frames.  For example, on the sparc, we must first flush
56232316Syokota     all register windows to the stack.  */
56332316Syokota#ifdef SETUP_FRAME_ADDRESSES
56432316Syokota  if (count > 0)
56532316Syokota    SETUP_FRAME_ADDRESSES ();
56632316Syokota#endif
56732316Syokota
56832316Syokota  /* On the sparc, the return address is not in the frame, it is in a
56932316Syokota     register.  There is no way to access it off of the current frame
57032316Syokota     pointer, but it can be accessed off the previous frame pointer by
57132316Syokota     reading the value from the register window save area.  */
57232316Syokota#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
57332316Syokota  if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
57432316Syokota    count--;
57532316Syokota#endif
57632316Syokota
57732316Syokota  /* Scan back COUNT frames to the specified frame.  */
57832486Syokota  for (i = 0; i < count; i++)
57932316Syokota    {
58032316Syokota      /* Assume the dynamic chain pointer is in the word that the
58132486Syokota	 frame address points to, unless otherwise specified.  */
58232486Syokota#ifdef DYNAMIC_CHAIN_ADDRESS
58332486Syokota      tem = DYNAMIC_CHAIN_ADDRESS (tem);
58432316Syokota#endif
58532316Syokota      tem = memory_address (Pmode, tem);
58632316Syokota      tem = gen_frame_mem (Pmode, tem);
58732486Syokota      tem = copy_to_reg (tem);
58832316Syokota    }
58932316Syokota
59032316Syokota  /* For __builtin_frame_address, return what we've got.  */
59132316Syokota  if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
59232316Syokota    return tem;
59332316Syokota
59432486Syokota  /* For __builtin_return_address, Get the return address from that
59532316Syokota     frame.  */
59632316Syokota#ifdef RETURN_ADDR_RTX
59732316Syokota  tem = RETURN_ADDR_RTX (count, tem);
59832486Syokota#else
59932316Syokota  tem = memory_address (Pmode,
60032316Syokota			plus_constant (tem, GET_MODE_SIZE (Pmode)));
60132316Syokota  tem = gen_frame_mem (Pmode, tem);
60232316Syokota#endif
60332316Syokota  return tem;
60432316Syokota}
60532316Syokota
60632316Syokota/* Alias set used for setjmp buffer.  */
60732486Syokotastatic HOST_WIDE_INT setjmp_alias_set = -1;
60832316Syokota
60932486Syokota/* Construct the leading half of a __builtin_setjmp call.  Control will
61032486Syokota   return to RECEIVER_LABEL.  This is used directly by sjlj exception
61132486Syokota   handling code.  */
61232486Syokota
61332486Syokotavoid
61432316Syokotaexpand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
61532316Syokota{
61632316Syokota  enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
61732316Syokota  rtx stack_save;
61832316Syokota  rtx mem;
61932316Syokota
62032316Syokota  if (setjmp_alias_set == -1)
62132316Syokota    setjmp_alias_set = new_alias_set ();
62232316Syokota
62332316Syokota  buf_addr = convert_memory_address (Pmode, buf_addr);
62432316Syokota
62532316Syokota  buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
62632316Syokota
62732316Syokota  /* We store the frame pointer and the address of receiver_label in
62832316Syokota     the buffer and use the rest of it for the stack save area, which
62932316Syokota     is machine-dependent.  */
63032316Syokota
63132316Syokota  mem = gen_rtx_MEM (Pmode, buf_addr);
63232316Syokota  set_mem_alias_set (mem, setjmp_alias_set);
63332316Syokota  emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
63432316Syokota
63532316Syokota  mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
63632316Syokota  set_mem_alias_set (mem, setjmp_alias_set);
63732316Syokota
63832316Syokota  emit_move_insn (validize_mem (mem),
63932316Syokota		  force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
64032316Syokota
64132316Syokota  stack_save = gen_rtx_MEM (sa_mode,
64232486Syokota			    plus_constant (buf_addr,
64332316Syokota					   2 * GET_MODE_SIZE (Pmode)));
64432316Syokota  set_mem_alias_set (stack_save, setjmp_alias_set);
64532316Syokota  emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
64619569Sjoerg
6472088Ssos  /* If there is further processing to do, do it.  */
64832316Syokota#ifdef HAVE_builtin_setjmp_setup
64932316Syokota  if (HAVE_builtin_setjmp_setup)
6502088Ssos    emit_insn (gen_builtin_setjmp_setup (buf_addr));
65132316Syokota#endif
65219569Sjoerg
65335750Sdes  /* Tell optimize_save_area_alloca that extra work is going to
65435750Sdes     need to go on during alloca.  */
6552088Ssos  current_function_calls_setjmp = 1;
6562088Ssos
6572088Ssos  /* Set this so all the registers get saved in our frame; we need to be
65829603Scharnier     able to copy the saved values for any registers from frames we unwind.  */
6592088Ssos  current_function_has_nonlocal_label = 1;
6602088Ssos}
6612088Ssos
66229603Scharnier/* Construct the trailing part of a __builtin_setjmp call.
6632088Ssos   This is used directly by sjlj exception handling code.  */
6642088Ssos
66532316Syokotavoid
66632316Syokotaexpand_builtin_setjmp_receiver (rtx receiver_label ATTRIBUTE_UNUSED)
66732316Syokota{
6682088Ssos  /* Clobber the FP when we get here, so we have to make sure it's
66932316Syokota     marked as used by this function.  */
6702088Ssos  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
6712088Ssos
67219569Sjoerg  /* Mark the static chain as clobbered here so life information
67319569Sjoerg     doesn't get messed up for it.  */
67419569Sjoerg  emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
67519569Sjoerg
67632316Syokota  /* Now put in the code to restore the frame pointer, and argument
67732316Syokota     pointer, if needed.  */
67832316Syokota#ifdef HAVE_nonlocal_goto
67932316Syokota  if (! HAVE_nonlocal_goto)
68032316Syokota#endif
68132316Syokota    {
68219569Sjoerg      emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
68319569Sjoerg      /* This might change the hard frame pointer in ways that aren't
68432316Syokota	 apparent to early optimization passes, so force a clobber.  */
68529603Scharnier      emit_insn (gen_rtx_CLOBBER (VOIDmode, hard_frame_pointer_rtx));
6862088Ssos    }
6872088Ssos
6882088Ssos#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
68932316Syokota  if (fixed_regs[ARG_POINTER_REGNUM])
69032316Syokota    {
69132316Syokota#ifdef ELIMINABLE_REGS
69232316Syokota      size_t i;
69332316Syokota      static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
69432316Syokota
6952088Ssos      for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
6962088Ssos	if (elim_regs[i].from == ARG_POINTER_REGNUM
6972088Ssos	    && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
6982088Ssos	  break;
6992088Ssos
70032316Syokota      if (i == ARRAY_SIZE (elim_regs))
70132316Syokota#endif
7022088Ssos	{
7032088Ssos	  /* Now restore our arg pointer from the address at which it
70432316Syokota	     was saved in our stack frame.  */
70529603Scharnier	  emit_move_insn (virtual_incoming_args_rtx,
70632316Syokota			  copy_to_reg (get_arg_pointer_save_area (cfun)));
70732316Syokota	}
7082088Ssos    }
7092088Ssos#endif
7102088Ssos
7112088Ssos#ifdef HAVE_builtin_setjmp_receiver
7122088Ssos  if (HAVE_builtin_setjmp_receiver)
7132088Ssos    emit_insn (gen_builtin_setjmp_receiver (receiver_label));
71432316Syokota  else
71532316Syokota#endif
71632316Syokota#ifdef HAVE_nonlocal_goto_receiver
71732316Syokota    if (HAVE_nonlocal_goto_receiver)
71832316Syokota      emit_insn (gen_nonlocal_goto_receiver ());
71932316Syokota    else
72032316Syokota#endif
7212088Ssos      { /* Nothing */ }
7222088Ssos
7232088Ssos  /* @@@ This is a kludge.  Not all machine descriptions define a blockage
7242088Ssos     insn, but we must not allow the code we just generated to be reordered
7252088Ssos     by scheduling.  Specifically, the update of the frame pointer must
7262088Ssos     happen immediately, not later.  So emit an ASM_INPUT to act as blockage
7272088Ssos     insn.  */
7282088Ssos  emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
7292088Ssos}
7302088Ssos
7312088Ssos/* __builtin_setjmp is passed a pointer to an array of five words (not
7322088Ssos   all will be used on all machines).  It operates similarly to the C
7332088Ssos   library function of the same name, but is more efficient.  Much of
7342088Ssos   the code below (and for longjmp) is copied from the handling of
73529603Scharnier   non-local gotos.
7362088Ssos
7372088Ssos   NOTE: This is intended for use by GNAT and the exception handling
7382088Ssos   scheme in the compiler and will only work in the method used by
7392088Ssos   them.  */
7402088Ssos
7412088Ssosstatic rtx
7422088Ssosexpand_builtin_setjmp (tree arglist, rtx target)
7432088Ssos{
7442088Ssos  rtx buf_addr, next_lab, cont_lab;
7452088Ssos
7462088Ssos  if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
7472088Ssos    return NULL_RTX;
7482088Ssos
7492088Ssos  if (target == 0 || !REG_P (target)
75029603Scharnier      || REGNO (target) < FIRST_PSEUDO_REGISTER)
7512088Ssos    target = gen_reg_rtx (TYPE_MODE (integer_type_node));
7522088Ssos
7532088Ssos  buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
7542088Ssos
75529603Scharnier  next_lab = gen_label_rtx ();
7562088Ssos  cont_lab = gen_label_rtx ();
7572088Ssos
7582088Ssos  expand_builtin_setjmp_setup (buf_addr, next_lab);
7592088Ssos
7602088Ssos  /* Set TARGET to zero and branch to the continue label.  Use emit_jump to
7612088Ssos     ensure that pending stack adjustments are flushed.  */
76229603Scharnier  emit_move_insn (target, const0_rtx);
7632088Ssos  emit_jump (cont_lab);
7642088Ssos
7652088Ssos  emit_label (next_lab);
7662088Ssos
7672088Ssos  /* Because setjmp and longjmp are not represented in the CFG, a cfgcleanup
7682088Ssos     may find that the basic block starting with NEXT_LAB is unreachable.
7695536Ssos     The whole block, along with NEXT_LAB, would be removed (see PR26983).
7702088Ssos     Make sure that never happens.  */
77138044Syokota  LABEL_PRESERVE_P (next_lab) = 1;
77238044Syokota
77338044Syokota  expand_builtin_setjmp_receiver (next_lab);
77438044Syokota
77538044Syokota  /* Set TARGET to one.  */
7768857Srgrimes  emit_move_insn (target, const1_rtx);
77738044Syokota  emit_label (cont_lab);
7785536Ssos
77938044Syokota  /* Tell flow about the strange goings on.  Putting `next_lab' on
7802088Ssos     `nonlocal_goto_handler_labels' to indicates that function
7812088Ssos     calls may traverse the arc back to this label.  */
7828857Srgrimes
7835536Ssos  current_function_has_nonlocal_label = 1;
7842088Ssos  nonlocal_goto_handler_labels
7852088Ssos    = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
7862088Ssos
7872088Ssos  return target;
7882088Ssos}
7892088Ssos
7902088Ssos/* __builtin_longjmp is passed a pointer to an array of five words (not
79129603Scharnier   all will be used on all machines).  It operates similarly to the C
7922088Ssos   library function of the same name, but is more efficient.  Much of
7932088Ssos   the code below is copied from the handling of non-local gotos.
79438044Syokota
79538044Syokota   NOTE: This is intended for use by GNAT and the exception handling
79638044Syokota   scheme in the compiler and will only work in the method used by
7972088Ssos   them.  */
7982088Ssos
7995536Ssosstatic void
80038044Syokotaexpand_builtin_longjmp (rtx buf_addr, rtx value)
8015536Ssos{
8022088Ssos  rtx fp, lab, stack, insn, last;
8032088Ssos  enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
8042088Ssos
8052088Ssos  if (setjmp_alias_set == -1)
8062088Ssos    setjmp_alias_set = new_alias_set ();
8072088Ssos
8082088Ssos  buf_addr = convert_memory_address (Pmode, buf_addr);
8092088Ssos
8102088Ssos  buf_addr = force_reg (Pmode, buf_addr);
8112088Ssos
8122088Ssos  /* We used to store value in static_chain_rtx, but that fails if pointers
8132088Ssos     are smaller than integers.  We instead require that the user must pass
8142088Ssos     a second argument of 1, because that is what builtin_setjmp will
8152088Ssos     return.  This also makes EH slightly more efficient, since we are no
8162088Ssos     longer copying around a value that we don't care about.  */
8172088Ssos  gcc_assert (value == const1_rtx);
8182088Ssos
8192088Ssos  last = get_last_insn ();
8202088Ssos#ifdef HAVE_builtin_longjmp
8212088Ssos  if (HAVE_builtin_longjmp)
8222088Ssos    emit_insn (gen_builtin_longjmp (buf_addr));
8232088Ssos  else
8242088Ssos#endif
8252088Ssos    {
8262088Ssos      fp = gen_rtx_MEM (Pmode, buf_addr);
8272088Ssos      lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
8282088Ssos					       GET_MODE_SIZE (Pmode)));
8292088Ssos
8302088Ssos      stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
8312088Ssos						   2 * GET_MODE_SIZE (Pmode)));
83229603Scharnier      set_mem_alias_set (fp, setjmp_alias_set);
8332088Ssos      set_mem_alias_set (lab, setjmp_alias_set);
8342088Ssos      set_mem_alias_set (stack, setjmp_alias_set);
8352088Ssos
8362088Ssos      /* Pick up FP, label, and SP from the block and jump.  This code is
8372088Ssos	 from expand_goto in stmt.c; see there for detailed comments.  */
8382088Ssos#if HAVE_nonlocal_goto
8392088Ssos      if (HAVE_nonlocal_goto)
8402088Ssos	/* We have to pass a value to the nonlocal_goto pattern that will
8412088Ssos	   get copied into the static_chain pointer, but it does not matter
8422088Ssos	   what that value is, because builtin_setjmp does not use it.  */
8432088Ssos	emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
8442088Ssos      else
8452088Ssos#endif
84629603Scharnier	{
8472088Ssos	  lab = copy_to_reg (lab);
8482088Ssos
8492088Ssos	  emit_insn (gen_rtx_CLOBBER (VOIDmode,
8506046Ssos				      gen_rtx_MEM (BLKmode,
8516046Ssos						   gen_rtx_SCRATCH (VOIDmode))));
8526046Ssos	  emit_insn (gen_rtx_CLOBBER (VOIDmode,
8536046Ssos				      gen_rtx_MEM (BLKmode,
8546046Ssos						   hard_frame_pointer_rtx)));
8556046Ssos
8566046Ssos	  emit_move_insn (hard_frame_pointer_rtx, fp);
85729603Scharnier	  emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
8586046Ssos
8596046Ssos	  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
8606046Ssos	  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
86129603Scharnier	  emit_indirect_jump (lab);
8626046Ssos	}
8636046Ssos    }
8646046Ssos
86529603Scharnier  /* Search backwards and mark the jump insn as a non-local goto.
8662088Ssos     Note that this precludes the use of __builtin_longjmp to a
8672088Ssos     __builtin_setjmp target in the same function.  However, we've
86829603Scharnier     already cautioned the user that these functions are for
86938044Syokota     internal exception handling use only.  */
87029603Scharnier  for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
87129603Scharnier    {
87229603Scharnier      gcc_assert (insn != last);
8732088Ssos
8742088Ssos      if (JUMP_P (insn))
8752088Ssos	{
8762088Ssos	  REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
8772088Ssos					      REG_NOTES (insn));
8782088Ssos	  break;
8792088Ssos	}
8802088Ssos      else if (CALL_P (insn))
88119569Sjoerg	break;
8822088Ssos    }
8832088Ssos}
8842088Ssos
8852088Ssos/* Expand a call to __builtin_nonlocal_goto.  We're passed the target label
8862088Ssos   and the address of the save area.  */
8872088Ssos
8882088Ssosstatic rtx
8892088Ssosexpand_builtin_nonlocal_goto (tree arglist)
89019569Sjoerg{
8912088Ssos  tree t_label, t_save_area;
89219569Sjoerg  rtx r_label, r_save_area, r_fp, r_sp, insn;
89319569Sjoerg
89419569Sjoerg  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8952088Ssos    return NULL_RTX;
8968857Srgrimes
8972088Ssos  t_label = TREE_VALUE (arglist);
8982088Ssos  arglist = TREE_CHAIN (arglist);
8992088Ssos  t_save_area = TREE_VALUE (arglist);
9002088Ssos
9012088Ssos  r_label = expand_expr (t_label, NULL_RTX, VOIDmode, 0);
9026046Ssos  r_label = convert_memory_address (Pmode, r_label);
9036046Ssos  r_save_area = expand_expr (t_save_area, NULL_RTX, VOIDmode, 0);
9046046Ssos  r_save_area = convert_memory_address (Pmode, r_save_area);
9052088Ssos  r_fp = gen_rtx_MEM (Pmode, r_save_area);
9062088Ssos  r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
9072088Ssos		      plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
9082088Ssos
9092088Ssos  current_function_has_nonlocal_goto = 1;
9102088Ssos
9112088Ssos#if HAVE_nonlocal_goto
9122088Ssos  /* ??? We no longer need to pass the static chain value, afaik.  */
9132088Ssos  if (HAVE_nonlocal_goto)
91429603Scharnier    emit_insn (gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
9152088Ssos  else
9162088Ssos#endif
9172088Ssos    {
9182088Ssos      r_label = copy_to_reg (r_label);
9192088Ssos
920      emit_insn (gen_rtx_CLOBBER (VOIDmode,
921				  gen_rtx_MEM (BLKmode,
922					       gen_rtx_SCRATCH (VOIDmode))));
923
924      emit_insn (gen_rtx_CLOBBER (VOIDmode,
925				  gen_rtx_MEM (BLKmode,
926					       hard_frame_pointer_rtx)));
927
928      /* Restore frame pointer for containing function.
929	 This sets the actual hard register used for the frame pointer
930	 to the location of the function's incoming static chain info.
931	 The non-local goto handler will then adjust it to contain the
932	 proper value and reload the argument pointer, if needed.  */
933      emit_move_insn (hard_frame_pointer_rtx, r_fp);
934      emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX);
935
936      /* USE of hard_frame_pointer_rtx added for consistency;
937	 not clear if really needed.  */
938      emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
939      emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
940      emit_indirect_jump (r_label);
941    }
942
943  /* Search backwards to the jump insn and mark it as a
944     non-local goto.  */
945  for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
946    {
947      if (JUMP_P (insn))
948	{
949	  REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
950					      const0_rtx, REG_NOTES (insn));
951	  break;
952	}
953      else if (CALL_P (insn))
954	break;
955    }
956
957  return const0_rtx;
958}
959
960/* __builtin_update_setjmp_buf is passed a pointer to an array of five words
961   (not all will be used on all machines) that was passed to __builtin_setjmp.
962   It updates the stack pointer in that block to correspond to the current
963   stack pointer.  */
964
965static void
966expand_builtin_update_setjmp_buf (rtx buf_addr)
967{
968  enum machine_mode sa_mode = Pmode;
969  rtx stack_save;
970
971
972#ifdef HAVE_save_stack_nonlocal
973  if (HAVE_save_stack_nonlocal)
974    sa_mode = insn_data[(int) CODE_FOR_save_stack_nonlocal].operand[0].mode;
975#endif
976#ifdef STACK_SAVEAREA_MODE
977  sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
978#endif
979
980  stack_save
981    = gen_rtx_MEM (sa_mode,
982		   memory_address
983		   (sa_mode,
984		    plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))));
985
986#ifdef HAVE_setjmp
987  if (HAVE_setjmp)
988    emit_insn (gen_setjmp ());
989#endif
990
991  emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
992}
993
994/* Expand a call to __builtin_prefetch.  For a target that does not support
995   data prefetch, evaluate the memory address argument in case it has side
996   effects.  */
997
998static void
999expand_builtin_prefetch (tree arglist)
1000{
1001  tree arg0, arg1, arg2;
1002  rtx op0, op1, op2;
1003
1004  if (!validate_arglist (arglist, POINTER_TYPE, 0))
1005    return;
1006
1007  arg0 = TREE_VALUE (arglist);
1008  /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
1009     zero (read) and argument 2 (locality) defaults to 3 (high degree of
1010     locality).  */
1011  if (TREE_CHAIN (arglist))
1012    {
1013      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
1014      if (TREE_CHAIN (TREE_CHAIN (arglist)))
1015	arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1016      else
1017	arg2 = build_int_cst (NULL_TREE, 3);
1018    }
1019  else
1020    {
1021      arg1 = integer_zero_node;
1022      arg2 = build_int_cst (NULL_TREE, 3);
1023    }
1024
1025  /* Argument 0 is an address.  */
1026  op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
1027
1028  /* Argument 1 (read/write flag) must be a compile-time constant int.  */
1029  if (TREE_CODE (arg1) != INTEGER_CST)
1030    {
1031      error ("second argument to %<__builtin_prefetch%> must be a constant");
1032      arg1 = integer_zero_node;
1033    }
1034  op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
1035  /* Argument 1 must be either zero or one.  */
1036  if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
1037    {
1038      warning (0, "invalid second argument to %<__builtin_prefetch%>;"
1039	       " using zero");
1040      op1 = const0_rtx;
1041    }
1042
1043  /* Argument 2 (locality) must be a compile-time constant int.  */
1044  if (TREE_CODE (arg2) != INTEGER_CST)
1045    {
1046      error ("third argument to %<__builtin_prefetch%> must be a constant");
1047      arg2 = integer_zero_node;
1048    }
1049  op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
1050  /* Argument 2 must be 0, 1, 2, or 3.  */
1051  if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
1052    {
1053      warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero");
1054      op2 = const0_rtx;
1055    }
1056
1057#ifdef HAVE_prefetch
1058  if (HAVE_prefetch)
1059    {
1060      if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
1061	     (op0,
1062	      insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
1063	  || (GET_MODE (op0) != Pmode))
1064	{
1065	  op0 = convert_memory_address (Pmode, op0);
1066	  op0 = force_reg (Pmode, op0);
1067	}
1068      emit_insn (gen_prefetch (op0, op1, op2));
1069    }
1070#endif
1071
1072  /* Don't do anything with direct references to volatile memory, but
1073     generate code to handle other side effects.  */
1074  if (!MEM_P (op0) && side_effects_p (op0))
1075    emit_insn (op0);
1076}
1077
1078/* Get a MEM rtx for expression EXP which is the address of an operand
1079   to be used in a string instruction (cmpstrsi, movmemsi, ..).  LEN is
1080   the maximum length of the block of memory that might be accessed or
1081   NULL if unknown.  */
1082
1083static rtx
1084get_memory_rtx (tree exp, tree len)
1085{
1086  rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_NORMAL);
1087  rtx mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
1088
1089  /* Get an expression we can use to find the attributes to assign to MEM.
1090     If it is an ADDR_EXPR, use the operand.  Otherwise, dereference it if
1091     we can.  First remove any nops.  */
1092  while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
1093	  || TREE_CODE (exp) == NON_LVALUE_EXPR)
1094	 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
1095    exp = TREE_OPERAND (exp, 0);
1096
1097  if (TREE_CODE (exp) == ADDR_EXPR)
1098    exp = TREE_OPERAND (exp, 0);
1099  else if (POINTER_TYPE_P (TREE_TYPE (exp)))
1100    exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
1101  else
1102    exp = NULL;
1103
1104  /* Honor attributes derived from exp, except for the alias set
1105     (as builtin stringops may alias with anything) and the size
1106     (as stringops may access multiple array elements).  */
1107  if (exp)
1108    {
1109      set_mem_attributes (mem, exp, 0);
1110
1111      /* Allow the string and memory builtins to overflow from one
1112	 field into another, see http://gcc.gnu.org/PR23561.
1113	 Thus avoid COMPONENT_REFs in MEM_EXPR unless we know the whole
1114	 memory accessed by the string or memory builtin will fit
1115	 within the field.  */
1116      if (MEM_EXPR (mem) && TREE_CODE (MEM_EXPR (mem)) == COMPONENT_REF)
1117	{
1118	  tree mem_expr = MEM_EXPR (mem);
1119	  HOST_WIDE_INT offset = -1, length = -1;
1120	  tree inner = exp;
1121
1122	  while (TREE_CODE (inner) == ARRAY_REF
1123		 || TREE_CODE (inner) == NOP_EXPR
1124		 || TREE_CODE (inner) == CONVERT_EXPR
1125		 || TREE_CODE (inner) == NON_LVALUE_EXPR
1126		 || TREE_CODE (inner) == VIEW_CONVERT_EXPR
1127		 || TREE_CODE (inner) == SAVE_EXPR)
1128	    inner = TREE_OPERAND (inner, 0);
1129
1130	  gcc_assert (TREE_CODE (inner) == COMPONENT_REF);
1131
1132	  if (MEM_OFFSET (mem)
1133	      && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
1134	    offset = INTVAL (MEM_OFFSET (mem));
1135
1136	  if (offset >= 0 && len && host_integerp (len, 0))
1137	    length = tree_low_cst (len, 0);
1138
1139	  while (TREE_CODE (inner) == COMPONENT_REF)
1140	    {
1141	      tree field = TREE_OPERAND (inner, 1);
1142	      gcc_assert (! DECL_BIT_FIELD (field));
1143	      gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
1144	      gcc_assert (field == TREE_OPERAND (mem_expr, 1));
1145
1146	      if (length >= 0
1147		  && TYPE_SIZE_UNIT (TREE_TYPE (inner))
1148		  && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0))
1149		{
1150		  HOST_WIDE_INT size
1151		    = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0);
1152		  /* If we can prove the memory starting at XEXP (mem, 0)
1153		     and ending at XEXP (mem, 0) + LENGTH will fit into
1154		     this field, we can keep that COMPONENT_REF in MEM_EXPR.  */
1155		  if (offset <= size
1156		      && length <= size
1157		      && offset + length <= size)
1158		    break;
1159		}
1160
1161	      if (offset >= 0
1162		  && host_integerp (DECL_FIELD_OFFSET (field), 0))
1163		offset += tree_low_cst (DECL_FIELD_OFFSET (field), 0)
1164			  + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
1165			    / BITS_PER_UNIT;
1166	      else
1167		{
1168		  offset = -1;
1169		  length = -1;
1170		}
1171
1172	      mem_expr = TREE_OPERAND (mem_expr, 0);
1173	      inner = TREE_OPERAND (inner, 0);
1174	    }
1175
1176	  if (mem_expr == NULL)
1177	    offset = -1;
1178	  if (mem_expr != MEM_EXPR (mem))
1179	    {
1180	      set_mem_expr (mem, mem_expr);
1181	      set_mem_offset (mem, offset >= 0 ? GEN_INT (offset) : NULL_RTX);
1182	    }
1183	}
1184      set_mem_alias_set (mem, 0);
1185      set_mem_size (mem, NULL_RTX);
1186    }
1187
1188  return mem;
1189}
1190
1191/* Built-in functions to perform an untyped call and return.  */
1192
1193/* For each register that may be used for calling a function, this
1194   gives a mode used to copy the register's value.  VOIDmode indicates
1195   the register is not used for calling a function.  If the machine
1196   has register windows, this gives only the outbound registers.
1197   INCOMING_REGNO gives the corresponding inbound register.  */
1198static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
1199
1200/* For each register that may be used for returning values, this gives
1201   a mode used to copy the register's value.  VOIDmode indicates the
1202   register is not used for returning values.  If the machine has
1203   register windows, this gives only the outbound registers.
1204   INCOMING_REGNO gives the corresponding inbound register.  */
1205static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
1206
1207/* For each register that may be used for calling a function, this
1208   gives the offset of that register into the block returned by
1209   __builtin_apply_args.  0 indicates that the register is not
1210   used for calling a function.  */
1211static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
1212
1213/* Return the size required for the block returned by __builtin_apply_args,
1214   and initialize apply_args_mode.  */
1215
1216static int
1217apply_args_size (void)
1218{
1219  static int size = -1;
1220  int align;
1221  unsigned int regno;
1222  enum machine_mode mode;
1223
1224  /* The values computed by this function never change.  */
1225  if (size < 0)
1226    {
1227      /* The first value is the incoming arg-pointer.  */
1228      size = GET_MODE_SIZE (Pmode);
1229
1230      /* The second value is the structure value address unless this is
1231	 passed as an "invisible" first argument.  */
1232      if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1233	size += GET_MODE_SIZE (Pmode);
1234
1235      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1236	if (FUNCTION_ARG_REGNO_P (regno))
1237	  {
1238	    mode = reg_raw_mode[regno];
1239
1240	    gcc_assert (mode != VOIDmode);
1241
1242	    align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1243	    if (size % align != 0)
1244	      size = CEIL (size, align) * align;
1245	    apply_args_reg_offset[regno] = size;
1246	    size += GET_MODE_SIZE (mode);
1247	    apply_args_mode[regno] = mode;
1248	  }
1249	else
1250	  {
1251	    apply_args_mode[regno] = VOIDmode;
1252	    apply_args_reg_offset[regno] = 0;
1253	  }
1254    }
1255  return size;
1256}
1257
1258/* Return the size required for the block returned by __builtin_apply,
1259   and initialize apply_result_mode.  */
1260
1261static int
1262apply_result_size (void)
1263{
1264  static int size = -1;
1265  int align, regno;
1266  enum machine_mode mode;
1267
1268  /* The values computed by this function never change.  */
1269  if (size < 0)
1270    {
1271      size = 0;
1272
1273      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1274	if (FUNCTION_VALUE_REGNO_P (regno))
1275	  {
1276	    mode = reg_raw_mode[regno];
1277
1278	    gcc_assert (mode != VOIDmode);
1279
1280	    align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1281	    if (size % align != 0)
1282	      size = CEIL (size, align) * align;
1283	    size += GET_MODE_SIZE (mode);
1284	    apply_result_mode[regno] = mode;
1285	  }
1286	else
1287	  apply_result_mode[regno] = VOIDmode;
1288
1289      /* Allow targets that use untyped_call and untyped_return to override
1290	 the size so that machine-specific information can be stored here.  */
1291#ifdef APPLY_RESULT_SIZE
1292      size = APPLY_RESULT_SIZE;
1293#endif
1294    }
1295  return size;
1296}
1297
1298#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1299/* Create a vector describing the result block RESULT.  If SAVEP is true,
1300   the result block is used to save the values; otherwise it is used to
1301   restore the values.  */
1302
1303static rtx
1304result_vector (int savep, rtx result)
1305{
1306  int regno, size, align, nelts;
1307  enum machine_mode mode;
1308  rtx reg, mem;
1309  rtx *savevec = alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
1310
1311  size = nelts = 0;
1312  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1313    if ((mode = apply_result_mode[regno]) != VOIDmode)
1314      {
1315	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1316	if (size % align != 0)
1317	  size = CEIL (size, align) * align;
1318	reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
1319	mem = adjust_address (result, mode, size);
1320	savevec[nelts++] = (savep
1321			    ? gen_rtx_SET (VOIDmode, mem, reg)
1322			    : gen_rtx_SET (VOIDmode, reg, mem));
1323	size += GET_MODE_SIZE (mode);
1324      }
1325  return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1326}
1327#endif /* HAVE_untyped_call or HAVE_untyped_return */
1328
1329/* Save the state required to perform an untyped call with the same
1330   arguments as were passed to the current function.  */
1331
1332static rtx
1333expand_builtin_apply_args_1 (void)
1334{
1335  rtx registers, tem;
1336  int size, align, regno;
1337  enum machine_mode mode;
1338  rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
1339
1340  /* Create a block where the arg-pointer, structure value address,
1341     and argument registers can be saved.  */
1342  registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1343
1344  /* Walk past the arg-pointer and structure value address.  */
1345  size = GET_MODE_SIZE (Pmode);
1346  if (targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0))
1347    size += GET_MODE_SIZE (Pmode);
1348
1349  /* Save each register used in calling a function to the block.  */
1350  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1351    if ((mode = apply_args_mode[regno]) != VOIDmode)
1352      {
1353	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1354	if (size % align != 0)
1355	  size = CEIL (size, align) * align;
1356
1357	tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1358
1359	emit_move_insn (adjust_address (registers, mode, size), tem);
1360	size += GET_MODE_SIZE (mode);
1361      }
1362
1363  /* Save the arg pointer to the block.  */
1364  tem = copy_to_reg (virtual_incoming_args_rtx);
1365#ifdef STACK_GROWS_DOWNWARD
1366  /* We need the pointer as the caller actually passed them to us, not
1367     as we might have pretended they were passed.  Make sure it's a valid
1368     operand, as emit_move_insn isn't expected to handle a PLUS.  */
1369  tem
1370    = force_operand (plus_constant (tem, current_function_pretend_args_size),
1371		     NULL_RTX);
1372#endif
1373  emit_move_insn (adjust_address (registers, Pmode, 0), tem);
1374
1375  size = GET_MODE_SIZE (Pmode);
1376
1377  /* Save the structure value address unless this is passed as an
1378     "invisible" first argument.  */
1379  if (struct_incoming_value)
1380    {
1381      emit_move_insn (adjust_address (registers, Pmode, size),
1382		      copy_to_reg (struct_incoming_value));
1383      size += GET_MODE_SIZE (Pmode);
1384    }
1385
1386  /* Return the address of the block.  */
1387  return copy_addr_to_reg (XEXP (registers, 0));
1388}
1389
1390/* __builtin_apply_args returns block of memory allocated on
1391   the stack into which is stored the arg pointer, structure
1392   value address, static chain, and all the registers that might
1393   possibly be used in performing a function call.  The code is
1394   moved to the start of the function so the incoming values are
1395   saved.  */
1396
1397static rtx
1398expand_builtin_apply_args (void)
1399{
1400  /* Don't do __builtin_apply_args more than once in a function.
1401     Save the result of the first call and reuse it.  */
1402  if (apply_args_value != 0)
1403    return apply_args_value;
1404  {
1405    /* When this function is called, it means that registers must be
1406       saved on entry to this function.  So we migrate the
1407       call to the first insn of this function.  */
1408    rtx temp;
1409    rtx seq;
1410
1411    start_sequence ();
1412    temp = expand_builtin_apply_args_1 ();
1413    seq = get_insns ();
1414    end_sequence ();
1415
1416    apply_args_value = temp;
1417
1418    /* Put the insns after the NOTE that starts the function.
1419       If this is inside a start_sequence, make the outer-level insn
1420       chain current, so the code is placed at the start of the
1421       function.  */
1422    push_topmost_sequence ();
1423    emit_insn_before (seq, NEXT_INSN (entry_of_function ()));
1424    pop_topmost_sequence ();
1425    return temp;
1426  }
1427}
1428
1429/* Perform an untyped call and save the state required to perform an
1430   untyped return of whatever value was returned by the given function.  */
1431
1432static rtx
1433expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
1434{
1435  int size, align, regno;
1436  enum machine_mode mode;
1437  rtx incoming_args, result, reg, dest, src, call_insn;
1438  rtx old_stack_level = 0;
1439  rtx call_fusage = 0;
1440  rtx struct_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 0);
1441
1442  arguments = convert_memory_address (Pmode, arguments);
1443
1444  /* Create a block where the return registers can be saved.  */
1445  result = assign_stack_local (BLKmode, apply_result_size (), -1);
1446
1447  /* Fetch the arg pointer from the ARGUMENTS block.  */
1448  incoming_args = gen_reg_rtx (Pmode);
1449  emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1450#ifndef STACK_GROWS_DOWNWARD
1451  incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1452				       incoming_args, 0, OPTAB_LIB_WIDEN);
1453#endif
1454
1455  /* Push a new argument block and copy the arguments.  Do not allow
1456     the (potential) memcpy call below to interfere with our stack
1457     manipulations.  */
1458  do_pending_stack_adjust ();
1459  NO_DEFER_POP;
1460
1461  /* Save the stack with nonlocal if available.  */
1462#ifdef HAVE_save_stack_nonlocal
1463  if (HAVE_save_stack_nonlocal)
1464    emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1465  else
1466#endif
1467    emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1468
1469  /* Allocate a block of memory onto the stack and copy the memory
1470     arguments to the outgoing arguments address.  */
1471  allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1472  dest = virtual_outgoing_args_rtx;
1473#ifndef STACK_GROWS_DOWNWARD
1474  if (GET_CODE (argsize) == CONST_INT)
1475    dest = plus_constant (dest, -INTVAL (argsize));
1476  else
1477    dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
1478#endif
1479  dest = gen_rtx_MEM (BLKmode, dest);
1480  set_mem_align (dest, PARM_BOUNDARY);
1481  src = gen_rtx_MEM (BLKmode, incoming_args);
1482  set_mem_align (src, PARM_BOUNDARY);
1483  emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
1484
1485  /* Refer to the argument block.  */
1486  apply_args_size ();
1487  arguments = gen_rtx_MEM (BLKmode, arguments);
1488  set_mem_align (arguments, PARM_BOUNDARY);
1489
1490  /* Walk past the arg-pointer and structure value address.  */
1491  size = GET_MODE_SIZE (Pmode);
1492  if (struct_value)
1493    size += GET_MODE_SIZE (Pmode);
1494
1495  /* Restore each of the registers previously saved.  Make USE insns
1496     for each of these registers for use in making the call.  */
1497  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1498    if ((mode = apply_args_mode[regno]) != VOIDmode)
1499      {
1500	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1501	if (size % align != 0)
1502	  size = CEIL (size, align) * align;
1503	reg = gen_rtx_REG (mode, regno);
1504	emit_move_insn (reg, adjust_address (arguments, mode, size));
1505	use_reg (&call_fusage, reg);
1506	size += GET_MODE_SIZE (mode);
1507      }
1508
1509  /* Restore the structure value address unless this is passed as an
1510     "invisible" first argument.  */
1511  size = GET_MODE_SIZE (Pmode);
1512  if (struct_value)
1513    {
1514      rtx value = gen_reg_rtx (Pmode);
1515      emit_move_insn (value, adjust_address (arguments, Pmode, size));
1516      emit_move_insn (struct_value, value);
1517      if (REG_P (struct_value))
1518	use_reg (&call_fusage, struct_value);
1519      size += GET_MODE_SIZE (Pmode);
1520    }
1521
1522  /* All arguments and registers used for the call are set up by now!  */
1523  function = prepare_call_address (function, NULL, &call_fusage, 0, 0);
1524
1525  /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
1526     and we don't want to load it into a register as an optimization,
1527     because prepare_call_address already did it if it should be done.  */
1528  if (GET_CODE (function) != SYMBOL_REF)
1529    function = memory_address (FUNCTION_MODE, function);
1530
1531  /* Generate the actual call instruction and save the return value.  */
1532#ifdef HAVE_untyped_call
1533  if (HAVE_untyped_call)
1534    emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1535				      result, result_vector (1, result)));
1536  else
1537#endif
1538#ifdef HAVE_call_value
1539  if (HAVE_call_value)
1540    {
1541      rtx valreg = 0;
1542
1543      /* Locate the unique return register.  It is not possible to
1544	 express a call that sets more than one return register using
1545	 call_value; use untyped_call for that.  In fact, untyped_call
1546	 only needs to save the return registers in the given block.  */
1547      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1548	if ((mode = apply_result_mode[regno]) != VOIDmode)
1549	  {
1550	    gcc_assert (!valreg); /* HAVE_untyped_call required.  */
1551
1552	    valreg = gen_rtx_REG (mode, regno);
1553	  }
1554
1555      emit_call_insn (GEN_CALL_VALUE (valreg,
1556				      gen_rtx_MEM (FUNCTION_MODE, function),
1557				      const0_rtx, NULL_RTX, const0_rtx));
1558
1559      emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1560    }
1561  else
1562#endif
1563    gcc_unreachable ();
1564
1565  /* Find the CALL insn we just emitted, and attach the register usage
1566     information.  */
1567  call_insn = last_call_insn ();
1568  add_function_usage_to (call_insn, call_fusage);
1569
1570  /* Restore the stack.  */
1571#ifdef HAVE_save_stack_nonlocal
1572  if (HAVE_save_stack_nonlocal)
1573    emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1574  else
1575#endif
1576    emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1577
1578  OK_DEFER_POP;
1579
1580  /* Return the address of the result block.  */
1581  result = copy_addr_to_reg (XEXP (result, 0));
1582  return convert_memory_address (ptr_mode, result);
1583}
1584
1585/* Perform an untyped return.  */
1586
1587static void
1588expand_builtin_return (rtx result)
1589{
1590  int size, align, regno;
1591  enum machine_mode mode;
1592  rtx reg;
1593  rtx call_fusage = 0;
1594
1595  result = convert_memory_address (Pmode, result);
1596
1597  apply_result_size ();
1598  result = gen_rtx_MEM (BLKmode, result);
1599
1600#ifdef HAVE_untyped_return
1601  if (HAVE_untyped_return)
1602    {
1603      emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1604      emit_barrier ();
1605      return;
1606    }
1607#endif
1608
1609  /* Restore the return value and note that each value is used.  */
1610  size = 0;
1611  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1612    if ((mode = apply_result_mode[regno]) != VOIDmode)
1613      {
1614	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1615	if (size % align != 0)
1616	  size = CEIL (size, align) * align;
1617	reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1618	emit_move_insn (reg, adjust_address (result, mode, size));
1619
1620	push_to_sequence (call_fusage);
1621	emit_insn (gen_rtx_USE (VOIDmode, reg));
1622	call_fusage = get_insns ();
1623	end_sequence ();
1624	size += GET_MODE_SIZE (mode);
1625      }
1626
1627  /* Put the USE insns before the return.  */
1628  emit_insn (call_fusage);
1629
1630  /* Return whatever values was restored by jumping directly to the end
1631     of the function.  */
1632  expand_naked_return ();
1633}
1634
1635/* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
1636
1637static enum type_class
1638type_to_class (tree type)
1639{
1640  switch (TREE_CODE (type))
1641    {
1642    case VOID_TYPE:	   return void_type_class;
1643    case INTEGER_TYPE:	   return integer_type_class;
1644    case CHAR_TYPE:	   return char_type_class;
1645    case ENUMERAL_TYPE:	   return enumeral_type_class;
1646    case BOOLEAN_TYPE:	   return boolean_type_class;
1647    case POINTER_TYPE:	   return pointer_type_class;
1648    case REFERENCE_TYPE:   return reference_type_class;
1649    case OFFSET_TYPE:	   return offset_type_class;
1650    case REAL_TYPE:	   return real_type_class;
1651    case COMPLEX_TYPE:	   return complex_type_class;
1652    case FUNCTION_TYPE:	   return function_type_class;
1653    case METHOD_TYPE:	   return method_type_class;
1654    case RECORD_TYPE:	   return record_type_class;
1655    case UNION_TYPE:
1656    case QUAL_UNION_TYPE:  return union_type_class;
1657    case ARRAY_TYPE:	   return (TYPE_STRING_FLAG (type)
1658				   ? string_type_class : array_type_class);
1659    case LANG_TYPE:	   return lang_type_class;
1660    default:		   return no_type_class;
1661    }
1662}
1663
1664/* Expand a call to __builtin_classify_type with arguments found in
1665   ARGLIST.  */
1666
1667static rtx
1668expand_builtin_classify_type (tree arglist)
1669{
1670  if (arglist != 0)
1671    return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
1672  return GEN_INT (no_type_class);
1673}
1674
1675/* This helper macro, meant to be used in mathfn_built_in below,
1676   determines which among a set of three builtin math functions is
1677   appropriate for a given type mode.  The `F' and `L' cases are
1678   automatically generated from the `double' case.  */
1679#define CASE_MATHFN(BUILT_IN_MATHFN) \
1680  case BUILT_IN_MATHFN: case BUILT_IN_MATHFN##F: case BUILT_IN_MATHFN##L: \
1681  fcode = BUILT_IN_MATHFN; fcodef = BUILT_IN_MATHFN##F ; \
1682  fcodel = BUILT_IN_MATHFN##L ; break;
1683
1684/* Return mathematic function equivalent to FN but operating directly
1685   on TYPE, if available.  If we can't do the conversion, return zero.  */
1686tree
1687mathfn_built_in (tree type, enum built_in_function fn)
1688{
1689  enum built_in_function fcode, fcodef, fcodel;
1690
1691  switch (fn)
1692    {
1693      CASE_MATHFN (BUILT_IN_ACOS)
1694      CASE_MATHFN (BUILT_IN_ACOSH)
1695      CASE_MATHFN (BUILT_IN_ASIN)
1696      CASE_MATHFN (BUILT_IN_ASINH)
1697      CASE_MATHFN (BUILT_IN_ATAN)
1698      CASE_MATHFN (BUILT_IN_ATAN2)
1699      CASE_MATHFN (BUILT_IN_ATANH)
1700      CASE_MATHFN (BUILT_IN_CBRT)
1701      CASE_MATHFN (BUILT_IN_CEIL)
1702      CASE_MATHFN (BUILT_IN_COPYSIGN)
1703      CASE_MATHFN (BUILT_IN_COS)
1704      CASE_MATHFN (BUILT_IN_COSH)
1705      CASE_MATHFN (BUILT_IN_DREM)
1706      CASE_MATHFN (BUILT_IN_ERF)
1707      CASE_MATHFN (BUILT_IN_ERFC)
1708      CASE_MATHFN (BUILT_IN_EXP)
1709      CASE_MATHFN (BUILT_IN_EXP10)
1710      CASE_MATHFN (BUILT_IN_EXP2)
1711      CASE_MATHFN (BUILT_IN_EXPM1)
1712      CASE_MATHFN (BUILT_IN_FABS)
1713      CASE_MATHFN (BUILT_IN_FDIM)
1714      CASE_MATHFN (BUILT_IN_FLOOR)
1715      CASE_MATHFN (BUILT_IN_FMA)
1716      CASE_MATHFN (BUILT_IN_FMAX)
1717      CASE_MATHFN (BUILT_IN_FMIN)
1718      CASE_MATHFN (BUILT_IN_FMOD)
1719      CASE_MATHFN (BUILT_IN_FREXP)
1720      CASE_MATHFN (BUILT_IN_GAMMA)
1721      CASE_MATHFN (BUILT_IN_HUGE_VAL)
1722      CASE_MATHFN (BUILT_IN_HYPOT)
1723      CASE_MATHFN (BUILT_IN_ILOGB)
1724      CASE_MATHFN (BUILT_IN_INF)
1725      CASE_MATHFN (BUILT_IN_J0)
1726      CASE_MATHFN (BUILT_IN_J1)
1727      CASE_MATHFN (BUILT_IN_JN)
1728      CASE_MATHFN (BUILT_IN_LCEIL)
1729      CASE_MATHFN (BUILT_IN_LDEXP)
1730      CASE_MATHFN (BUILT_IN_LFLOOR)
1731      CASE_MATHFN (BUILT_IN_LGAMMA)
1732      CASE_MATHFN (BUILT_IN_LLCEIL)
1733      CASE_MATHFN (BUILT_IN_LLFLOOR)
1734      CASE_MATHFN (BUILT_IN_LLRINT)
1735      CASE_MATHFN (BUILT_IN_LLROUND)
1736      CASE_MATHFN (BUILT_IN_LOG)
1737      CASE_MATHFN (BUILT_IN_LOG10)
1738      CASE_MATHFN (BUILT_IN_LOG1P)
1739      CASE_MATHFN (BUILT_IN_LOG2)
1740      CASE_MATHFN (BUILT_IN_LOGB)
1741      CASE_MATHFN (BUILT_IN_LRINT)
1742      CASE_MATHFN (BUILT_IN_LROUND)
1743      CASE_MATHFN (BUILT_IN_MODF)
1744      CASE_MATHFN (BUILT_IN_NAN)
1745      CASE_MATHFN (BUILT_IN_NANS)
1746      CASE_MATHFN (BUILT_IN_NEARBYINT)
1747      CASE_MATHFN (BUILT_IN_NEXTAFTER)
1748      CASE_MATHFN (BUILT_IN_NEXTTOWARD)
1749      CASE_MATHFN (BUILT_IN_POW)
1750      CASE_MATHFN (BUILT_IN_POWI)
1751      CASE_MATHFN (BUILT_IN_POW10)
1752      CASE_MATHFN (BUILT_IN_REMAINDER)
1753      CASE_MATHFN (BUILT_IN_REMQUO)
1754      CASE_MATHFN (BUILT_IN_RINT)
1755      CASE_MATHFN (BUILT_IN_ROUND)
1756      CASE_MATHFN (BUILT_IN_SCALB)
1757      CASE_MATHFN (BUILT_IN_SCALBLN)
1758      CASE_MATHFN (BUILT_IN_SCALBN)
1759      CASE_MATHFN (BUILT_IN_SIGNIFICAND)
1760      CASE_MATHFN (BUILT_IN_SIN)
1761      CASE_MATHFN (BUILT_IN_SINCOS)
1762      CASE_MATHFN (BUILT_IN_SINH)
1763      CASE_MATHFN (BUILT_IN_SQRT)
1764      CASE_MATHFN (BUILT_IN_TAN)
1765      CASE_MATHFN (BUILT_IN_TANH)
1766      CASE_MATHFN (BUILT_IN_TGAMMA)
1767      CASE_MATHFN (BUILT_IN_TRUNC)
1768      CASE_MATHFN (BUILT_IN_Y0)
1769      CASE_MATHFN (BUILT_IN_Y1)
1770      CASE_MATHFN (BUILT_IN_YN)
1771
1772      default:
1773	return 0;
1774      }
1775
1776  if (TYPE_MAIN_VARIANT (type) == double_type_node)
1777    return implicit_built_in_decls[fcode];
1778  else if (TYPE_MAIN_VARIANT (type) == float_type_node)
1779    return implicit_built_in_decls[fcodef];
1780  else if (TYPE_MAIN_VARIANT (type) == long_double_type_node)
1781    return implicit_built_in_decls[fcodel];
1782  else
1783    return 0;
1784}
1785
1786/* If errno must be maintained, expand the RTL to check if the result,
1787   TARGET, of a built-in function call, EXP, is NaN, and if so set
1788   errno to EDOM.  */
1789
1790static void
1791expand_errno_check (tree exp, rtx target)
1792{
1793  rtx lab = gen_label_rtx ();
1794
1795  /* Test the result; if it is NaN, set errno=EDOM because
1796     the argument was not in the domain.  */
1797  emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1798			   0, lab);
1799
1800#ifdef TARGET_EDOM
1801  /* If this built-in doesn't throw an exception, set errno directly.  */
1802  if (TREE_NOTHROW (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
1803    {
1804#ifdef GEN_ERRNO_RTX
1805      rtx errno_rtx = GEN_ERRNO_RTX;
1806#else
1807      rtx errno_rtx
1808	  = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1809#endif
1810      emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1811      emit_label (lab);
1812      return;
1813    }
1814#endif
1815
1816  /* We can't set errno=EDOM directly; let the library call do it.
1817     Pop the arguments right away in case the call gets deleted.  */
1818  NO_DEFER_POP;
1819  expand_call (exp, target, 0);
1820  OK_DEFER_POP;
1821  emit_label (lab);
1822}
1823
1824
1825/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
1826   Return 0 if a normal call should be emitted rather than expanding the
1827   function in-line.  EXP is the expression that is a call to the builtin
1828   function; if convenient, the result should be placed in TARGET.
1829   SUBTARGET may be used as the target for computing one of EXP's operands.  */
1830
1831static rtx
1832expand_builtin_mathfn (tree exp, rtx target, rtx subtarget)
1833{
1834  optab builtin_optab;
1835  rtx op0, insns, before_call;
1836  tree fndecl = get_callee_fndecl (exp);
1837  tree arglist = TREE_OPERAND (exp, 1);
1838  enum machine_mode mode;
1839  bool errno_set = false;
1840  tree arg, narg;
1841
1842  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
1843    return 0;
1844
1845  arg = TREE_VALUE (arglist);
1846
1847  switch (DECL_FUNCTION_CODE (fndecl))
1848    {
1849    case BUILT_IN_SQRT:
1850    case BUILT_IN_SQRTF:
1851    case BUILT_IN_SQRTL:
1852      errno_set = ! tree_expr_nonnegative_p (arg);
1853      builtin_optab = sqrt_optab;
1854      break;
1855    case BUILT_IN_EXP:
1856    case BUILT_IN_EXPF:
1857    case BUILT_IN_EXPL:
1858      errno_set = true; builtin_optab = exp_optab; break;
1859    case BUILT_IN_EXP10:
1860    case BUILT_IN_EXP10F:
1861    case BUILT_IN_EXP10L:
1862    case BUILT_IN_POW10:
1863    case BUILT_IN_POW10F:
1864    case BUILT_IN_POW10L:
1865      errno_set = true; builtin_optab = exp10_optab; break;
1866    case BUILT_IN_EXP2:
1867    case BUILT_IN_EXP2F:
1868    case BUILT_IN_EXP2L:
1869      errno_set = true; builtin_optab = exp2_optab; break;
1870    case BUILT_IN_EXPM1:
1871    case BUILT_IN_EXPM1F:
1872    case BUILT_IN_EXPM1L:
1873      errno_set = true; builtin_optab = expm1_optab; break;
1874    case BUILT_IN_LOGB:
1875    case BUILT_IN_LOGBF:
1876    case BUILT_IN_LOGBL:
1877      errno_set = true; builtin_optab = logb_optab; break;
1878    case BUILT_IN_ILOGB:
1879    case BUILT_IN_ILOGBF:
1880    case BUILT_IN_ILOGBL:
1881      errno_set = true; builtin_optab = ilogb_optab; break;
1882    case BUILT_IN_LOG:
1883    case BUILT_IN_LOGF:
1884    case BUILT_IN_LOGL:
1885      errno_set = true; builtin_optab = log_optab; break;
1886    case BUILT_IN_LOG10:
1887    case BUILT_IN_LOG10F:
1888    case BUILT_IN_LOG10L:
1889      errno_set = true; builtin_optab = log10_optab; break;
1890    case BUILT_IN_LOG2:
1891    case BUILT_IN_LOG2F:
1892    case BUILT_IN_LOG2L:
1893      errno_set = true; builtin_optab = log2_optab; break;
1894    case BUILT_IN_LOG1P:
1895    case BUILT_IN_LOG1PF:
1896    case BUILT_IN_LOG1PL:
1897      errno_set = true; builtin_optab = log1p_optab; break;
1898    case BUILT_IN_ASIN:
1899    case BUILT_IN_ASINF:
1900    case BUILT_IN_ASINL:
1901      builtin_optab = asin_optab; break;
1902    case BUILT_IN_ACOS:
1903    case BUILT_IN_ACOSF:
1904    case BUILT_IN_ACOSL:
1905      builtin_optab = acos_optab; break;
1906    case BUILT_IN_TAN:
1907    case BUILT_IN_TANF:
1908    case BUILT_IN_TANL:
1909      builtin_optab = tan_optab; break;
1910    case BUILT_IN_ATAN:
1911    case BUILT_IN_ATANF:
1912    case BUILT_IN_ATANL:
1913      builtin_optab = atan_optab; break;
1914    case BUILT_IN_FLOOR:
1915    case BUILT_IN_FLOORF:
1916    case BUILT_IN_FLOORL:
1917      builtin_optab = floor_optab; break;
1918    case BUILT_IN_CEIL:
1919    case BUILT_IN_CEILF:
1920    case BUILT_IN_CEILL:
1921      builtin_optab = ceil_optab; break;
1922    case BUILT_IN_TRUNC:
1923    case BUILT_IN_TRUNCF:
1924    case BUILT_IN_TRUNCL:
1925      builtin_optab = btrunc_optab; break;
1926    case BUILT_IN_ROUND:
1927    case BUILT_IN_ROUNDF:
1928    case BUILT_IN_ROUNDL:
1929      builtin_optab = round_optab; break;
1930    case BUILT_IN_NEARBYINT:
1931    case BUILT_IN_NEARBYINTF:
1932    case BUILT_IN_NEARBYINTL:
1933      builtin_optab = nearbyint_optab; break;
1934    case BUILT_IN_RINT:
1935    case BUILT_IN_RINTF:
1936    case BUILT_IN_RINTL:
1937      builtin_optab = rint_optab; break;
1938    case BUILT_IN_LRINT:
1939    case BUILT_IN_LRINTF:
1940    case BUILT_IN_LRINTL:
1941    case BUILT_IN_LLRINT:
1942    case BUILT_IN_LLRINTF:
1943    case BUILT_IN_LLRINTL:
1944      builtin_optab = lrint_optab; break;
1945    default:
1946      gcc_unreachable ();
1947    }
1948
1949  /* Make a suitable register to place result in.  */
1950  mode = TYPE_MODE (TREE_TYPE (exp));
1951
1952  if (! flag_errno_math || ! HONOR_NANS (mode))
1953    errno_set = false;
1954
1955  /* Before working hard, check whether the instruction is available.  */
1956  if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1957    {
1958      target = gen_reg_rtx (mode);
1959
1960      /* Wrap the computation of the argument in a SAVE_EXPR, as we may
1961	 need to expand the argument again.  This way, we will not perform
1962	 side-effects more the once.  */
1963      narg = builtin_save_expr (arg);
1964      if (narg != arg)
1965	{
1966	  arg = narg;
1967	  arglist = build_tree_list (NULL_TREE, arg);
1968	  exp = build_function_call_expr (fndecl, arglist);
1969	}
1970
1971      op0 = expand_expr (arg, subtarget, VOIDmode, 0);
1972
1973      start_sequence ();
1974
1975      /* Compute into TARGET.
1976	 Set TARGET to wherever the result comes back.  */
1977      target = expand_unop (mode, builtin_optab, op0, target, 0);
1978
1979      if (target != 0)
1980	{
1981	  if (errno_set)
1982	    expand_errno_check (exp, target);
1983
1984	  /* Output the entire sequence.  */
1985	  insns = get_insns ();
1986	  end_sequence ();
1987	  emit_insn (insns);
1988	  return target;
1989	}
1990
1991      /* If we were unable to expand via the builtin, stop the sequence
1992	 (without outputting the insns) and call to the library function
1993	 with the stabilized argument list.  */
1994      end_sequence ();
1995    }
1996
1997  before_call = get_last_insn ();
1998
1999  target = expand_call (exp, target, target == const0_rtx);
2000
2001  /* If this is a sqrt operation and we don't care about errno, try to
2002     attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
2003     This allows the semantics of the libcall to be visible to the RTL
2004     optimizers.  */
2005  if (builtin_optab == sqrt_optab && !errno_set)
2006    {
2007      /* Search backwards through the insns emitted by expand_call looking
2008	 for the instruction with the REG_RETVAL note.  */
2009      rtx last = get_last_insn ();
2010      while (last != before_call)
2011	{
2012	  if (find_reg_note (last, REG_RETVAL, NULL))
2013	    {
2014	      rtx note = find_reg_note (last, REG_EQUAL, NULL);
2015	      /* Check that the REQ_EQUAL note is an EXPR_LIST with
2016		 two elements, i.e. symbol_ref(sqrt) and the operand.  */
2017	      if (note
2018		  && GET_CODE (note) == EXPR_LIST
2019		  && GET_CODE (XEXP (note, 0)) == EXPR_LIST
2020		  && XEXP (XEXP (note, 0), 1) != NULL_RTX
2021		  && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
2022		{
2023		  rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
2024		  /* Check operand is a register with expected mode.  */
2025		  if (operand
2026		      && REG_P (operand)
2027		      && GET_MODE (operand) == mode)
2028		    {
2029		      /* Replace the REG_EQUAL note with a SQRT rtx.  */
2030		      rtx equiv = gen_rtx_SQRT (mode, operand);
2031		      set_unique_reg_note (last, REG_EQUAL, equiv);
2032		    }
2033		}
2034	      break;
2035	    }
2036	  last = PREV_INSN (last);
2037	}
2038    }
2039
2040  return target;
2041}
2042
2043/* Expand a call to the builtin binary math functions (pow and atan2).
2044   Return 0 if a normal call should be emitted rather than expanding the
2045   function in-line.  EXP is the expression that is a call to the builtin
2046   function; if convenient, the result should be placed in TARGET.
2047   SUBTARGET may be used as the target for computing one of EXP's
2048   operands.  */
2049
2050static rtx
2051expand_builtin_mathfn_2 (tree exp, rtx target, rtx subtarget)
2052{
2053  optab builtin_optab;
2054  rtx op0, op1, insns;
2055  int op1_type = REAL_TYPE;
2056  tree fndecl = get_callee_fndecl (exp);
2057  tree arglist = TREE_OPERAND (exp, 1);
2058  tree arg0, arg1, temp, narg;
2059  enum machine_mode mode;
2060  bool errno_set = true;
2061  bool stable = true;
2062
2063  if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXP)
2064      || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPF)
2065      || (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
2066    op1_type = INTEGER_TYPE;
2067
2068  if (!validate_arglist (arglist, REAL_TYPE, op1_type, VOID_TYPE))
2069    return 0;
2070
2071  arg0 = TREE_VALUE (arglist);
2072  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2073
2074  switch (DECL_FUNCTION_CODE (fndecl))
2075    {
2076    case BUILT_IN_POW:
2077    case BUILT_IN_POWF:
2078    case BUILT_IN_POWL:
2079      builtin_optab = pow_optab; break;
2080    case BUILT_IN_ATAN2:
2081    case BUILT_IN_ATAN2F:
2082    case BUILT_IN_ATAN2L:
2083      builtin_optab = atan2_optab; break;
2084    case BUILT_IN_LDEXP:
2085    case BUILT_IN_LDEXPF:
2086    case BUILT_IN_LDEXPL:
2087      builtin_optab = ldexp_optab; break;
2088    case BUILT_IN_FMOD:
2089    case BUILT_IN_FMODF:
2090    case BUILT_IN_FMODL:
2091      builtin_optab = fmod_optab; break;
2092    case BUILT_IN_DREM:
2093    case BUILT_IN_DREMF:
2094    case BUILT_IN_DREML:
2095      builtin_optab = drem_optab; break;
2096    default:
2097      gcc_unreachable ();
2098    }
2099
2100  /* Make a suitable register to place result in.  */
2101  mode = TYPE_MODE (TREE_TYPE (exp));
2102
2103  /* Before working hard, check whether the instruction is available.  */
2104  if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
2105    return 0;
2106
2107  target = gen_reg_rtx (mode);
2108
2109  if (! flag_errno_math || ! HONOR_NANS (mode))
2110    errno_set = false;
2111
2112  /* Always stabilize the argument list.  */
2113  narg = builtin_save_expr (arg1);
2114  if (narg != arg1)
2115    {
2116      arg1 = narg;
2117      temp = build_tree_list (NULL_TREE, narg);
2118      stable = false;
2119    }
2120  else
2121    temp = TREE_CHAIN (arglist);
2122
2123  narg = builtin_save_expr (arg0);
2124  if (narg != arg0)
2125    {
2126      arg0 = narg;
2127      arglist = tree_cons (NULL_TREE, narg, temp);
2128      stable = false;
2129    }
2130  else if (! stable)
2131    arglist = tree_cons (NULL_TREE, arg0, temp);
2132
2133  if (! stable)
2134    exp = build_function_call_expr (fndecl, arglist);
2135
2136  op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
2137  op1 = expand_expr (arg1, 0, VOIDmode, 0);
2138
2139  start_sequence ();
2140
2141  /* Compute into TARGET.
2142     Set TARGET to wherever the result comes back.  */
2143  target = expand_binop (mode, builtin_optab, op0, op1,
2144			 target, 0, OPTAB_DIRECT);
2145
2146  /* If we were unable to expand via the builtin, stop the sequence
2147     (without outputting the insns) and call to the library function
2148     with the stabilized argument list.  */
2149  if (target == 0)
2150    {
2151      end_sequence ();
2152      return expand_call (exp, target, target == const0_rtx);
2153    }
2154
2155  if (errno_set)
2156    expand_errno_check (exp, target);
2157
2158  /* Output the entire sequence.  */
2159  insns = get_insns ();
2160  end_sequence ();
2161  emit_insn (insns);
2162
2163  return target;
2164}
2165
2166/* Expand a call to the builtin sin and cos math functions.
2167   Return 0 if a normal call should be emitted rather than expanding the
2168   function in-line.  EXP is the expression that is a call to the builtin
2169   function; if convenient, the result should be placed in TARGET.
2170   SUBTARGET may be used as the target for computing one of EXP's
2171   operands.  */
2172
2173static rtx
2174expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
2175{
2176  optab builtin_optab;
2177  rtx op0, insns;
2178  tree fndecl = get_callee_fndecl (exp);
2179  tree arglist = TREE_OPERAND (exp, 1);
2180  enum machine_mode mode;
2181  bool errno_set = false;
2182  tree arg, narg;
2183
2184  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
2185    return 0;
2186
2187  arg = TREE_VALUE (arglist);
2188
2189  switch (DECL_FUNCTION_CODE (fndecl))
2190    {
2191    case BUILT_IN_SIN:
2192    case BUILT_IN_SINF:
2193    case BUILT_IN_SINL:
2194    case BUILT_IN_COS:
2195    case BUILT_IN_COSF:
2196    case BUILT_IN_COSL:
2197      builtin_optab = sincos_optab; break;
2198    default:
2199      gcc_unreachable ();
2200    }
2201
2202  /* Make a suitable register to place result in.  */
2203  mode = TYPE_MODE (TREE_TYPE (exp));
2204
2205  if (! flag_errno_math || ! HONOR_NANS (mode))
2206    errno_set = false;
2207
2208  /* Check if sincos insn is available, otherwise fallback
2209     to sin or cos insn.  */
2210  if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) {
2211    switch (DECL_FUNCTION_CODE (fndecl))
2212      {
2213      case BUILT_IN_SIN:
2214      case BUILT_IN_SINF:
2215      case BUILT_IN_SINL:
2216	builtin_optab = sin_optab; break;
2217      case BUILT_IN_COS:
2218      case BUILT_IN_COSF:
2219      case BUILT_IN_COSL:
2220	builtin_optab = cos_optab; break;
2221      default:
2222	gcc_unreachable ();
2223      }
2224  }
2225
2226  /* Before working hard, check whether the instruction is available.  */
2227  if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2228    {
2229      target = gen_reg_rtx (mode);
2230
2231      /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2232	 need to expand the argument again.  This way, we will not perform
2233	 side-effects more the once.  */
2234      narg = save_expr (arg);
2235      if (narg != arg)
2236	{
2237	  arg = narg;
2238	  arglist = build_tree_list (NULL_TREE, arg);
2239	  exp = build_function_call_expr (fndecl, arglist);
2240	}
2241
2242      op0 = expand_expr (arg, subtarget, VOIDmode, 0);
2243
2244      start_sequence ();
2245
2246      /* Compute into TARGET.
2247	 Set TARGET to wherever the result comes back.  */
2248      if (builtin_optab == sincos_optab)
2249	{
2250	  int result;
2251
2252	  switch (DECL_FUNCTION_CODE (fndecl))
2253	    {
2254	    case BUILT_IN_SIN:
2255	    case BUILT_IN_SINF:
2256	    case BUILT_IN_SINL:
2257	      result = expand_twoval_unop (builtin_optab, op0, 0, target, 0);
2258	      break;
2259	    case BUILT_IN_COS:
2260	    case BUILT_IN_COSF:
2261	    case BUILT_IN_COSL:
2262	      result = expand_twoval_unop (builtin_optab, op0, target, 0, 0);
2263	      break;
2264	    default:
2265	      gcc_unreachable ();
2266	    }
2267	  gcc_assert (result);
2268	}
2269      else
2270	{
2271	  target = expand_unop (mode, builtin_optab, op0, target, 0);
2272	}
2273
2274      if (target != 0)
2275	{
2276	  if (errno_set)
2277	    expand_errno_check (exp, target);
2278
2279	  /* Output the entire sequence.  */
2280	  insns = get_insns ();
2281	  end_sequence ();
2282	  emit_insn (insns);
2283	  return target;
2284	}
2285
2286      /* If we were unable to expand via the builtin, stop the sequence
2287	 (without outputting the insns) and call to the library function
2288	 with the stabilized argument list.  */
2289      end_sequence ();
2290    }
2291
2292  target = expand_call (exp, target, target == const0_rtx);
2293
2294  return target;
2295}
2296
2297/* Expand a call to one of the builtin rounding functions (lfloor).
2298   If expanding via optab fails, lower expression to (int)(floor(x)).
2299   EXP is the expression that is a call to the builtin function;
2300   if convenient, the result should be placed in TARGET.  SUBTARGET may
2301   be used as the target for computing one of EXP's operands.  */
2302
2303static rtx
2304expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget)
2305{
2306  optab builtin_optab;
2307  rtx op0, insns, tmp;
2308  tree fndecl = get_callee_fndecl (exp);
2309  tree arglist = TREE_OPERAND (exp, 1);
2310  enum built_in_function fallback_fn;
2311  tree fallback_fndecl;
2312  enum machine_mode mode;
2313  tree arg, narg;
2314
2315  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
2316    gcc_unreachable ();
2317
2318  arg = TREE_VALUE (arglist);
2319
2320  switch (DECL_FUNCTION_CODE (fndecl))
2321    {
2322    case BUILT_IN_LCEIL:
2323    case BUILT_IN_LCEILF:
2324    case BUILT_IN_LCEILL:
2325    case BUILT_IN_LLCEIL:
2326    case BUILT_IN_LLCEILF:
2327    case BUILT_IN_LLCEILL:
2328      builtin_optab = lceil_optab;
2329      fallback_fn = BUILT_IN_CEIL;
2330      break;
2331
2332    case BUILT_IN_LFLOOR:
2333    case BUILT_IN_LFLOORF:
2334    case BUILT_IN_LFLOORL:
2335    case BUILT_IN_LLFLOOR:
2336    case BUILT_IN_LLFLOORF:
2337    case BUILT_IN_LLFLOORL:
2338      builtin_optab = lfloor_optab;
2339      fallback_fn = BUILT_IN_FLOOR;
2340      break;
2341
2342    default:
2343      gcc_unreachable ();
2344    }
2345
2346  /* Make a suitable register to place result in.  */
2347  mode = TYPE_MODE (TREE_TYPE (exp));
2348
2349  /* Before working hard, check whether the instruction is available.  */
2350  if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
2351    {
2352      target = gen_reg_rtx (mode);
2353
2354      /* Wrap the computation of the argument in a SAVE_EXPR, as we may
2355	 need to expand the argument again.  This way, we will not perform
2356	 side-effects more the once.  */
2357      narg = builtin_save_expr (arg);
2358      if (narg != arg)
2359	{
2360	  arg = narg;
2361	  arglist = build_tree_list (NULL_TREE, arg);
2362	  exp = build_function_call_expr (fndecl, arglist);
2363	}
2364
2365      op0 = expand_expr (arg, subtarget, VOIDmode, 0);
2366
2367      start_sequence ();
2368
2369      /* Compute into TARGET.
2370	 Set TARGET to wherever the result comes back.  */
2371      target = expand_unop (mode, builtin_optab, op0, target, 0);
2372
2373      if (target != 0)
2374	{
2375	  /* Output the entire sequence.  */
2376	  insns = get_insns ();
2377	  end_sequence ();
2378	  emit_insn (insns);
2379	  return target;
2380	}
2381
2382      /* If we were unable to expand via the builtin, stop the sequence
2383	 (without outputting the insns).  */
2384      end_sequence ();
2385    }
2386
2387  /* Fall back to floating point rounding optab.  */
2388  fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn);
2389  /* We shouldn't get here on targets without TARGET_C99_FUNCTIONS.
2390     ??? Perhaps convert (int)floorf(x) into (int)floor((double)x).  */
2391  gcc_assert (fallback_fndecl != NULL_TREE);
2392  exp = build_function_call_expr (fallback_fndecl, arglist);
2393
2394  tmp = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL);
2395
2396  /* Truncate the result of floating point optab to integer
2397     via expand_fix ().  */
2398  target = gen_reg_rtx (mode);
2399  expand_fix (target, tmp, 0);
2400
2401  return target;
2402}
2403
2404/* To evaluate powi(x,n), the floating point value x raised to the
2405   constant integer exponent n, we use a hybrid algorithm that
2406   combines the "window method" with look-up tables.  For an
2407   introduction to exponentiation algorithms and "addition chains",
2408   see section 4.6.3, "Evaluation of Powers" of Donald E. Knuth,
2409   "Seminumerical Algorithms", Vol. 2, "The Art of Computer Programming",
2410   3rd Edition, 1998, and Daniel M. Gordon, "A Survey of Fast Exponentiation
2411   Methods", Journal of Algorithms, Vol. 27, pp. 129-146, 1998.  */
2412
2413/* Provide a default value for POWI_MAX_MULTS, the maximum number of
2414   multiplications to inline before calling the system library's pow
2415   function.  powi(x,n) requires at worst 2*bits(n)-2 multiplications,
2416   so this default never requires calling pow, powf or powl.  */
2417
2418#ifndef POWI_MAX_MULTS
2419#define POWI_MAX_MULTS  (2*HOST_BITS_PER_WIDE_INT-2)
2420#endif
2421
2422/* The size of the "optimal power tree" lookup table.  All
2423   exponents less than this value are simply looked up in the
2424   powi_table below.  This threshold is also used to size the
2425   cache of pseudo registers that hold intermediate results.  */
2426#define POWI_TABLE_SIZE 256
2427
2428/* The size, in bits of the window, used in the "window method"
2429   exponentiation algorithm.  This is equivalent to a radix of
2430   (1<<POWI_WINDOW_SIZE) in the corresponding "m-ary method".  */
2431#define POWI_WINDOW_SIZE 3
2432
2433/* The following table is an efficient representation of an
2434   "optimal power tree".  For each value, i, the corresponding
2435   value, j, in the table states than an optimal evaluation
2436   sequence for calculating pow(x,i) can be found by evaluating
2437   pow(x,j)*pow(x,i-j).  An optimal power tree for the first
2438   100 integers is given in Knuth's "Seminumerical algorithms".  */
2439
2440static const unsigned char powi_table[POWI_TABLE_SIZE] =
2441  {
2442      0,   1,   1,   2,   2,   3,   3,   4,  /*   0 -   7 */
2443      4,   6,   5,   6,   6,  10,   7,   9,  /*   8 -  15 */
2444      8,  16,   9,  16,  10,  12,  11,  13,  /*  16 -  23 */
2445     12,  17,  13,  18,  14,  24,  15,  26,  /*  24 -  31 */
2446     16,  17,  17,  19,  18,  33,  19,  26,  /*  32 -  39 */
2447     20,  25,  21,  40,  22,  27,  23,  44,  /*  40 -  47 */
2448     24,  32,  25,  34,  26,  29,  27,  44,  /*  48 -  55 */
2449     28,  31,  29,  34,  30,  60,  31,  36,  /*  56 -  63 */
2450     32,  64,  33,  34,  34,  46,  35,  37,  /*  64 -  71 */
2451     36,  65,  37,  50,  38,  48,  39,  69,  /*  72 -  79 */
2452     40,  49,  41,  43,  42,  51,  43,  58,  /*  80 -  87 */
2453     44,  64,  45,  47,  46,  59,  47,  76,  /*  88 -  95 */
2454     48,  65,  49,  66,  50,  67,  51,  66,  /*  96 - 103 */
2455     52,  70,  53,  74,  54, 104,  55,  74,  /* 104 - 111 */
2456     56,  64,  57,  69,  58,  78,  59,  68,  /* 112 - 119 */
2457     60,  61,  61,  80,  62,  75,  63,  68,  /* 120 - 127 */
2458     64,  65,  65, 128,  66, 129,  67,  90,  /* 128 - 135 */
2459     68,  73,  69, 131,  70,  94,  71,  88,  /* 136 - 143 */
2460     72, 128,  73,  98,  74, 132,  75, 121,  /* 144 - 151 */
2461     76, 102,  77, 124,  78, 132,  79, 106,  /* 152 - 159 */
2462     80,  97,  81, 160,  82,  99,  83, 134,  /* 160 - 167 */
2463     84,  86,  85,  95,  86, 160,  87, 100,  /* 168 - 175 */
2464     88, 113,  89,  98,  90, 107,  91, 122,  /* 176 - 183 */
2465     92, 111,  93, 102,  94, 126,  95, 150,  /* 184 - 191 */
2466     96, 128,  97, 130,  98, 133,  99, 195,  /* 192 - 199 */
2467    100, 128, 101, 123, 102, 164, 103, 138,  /* 200 - 207 */
2468    104, 145, 105, 146, 106, 109, 107, 149,  /* 208 - 215 */
2469    108, 200, 109, 146, 110, 170, 111, 157,  /* 216 - 223 */
2470    112, 128, 113, 130, 114, 182, 115, 132,  /* 224 - 231 */
2471    116, 200, 117, 132, 118, 158, 119, 206,  /* 232 - 239 */
2472    120, 240, 121, 162, 122, 147, 123, 152,  /* 240 - 247 */
2473    124, 166, 125, 214, 126, 138, 127, 153,  /* 248 - 255 */
2474  };
2475
2476
2477/* Return the number of multiplications required to calculate
2478   powi(x,n) where n is less than POWI_TABLE_SIZE.  This is a
2479   subroutine of powi_cost.  CACHE is an array indicating
2480   which exponents have already been calculated.  */
2481
2482static int
2483powi_lookup_cost (unsigned HOST_WIDE_INT n, bool *cache)
2484{
2485  /* If we've already calculated this exponent, then this evaluation
2486     doesn't require any additional multiplications.  */
2487  if (cache[n])
2488    return 0;
2489
2490  cache[n] = true;
2491  return powi_lookup_cost (n - powi_table[n], cache)
2492	 + powi_lookup_cost (powi_table[n], cache) + 1;
2493}
2494
2495/* Return the number of multiplications required to calculate
2496   powi(x,n) for an arbitrary x, given the exponent N.  This
2497   function needs to be kept in sync with expand_powi below.  */
2498
2499static int
2500powi_cost (HOST_WIDE_INT n)
2501{
2502  bool cache[POWI_TABLE_SIZE];
2503  unsigned HOST_WIDE_INT digit;
2504  unsigned HOST_WIDE_INT val;
2505  int result;
2506
2507  if (n == 0)
2508    return 0;
2509
2510  /* Ignore the reciprocal when calculating the cost.  */
2511  val = (n < 0) ? -n : n;
2512
2513  /* Initialize the exponent cache.  */
2514  memset (cache, 0, POWI_TABLE_SIZE * sizeof (bool));
2515  cache[1] = true;
2516
2517  result = 0;
2518
2519  while (val >= POWI_TABLE_SIZE)
2520    {
2521      if (val & 1)
2522	{
2523	  digit = val & ((1 << POWI_WINDOW_SIZE) - 1);
2524	  result += powi_lookup_cost (digit, cache)
2525		    + POWI_WINDOW_SIZE + 1;
2526	  val >>= POWI_WINDOW_SIZE;
2527	}
2528      else
2529	{
2530	  val >>= 1;
2531	  result++;
2532	}
2533    }
2534
2535  return result + powi_lookup_cost (val, cache);
2536}
2537
2538/* Recursive subroutine of expand_powi.  This function takes the array,
2539   CACHE, of already calculated exponents and an exponent N and returns
2540   an RTX that corresponds to CACHE[1]**N, as calculated in mode MODE.  */
2541
2542static rtx
2543expand_powi_1 (enum machine_mode mode, unsigned HOST_WIDE_INT n, rtx *cache)
2544{
2545  unsigned HOST_WIDE_INT digit;
2546  rtx target, result;
2547  rtx op0, op1;
2548
2549  if (n < POWI_TABLE_SIZE)
2550    {
2551      if (cache[n])
2552        return cache[n];
2553
2554      target = gen_reg_rtx (mode);
2555      cache[n] = target;
2556
2557      op0 = expand_powi_1 (mode, n - powi_table[n], cache);
2558      op1 = expand_powi_1 (mode, powi_table[n], cache);
2559    }
2560  else if (n & 1)
2561    {
2562      target = gen_reg_rtx (mode);
2563      digit = n & ((1 << POWI_WINDOW_SIZE) - 1);
2564      op0 = expand_powi_1 (mode, n - digit, cache);
2565      op1 = expand_powi_1 (mode, digit, cache);
2566    }
2567  else
2568    {
2569      target = gen_reg_rtx (mode);
2570      op0 = expand_powi_1 (mode, n >> 1, cache);
2571      op1 = op0;
2572    }
2573
2574  result = expand_mult (mode, op0, op1, target, 0);
2575  if (result != target)
2576    emit_move_insn (target, result);
2577  return target;
2578}
2579
2580/* Expand the RTL to evaluate powi(x,n) in mode MODE.  X is the
2581   floating point operand in mode MODE, and N is the exponent.  This
2582   function needs to be kept in sync with powi_cost above.  */
2583
2584static rtx
2585expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
2586{
2587  unsigned HOST_WIDE_INT val;
2588  rtx cache[POWI_TABLE_SIZE];
2589  rtx result;
2590
2591  if (n == 0)
2592    return CONST1_RTX (mode);
2593
2594  val = (n < 0) ? -n : n;
2595
2596  memset (cache, 0, sizeof (cache));
2597  cache[1] = x;
2598
2599  result = expand_powi_1 (mode, (n < 0) ? -n : n, cache);
2600
2601  /* If the original exponent was negative, reciprocate the result.  */
2602  if (n < 0)
2603    result = expand_binop (mode, sdiv_optab, CONST1_RTX (mode),
2604			   result, NULL_RTX, 0, OPTAB_LIB_WIDEN);
2605
2606  return result;
2607}
2608
2609/* Expand a call to the pow built-in mathematical function.  Return 0 if
2610   a normal call should be emitted rather than expanding the function
2611   in-line.  EXP is the expression that is a call to the builtin
2612   function; if convenient, the result should be placed in TARGET.  */
2613
2614static rtx
2615expand_builtin_pow (tree exp, rtx target, rtx subtarget)
2616{
2617  tree arglist = TREE_OPERAND (exp, 1);
2618  tree arg0, arg1;
2619
2620  if (! validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
2621    return 0;
2622
2623  arg0 = TREE_VALUE (arglist);
2624  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2625
2626  if (TREE_CODE (arg1) == REAL_CST
2627      && ! TREE_CONSTANT_OVERFLOW (arg1))
2628    {
2629      REAL_VALUE_TYPE cint;
2630      REAL_VALUE_TYPE c;
2631      HOST_WIDE_INT n;
2632
2633      c = TREE_REAL_CST (arg1);
2634      n = real_to_integer (&c);
2635      real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
2636      if (real_identical (&c, &cint))
2637	{
2638	  /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
2639	     Otherwise, check the number of multiplications required.
2640	     Note that pow never sets errno for an integer exponent.  */
2641	  if ((n >= -1 && n <= 2)
2642	      || (flag_unsafe_math_optimizations
2643		  && ! optimize_size
2644		  && powi_cost (n) <= POWI_MAX_MULTS))
2645	    {
2646	      enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
2647	      rtx op = expand_expr (arg0, subtarget, VOIDmode, 0);
2648	      op = force_reg (mode, op);
2649	      return expand_powi (op, mode, n);
2650	    }
2651	}
2652    }
2653
2654  if (! flag_unsafe_math_optimizations)
2655    return NULL_RTX;
2656  return expand_builtin_mathfn_2 (exp, target, subtarget);
2657}
2658
2659/* Expand a call to the powi built-in mathematical function.  Return 0 if
2660   a normal call should be emitted rather than expanding the function
2661   in-line.  EXP is the expression that is a call to the builtin
2662   function; if convenient, the result should be placed in TARGET.  */
2663
2664static rtx
2665expand_builtin_powi (tree exp, rtx target, rtx subtarget)
2666{
2667  tree arglist = TREE_OPERAND (exp, 1);
2668  tree arg0, arg1;
2669  rtx op0, op1;
2670  enum machine_mode mode;
2671  enum machine_mode mode2;
2672
2673  if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
2674    return 0;
2675
2676  arg0 = TREE_VALUE (arglist);
2677  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
2678  mode = TYPE_MODE (TREE_TYPE (exp));
2679
2680  /* Handle constant power.  */
2681
2682  if (TREE_CODE (arg1) == INTEGER_CST
2683      && ! TREE_CONSTANT_OVERFLOW (arg1))
2684    {
2685      HOST_WIDE_INT n = TREE_INT_CST_LOW (arg1);
2686
2687      /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
2688	 Otherwise, check the number of multiplications required.  */
2689      if ((TREE_INT_CST_HIGH (arg1) == 0
2690	   || TREE_INT_CST_HIGH (arg1) == -1)
2691	  && ((n >= -1 && n <= 2)
2692	      || (! optimize_size
2693		  && powi_cost (n) <= POWI_MAX_MULTS)))
2694	{
2695	  op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
2696	  op0 = force_reg (mode, op0);
2697	  return expand_powi (op0, mode, n);
2698	}
2699    }
2700
2701  /* Emit a libcall to libgcc.  */
2702
2703  /* Mode of the 2nd argument must match that of an int. */
2704  mode2 = mode_for_size (INT_TYPE_SIZE, MODE_INT, 0);
2705
2706  if (target == NULL_RTX)
2707    target = gen_reg_rtx (mode);
2708
2709  op0 = expand_expr (arg0, subtarget, mode, 0);
2710  if (GET_MODE (op0) != mode)
2711    op0 = convert_to_mode (mode, op0, 0);
2712  op1 = expand_expr (arg1, 0, mode2, 0);
2713  if (GET_MODE (op1) != mode2)
2714    op1 = convert_to_mode (mode2, op1, 0);
2715
2716  target = emit_library_call_value (powi_optab->handlers[(int) mode].libfunc,
2717				    target, LCT_CONST_MAKE_BLOCK, mode, 2,
2718				    op0, mode, op1, mode2);
2719
2720  return target;
2721}
2722
2723/* Expand expression EXP which is a call to the strlen builtin.  Return 0
2724   if we failed the caller should emit a normal call, otherwise
2725   try to get the result in TARGET, if convenient.  */
2726
2727static rtx
2728expand_builtin_strlen (tree arglist, rtx target,
2729		       enum machine_mode target_mode)
2730{
2731  if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
2732    return 0;
2733  else
2734    {
2735      rtx pat;
2736      tree len, src = TREE_VALUE (arglist);
2737      rtx result, src_reg, char_rtx, before_strlen;
2738      enum machine_mode insn_mode = target_mode, char_mode;
2739      enum insn_code icode = CODE_FOR_nothing;
2740      int align;
2741
2742      /* If the length can be computed at compile-time, return it.  */
2743      len = c_strlen (src, 0);
2744      if (len)
2745	return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2746
2747      /* If the length can be computed at compile-time and is constant
2748	 integer, but there are side-effects in src, evaluate
2749	 src for side-effects, then return len.
2750	 E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
2751	 can be optimized into: i++; x = 3;  */
2752      len = c_strlen (src, 1);
2753      if (len && TREE_CODE (len) == INTEGER_CST)
2754	{
2755	  expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2756	  return expand_expr (len, target, target_mode, EXPAND_NORMAL);
2757	}
2758
2759      align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2760
2761      /* If SRC is not a pointer type, don't do this operation inline.  */
2762      if (align == 0)
2763	return 0;
2764
2765      /* Bail out if we can't compute strlen in the right mode.  */
2766      while (insn_mode != VOIDmode)
2767	{
2768	  icode = strlen_optab->handlers[(int) insn_mode].insn_code;
2769	  if (icode != CODE_FOR_nothing)
2770	    break;
2771
2772	  insn_mode = GET_MODE_WIDER_MODE (insn_mode);
2773	}
2774      if (insn_mode == VOIDmode)
2775	return 0;
2776
2777      /* Make a place to write the result of the instruction.  */
2778      result = target;
2779      if (! (result != 0
2780	     && REG_P (result)
2781	     && GET_MODE (result) == insn_mode
2782	     && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2783	result = gen_reg_rtx (insn_mode);
2784
2785      /* Make a place to hold the source address.  We will not expand
2786	 the actual source until we are sure that the expansion will
2787	 not fail -- there are trees that cannot be expanded twice.  */
2788      src_reg = gen_reg_rtx (Pmode);
2789
2790      /* Mark the beginning of the strlen sequence so we can emit the
2791	 source operand later.  */
2792      before_strlen = get_last_insn ();
2793
2794      char_rtx = const0_rtx;
2795      char_mode = insn_data[(int) icode].operand[2].mode;
2796      if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
2797							    char_mode))
2798	char_rtx = copy_to_mode_reg (char_mode, char_rtx);
2799
2800      pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
2801			     char_rtx, GEN_INT (align));
2802      if (! pat)
2803	return 0;
2804      emit_insn (pat);
2805
2806      /* Now that we are assured of success, expand the source.  */
2807      start_sequence ();
2808      pat = expand_expr (src, src_reg, ptr_mode, EXPAND_NORMAL);
2809      if (pat != src_reg)
2810	emit_move_insn (src_reg, pat);
2811      pat = get_insns ();
2812      end_sequence ();
2813
2814      if (before_strlen)
2815	emit_insn_after (pat, before_strlen);
2816      else
2817	emit_insn_before (pat, get_insns ());
2818
2819      /* Return the value in the proper mode for this function.  */
2820      if (GET_MODE (result) == target_mode)
2821	target = result;
2822      else if (target != 0)
2823	convert_move (target, result, 0);
2824      else
2825	target = convert_to_mode (target_mode, result, 0);
2826
2827      return target;
2828    }
2829}
2830
2831/* Expand a call to the strstr builtin.  Return 0 if we failed the
2832   caller should emit a normal call, otherwise try to get the result
2833   in TARGET, if convenient (and in mode MODE if that's convenient).  */
2834
2835static rtx
2836expand_builtin_strstr (tree arglist, tree type, rtx target, enum machine_mode mode)
2837{
2838  if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2839    {
2840      tree result = fold_builtin_strstr (arglist, type);
2841      if (result)
2842	return expand_expr (result, target, mode, EXPAND_NORMAL);
2843    }
2844  return 0;
2845}
2846
2847/* Expand a call to the strchr builtin.  Return 0 if we failed the
2848   caller should emit a normal call, otherwise try to get the result
2849   in TARGET, if convenient (and in mode MODE if that's convenient).  */
2850
2851static rtx
2852expand_builtin_strchr (tree arglist, tree type, rtx target, enum machine_mode mode)
2853{
2854  if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2855    {
2856      tree result = fold_builtin_strchr (arglist, type);
2857      if (result)
2858	return expand_expr (result, target, mode, EXPAND_NORMAL);
2859
2860      /* FIXME: Should use strchrM optab so that ports can optimize this.  */
2861    }
2862  return 0;
2863}
2864
2865/* Expand a call to the strrchr builtin.  Return 0 if we failed the
2866   caller should emit a normal call, otherwise try to get the result
2867   in TARGET, if convenient (and in mode MODE if that's convenient).  */
2868
2869static rtx
2870expand_builtin_strrchr (tree arglist, tree type, rtx target, enum machine_mode mode)
2871{
2872  if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2873    {
2874      tree result = fold_builtin_strrchr (arglist, type);
2875      if (result)
2876	return expand_expr (result, target, mode, EXPAND_NORMAL);
2877    }
2878  return 0;
2879}
2880
2881/* Expand a call to the strpbrk builtin.  Return 0 if we failed the
2882   caller should emit a normal call, otherwise try to get the result
2883   in TARGET, if convenient (and in mode MODE if that's convenient).  */
2884
2885static rtx
2886expand_builtin_strpbrk (tree arglist, tree type, rtx target, enum machine_mode mode)
2887{
2888  if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2889    {
2890      tree result = fold_builtin_strpbrk (arglist, type);
2891      if (result)
2892	return expand_expr (result, target, mode, EXPAND_NORMAL);
2893    }
2894  return 0;
2895}
2896
2897/* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
2898   bytes from constant string DATA + OFFSET and return it as target
2899   constant.  */
2900
2901static rtx
2902builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
2903			 enum machine_mode mode)
2904{
2905  const char *str = (const char *) data;
2906
2907  gcc_assert (offset >= 0
2908	      && ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
2909		  <= strlen (str) + 1));
2910
2911  return c_readstr (str + offset, mode);
2912}
2913
2914/* Expand a call to the memcpy builtin, with arguments in ARGLIST.
2915   Return 0 if we failed, the caller should emit a normal call,
2916   otherwise try to get the result in TARGET, if convenient (and in
2917   mode MODE if that's convenient).  */
2918static rtx
2919expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
2920{
2921  tree fndecl = get_callee_fndecl (exp);
2922  tree arglist = TREE_OPERAND (exp, 1);
2923  if (!validate_arglist (arglist,
2924			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2925    return 0;
2926  else
2927    {
2928      tree dest = TREE_VALUE (arglist);
2929      tree src = TREE_VALUE (TREE_CHAIN (arglist));
2930      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2931      const char *src_str;
2932      unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2933      unsigned int dest_align
2934	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2935      rtx dest_mem, src_mem, dest_addr, len_rtx;
2936      tree result = fold_builtin_memcpy (fndecl, arglist);
2937
2938      if (result)
2939	return expand_expr (result, target, mode, EXPAND_NORMAL);
2940
2941      /* If DEST is not a pointer type, call the normal function.  */
2942      if (dest_align == 0)
2943	return 0;
2944
2945      /* If either SRC is not a pointer type, don't do this
2946         operation in-line.  */
2947      if (src_align == 0)
2948	return 0;
2949
2950      dest_mem = get_memory_rtx (dest, len);
2951      set_mem_align (dest_mem, dest_align);
2952      len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2953      src_str = c_getstr (src);
2954
2955      /* If SRC is a string constant and block move would be done
2956	 by pieces, we can avoid loading the string from memory
2957	 and only stored the computed constants.  */
2958      if (src_str
2959	  && GET_CODE (len_rtx) == CONST_INT
2960	  && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2961	  && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2962				  (void *) src_str, dest_align))
2963	{
2964	  dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
2965				      builtin_memcpy_read_str,
2966				      (void *) src_str, dest_align, 0);
2967	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2968	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
2969	  return dest_mem;
2970	}
2971
2972      src_mem = get_memory_rtx (src, len);
2973      set_mem_align (src_mem, src_align);
2974
2975      /* Copy word part most expediently.  */
2976      dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
2977				   CALL_EXPR_TAILCALL (exp)
2978				   ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
2979
2980      if (dest_addr == 0)
2981	{
2982	  dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2983	  dest_addr = convert_memory_address (ptr_mode, dest_addr);
2984	}
2985      return dest_addr;
2986    }
2987}
2988
2989/* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
2990   Return 0 if we failed; the caller should emit a normal call,
2991   otherwise try to get the result in TARGET, if convenient (and in
2992   mode MODE if that's convenient).  If ENDP is 0 return the
2993   destination pointer, if ENDP is 1 return the end pointer ala
2994   mempcpy, and if ENDP is 2 return the end pointer minus one ala
2995   stpcpy.  */
2996
2997static rtx
2998expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode,
2999			int endp)
3000{
3001  if (!validate_arglist (arglist,
3002			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3003    return 0;
3004  /* If return value is ignored, transform mempcpy into memcpy.  */
3005  else if (target == const0_rtx)
3006    {
3007      tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3008
3009      if (!fn)
3010	return 0;
3011
3012      return expand_expr (build_function_call_expr (fn, arglist),
3013			  target, mode, EXPAND_NORMAL);
3014    }
3015  else
3016    {
3017      tree dest = TREE_VALUE (arglist);
3018      tree src = TREE_VALUE (TREE_CHAIN (arglist));
3019      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3020      const char *src_str;
3021      unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3022      unsigned int dest_align
3023	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3024      rtx dest_mem, src_mem, len_rtx;
3025      tree result = fold_builtin_mempcpy (arglist, type, endp);
3026
3027      if (result)
3028	return expand_expr (result, target, mode, EXPAND_NORMAL);
3029
3030      /* If either SRC or DEST is not a pointer type, don't do this
3031         operation in-line.  */
3032      if (dest_align == 0 || src_align == 0)
3033	return 0;
3034
3035      /* If LEN is not constant, call the normal function.  */
3036      if (! host_integerp (len, 1))
3037	return 0;
3038
3039      len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3040      src_str = c_getstr (src);
3041
3042      /* If SRC is a string constant and block move would be done
3043	 by pieces, we can avoid loading the string from memory
3044	 and only stored the computed constants.  */
3045      if (src_str
3046	  && GET_CODE (len_rtx) == CONST_INT
3047	  && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
3048	  && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
3049				  (void *) src_str, dest_align))
3050	{
3051	  dest_mem = get_memory_rtx (dest, len);
3052	  set_mem_align (dest_mem, dest_align);
3053	  dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
3054				      builtin_memcpy_read_str,
3055				      (void *) src_str, dest_align, endp);
3056	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3057	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3058	  return dest_mem;
3059	}
3060
3061      if (GET_CODE (len_rtx) == CONST_INT
3062	  && can_move_by_pieces (INTVAL (len_rtx),
3063				 MIN (dest_align, src_align)))
3064	{
3065	  dest_mem = get_memory_rtx (dest, len);
3066	  set_mem_align (dest_mem, dest_align);
3067	  src_mem = get_memory_rtx (src, len);
3068	  set_mem_align (src_mem, src_align);
3069	  dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
3070				     MIN (dest_align, src_align), endp);
3071	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3072	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3073	  return dest_mem;
3074	}
3075
3076      return 0;
3077    }
3078}
3079
3080/* Expand expression EXP, which is a call to the memmove builtin.  Return 0
3081   if we failed; the caller should emit a normal call.  */
3082
3083static rtx
3084expand_builtin_memmove (tree arglist, tree type, rtx target,
3085			enum machine_mode mode, tree orig_exp)
3086{
3087  if (!validate_arglist (arglist,
3088			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3089    return 0;
3090  else
3091    {
3092      tree dest = TREE_VALUE (arglist);
3093      tree src = TREE_VALUE (TREE_CHAIN (arglist));
3094      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3095
3096      unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
3097      unsigned int dest_align
3098	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3099      tree result = fold_builtin_memmove (arglist, type);
3100
3101      if (result)
3102	return expand_expr (result, target, mode, EXPAND_NORMAL);
3103
3104      /* If DEST is not a pointer type, call the normal function.  */
3105      if (dest_align == 0)
3106	return 0;
3107
3108      /* If either SRC is not a pointer type, don't do this
3109         operation in-line.  */
3110      if (src_align == 0)
3111	return 0;
3112
3113      /* If src is categorized for a readonly section we can use
3114	 normal memcpy.  */
3115      if (readonly_data_expr (src))
3116        {
3117	  tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
3118	  if (!fn)
3119	    return 0;
3120	  fn = build_function_call_expr (fn, arglist);
3121	  if (TREE_CODE (fn) == CALL_EXPR)
3122	    CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
3123	  return expand_expr (fn, target, mode, EXPAND_NORMAL);
3124	}
3125
3126      /* If length is 1 and we can expand memcpy call inline,
3127	 it is ok to use memcpy as well.  */
3128      if (integer_onep (len))
3129        {
3130	  rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
3131					    /*endp=*/0);
3132	  if (ret)
3133	    return ret;
3134        }
3135
3136      /* Otherwise, call the normal function.  */
3137      return 0;
3138   }
3139}
3140
3141/* Expand expression EXP, which is a call to the bcopy builtin.  Return 0
3142   if we failed the caller should emit a normal call.  */
3143
3144static rtx
3145expand_builtin_bcopy (tree exp)
3146{
3147  tree arglist = TREE_OPERAND (exp, 1);
3148  tree type = TREE_TYPE (exp);
3149  tree src, dest, size, newarglist;
3150
3151  if (!validate_arglist (arglist,
3152			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3153    return NULL_RTX;
3154
3155  src = TREE_VALUE (arglist);
3156  dest = TREE_VALUE (TREE_CHAIN (arglist));
3157  size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3158
3159  /* New argument list transforming bcopy(ptr x, ptr y, int z) to
3160     memmove(ptr y, ptr x, size_t z).   This is done this way
3161     so that if it isn't expanded inline, we fallback to
3162     calling bcopy instead of memmove.  */
3163
3164  newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
3165  newarglist = tree_cons (NULL_TREE, src, newarglist);
3166  newarglist = tree_cons (NULL_TREE, dest, newarglist);
3167
3168  return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode, exp);
3169}
3170
3171#ifndef HAVE_movstr
3172# define HAVE_movstr 0
3173# define CODE_FOR_movstr CODE_FOR_nothing
3174#endif
3175
3176/* Expand into a movstr instruction, if one is available.  Return 0 if
3177   we failed, the caller should emit a normal call, otherwise try to
3178   get the result in TARGET, if convenient.  If ENDP is 0 return the
3179   destination pointer, if ENDP is 1 return the end pointer ala
3180   mempcpy, and if ENDP is 2 return the end pointer minus one ala
3181   stpcpy.  */
3182
3183static rtx
3184expand_movstr (tree dest, tree src, rtx target, int endp)
3185{
3186  rtx end;
3187  rtx dest_mem;
3188  rtx src_mem;
3189  rtx insn;
3190  const struct insn_data * data;
3191
3192  if (!HAVE_movstr)
3193    return 0;
3194
3195  dest_mem = get_memory_rtx (dest, NULL);
3196  src_mem = get_memory_rtx (src, NULL);
3197  if (!endp)
3198    {
3199      target = force_reg (Pmode, XEXP (dest_mem, 0));
3200      dest_mem = replace_equiv_address (dest_mem, target);
3201      end = gen_reg_rtx (Pmode);
3202    }
3203  else
3204    {
3205      if (target == 0 || target == const0_rtx)
3206	{
3207	  end = gen_reg_rtx (Pmode);
3208	  if (target == 0)
3209	    target = end;
3210	}
3211      else
3212	end = target;
3213    }
3214
3215  data = insn_data + CODE_FOR_movstr;
3216
3217  if (data->operand[0].mode != VOIDmode)
3218    end = gen_lowpart (data->operand[0].mode, end);
3219
3220  insn = data->genfun (end, dest_mem, src_mem);
3221
3222  gcc_assert (insn);
3223
3224  emit_insn (insn);
3225
3226  /* movstr is supposed to set end to the address of the NUL
3227     terminator.  If the caller requested a mempcpy-like return value,
3228     adjust it.  */
3229  if (endp == 1 && target != const0_rtx)
3230    {
3231      rtx tem = plus_constant (gen_lowpart (GET_MODE (target), end), 1);
3232      emit_move_insn (target, force_operand (tem, NULL_RTX));
3233    }
3234
3235  return target;
3236}
3237
3238/* Expand expression EXP, which is a call to the strcpy builtin.  Return 0
3239   if we failed the caller should emit a normal call, otherwise try to get
3240   the result in TARGET, if convenient (and in mode MODE if that's
3241   convenient).  */
3242
3243static rtx
3244expand_builtin_strcpy (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
3245{
3246  if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3247    {
3248      tree result = fold_builtin_strcpy (fndecl, arglist, 0);
3249      if (result)
3250	return expand_expr (result, target, mode, EXPAND_NORMAL);
3251
3252      return expand_movstr (TREE_VALUE (arglist),
3253			    TREE_VALUE (TREE_CHAIN (arglist)),
3254			    target, /*endp=*/0);
3255    }
3256  return 0;
3257}
3258
3259/* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
3260   Return 0 if we failed the caller should emit a normal call,
3261   otherwise try to get the result in TARGET, if convenient (and in
3262   mode MODE if that's convenient).  */
3263
3264static rtx
3265expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
3266{
3267  tree arglist = TREE_OPERAND (exp, 1);
3268  /* If return value is ignored, transform stpcpy into strcpy.  */
3269  if (target == const0_rtx)
3270    {
3271      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
3272      if (!fn)
3273	return 0;
3274
3275      return expand_expr (build_function_call_expr (fn, arglist),
3276			  target, mode, EXPAND_NORMAL);
3277    }
3278
3279  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3280    return 0;
3281  else
3282    {
3283      tree dst, src, len, lenp1;
3284      tree narglist;
3285      rtx ret;
3286
3287      /* Ensure we get an actual string whose length can be evaluated at
3288         compile-time, not an expression containing a string.  This is
3289         because the latter will potentially produce pessimized code
3290         when used to produce the return value.  */
3291      src = TREE_VALUE (TREE_CHAIN (arglist));
3292      if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
3293	return expand_movstr (TREE_VALUE (arglist),
3294			      TREE_VALUE (TREE_CHAIN (arglist)),
3295			      target, /*endp=*/2);
3296
3297      dst = TREE_VALUE (arglist);
3298      lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
3299      narglist = build_tree_list (NULL_TREE, lenp1);
3300      narglist = tree_cons (NULL_TREE, src, narglist);
3301      narglist = tree_cons (NULL_TREE, dst, narglist);
3302      ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp),
3303				    target, mode, /*endp=*/2);
3304
3305      if (ret)
3306	return ret;
3307
3308      if (TREE_CODE (len) == INTEGER_CST)
3309	{
3310	  rtx len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3311
3312	  if (GET_CODE (len_rtx) == CONST_INT)
3313	    {
3314	      ret = expand_builtin_strcpy (get_callee_fndecl (exp),
3315					   arglist, target, mode);
3316
3317	      if (ret)
3318		{
3319		  if (! target)
3320		    {
3321		      if (mode != VOIDmode)
3322			target = gen_reg_rtx (mode);
3323		      else
3324			target = gen_reg_rtx (GET_MODE (ret));
3325		    }
3326		  if (GET_MODE (target) != GET_MODE (ret))
3327		    ret = gen_lowpart (GET_MODE (target), ret);
3328
3329		  ret = plus_constant (ret, INTVAL (len_rtx));
3330		  ret = emit_move_insn (target, force_operand (ret, NULL_RTX));
3331		  gcc_assert (ret);
3332
3333		  return target;
3334		}
3335	    }
3336	}
3337
3338      return expand_movstr (TREE_VALUE (arglist),
3339			    TREE_VALUE (TREE_CHAIN (arglist)),
3340			    target, /*endp=*/2);
3341    }
3342}
3343
3344/* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
3345   bytes from constant string DATA + OFFSET and return it as target
3346   constant.  */
3347
3348static rtx
3349builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
3350			  enum machine_mode mode)
3351{
3352  const char *str = (const char *) data;
3353
3354  if ((unsigned HOST_WIDE_INT) offset > strlen (str))
3355    return const0_rtx;
3356
3357  return c_readstr (str + offset, mode);
3358}
3359
3360/* Expand expression EXP, which is a call to the strncpy builtin.  Return 0
3361   if we failed the caller should emit a normal call.  */
3362
3363static rtx
3364expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
3365{
3366  tree fndecl = get_callee_fndecl (exp);
3367  tree arglist = TREE_OPERAND (exp, 1);
3368  if (validate_arglist (arglist,
3369			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3370    {
3371      tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
3372      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3373      tree result = fold_builtin_strncpy (fndecl, arglist, slen);
3374
3375      if (result)
3376	return expand_expr (result, target, mode, EXPAND_NORMAL);
3377
3378      /* We must be passed a constant len and src parameter.  */
3379      if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
3380	return 0;
3381
3382      slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
3383
3384      /* We're required to pad with trailing zeros if the requested
3385         len is greater than strlen(s2)+1.  In that case try to
3386	 use store_by_pieces, if it fails, punt.  */
3387      if (tree_int_cst_lt (slen, len))
3388	{
3389	  tree dest = TREE_VALUE (arglist);
3390	  unsigned int dest_align
3391	    = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3392	  const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
3393	  rtx dest_mem;
3394
3395	  if (!p || dest_align == 0 || !host_integerp (len, 1)
3396	      || !can_store_by_pieces (tree_low_cst (len, 1),
3397				       builtin_strncpy_read_str,
3398				       (void *) p, dest_align))
3399	    return 0;
3400
3401	  dest_mem = get_memory_rtx (dest, len);
3402	  store_by_pieces (dest_mem, tree_low_cst (len, 1),
3403			   builtin_strncpy_read_str,
3404			   (void *) p, dest_align, 0);
3405	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3406	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3407	  return dest_mem;
3408	}
3409    }
3410  return 0;
3411}
3412
3413/* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
3414   bytes from constant string DATA + OFFSET and return it as target
3415   constant.  */
3416
3417static rtx
3418builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3419			 enum machine_mode mode)
3420{
3421  const char *c = (const char *) data;
3422  char *p = alloca (GET_MODE_SIZE (mode));
3423
3424  memset (p, *c, GET_MODE_SIZE (mode));
3425
3426  return c_readstr (p, mode);
3427}
3428
3429/* Callback routine for store_by_pieces.  Return the RTL of a register
3430   containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
3431   char value given in the RTL register data.  For example, if mode is
3432   4 bytes wide, return the RTL for 0x01010101*data.  */
3433
3434static rtx
3435builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
3436			enum machine_mode mode)
3437{
3438  rtx target, coeff;
3439  size_t size;
3440  char *p;
3441
3442  size = GET_MODE_SIZE (mode);
3443  if (size == 1)
3444    return (rtx) data;
3445
3446  p = alloca (size);
3447  memset (p, 1, size);
3448  coeff = c_readstr (p, mode);
3449
3450  target = convert_to_mode (mode, (rtx) data, 1);
3451  target = expand_mult (mode, target, coeff, NULL_RTX, 1);
3452  return force_reg (mode, target);
3453}
3454
3455/* Expand expression EXP, which is a call to the memset builtin.  Return 0
3456   if we failed the caller should emit a normal call, otherwise try to get
3457   the result in TARGET, if convenient (and in mode MODE if that's
3458   convenient).  */
3459
3460static rtx
3461expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
3462		       tree orig_exp)
3463{
3464  if (!validate_arglist (arglist,
3465			 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
3466    return 0;
3467  else
3468    {
3469      tree dest = TREE_VALUE (arglist);
3470      tree val = TREE_VALUE (TREE_CHAIN (arglist));
3471      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3472      tree fndecl, fn;
3473      enum built_in_function fcode;
3474      char c;
3475      unsigned int dest_align;
3476      rtx dest_mem, dest_addr, len_rtx;
3477
3478      dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
3479
3480      /* If DEST is not a pointer type, don't do this
3481	 operation in-line.  */
3482      if (dest_align == 0)
3483	return 0;
3484
3485      /* If the LEN parameter is zero, return DEST.  */
3486      if (integer_zerop (len))
3487	{
3488	  /* Evaluate and ignore VAL in case it has side-effects.  */
3489	  expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
3490	  return expand_expr (dest, target, mode, EXPAND_NORMAL);
3491	}
3492
3493      /* Stabilize the arguments in case we fail.  */
3494      dest = builtin_save_expr (dest);
3495      val = builtin_save_expr (val);
3496      len = builtin_save_expr (len);
3497
3498      len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3499      dest_mem = get_memory_rtx (dest, len);
3500
3501      if (TREE_CODE (val) != INTEGER_CST)
3502	{
3503	  rtx val_rtx;
3504
3505	  val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
3506	  val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
3507				     val_rtx, 0);
3508
3509	  /* Assume that we can memset by pieces if we can store the
3510	   * the coefficients by pieces (in the required modes).
3511	   * We can't pass builtin_memset_gen_str as that emits RTL.  */
3512	  c = 1;
3513	  if (host_integerp (len, 1)
3514	      && !(optimize_size && tree_low_cst (len, 1) > 1)
3515	      && can_store_by_pieces (tree_low_cst (len, 1),
3516				      builtin_memset_read_str, &c, dest_align))
3517	    {
3518	      val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
3519				   val_rtx);
3520	      store_by_pieces (dest_mem, tree_low_cst (len, 1),
3521			       builtin_memset_gen_str, val_rtx, dest_align, 0);
3522	    }
3523	  else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
3524					    dest_align))
3525	    goto do_libcall;
3526
3527	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3528	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3529	  return dest_mem;
3530	}
3531
3532      if (target_char_cast (val, &c))
3533	goto do_libcall;
3534
3535      if (c)
3536	{
3537	  if (host_integerp (len, 1)
3538	      && !(optimize_size && tree_low_cst (len, 1) > 1)
3539	      && can_store_by_pieces (tree_low_cst (len, 1),
3540				      builtin_memset_read_str, &c, dest_align))
3541	    store_by_pieces (dest_mem, tree_low_cst (len, 1),
3542			     builtin_memset_read_str, &c, dest_align, 0);
3543	  else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
3544					    dest_align))
3545	    goto do_libcall;
3546
3547	  dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3548	  dest_mem = convert_memory_address (ptr_mode, dest_mem);
3549	  return dest_mem;
3550	}
3551
3552      set_mem_align (dest_mem, dest_align);
3553      dest_addr = clear_storage (dest_mem, len_rtx,
3554				 CALL_EXPR_TAILCALL (orig_exp)
3555				 ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
3556
3557      if (dest_addr == 0)
3558	{
3559	  dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
3560	  dest_addr = convert_memory_address (ptr_mode, dest_addr);
3561	}
3562
3563      return dest_addr;
3564
3565    do_libcall:
3566      fndecl = get_callee_fndecl (orig_exp);
3567      fcode = DECL_FUNCTION_CODE (fndecl);
3568      gcc_assert (fcode == BUILT_IN_MEMSET || fcode == BUILT_IN_BZERO);
3569      arglist = build_tree_list (NULL_TREE, len);
3570      if (fcode == BUILT_IN_MEMSET)
3571	arglist = tree_cons (NULL_TREE, val, arglist);
3572      arglist = tree_cons (NULL_TREE, dest, arglist);
3573      fn = build_function_call_expr (fndecl, arglist);
3574      if (TREE_CODE (fn) == CALL_EXPR)
3575	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
3576      return expand_call (fn, target, target == const0_rtx);
3577    }
3578}
3579
3580/* Expand expression EXP, which is a call to the bzero builtin.  Return 0
3581   if we failed the caller should emit a normal call.  */
3582
3583static rtx
3584expand_builtin_bzero (tree exp)
3585{
3586  tree arglist = TREE_OPERAND (exp, 1);
3587  tree dest, size, newarglist;
3588
3589  if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3590    return NULL_RTX;
3591
3592  dest = TREE_VALUE (arglist);
3593  size = TREE_VALUE (TREE_CHAIN (arglist));
3594
3595  /* New argument list transforming bzero(ptr x, int y) to
3596     memset(ptr x, int 0, size_t y).   This is done this way
3597     so that if it isn't expanded inline, we fallback to
3598     calling bzero instead of memset.  */
3599
3600  newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
3601  newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
3602  newarglist = tree_cons (NULL_TREE, dest, newarglist);
3603
3604  return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp);
3605}
3606
3607/* Expand expression EXP, which is a call to the memcmp built-in function.
3608   ARGLIST is the argument list for this call.  Return 0 if we failed and the
3609   caller should emit a normal call, otherwise try to get the result in
3610   TARGET, if convenient (and in mode MODE, if that's convenient).  */
3611
3612static rtx
3613expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
3614		       enum machine_mode mode)
3615{
3616  if (!validate_arglist (arglist,
3617			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3618    return 0;
3619  else
3620    {
3621      tree result = fold_builtin_memcmp (arglist);
3622      if (result)
3623	return expand_expr (result, target, mode, EXPAND_NORMAL);
3624    }
3625
3626#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
3627  {
3628    tree arg1 = TREE_VALUE (arglist);
3629    tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3630    tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3631    rtx arg1_rtx, arg2_rtx, arg3_rtx;
3632    rtx result;
3633    rtx insn;
3634
3635    int arg1_align
3636      = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3637    int arg2_align
3638      = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3639    enum machine_mode insn_mode;
3640
3641#ifdef HAVE_cmpmemsi
3642    if (HAVE_cmpmemsi)
3643      insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode;
3644    else
3645#endif
3646#ifdef HAVE_cmpstrnsi
3647    if (HAVE_cmpstrnsi)
3648      insn_mode = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3649    else
3650#endif
3651      return 0;
3652
3653    /* If we don't have POINTER_TYPE, call the function.  */
3654    if (arg1_align == 0 || arg2_align == 0)
3655      return 0;
3656
3657    /* Make a place to write the result of the instruction.  */
3658    result = target;
3659    if (! (result != 0
3660	   && REG_P (result) && GET_MODE (result) == insn_mode
3661	   && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3662      result = gen_reg_rtx (insn_mode);
3663
3664    arg1_rtx = get_memory_rtx (arg1, len);
3665    arg2_rtx = get_memory_rtx (arg2, len);
3666    arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3667
3668    /* Set MEM_SIZE as appropriate.  */
3669    if (GET_CODE (arg3_rtx) == CONST_INT)
3670      {
3671	set_mem_size (arg1_rtx, arg3_rtx);
3672	set_mem_size (arg2_rtx, arg3_rtx);
3673      }
3674
3675#ifdef HAVE_cmpmemsi
3676    if (HAVE_cmpmemsi)
3677      insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3678			   GEN_INT (MIN (arg1_align, arg2_align)));
3679    else
3680#endif
3681#ifdef HAVE_cmpstrnsi
3682    if (HAVE_cmpstrnsi)
3683      insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3684			    GEN_INT (MIN (arg1_align, arg2_align)));
3685    else
3686#endif
3687      gcc_unreachable ();
3688
3689    if (insn)
3690      emit_insn (insn);
3691    else
3692      emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
3693			       TYPE_MODE (integer_type_node), 3,
3694			       XEXP (arg1_rtx, 0), Pmode,
3695			       XEXP (arg2_rtx, 0), Pmode,
3696			       convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
3697						TYPE_UNSIGNED (sizetype)),
3698			       TYPE_MODE (sizetype));
3699
3700    /* Return the value in the proper mode for this function.  */
3701    mode = TYPE_MODE (TREE_TYPE (exp));
3702    if (GET_MODE (result) == mode)
3703      return result;
3704    else if (target != 0)
3705      {
3706	convert_move (target, result, 0);
3707	return target;
3708      }
3709    else
3710      return convert_to_mode (mode, result, 0);
3711  }
3712#endif
3713
3714  return 0;
3715}
3716
3717/* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
3718   if we failed the caller should emit a normal call, otherwise try to get
3719   the result in TARGET, if convenient.  */
3720
3721static rtx
3722expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
3723{
3724  tree arglist = TREE_OPERAND (exp, 1);
3725
3726  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3727    return 0;
3728  else
3729    {
3730      tree result = fold_builtin_strcmp (arglist);
3731      if (result)
3732	return expand_expr (result, target, mode, EXPAND_NORMAL);
3733    }
3734
3735#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
3736  if (cmpstr_optab[SImode] != CODE_FOR_nothing
3737      || cmpstrn_optab[SImode] != CODE_FOR_nothing)
3738    {
3739      rtx arg1_rtx, arg2_rtx;
3740      rtx result, insn = NULL_RTX;
3741      tree fndecl, fn;
3742
3743      tree arg1 = TREE_VALUE (arglist);
3744      tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3745      int arg1_align
3746	= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3747      int arg2_align
3748	= get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3749
3750      /* If we don't have POINTER_TYPE, call the function.  */
3751      if (arg1_align == 0 || arg2_align == 0)
3752	return 0;
3753
3754      /* Stabilize the arguments in case gen_cmpstr(n)si fail.  */
3755      arg1 = builtin_save_expr (arg1);
3756      arg2 = builtin_save_expr (arg2);
3757
3758      arg1_rtx = get_memory_rtx (arg1, NULL);
3759      arg2_rtx = get_memory_rtx (arg2, NULL);
3760
3761#ifdef HAVE_cmpstrsi
3762      /* Try to call cmpstrsi.  */
3763      if (HAVE_cmpstrsi)
3764	{
3765	  enum machine_mode insn_mode
3766	    = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3767
3768	  /* Make a place to write the result of the instruction.  */
3769	  result = target;
3770	  if (! (result != 0
3771		 && REG_P (result) && GET_MODE (result) == insn_mode
3772		 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3773	    result = gen_reg_rtx (insn_mode);
3774
3775	  insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
3776			       GEN_INT (MIN (arg1_align, arg2_align)));
3777	}
3778#endif
3779#if HAVE_cmpstrnsi
3780      /* Try to determine at least one length and call cmpstrnsi.  */
3781      if (!insn && HAVE_cmpstrnsi)
3782	{
3783	  tree len;
3784	  rtx arg3_rtx;
3785
3786	  enum machine_mode insn_mode
3787	    = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3788	  tree len1 = c_strlen (arg1, 1);
3789	  tree len2 = c_strlen (arg2, 1);
3790
3791	  if (len1)
3792	    len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3793	  if (len2)
3794	    len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3795
3796	  /* If we don't have a constant length for the first, use the length
3797	     of the second, if we know it.  We don't require a constant for
3798	     this case; some cost analysis could be done if both are available
3799	     but neither is constant.  For now, assume they're equally cheap,
3800	     unless one has side effects.  If both strings have constant lengths,
3801	     use the smaller.  */
3802
3803	  if (!len1)
3804	    len = len2;
3805	  else if (!len2)
3806	    len = len1;
3807	  else if (TREE_SIDE_EFFECTS (len1))
3808	    len = len2;
3809	  else if (TREE_SIDE_EFFECTS (len2))
3810	    len = len1;
3811	  else if (TREE_CODE (len1) != INTEGER_CST)
3812	    len = len2;
3813	  else if (TREE_CODE (len2) != INTEGER_CST)
3814	    len = len1;
3815	  else if (tree_int_cst_lt (len1, len2))
3816	    len = len1;
3817	  else
3818	    len = len2;
3819
3820	  /* If both arguments have side effects, we cannot optimize.  */
3821	  if (!len || TREE_SIDE_EFFECTS (len))
3822	    goto do_libcall;
3823
3824	  arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3825
3826	  /* Make a place to write the result of the instruction.  */
3827	  result = target;
3828	  if (! (result != 0
3829		 && REG_P (result) && GET_MODE (result) == insn_mode
3830		 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3831	    result = gen_reg_rtx (insn_mode);
3832
3833	  insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3834				GEN_INT (MIN (arg1_align, arg2_align)));
3835	}
3836#endif
3837
3838      if (insn)
3839	{
3840	  emit_insn (insn);
3841
3842	  /* Return the value in the proper mode for this function.  */
3843	  mode = TYPE_MODE (TREE_TYPE (exp));
3844	  if (GET_MODE (result) == mode)
3845	    return result;
3846	  if (target == 0)
3847	    return convert_to_mode (mode, result, 0);
3848	  convert_move (target, result, 0);
3849	  return target;
3850	}
3851
3852      /* Expand the library call ourselves using a stabilized argument
3853	 list to avoid re-evaluating the function's arguments twice.  */
3854#if HAVE_cmpstrnsi
3855    do_libcall:
3856#endif
3857      arglist = build_tree_list (NULL_TREE, arg2);
3858      arglist = tree_cons (NULL_TREE, arg1, arglist);
3859      fndecl = get_callee_fndecl (exp);
3860      fn = build_function_call_expr (fndecl, arglist);
3861      if (TREE_CODE (fn) == CALL_EXPR)
3862	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
3863      return expand_call (fn, target, target == const0_rtx);
3864    }
3865#endif
3866  return 0;
3867}
3868
3869/* Expand expression EXP, which is a call to the strncmp builtin.  Return 0
3870   if we failed the caller should emit a normal call, otherwise try to get
3871   the result in TARGET, if convenient.  */
3872
3873static rtx
3874expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
3875{
3876  tree arglist = TREE_OPERAND (exp, 1);
3877
3878  if (!validate_arglist (arglist,
3879			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3880    return 0;
3881  else
3882    {
3883      tree result = fold_builtin_strncmp (arglist);
3884      if (result)
3885	return expand_expr (result, target, mode, EXPAND_NORMAL);
3886    }
3887
3888  /* If c_strlen can determine an expression for one of the string
3889     lengths, and it doesn't have side effects, then emit cmpstrnsi
3890     using length MIN(strlen(string)+1, arg3).  */
3891#ifdef HAVE_cmpstrnsi
3892  if (HAVE_cmpstrnsi)
3893  {
3894    tree arg1 = TREE_VALUE (arglist);
3895    tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3896    tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3897    tree len, len1, len2;
3898    rtx arg1_rtx, arg2_rtx, arg3_rtx;
3899    rtx result, insn;
3900    tree fndecl, fn;
3901
3902    int arg1_align
3903      = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3904    int arg2_align
3905      = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3906    enum machine_mode insn_mode
3907      = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
3908
3909    len1 = c_strlen (arg1, 1);
3910    len2 = c_strlen (arg2, 1);
3911
3912    if (len1)
3913      len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3914    if (len2)
3915      len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3916
3917    /* If we don't have a constant length for the first, use the length
3918       of the second, if we know it.  We don't require a constant for
3919       this case; some cost analysis could be done if both are available
3920       but neither is constant.  For now, assume they're equally cheap,
3921       unless one has side effects.  If both strings have constant lengths,
3922       use the smaller.  */
3923
3924    if (!len1)
3925      len = len2;
3926    else if (!len2)
3927      len = len1;
3928    else if (TREE_SIDE_EFFECTS (len1))
3929      len = len2;
3930    else if (TREE_SIDE_EFFECTS (len2))
3931      len = len1;
3932    else if (TREE_CODE (len1) != INTEGER_CST)
3933      len = len2;
3934    else if (TREE_CODE (len2) != INTEGER_CST)
3935      len = len1;
3936    else if (tree_int_cst_lt (len1, len2))
3937      len = len1;
3938    else
3939      len = len2;
3940
3941    /* If both arguments have side effects, we cannot optimize.  */
3942    if (!len || TREE_SIDE_EFFECTS (len))
3943      return 0;
3944
3945    /* The actual new length parameter is MIN(len,arg3).  */
3946    len = fold_build2 (MIN_EXPR, TREE_TYPE (len), len,
3947		       fold_convert (TREE_TYPE (len), arg3));
3948
3949    /* If we don't have POINTER_TYPE, call the function.  */
3950    if (arg1_align == 0 || arg2_align == 0)
3951      return 0;
3952
3953    /* Make a place to write the result of the instruction.  */
3954    result = target;
3955    if (! (result != 0
3956	   && REG_P (result) && GET_MODE (result) == insn_mode
3957	   && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3958      result = gen_reg_rtx (insn_mode);
3959
3960    /* Stabilize the arguments in case gen_cmpstrnsi fails.  */
3961    arg1 = builtin_save_expr (arg1);
3962    arg2 = builtin_save_expr (arg2);
3963    len = builtin_save_expr (len);
3964
3965    arg1_rtx = get_memory_rtx (arg1, len);
3966    arg2_rtx = get_memory_rtx (arg2, len);
3967    arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3968    insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3969			  GEN_INT (MIN (arg1_align, arg2_align)));
3970    if (insn)
3971      {
3972	emit_insn (insn);
3973
3974	/* Return the value in the proper mode for this function.  */
3975	mode = TYPE_MODE (TREE_TYPE (exp));
3976	if (GET_MODE (result) == mode)
3977	  return result;
3978	if (target == 0)
3979	  return convert_to_mode (mode, result, 0);
3980	convert_move (target, result, 0);
3981	return target;
3982      }
3983
3984    /* Expand the library call ourselves using a stabilized argument
3985       list to avoid re-evaluating the function's arguments twice.  */
3986    arglist = build_tree_list (NULL_TREE, len);
3987    arglist = tree_cons (NULL_TREE, arg2, arglist);
3988    arglist = tree_cons (NULL_TREE, arg1, arglist);
3989    fndecl = get_callee_fndecl (exp);
3990    fn = build_function_call_expr (fndecl, arglist);
3991    if (TREE_CODE (fn) == CALL_EXPR)
3992      CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
3993    return expand_call (fn, target, target == const0_rtx);
3994  }
3995#endif
3996  return 0;
3997}
3998
3999/* Expand expression EXP, which is a call to the strcat builtin.
4000   Return 0 if we failed the caller should emit a normal call,
4001   otherwise try to get the result in TARGET, if convenient.  */
4002
4003static rtx
4004expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
4005{
4006  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4007    return 0;
4008  else
4009    {
4010      tree dst = TREE_VALUE (arglist),
4011      src = TREE_VALUE (TREE_CHAIN (arglist));
4012      const char *p = c_getstr (src);
4013
4014      /* If the string length is zero, return the dst parameter.  */
4015      if (p && *p == '\0')
4016	return expand_expr (dst, target, mode, EXPAND_NORMAL);
4017
4018      if (!optimize_size)
4019	{
4020	  /* See if we can store by pieces into (dst + strlen(dst)).  */
4021	  tree newsrc, newdst,
4022	    strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
4023	  rtx insns;
4024
4025	  /* Stabilize the argument list.  */
4026	  newsrc = builtin_save_expr (src);
4027	  if (newsrc != src)
4028	    arglist = build_tree_list (NULL_TREE, newsrc);
4029	  else
4030	    arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe.  */
4031
4032	  dst = builtin_save_expr (dst);
4033
4034	  start_sequence ();
4035
4036	  /* Create strlen (dst).  */
4037	  newdst =
4038	    build_function_call_expr (strlen_fn,
4039				      build_tree_list (NULL_TREE, dst));
4040	  /* Create (dst + (cast) strlen (dst)).  */
4041	  newdst = fold_convert (TREE_TYPE (dst), newdst);
4042	  newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
4043
4044	  newdst = builtin_save_expr (newdst);
4045	  arglist = tree_cons (NULL_TREE, newdst, arglist);
4046
4047	  if (!expand_builtin_strcpy (fndecl, arglist, target, mode))
4048	    {
4049	      end_sequence (); /* Stop sequence.  */
4050	      return 0;
4051	    }
4052
4053	  /* Output the entire sequence.  */
4054	  insns = get_insns ();
4055	  end_sequence ();
4056	  emit_insn (insns);
4057
4058	  return expand_expr (dst, target, mode, EXPAND_NORMAL);
4059	}
4060
4061      return 0;
4062    }
4063}
4064
4065/* Expand expression EXP, which is a call to the strncat builtin.
4066   Return 0 if we failed the caller should emit a normal call,
4067   otherwise try to get the result in TARGET, if convenient.  */
4068
4069static rtx
4070expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
4071{
4072  if (validate_arglist (arglist,
4073			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4074    {
4075      tree result = fold_builtin_strncat (arglist);
4076      if (result)
4077	return expand_expr (result, target, mode, EXPAND_NORMAL);
4078    }
4079  return 0;
4080}
4081
4082/* Expand expression EXP, which is a call to the strspn builtin.
4083   Return 0 if we failed the caller should emit a normal call,
4084   otherwise try to get the result in TARGET, if convenient.  */
4085
4086static rtx
4087expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
4088{
4089  if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4090    {
4091      tree result = fold_builtin_strspn (arglist);
4092      if (result)
4093	return expand_expr (result, target, mode, EXPAND_NORMAL);
4094    }
4095  return 0;
4096}
4097
4098/* Expand expression EXP, which is a call to the strcspn builtin.
4099   Return 0 if we failed the caller should emit a normal call,
4100   otherwise try to get the result in TARGET, if convenient.  */
4101
4102static rtx
4103expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
4104{
4105  if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4106    {
4107      tree result = fold_builtin_strcspn (arglist);
4108      if (result)
4109	return expand_expr (result, target, mode, EXPAND_NORMAL);
4110    }
4111  return 0;
4112}
4113
4114/* Expand a call to __builtin_saveregs, generating the result in TARGET,
4115   if that's convenient.  */
4116
4117rtx
4118expand_builtin_saveregs (void)
4119{
4120  rtx val, seq;
4121
4122  /* Don't do __builtin_saveregs more than once in a function.
4123     Save the result of the first call and reuse it.  */
4124  if (saveregs_value != 0)
4125    return saveregs_value;
4126
4127  /* When this function is called, it means that registers must be
4128     saved on entry to this function.  So we migrate the call to the
4129     first insn of this function.  */
4130
4131  start_sequence ();
4132
4133  /* Do whatever the machine needs done in this case.  */
4134  val = targetm.calls.expand_builtin_saveregs ();
4135
4136  seq = get_insns ();
4137  end_sequence ();
4138
4139  saveregs_value = val;
4140
4141  /* Put the insns after the NOTE that starts the function.  If this
4142     is inside a start_sequence, make the outer-level insn chain current, so
4143     the code is placed at the start of the function.  */
4144  push_topmost_sequence ();
4145  emit_insn_after (seq, entry_of_function ());
4146  pop_topmost_sequence ();
4147
4148  return val;
4149}
4150
4151/* __builtin_args_info (N) returns word N of the arg space info
4152   for the current function.  The number and meanings of words
4153   is controlled by the definition of CUMULATIVE_ARGS.  */
4154
4155static rtx
4156expand_builtin_args_info (tree arglist)
4157{
4158  int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
4159  int *word_ptr = (int *) &current_function_args_info;
4160
4161  gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
4162
4163  if (arglist != 0)
4164    {
4165      if (!host_integerp (TREE_VALUE (arglist), 0))
4166	error ("argument of %<__builtin_args_info%> must be constant");
4167      else
4168	{
4169	  HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
4170
4171	  if (wordnum < 0 || wordnum >= nwords)
4172	    error ("argument of %<__builtin_args_info%> out of range");
4173	  else
4174	    return GEN_INT (word_ptr[wordnum]);
4175	}
4176    }
4177  else
4178    error ("missing argument in %<__builtin_args_info%>");
4179
4180  return const0_rtx;
4181}
4182
4183/* Expand a call to __builtin_next_arg.  */
4184
4185static rtx
4186expand_builtin_next_arg (void)
4187{
4188  /* Checking arguments is already done in fold_builtin_next_arg
4189     that must be called before this function.  */
4190  return expand_binop (Pmode, add_optab,
4191		       current_function_internal_arg_pointer,
4192		       current_function_arg_offset_rtx,
4193		       NULL_RTX, 0, OPTAB_LIB_WIDEN);
4194}
4195
4196/* Make it easier for the backends by protecting the valist argument
4197   from multiple evaluations.  */
4198
4199static tree
4200stabilize_va_list (tree valist, int needs_lvalue)
4201{
4202  if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
4203    {
4204      if (TREE_SIDE_EFFECTS (valist))
4205	valist = save_expr (valist);
4206
4207      /* For this case, the backends will be expecting a pointer to
4208	 TREE_TYPE (va_list_type_node), but it's possible we've
4209	 actually been given an array (an actual va_list_type_node).
4210	 So fix it.  */
4211      if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4212	{
4213	  tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
4214	  valist = build_fold_addr_expr_with_type (valist, p1);
4215	}
4216    }
4217  else
4218    {
4219      tree pt;
4220
4221      if (! needs_lvalue)
4222	{
4223	  if (! TREE_SIDE_EFFECTS (valist))
4224	    return valist;
4225
4226	  pt = build_pointer_type (va_list_type_node);
4227	  valist = fold_build1 (ADDR_EXPR, pt, valist);
4228	  TREE_SIDE_EFFECTS (valist) = 1;
4229	}
4230
4231      if (TREE_SIDE_EFFECTS (valist))
4232	valist = save_expr (valist);
4233      valist = build_fold_indirect_ref (valist);
4234    }
4235
4236  return valist;
4237}
4238
4239/* The "standard" definition of va_list is void*.  */
4240
4241tree
4242std_build_builtin_va_list (void)
4243{
4244  return ptr_type_node;
4245}
4246
4247/* The "standard" implementation of va_start: just assign `nextarg' to
4248   the variable.  */
4249
4250void
4251std_expand_builtin_va_start (tree valist, rtx nextarg)
4252{
4253  tree t;
4254
4255  t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
4256	      make_tree (ptr_type_node, nextarg));
4257  TREE_SIDE_EFFECTS (t) = 1;
4258
4259  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4260}
4261
4262/* Expand ARGLIST, from a call to __builtin_va_start.  */
4263
4264static rtx
4265expand_builtin_va_start (tree arglist)
4266{
4267  rtx nextarg;
4268  tree chain, valist;
4269
4270  chain = TREE_CHAIN (arglist);
4271
4272  if (!chain)
4273    {
4274      error ("too few arguments to function %<va_start%>");
4275      return const0_rtx;
4276    }
4277
4278  if (fold_builtin_next_arg (chain))
4279    return const0_rtx;
4280
4281  nextarg = expand_builtin_next_arg ();
4282  valist = stabilize_va_list (TREE_VALUE (arglist), 1);
4283
4284#ifdef EXPAND_BUILTIN_VA_START
4285  EXPAND_BUILTIN_VA_START (valist, nextarg);
4286#else
4287  std_expand_builtin_va_start (valist, nextarg);
4288#endif
4289
4290  return const0_rtx;
4291}
4292
4293/* The "standard" implementation of va_arg: read the value from the
4294   current (padded) address and increment by the (padded) size.  */
4295
4296tree
4297std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
4298{
4299  tree addr, t, type_size, rounded_size, valist_tmp;
4300  unsigned HOST_WIDE_INT align, boundary;
4301  bool indirect;
4302
4303#ifdef ARGS_GROW_DOWNWARD
4304  /* All of the alignment and movement below is for args-grow-up machines.
4305     As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
4306     implement their own specialized gimplify_va_arg_expr routines.  */
4307  gcc_unreachable ();
4308#endif
4309
4310  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
4311  if (indirect)
4312    type = build_pointer_type (type);
4313
4314  align = PARM_BOUNDARY / BITS_PER_UNIT;
4315  boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type) / BITS_PER_UNIT;
4316
4317  /* Hoist the valist value into a temporary for the moment.  */
4318  valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
4319
4320  /* va_list pointer is aligned to PARM_BOUNDARY.  If argument actually
4321     requires greater alignment, we must perform dynamic alignment.  */
4322  if (boundary > align
4323      && !integer_zerop (TYPE_SIZE (type)))
4324    {
4325      t = fold_convert (TREE_TYPE (valist), size_int (boundary - 1));
4326      t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
4327		  build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t));
4328      gimplify_and_add (t, pre_p);
4329
4330      t = fold_convert (TREE_TYPE (valist), size_int (-boundary));
4331      t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
4332		  build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, t));
4333      gimplify_and_add (t, pre_p);
4334    }
4335  else
4336    boundary = align;
4337
4338  /* If the actual alignment is less than the alignment of the type,
4339     adjust the type accordingly so that we don't assume strict alignment
4340     when deferencing the pointer.  */
4341  boundary *= BITS_PER_UNIT;
4342  if (boundary < TYPE_ALIGN (type))
4343    {
4344      type = build_variant_type_copy (type);
4345      TYPE_ALIGN (type) = boundary;
4346    }
4347
4348  /* Compute the rounded size of the type.  */
4349  type_size = size_in_bytes (type);
4350  rounded_size = round_up (type_size, align);
4351
4352  /* Reduce rounded_size so it's sharable with the postqueue.  */
4353  gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
4354
4355  /* Get AP.  */
4356  addr = valist_tmp;
4357  if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
4358    {
4359      /* Small args are padded downward.  */
4360      t = fold_build2 (GT_EXPR, sizetype, rounded_size, size_int (align));
4361      t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
4362		       size_binop (MINUS_EXPR, rounded_size, type_size));
4363      t = fold_convert (TREE_TYPE (addr), t);
4364      addr = fold_build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t);
4365    }
4366
4367  /* Compute new value for AP.  */
4368  t = fold_convert (TREE_TYPE (valist), rounded_size);
4369  t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t);
4370  t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
4371  gimplify_and_add (t, pre_p);
4372
4373  addr = fold_convert (build_pointer_type (type), addr);
4374
4375  if (indirect)
4376    addr = build_va_arg_indirect_ref (addr);
4377
4378  return build_va_arg_indirect_ref (addr);
4379}
4380
4381/* Build an indirect-ref expression over the given TREE, which represents a
4382   piece of a va_arg() expansion.  */
4383tree
4384build_va_arg_indirect_ref (tree addr)
4385{
4386  addr = build_fold_indirect_ref (addr);
4387
4388  if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF.  */
4389    mf_mark (addr);
4390
4391  return addr;
4392}
4393
4394/* Return a dummy expression of type TYPE in order to keep going after an
4395   error.  */
4396
4397static tree
4398dummy_object (tree type)
4399{
4400  tree t = convert (build_pointer_type (type), null_pointer_node);
4401  return build1 (INDIRECT_REF, type, t);
4402}
4403
4404/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
4405   builtin function, but a very special sort of operator.  */
4406
4407enum gimplify_status
4408gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p)
4409{
4410  tree promoted_type, want_va_type, have_va_type;
4411  tree valist = TREE_OPERAND (*expr_p, 0);
4412  tree type = TREE_TYPE (*expr_p);
4413  tree t;
4414
4415  /* Verify that valist is of the proper type.  */
4416  want_va_type = va_list_type_node;
4417  have_va_type = TREE_TYPE (valist);
4418
4419  if (have_va_type == error_mark_node)
4420    return GS_ERROR;
4421
4422  if (TREE_CODE (want_va_type) == ARRAY_TYPE)
4423    {
4424      /* If va_list is an array type, the argument may have decayed
4425	 to a pointer type, e.g. by being passed to another function.
4426         In that case, unwrap both types so that we can compare the
4427	 underlying records.  */
4428      if (TREE_CODE (have_va_type) == ARRAY_TYPE
4429	  || POINTER_TYPE_P (have_va_type))
4430	{
4431	  want_va_type = TREE_TYPE (want_va_type);
4432	  have_va_type = TREE_TYPE (have_va_type);
4433	}
4434    }
4435
4436  if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
4437    {
4438      error ("first argument to %<va_arg%> not of type %<va_list%>");
4439      return GS_ERROR;
4440    }
4441
4442  /* Generate a diagnostic for requesting data of a type that cannot
4443     be passed through `...' due to type promotion at the call site.  */
4444  else if ((promoted_type = lang_hooks.types.type_promotes_to (type))
4445	   != type)
4446    {
4447      static bool gave_help;
4448
4449      /* Unfortunately, this is merely undefined, rather than a constraint
4450	 violation, so we cannot make this an error.  If this call is never
4451	 executed, the program is still strictly conforming.  */
4452      warning (0, "%qT is promoted to %qT when passed through %<...%>",
4453	       type, promoted_type);
4454      if (! gave_help)
4455	{
4456	  gave_help = true;
4457	  warning (0, "(so you should pass %qT not %qT to %<va_arg%>)",
4458		   promoted_type, type);
4459	}
4460
4461      /* We can, however, treat "undefined" any way we please.
4462	 Call abort to encourage the user to fix the program.  */
4463      inform ("if this code is reached, the program will abort");
4464      t = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP],
4465				    NULL);
4466      append_to_statement_list (t, pre_p);
4467
4468      /* This is dead code, but go ahead and finish so that the
4469	 mode of the result comes out right.  */
4470      *expr_p = dummy_object (type);
4471      return GS_ALL_DONE;
4472    }
4473  else
4474    {
4475      /* Make it easier for the backends by protecting the valist argument
4476         from multiple evaluations.  */
4477      if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
4478	{
4479	  /* For this case, the backends will be expecting a pointer to
4480	     TREE_TYPE (va_list_type_node), but it's possible we've
4481	     actually been given an array (an actual va_list_type_node).
4482	     So fix it.  */
4483	  if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
4484	    {
4485	      tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
4486	      valist = build_fold_addr_expr_with_type (valist, p1);
4487	    }
4488	  gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
4489	}
4490      else
4491	gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
4492
4493      if (!targetm.gimplify_va_arg_expr)
4494	/* FIXME:Once most targets are converted we should merely
4495	   assert this is non-null.  */
4496	return GS_ALL_DONE;
4497
4498      *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
4499      return GS_OK;
4500    }
4501}
4502
4503/* Expand ARGLIST, from a call to __builtin_va_end.  */
4504
4505static rtx
4506expand_builtin_va_end (tree arglist)
4507{
4508  tree valist = TREE_VALUE (arglist);
4509
4510  /* Evaluate for side effects, if needed.  I hate macros that don't
4511     do that.  */
4512  if (TREE_SIDE_EFFECTS (valist))
4513    expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
4514
4515  return const0_rtx;
4516}
4517
4518/* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a
4519   builtin rather than just as an assignment in stdarg.h because of the
4520   nastiness of array-type va_list types.  */
4521
4522static rtx
4523expand_builtin_va_copy (tree arglist)
4524{
4525  tree dst, src, t;
4526
4527  dst = TREE_VALUE (arglist);
4528  src = TREE_VALUE (TREE_CHAIN (arglist));
4529
4530  dst = stabilize_va_list (dst, 1);
4531  src = stabilize_va_list (src, 0);
4532
4533  if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
4534    {
4535      t = build2 (MODIFY_EXPR, va_list_type_node, dst, src);
4536      TREE_SIDE_EFFECTS (t) = 1;
4537      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
4538    }
4539  else
4540    {
4541      rtx dstb, srcb, size;
4542
4543      /* Evaluate to pointers.  */
4544      dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
4545      srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
4546      size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
4547			  VOIDmode, EXPAND_NORMAL);
4548
4549      dstb = convert_memory_address (Pmode, dstb);
4550      srcb = convert_memory_address (Pmode, srcb);
4551
4552      /* "Dereference" to BLKmode memories.  */
4553      dstb = gen_rtx_MEM (BLKmode, dstb);
4554      set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
4555      set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
4556      srcb = gen_rtx_MEM (BLKmode, srcb);
4557      set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
4558      set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
4559
4560      /* Copy.  */
4561      emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
4562    }
4563
4564  return const0_rtx;
4565}
4566
4567/* Expand a call to one of the builtin functions __builtin_frame_address or
4568   __builtin_return_address.  */
4569
4570static rtx
4571expand_builtin_frame_address (tree fndecl, tree arglist)
4572{
4573  /* The argument must be a nonnegative integer constant.
4574     It counts the number of frames to scan up the stack.
4575     The value is the return address saved in that frame.  */
4576  if (arglist == 0)
4577    /* Warning about missing arg was already issued.  */
4578    return const0_rtx;
4579  else if (! host_integerp (TREE_VALUE (arglist), 1))
4580    {
4581      if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4582	error ("invalid argument to %<__builtin_frame_address%>");
4583      else
4584	error ("invalid argument to %<__builtin_return_address%>");
4585      return const0_rtx;
4586    }
4587  else
4588    {
4589      rtx tem
4590	= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
4591				      tree_low_cst (TREE_VALUE (arglist), 1));
4592
4593      /* Some ports cannot access arbitrary stack frames.  */
4594      if (tem == NULL)
4595	{
4596	  if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4597	    warning (0, "unsupported argument to %<__builtin_frame_address%>");
4598	  else
4599	    warning (0, "unsupported argument to %<__builtin_return_address%>");
4600	  return const0_rtx;
4601	}
4602
4603      /* For __builtin_frame_address, return what we've got.  */
4604      if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
4605	return tem;
4606
4607      if (!REG_P (tem)
4608	  && ! CONSTANT_P (tem))
4609	tem = copy_to_mode_reg (Pmode, tem);
4610      return tem;
4611    }
4612}
4613
4614/* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
4615   we failed and the caller should emit a normal call, otherwise try to get
4616   the result in TARGET, if convenient.  */
4617
4618static rtx
4619expand_builtin_alloca (tree arglist, rtx target)
4620{
4621  rtx op0;
4622  rtx result;
4623
4624  /* In -fmudflap-instrumented code, alloca() and __builtin_alloca()
4625     should always expand to function calls.  These can be intercepted
4626     in libmudflap.  */
4627  if (flag_mudflap)
4628    return 0;
4629
4630  if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
4631    return 0;
4632
4633  /* Compute the argument.  */
4634  op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
4635
4636  /* Allocate the desired space.  */
4637  result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
4638  result = convert_memory_address (ptr_mode, result);
4639
4640  return result;
4641}
4642
4643/* Expand a call to a unary builtin.  The arguments are in ARGLIST.
4644   Return 0 if a normal call should be emitted rather than expanding the
4645   function in-line.  If convenient, the result should be placed in TARGET.
4646   SUBTARGET may be used as the target for computing one of EXP's operands.  */
4647
4648static rtx
4649expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target,
4650		     rtx subtarget, optab op_optab)
4651{
4652  rtx op0;
4653  if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
4654    return 0;
4655
4656  /* Compute the argument.  */
4657  op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
4658  /* Compute op, into TARGET if possible.
4659     Set TARGET to wherever the result comes back.  */
4660  target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
4661			op_optab, op0, target, 1);
4662  gcc_assert (target);
4663
4664  return convert_to_mode (target_mode, target, 0);
4665}
4666
4667/* If the string passed to fputs is a constant and is one character
4668   long, we attempt to transform this call into __builtin_fputc().  */
4669
4670static rtx
4671expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
4672{
4673  /* Verify the arguments in the original call.  */
4674  if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4675    {
4676      tree result = fold_builtin_fputs (arglist, (target == const0_rtx),
4677					unlocked, NULL_TREE);
4678      if (result)
4679	return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
4680    }
4681  return 0;
4682}
4683
4684/* Expand a call to __builtin_expect.  We return our argument and emit a
4685   NOTE_INSN_EXPECTED_VALUE note.  This is the expansion of __builtin_expect in
4686   a non-jump context.  */
4687
4688static rtx
4689expand_builtin_expect (tree arglist, rtx target)
4690{
4691  tree exp, c;
4692  rtx note, rtx_c;
4693
4694  if (arglist == NULL_TREE
4695      || TREE_CHAIN (arglist) == NULL_TREE)
4696    return const0_rtx;
4697  exp = TREE_VALUE (arglist);
4698  c = TREE_VALUE (TREE_CHAIN (arglist));
4699
4700  if (TREE_CODE (c) != INTEGER_CST)
4701    {
4702      error ("second argument to %<__builtin_expect%> must be a constant");
4703      c = integer_zero_node;
4704    }
4705
4706  target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
4707
4708  /* Don't bother with expected value notes for integral constants.  */
4709  if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
4710    {
4711      /* We do need to force this into a register so that we can be
4712	 moderately sure to be able to correctly interpret the branch
4713	 condition later.  */
4714      target = force_reg (GET_MODE (target), target);
4715
4716      rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
4717
4718      note = emit_note (NOTE_INSN_EXPECTED_VALUE);
4719      NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
4720    }
4721
4722  return target;
4723}
4724
4725/* Like expand_builtin_expect, except do this in a jump context.  This is
4726   called from do_jump if the conditional is a __builtin_expect.  Return either
4727   a list of insns to emit the jump or NULL if we cannot optimize
4728   __builtin_expect.  We need to optimize this at jump time so that machines
4729   like the PowerPC don't turn the test into a SCC operation, and then jump
4730   based on the test being 0/1.  */
4731
4732rtx
4733expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
4734{
4735  tree arglist = TREE_OPERAND (exp, 1);
4736  tree arg0 = TREE_VALUE (arglist);
4737  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4738  rtx ret = NULL_RTX;
4739
4740  /* Only handle __builtin_expect (test, 0) and
4741     __builtin_expect (test, 1).  */
4742  if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
4743      && (integer_zerop (arg1) || integer_onep (arg1)))
4744    {
4745      rtx insn, drop_through_label, temp;
4746
4747      /* Expand the jump insns.  */
4748      start_sequence ();
4749      do_jump (arg0, if_false_label, if_true_label);
4750      ret = get_insns ();
4751
4752      drop_through_label = get_last_insn ();
4753      if (drop_through_label && NOTE_P (drop_through_label))
4754	drop_through_label = prev_nonnote_insn (drop_through_label);
4755      if (drop_through_label && !LABEL_P (drop_through_label))
4756	drop_through_label = NULL_RTX;
4757      end_sequence ();
4758
4759      if (! if_true_label)
4760	if_true_label = drop_through_label;
4761      if (! if_false_label)
4762	if_false_label = drop_through_label;
4763
4764      /* Go through and add the expect's to each of the conditional jumps.  */
4765      insn = ret;
4766      while (insn != NULL_RTX)
4767	{
4768	  rtx next = NEXT_INSN (insn);
4769
4770	  if (JUMP_P (insn) && any_condjump_p (insn))
4771	    {
4772	      rtx ifelse = SET_SRC (pc_set (insn));
4773	      rtx then_dest = XEXP (ifelse, 1);
4774	      rtx else_dest = XEXP (ifelse, 2);
4775	      int taken = -1;
4776
4777	      /* First check if we recognize any of the labels.  */
4778	      if (GET_CODE (then_dest) == LABEL_REF
4779		  && XEXP (then_dest, 0) == if_true_label)
4780		taken = 1;
4781	      else if (GET_CODE (then_dest) == LABEL_REF
4782		       && XEXP (then_dest, 0) == if_false_label)
4783		taken = 0;
4784	      else if (GET_CODE (else_dest) == LABEL_REF
4785		       && XEXP (else_dest, 0) == if_false_label)
4786		taken = 1;
4787	      else if (GET_CODE (else_dest) == LABEL_REF
4788		       && XEXP (else_dest, 0) == if_true_label)
4789		taken = 0;
4790	      /* Otherwise check where we drop through.  */
4791	      else if (else_dest == pc_rtx)
4792		{
4793		  if (next && NOTE_P (next))
4794		    next = next_nonnote_insn (next);
4795
4796		  if (next && JUMP_P (next)
4797		      && any_uncondjump_p (next))
4798		    temp = XEXP (SET_SRC (pc_set (next)), 0);
4799		  else
4800		    temp = next;
4801
4802		  /* TEMP is either a CODE_LABEL, NULL_RTX or something
4803		     else that can't possibly match either target label.  */
4804		  if (temp == if_false_label)
4805		    taken = 1;
4806		  else if (temp == if_true_label)
4807		    taken = 0;
4808		}
4809	      else if (then_dest == pc_rtx)
4810		{
4811		  if (next && NOTE_P (next))
4812		    next = next_nonnote_insn (next);
4813
4814		  if (next && JUMP_P (next)
4815		      && any_uncondjump_p (next))
4816		    temp = XEXP (SET_SRC (pc_set (next)), 0);
4817		  else
4818		    temp = next;
4819
4820		  if (temp == if_false_label)
4821		    taken = 0;
4822		  else if (temp == if_true_label)
4823		    taken = 1;
4824		}
4825
4826	      if (taken != -1)
4827		{
4828		  /* If the test is expected to fail, reverse the
4829		     probabilities.  */
4830		  if (integer_zerop (arg1))
4831		    taken = 1 - taken;
4832	          predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
4833		}
4834	    }
4835
4836	  insn = next;
4837	}
4838    }
4839
4840  return ret;
4841}
4842
4843void
4844expand_builtin_trap (void)
4845{
4846#ifdef HAVE_trap
4847  if (HAVE_trap)
4848    emit_insn (gen_trap ());
4849  else
4850#endif
4851    emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4852  emit_barrier ();
4853}
4854
4855/* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST.
4856   Return 0 if a normal call should be emitted rather than expanding
4857   the function inline.  If convenient, the result should be placed
4858   in TARGET.  SUBTARGET may be used as the target for computing
4859   the operand.  */
4860
4861static rtx
4862expand_builtin_fabs (tree arglist, rtx target, rtx subtarget)
4863{
4864  enum machine_mode mode;
4865  tree arg;
4866  rtx op0;
4867
4868  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
4869    return 0;
4870
4871  arg = TREE_VALUE (arglist);
4872  mode = TYPE_MODE (TREE_TYPE (arg));
4873  op0 = expand_expr (arg, subtarget, VOIDmode, 0);
4874  return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4875}
4876
4877/* Expand a call to copysign, copysignf, or copysignl with arguments ARGLIST.
4878   Return NULL is a normal call should be emitted rather than expanding the
4879   function inline.  If convenient, the result should be placed in TARGET.
4880   SUBTARGET may be used as the target for computing the operand.  */
4881
4882static rtx
4883expand_builtin_copysign (tree arglist, rtx target, rtx subtarget)
4884{
4885  rtx op0, op1;
4886  tree arg;
4887
4888  if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4889    return 0;
4890
4891  arg = TREE_VALUE (arglist);
4892  op0 = expand_expr (arg, subtarget, VOIDmode, 0);
4893
4894  arg = TREE_VALUE (TREE_CHAIN (arglist));
4895  op1 = expand_expr (arg, NULL, VOIDmode, 0);
4896
4897  return expand_copysign (op0, op1, target);
4898}
4899
4900/* Create a new constant string literal and return a char* pointer to it.
4901   The STRING_CST value is the LEN characters at STR.  */
4902static tree
4903build_string_literal (int len, const char *str)
4904{
4905  tree t, elem, index, type;
4906
4907  t = build_string (len, str);
4908  elem = build_type_variant (char_type_node, 1, 0);
4909  index = build_index_type (build_int_cst (NULL_TREE, len - 1));
4910  type = build_array_type (elem, index);
4911  TREE_TYPE (t) = type;
4912  TREE_CONSTANT (t) = 1;
4913  TREE_INVARIANT (t) = 1;
4914  TREE_READONLY (t) = 1;
4915  TREE_STATIC (t) = 1;
4916
4917  type = build_pointer_type (type);
4918  t = build1 (ADDR_EXPR, type, t);
4919
4920  type = build_pointer_type (elem);
4921  t = build1 (NOP_EXPR, type, t);
4922  return t;
4923}
4924
4925/* Expand EXP, a call to printf or printf_unlocked.
4926   Return 0 if a normal call should be emitted rather than transforming
4927   the function inline.  If convenient, the result should be placed in
4928   TARGET with mode MODE.  UNLOCKED indicates this is a printf_unlocked
4929   call.  */
4930static rtx
4931expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
4932		       bool unlocked)
4933{
4934  tree arglist = TREE_OPERAND (exp, 1);
4935  /* If we're using an unlocked function, assume the other unlocked
4936     functions exist explicitly.  */
4937  tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
4938    : implicit_built_in_decls[BUILT_IN_PUTCHAR];
4939  tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
4940    : implicit_built_in_decls[BUILT_IN_PUTS];
4941  const char *fmt_str;
4942  tree fn, fmt, arg;
4943
4944  /* If the return value is used, don't do the transformation.  */
4945  if (target != const0_rtx)
4946    return 0;
4947
4948  /* Verify the required arguments in the original call.  */
4949  if (! arglist)
4950    return 0;
4951  fmt = TREE_VALUE (arglist);
4952  if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
4953    return 0;
4954  arglist = TREE_CHAIN (arglist);
4955
4956  /* Check whether the format is a literal string constant.  */
4957  fmt_str = c_getstr (fmt);
4958  if (fmt_str == NULL)
4959    return 0;
4960
4961  if (!init_target_chars())
4962    return 0;
4963
4964  /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
4965  if (strcmp (fmt_str, target_percent_s_newline) == 0)
4966    {
4967      if (! arglist
4968          || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
4969	  || TREE_CHAIN (arglist))
4970	return 0;
4971      fn = fn_puts;
4972    }
4973  /* If the format specifier was "%c", call __builtin_putchar(arg).  */
4974  else if (strcmp (fmt_str, target_percent_c) == 0)
4975    {
4976      if (! arglist
4977	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
4978	  || TREE_CHAIN (arglist))
4979	return 0;
4980      fn = fn_putchar;
4981    }
4982  else
4983    {
4984      /* We can't handle anything else with % args or %% ... yet.  */
4985      if (strchr (fmt_str, target_percent))
4986        return 0;
4987
4988      if (arglist)
4989	return 0;
4990
4991      /* If the format specifier was "", printf does nothing.  */
4992      if (fmt_str[0] == '\0')
4993	return const0_rtx;
4994      /* If the format specifier has length of 1, call putchar.  */
4995      if (fmt_str[1] == '\0')
4996	{
4997	  /* Given printf("c"), (where c is any one character,)
4998	     convert "c"[0] to an int and pass that to the replacement
4999	     function.  */
5000	  arg = build_int_cst (NULL_TREE, fmt_str[0]);
5001	  arglist = build_tree_list (NULL_TREE, arg);
5002	  fn = fn_putchar;
5003	}
5004      else
5005	{
5006	  /* If the format specifier was "string\n", call puts("string").  */
5007	  size_t len = strlen (fmt_str);
5008	  if ((unsigned char)fmt_str[len - 1] == target_newline)
5009	    {
5010	      /* Create a NUL-terminated string that's one char shorter
5011		 than the original, stripping off the trailing '\n'.  */
5012	      char *newstr = alloca (len);
5013	      memcpy (newstr, fmt_str, len - 1);
5014	      newstr[len - 1] = 0;
5015
5016	      arg = build_string_literal (len, newstr);
5017	      arglist = build_tree_list (NULL_TREE, arg);
5018	      fn = fn_puts;
5019	    }
5020	  else
5021	    /* We'd like to arrange to call fputs(string,stdout) here,
5022	       but we need stdout and don't have a way to get it yet.  */
5023	    return 0;
5024	}
5025    }
5026
5027  if (!fn)
5028    return 0;
5029  fn = build_function_call_expr (fn, arglist);
5030  if (TREE_CODE (fn) == CALL_EXPR)
5031    CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5032  return expand_expr (fn, target, mode, EXPAND_NORMAL);
5033}
5034
5035/* Expand EXP, a call to fprintf or fprintf_unlocked.
5036   Return 0 if a normal call should be emitted rather than transforming
5037   the function inline.  If convenient, the result should be placed in
5038   TARGET with mode MODE.  UNLOCKED indicates this is a fprintf_unlocked
5039   call.  */
5040static rtx
5041expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
5042		        bool unlocked)
5043{
5044  tree arglist = TREE_OPERAND (exp, 1);
5045  /* If we're using an unlocked function, assume the other unlocked
5046     functions exist explicitly.  */
5047  tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
5048    : implicit_built_in_decls[BUILT_IN_FPUTC];
5049  tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
5050    : implicit_built_in_decls[BUILT_IN_FPUTS];
5051  const char *fmt_str;
5052  tree fn, fmt, fp, arg;
5053
5054  /* If the return value is used, don't do the transformation.  */
5055  if (target != const0_rtx)
5056    return 0;
5057
5058  /* Verify the required arguments in the original call.  */
5059  if (! arglist)
5060    return 0;
5061  fp = TREE_VALUE (arglist);
5062  if (! POINTER_TYPE_P (TREE_TYPE (fp)))
5063    return 0;
5064  arglist = TREE_CHAIN (arglist);
5065  if (! arglist)
5066    return 0;
5067  fmt = TREE_VALUE (arglist);
5068  if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
5069    return 0;
5070  arglist = TREE_CHAIN (arglist);
5071
5072  /* Check whether the format is a literal string constant.  */
5073  fmt_str = c_getstr (fmt);
5074  if (fmt_str == NULL)
5075    return 0;
5076
5077  if (!init_target_chars())
5078    return 0;
5079
5080  /* If the format specifier was "%s", call __builtin_fputs(arg,fp).  */
5081  if (strcmp (fmt_str, target_percent_s) == 0)
5082    {
5083      if (! arglist
5084          || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
5085	  || TREE_CHAIN (arglist))
5086	return 0;
5087      arg = TREE_VALUE (arglist);
5088      arglist = build_tree_list (NULL_TREE, fp);
5089      arglist = tree_cons (NULL_TREE, arg, arglist);
5090      fn = fn_fputs;
5091    }
5092  /* If the format specifier was "%c", call __builtin_fputc(arg,fp).  */
5093  else if (strcmp (fmt_str, target_percent_c) == 0)
5094    {
5095      if (! arglist
5096	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
5097	  || TREE_CHAIN (arglist))
5098	return 0;
5099      arg = TREE_VALUE (arglist);
5100      arglist = build_tree_list (NULL_TREE, fp);
5101      arglist = tree_cons (NULL_TREE, arg, arglist);
5102      fn = fn_fputc;
5103    }
5104  else
5105    {
5106      /* We can't handle anything else with % args or %% ... yet.  */
5107      if (strchr (fmt_str, target_percent))
5108        return 0;
5109
5110      if (arglist)
5111	return 0;
5112
5113      /* If the format specifier was "", fprintf does nothing.  */
5114      if (fmt_str[0] == '\0')
5115	{
5116	  /* Evaluate and ignore FILE* argument for side-effects.  */
5117	  expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
5118	  return const0_rtx;
5119	}
5120
5121      /* When "string" doesn't contain %, replace all cases of
5122	 fprintf(stream,string) with fputs(string,stream).  The fputs
5123	 builtin will take care of special cases like length == 1.  */
5124      arglist = build_tree_list (NULL_TREE, fp);
5125      arglist = tree_cons (NULL_TREE, fmt, arglist);
5126      fn = fn_fputs;
5127    }
5128
5129  if (!fn)
5130    return 0;
5131  fn = build_function_call_expr (fn, arglist);
5132  if (TREE_CODE (fn) == CALL_EXPR)
5133    CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5134  return expand_expr (fn, target, mode, EXPAND_NORMAL);
5135}
5136
5137/* Expand a call to sprintf with argument list ARGLIST.  Return 0 if
5138   a normal call should be emitted rather than expanding the function
5139   inline.  If convenient, the result should be placed in TARGET with
5140   mode MODE.  */
5141
5142static rtx
5143expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
5144{
5145  tree orig_arglist, dest, fmt;
5146  const char *fmt_str;
5147
5148  orig_arglist = arglist;
5149
5150  /* Verify the required arguments in the original call.  */
5151  if (! arglist)
5152    return 0;
5153  dest = TREE_VALUE (arglist);
5154  if (! POINTER_TYPE_P (TREE_TYPE (dest)))
5155    return 0;
5156  arglist = TREE_CHAIN (arglist);
5157  if (! arglist)
5158    return 0;
5159  fmt = TREE_VALUE (arglist);
5160  if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
5161    return 0;
5162  arglist = TREE_CHAIN (arglist);
5163
5164  /* Check whether the format is a literal string constant.  */
5165  fmt_str = c_getstr (fmt);
5166  if (fmt_str == NULL)
5167    return 0;
5168
5169  if (!init_target_chars())
5170    return 0;
5171
5172  /* If the format doesn't contain % args or %%, use strcpy.  */
5173  if (strchr (fmt_str, target_percent) == 0)
5174    {
5175      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5176      tree exp;
5177
5178      if (arglist || ! fn)
5179	return 0;
5180      expand_expr (build_function_call_expr (fn, orig_arglist),
5181		   const0_rtx, VOIDmode, EXPAND_NORMAL);
5182      if (target == const0_rtx)
5183	return const0_rtx;
5184      exp = build_int_cst (NULL_TREE, strlen (fmt_str));
5185      return expand_expr (exp, target, mode, EXPAND_NORMAL);
5186    }
5187  /* If the format is "%s", use strcpy if the result isn't used.  */
5188  else if (strcmp (fmt_str, target_percent_s) == 0)
5189    {
5190      tree fn, arg, len;
5191      fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5192
5193      if (! fn)
5194	return 0;
5195
5196      if (! arglist || TREE_CHAIN (arglist))
5197	return 0;
5198      arg = TREE_VALUE (arglist);
5199      if (! POINTER_TYPE_P (TREE_TYPE (arg)))
5200	return 0;
5201
5202      if (target != const0_rtx)
5203	{
5204	  len = c_strlen (arg, 1);
5205	  if (! len || TREE_CODE (len) != INTEGER_CST)
5206	    return 0;
5207	}
5208      else
5209	len = NULL_TREE;
5210
5211      arglist = build_tree_list (NULL_TREE, arg);
5212      arglist = tree_cons (NULL_TREE, dest, arglist);
5213      expand_expr (build_function_call_expr (fn, arglist),
5214		   const0_rtx, VOIDmode, EXPAND_NORMAL);
5215
5216      if (target == const0_rtx)
5217	return const0_rtx;
5218      return expand_expr (len, target, mode, EXPAND_NORMAL);
5219    }
5220
5221  return 0;
5222}
5223
5224/* Expand a call to either the entry or exit function profiler.  */
5225
5226static rtx
5227expand_builtin_profile_func (bool exitp)
5228{
5229  rtx this, which;
5230
5231  this = DECL_RTL (current_function_decl);
5232  gcc_assert (MEM_P (this));
5233  this = XEXP (this, 0);
5234
5235  if (exitp)
5236    which = profile_function_exit_libfunc;
5237  else
5238    which = profile_function_entry_libfunc;
5239
5240  emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
5241		     expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
5242						 0),
5243		     Pmode);
5244
5245  return const0_rtx;
5246}
5247
5248/* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
5249
5250static rtx
5251round_trampoline_addr (rtx tramp)
5252{
5253  rtx temp, addend, mask;
5254
5255  /* If we don't need too much alignment, we'll have been guaranteed
5256     proper alignment by get_trampoline_type.  */
5257  if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5258    return tramp;
5259
5260  /* Round address up to desired boundary.  */
5261  temp = gen_reg_rtx (Pmode);
5262  addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5263  mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5264
5265  temp  = expand_simple_binop (Pmode, PLUS, tramp, addend,
5266			       temp, 0, OPTAB_LIB_WIDEN);
5267  tramp = expand_simple_binop (Pmode, AND, temp, mask,
5268			       temp, 0, OPTAB_LIB_WIDEN);
5269
5270  return tramp;
5271}
5272
5273static rtx
5274expand_builtin_init_trampoline (tree arglist)
5275{
5276  tree t_tramp, t_func, t_chain;
5277  rtx r_tramp, r_func, r_chain;
5278#ifdef TRAMPOLINE_TEMPLATE
5279  rtx blktramp;
5280#endif
5281
5282  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE,
5283			 POINTER_TYPE, VOID_TYPE))
5284    return NULL_RTX;
5285
5286  t_tramp = TREE_VALUE (arglist);
5287  arglist = TREE_CHAIN (arglist);
5288  t_func = TREE_VALUE (arglist);
5289  arglist = TREE_CHAIN (arglist);
5290  t_chain = TREE_VALUE (arglist);
5291
5292  r_tramp = expand_expr (t_tramp, NULL_RTX, VOIDmode, 0);
5293  r_func = expand_expr (t_func, NULL_RTX, VOIDmode, 0);
5294  r_chain = expand_expr (t_chain, NULL_RTX, VOIDmode, 0);
5295
5296  /* Generate insns to initialize the trampoline.  */
5297  r_tramp = round_trampoline_addr (r_tramp);
5298#ifdef TRAMPOLINE_TEMPLATE
5299  blktramp = gen_rtx_MEM (BLKmode, r_tramp);
5300  set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
5301  emit_block_move (blktramp, assemble_trampoline_template (),
5302		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
5303#endif
5304  trampolines_created = 1;
5305  INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
5306
5307  return const0_rtx;
5308}
5309
5310static rtx
5311expand_builtin_adjust_trampoline (tree arglist)
5312{
5313  rtx tramp;
5314
5315  if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5316    return NULL_RTX;
5317
5318  tramp = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
5319  tramp = round_trampoline_addr (tramp);
5320#ifdef TRAMPOLINE_ADJUST_ADDRESS
5321  TRAMPOLINE_ADJUST_ADDRESS (tramp);
5322#endif
5323
5324  return tramp;
5325}
5326
5327/* Expand a call to the built-in signbit, signbitf or signbitl function.
5328   Return NULL_RTX if a normal call should be emitted rather than expanding
5329   the function in-line.  EXP is the expression that is a call to the builtin
5330   function; if convenient, the result should be placed in TARGET.  */
5331
5332static rtx
5333expand_builtin_signbit (tree exp, rtx target)
5334{
5335  const struct real_format *fmt;
5336  enum machine_mode fmode, imode, rmode;
5337  HOST_WIDE_INT hi, lo;
5338  tree arg, arglist;
5339  int word, bitpos;
5340  rtx temp;
5341
5342  arglist = TREE_OPERAND (exp, 1);
5343  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5344    return 0;
5345
5346  arg = TREE_VALUE (arglist);
5347  fmode = TYPE_MODE (TREE_TYPE (arg));
5348  rmode = TYPE_MODE (TREE_TYPE (exp));
5349  fmt = REAL_MODE_FORMAT (fmode);
5350
5351  /* For floating point formats without a sign bit, implement signbit
5352     as "ARG < 0.0".  */
5353  bitpos = fmt->signbit_ro;
5354  if (bitpos < 0)
5355  {
5356    /* But we can't do this if the format supports signed zero.  */
5357    if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
5358      return 0;
5359
5360    arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
5361		       build_real (TREE_TYPE (arg), dconst0));
5362    return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5363  }
5364
5365  temp = expand_expr (arg, NULL_RTX, VOIDmode, 0);
5366  if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
5367    {
5368      imode = int_mode_for_mode (fmode);
5369      if (imode == BLKmode)
5370	return 0;
5371      temp = gen_lowpart (imode, temp);
5372    }
5373  else
5374    {
5375      imode = word_mode;
5376      /* Handle targets with different FP word orders.  */
5377      if (FLOAT_WORDS_BIG_ENDIAN)
5378        word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
5379      else
5380        word = bitpos / BITS_PER_WORD;
5381      temp = operand_subword_force (temp, word, fmode);
5382      bitpos = bitpos % BITS_PER_WORD;
5383    }
5384
5385  /* Force the intermediate word_mode (or narrower) result into a
5386     register.  This avoids attempting to create paradoxical SUBREGs
5387     of floating point modes below.  */
5388  temp = force_reg (imode, temp);
5389
5390  /* If the bitpos is within the "result mode" lowpart, the operation
5391     can be implement with a single bitwise AND.  Otherwise, we need
5392     a right shift and an AND.  */
5393
5394  if (bitpos < GET_MODE_BITSIZE (rmode))
5395    {
5396      if (bitpos < HOST_BITS_PER_WIDE_INT)
5397	{
5398	  hi = 0;
5399	  lo = (HOST_WIDE_INT) 1 << bitpos;
5400	}
5401      else
5402	{
5403	  hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5404	  lo = 0;
5405	}
5406
5407      if (imode != rmode)
5408	temp = gen_lowpart (rmode, temp);
5409      temp = expand_binop (rmode, and_optab, temp,
5410			   immed_double_const (lo, hi, rmode),
5411			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
5412    }
5413  else
5414    {
5415      /* Perform a logical right shift to place the signbit in the least
5416         significant bit, then truncate the result to the desired mode
5417	 and mask just this bit.  */
5418      temp = expand_shift (RSHIFT_EXPR, imode, temp,
5419			   build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5420      temp = gen_lowpart (rmode, temp);
5421      temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5422			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
5423    }
5424
5425  return temp;
5426}
5427
5428/* Expand fork or exec calls.  TARGET is the desired target of the
5429   call.  ARGLIST is the list of arguments of the call.  FN is the
5430   identificator of the actual function.  IGNORE is nonzero if the
5431   value is to be ignored.  */
5432
5433static rtx
5434expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
5435{
5436  tree id, decl;
5437  tree call;
5438
5439  /* If we are not profiling, just call the function.  */
5440  if (!profile_arc_flag)
5441    return NULL_RTX;
5442
5443  /* Otherwise call the wrapper.  This should be equivalent for the rest of
5444     compiler, so the code does not diverge, and the wrapper may run the
5445     code necessary for keeping the profiling sane.  */
5446
5447  switch (DECL_FUNCTION_CODE (fn))
5448    {
5449    case BUILT_IN_FORK:
5450      id = get_identifier ("__gcov_fork");
5451      break;
5452
5453    case BUILT_IN_EXECL:
5454      id = get_identifier ("__gcov_execl");
5455      break;
5456
5457    case BUILT_IN_EXECV:
5458      id = get_identifier ("__gcov_execv");
5459      break;
5460
5461    case BUILT_IN_EXECLP:
5462      id = get_identifier ("__gcov_execlp");
5463      break;
5464
5465    case BUILT_IN_EXECLE:
5466      id = get_identifier ("__gcov_execle");
5467      break;
5468
5469    case BUILT_IN_EXECVP:
5470      id = get_identifier ("__gcov_execvp");
5471      break;
5472
5473    case BUILT_IN_EXECVE:
5474      id = get_identifier ("__gcov_execve");
5475      break;
5476
5477    default:
5478      gcc_unreachable ();
5479    }
5480
5481  decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
5482  DECL_EXTERNAL (decl) = 1;
5483  TREE_PUBLIC (decl) = 1;
5484  DECL_ARTIFICIAL (decl) = 1;
5485  TREE_NOTHROW (decl) = 1;
5486  DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5487  DECL_VISIBILITY_SPECIFIED (decl) = 1;
5488  call = build_function_call_expr (decl, arglist);
5489
5490  return expand_call (call, target, ignore);
5491}
5492
5493
5494/* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
5495   the pointer in these functions is void*, the tree optimizers may remove
5496   casts.  The mode computed in expand_builtin isn't reliable either, due
5497   to __sync_bool_compare_and_swap.
5498
5499   FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5500   group of builtins.  This gives us log2 of the mode size.  */
5501
5502static inline enum machine_mode
5503get_builtin_sync_mode (int fcode_diff)
5504{
5505  /* The size is not negotiable, so ask not to get BLKmode in return
5506     if the target indicates that a smaller size would be better.  */
5507  return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
5508}
5509
5510/* Expand the memory expression LOC and return the appropriate memory operand
5511   for the builtin_sync operations.  */
5512
5513static rtx
5514get_builtin_sync_mem (tree loc, enum machine_mode mode)
5515{
5516  rtx addr, mem;
5517
5518  addr = expand_expr (loc, NULL, Pmode, EXPAND_SUM);
5519
5520  /* Note that we explicitly do not want any alias information for this
5521     memory, so that we kill all other live memories.  Otherwise we don't
5522     satisfy the full barrier semantics of the intrinsic.  */
5523  mem = validize_mem (gen_rtx_MEM (mode, addr));
5524
5525  set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
5526  set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
5527  MEM_VOLATILE_P (mem) = 1;
5528
5529  return mem;
5530}
5531
5532/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
5533   ARGLIST is the operands list to the function.  CODE is the rtx code
5534   that corresponds to the arithmetic or logical operation from the name;
5535   an exception here is that NOT actually means NAND.  TARGET is an optional
5536   place for us to store the results; AFTER is true if this is the
5537   fetch_and_xxx form.  IGNORE is true if we don't actually care about
5538   the result of the operation at all.  */
5539
5540static rtx
5541expand_builtin_sync_operation (enum machine_mode mode, tree arglist,
5542			       enum rtx_code code, bool after,
5543			       rtx target, bool ignore)
5544{
5545  rtx val, mem;
5546
5547  /* Expand the operands.  */
5548  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5549
5550  arglist = TREE_CHAIN (arglist);
5551  val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5552  /* If VAL is promoted to a wider mode, convert it back to MODE.  */
5553  val = convert_to_mode (mode, val, 1);
5554
5555  if (ignore)
5556    return expand_sync_operation (mem, val, code);
5557  else
5558    return expand_sync_fetch_operation (mem, val, code, after, target);
5559}
5560
5561/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
5562   intrinsics.  ARGLIST is the operands list to the function.  IS_BOOL is
5563   true if this is the boolean form.  TARGET is a place for us to store the
5564   results; this is NOT optional if IS_BOOL is true.  */
5565
5566static rtx
5567expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
5568				 bool is_bool, rtx target)
5569{
5570  rtx old_val, new_val, mem;
5571
5572  /* Expand the operands.  */
5573  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5574
5575  arglist = TREE_CHAIN (arglist);
5576  old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5577  /* If OLD_VAL is promoted to a wider mode, convert it back to MODE.  */
5578  old_val = convert_to_mode (mode, old_val, 1);
5579
5580  arglist = TREE_CHAIN (arglist);
5581  new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5582  /* If NEW_VAL is promoted to a wider mode, convert it back to MODE.  */
5583  new_val = convert_to_mode (mode, new_val, 1);
5584
5585  if (is_bool)
5586    return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5587  else
5588    return expand_val_compare_and_swap (mem, old_val, new_val, target);
5589}
5590
5591/* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
5592   general form is actually an atomic exchange, and some targets only
5593   support a reduced form with the second argument being a constant 1.
5594   ARGLIST is the operands list to the function; TARGET is an optional
5595   place for us to store the results.  */
5596
5597static rtx
5598expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
5599				  rtx target)
5600{
5601  rtx val, mem;
5602
5603  /* Expand the operands.  */
5604  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5605
5606  arglist = TREE_CHAIN (arglist);
5607  val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5608  /* If VAL is promoted to a wider mode, convert it back to MODE.  */
5609  val = convert_to_mode (mode, val, 1);
5610
5611  return expand_sync_lock_test_and_set (mem, val, target);
5612}
5613
5614/* Expand the __sync_synchronize intrinsic.  */
5615
5616static void
5617expand_builtin_synchronize (void)
5618{
5619  tree x;
5620
5621#ifdef HAVE_memory_barrier
5622  if (HAVE_memory_barrier)
5623    {
5624      emit_insn (gen_memory_barrier ());
5625      return;
5626    }
5627#endif
5628
5629  /* If no explicit memory barrier instruction is available, create an
5630     empty asm stmt with a memory clobber.  */
5631  x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
5632	      tree_cons (NULL, build_string (6, "memory"), NULL));
5633  ASM_VOLATILE_P (x) = 1;
5634  expand_asm_expr (x);
5635}
5636
5637/* Expand the __sync_lock_release intrinsic.  ARGLIST is the operands list
5638   to the function.  */
5639
5640static void
5641expand_builtin_lock_release (enum machine_mode mode, tree arglist)
5642{
5643  enum insn_code icode;
5644  rtx mem, insn;
5645  rtx val = const0_rtx;
5646
5647  /* Expand the operands.  */
5648  mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5649
5650  /* If there is an explicit operation in the md file, use it.  */
5651  icode = sync_lock_release[mode];
5652  if (icode != CODE_FOR_nothing)
5653    {
5654      if (!insn_data[icode].operand[1].predicate (val, mode))
5655	val = force_reg (mode, val);
5656
5657      insn = GEN_FCN (icode) (mem, val);
5658      if (insn)
5659	{
5660	  emit_insn (insn);
5661	  return;
5662	}
5663    }
5664
5665  /* Otherwise we can implement this operation by emitting a barrier
5666     followed by a store of zero.  */
5667  expand_builtin_synchronize ();
5668  emit_move_insn (mem, val);
5669}
5670
5671/* Expand an expression EXP that calls a built-in function,
5672   with result going to TARGET if that's convenient
5673   (and in mode MODE if that's convenient).
5674   SUBTARGET may be used as the target for computing one of EXP's operands.
5675   IGNORE is nonzero if the value is to be ignored.  */
5676
5677rtx
5678expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5679		int ignore)
5680{
5681  tree fndecl = get_callee_fndecl (exp);
5682  tree arglist = TREE_OPERAND (exp, 1);
5683  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5684  enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
5685
5686  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
5687    return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
5688
5689  /* When not optimizing, generate calls to library functions for a certain
5690     set of builtins.  */
5691  if (!optimize
5692      && !called_as_built_in (fndecl)
5693      && DECL_ASSEMBLER_NAME_SET_P (fndecl)
5694      && fcode != BUILT_IN_ALLOCA)
5695    return expand_call (exp, target, ignore);
5696
5697  /* The built-in function expanders test for target == const0_rtx
5698     to determine whether the function's result will be ignored.  */
5699  if (ignore)
5700    target = const0_rtx;
5701
5702  /* If the result of a pure or const built-in function is ignored, and
5703     none of its arguments are volatile, we can avoid expanding the
5704     built-in call and just evaluate the arguments for side-effects.  */
5705  if (target == const0_rtx
5706      && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
5707    {
5708      bool volatilep = false;
5709      tree arg;
5710
5711      for (arg = arglist; arg; arg = TREE_CHAIN (arg))
5712	if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
5713	  {
5714	    volatilep = true;
5715	    break;
5716	  }
5717
5718      if (! volatilep)
5719	{
5720	  for (arg = arglist; arg; arg = TREE_CHAIN (arg))
5721	    expand_expr (TREE_VALUE (arg), const0_rtx,
5722			 VOIDmode, EXPAND_NORMAL);
5723	  return const0_rtx;
5724	}
5725    }
5726
5727  switch (fcode)
5728    {
5729    case BUILT_IN_FABS:
5730    case BUILT_IN_FABSF:
5731    case BUILT_IN_FABSL:
5732      target = expand_builtin_fabs (arglist, target, subtarget);
5733      if (target)
5734        return target;
5735      break;
5736
5737    case BUILT_IN_COPYSIGN:
5738    case BUILT_IN_COPYSIGNF:
5739    case BUILT_IN_COPYSIGNL:
5740      target = expand_builtin_copysign (arglist, target, subtarget);
5741      if (target)
5742	return target;
5743      break;
5744
5745      /* Just do a normal library call if we were unable to fold
5746	 the values.  */
5747    case BUILT_IN_CABS:
5748    case BUILT_IN_CABSF:
5749    case BUILT_IN_CABSL:
5750      break;
5751
5752    case BUILT_IN_EXP:
5753    case BUILT_IN_EXPF:
5754    case BUILT_IN_EXPL:
5755    case BUILT_IN_EXP10:
5756    case BUILT_IN_EXP10F:
5757    case BUILT_IN_EXP10L:
5758    case BUILT_IN_POW10:
5759    case BUILT_IN_POW10F:
5760    case BUILT_IN_POW10L:
5761    case BUILT_IN_EXP2:
5762    case BUILT_IN_EXP2F:
5763    case BUILT_IN_EXP2L:
5764    case BUILT_IN_EXPM1:
5765    case BUILT_IN_EXPM1F:
5766    case BUILT_IN_EXPM1L:
5767    case BUILT_IN_LOGB:
5768    case BUILT_IN_LOGBF:
5769    case BUILT_IN_LOGBL:
5770    case BUILT_IN_ILOGB:
5771    case BUILT_IN_ILOGBF:
5772    case BUILT_IN_ILOGBL:
5773    case BUILT_IN_LOG:
5774    case BUILT_IN_LOGF:
5775    case BUILT_IN_LOGL:
5776    case BUILT_IN_LOG10:
5777    case BUILT_IN_LOG10F:
5778    case BUILT_IN_LOG10L:
5779    case BUILT_IN_LOG2:
5780    case BUILT_IN_LOG2F:
5781    case BUILT_IN_LOG2L:
5782    case BUILT_IN_LOG1P:
5783    case BUILT_IN_LOG1PF:
5784    case BUILT_IN_LOG1PL:
5785    case BUILT_IN_TAN:
5786    case BUILT_IN_TANF:
5787    case BUILT_IN_TANL:
5788    case BUILT_IN_ASIN:
5789    case BUILT_IN_ASINF:
5790    case BUILT_IN_ASINL:
5791    case BUILT_IN_ACOS:
5792    case BUILT_IN_ACOSF:
5793    case BUILT_IN_ACOSL:
5794    case BUILT_IN_ATAN:
5795    case BUILT_IN_ATANF:
5796    case BUILT_IN_ATANL:
5797      /* Treat these like sqrt only if unsafe math optimizations are allowed,
5798	 because of possible accuracy problems.  */
5799      if (! flag_unsafe_math_optimizations)
5800	break;
5801    case BUILT_IN_SQRT:
5802    case BUILT_IN_SQRTF:
5803    case BUILT_IN_SQRTL:
5804    case BUILT_IN_FLOOR:
5805    case BUILT_IN_FLOORF:
5806    case BUILT_IN_FLOORL:
5807    case BUILT_IN_CEIL:
5808    case BUILT_IN_CEILF:
5809    case BUILT_IN_CEILL:
5810    case BUILT_IN_TRUNC:
5811    case BUILT_IN_TRUNCF:
5812    case BUILT_IN_TRUNCL:
5813    case BUILT_IN_ROUND:
5814    case BUILT_IN_ROUNDF:
5815    case BUILT_IN_ROUNDL:
5816    case BUILT_IN_NEARBYINT:
5817    case BUILT_IN_NEARBYINTF:
5818    case BUILT_IN_NEARBYINTL:
5819    case BUILT_IN_RINT:
5820    case BUILT_IN_RINTF:
5821    case BUILT_IN_RINTL:
5822    case BUILT_IN_LRINT:
5823    case BUILT_IN_LRINTF:
5824    case BUILT_IN_LRINTL:
5825    case BUILT_IN_LLRINT:
5826    case BUILT_IN_LLRINTF:
5827    case BUILT_IN_LLRINTL:
5828      target = expand_builtin_mathfn (exp, target, subtarget);
5829      if (target)
5830	return target;
5831      break;
5832
5833    case BUILT_IN_LCEIL:
5834    case BUILT_IN_LCEILF:
5835    case BUILT_IN_LCEILL:
5836    case BUILT_IN_LLCEIL:
5837    case BUILT_IN_LLCEILF:
5838    case BUILT_IN_LLCEILL:
5839    case BUILT_IN_LFLOOR:
5840    case BUILT_IN_LFLOORF:
5841    case BUILT_IN_LFLOORL:
5842    case BUILT_IN_LLFLOOR:
5843    case BUILT_IN_LLFLOORF:
5844    case BUILT_IN_LLFLOORL:
5845      target = expand_builtin_int_roundingfn (exp, target, subtarget);
5846      if (target)
5847	return target;
5848      break;
5849
5850    case BUILT_IN_POW:
5851    case BUILT_IN_POWF:
5852    case BUILT_IN_POWL:
5853      target = expand_builtin_pow (exp, target, subtarget);
5854      if (target)
5855	return target;
5856      break;
5857
5858    case BUILT_IN_POWI:
5859    case BUILT_IN_POWIF:
5860    case BUILT_IN_POWIL:
5861      target = expand_builtin_powi (exp, target, subtarget);
5862      if (target)
5863	return target;
5864      break;
5865
5866    case BUILT_IN_ATAN2:
5867    case BUILT_IN_ATAN2F:
5868    case BUILT_IN_ATAN2L:
5869    case BUILT_IN_LDEXP:
5870    case BUILT_IN_LDEXPF:
5871    case BUILT_IN_LDEXPL:
5872    case BUILT_IN_FMOD:
5873    case BUILT_IN_FMODF:
5874    case BUILT_IN_FMODL:
5875    case BUILT_IN_DREM:
5876    case BUILT_IN_DREMF:
5877    case BUILT_IN_DREML:
5878      if (! flag_unsafe_math_optimizations)
5879	break;
5880      target = expand_builtin_mathfn_2 (exp, target, subtarget);
5881      if (target)
5882	return target;
5883      break;
5884
5885    case BUILT_IN_SIN:
5886    case BUILT_IN_SINF:
5887    case BUILT_IN_SINL:
5888    case BUILT_IN_COS:
5889    case BUILT_IN_COSF:
5890    case BUILT_IN_COSL:
5891      if (! flag_unsafe_math_optimizations)
5892	break;
5893      target = expand_builtin_mathfn_3 (exp, target, subtarget);
5894      if (target)
5895	return target;
5896      break;
5897
5898    case BUILT_IN_APPLY_ARGS:
5899      return expand_builtin_apply_args ();
5900
5901      /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5902	 FUNCTION with a copy of the parameters described by
5903	 ARGUMENTS, and ARGSIZE.  It returns a block of memory
5904	 allocated on the stack into which is stored all the registers
5905	 that might possibly be used for returning the result of a
5906	 function.  ARGUMENTS is the value returned by
5907	 __builtin_apply_args.  ARGSIZE is the number of bytes of
5908	 arguments that must be copied.  ??? How should this value be
5909	 computed?  We'll also need a safe worst case value for varargs
5910	 functions.  */
5911    case BUILT_IN_APPLY:
5912      if (!validate_arglist (arglist, POINTER_TYPE,
5913			     POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
5914	  && !validate_arglist (arglist, REFERENCE_TYPE,
5915				POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
5916	return const0_rtx;
5917      else
5918	{
5919	  int i;
5920	  tree t;
5921	  rtx ops[3];
5922
5923	  for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
5924	    ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
5925
5926	  return expand_builtin_apply (ops[0], ops[1], ops[2]);
5927	}
5928
5929      /* __builtin_return (RESULT) causes the function to return the
5930	 value described by RESULT.  RESULT is address of the block of
5931	 memory returned by __builtin_apply.  */
5932    case BUILT_IN_RETURN:
5933      if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5934	expand_builtin_return (expand_expr (TREE_VALUE (arglist),
5935					    NULL_RTX, VOIDmode, 0));
5936      return const0_rtx;
5937
5938    case BUILT_IN_SAVEREGS:
5939      return expand_builtin_saveregs ();
5940
5941    case BUILT_IN_ARGS_INFO:
5942      return expand_builtin_args_info (arglist);
5943
5944      /* Return the address of the first anonymous stack arg.  */
5945    case BUILT_IN_NEXT_ARG:
5946      if (fold_builtin_next_arg (arglist))
5947        return const0_rtx;
5948      return expand_builtin_next_arg ();
5949
5950    case BUILT_IN_CLASSIFY_TYPE:
5951      return expand_builtin_classify_type (arglist);
5952
5953    case BUILT_IN_CONSTANT_P:
5954      return const0_rtx;
5955
5956    case BUILT_IN_FRAME_ADDRESS:
5957    case BUILT_IN_RETURN_ADDRESS:
5958      return expand_builtin_frame_address (fndecl, arglist);
5959
5960    /* Returns the address of the area where the structure is returned.
5961       0 otherwise.  */
5962    case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
5963      if (arglist != 0
5964	  || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
5965	  || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
5966	return const0_rtx;
5967      else
5968	return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
5969
5970    case BUILT_IN_ALLOCA:
5971      target = expand_builtin_alloca (arglist, target);
5972      if (target)
5973	return target;
5974      break;
5975
5976    case BUILT_IN_STACK_SAVE:
5977      return expand_stack_save ();
5978
5979    case BUILT_IN_STACK_RESTORE:
5980      expand_stack_restore (TREE_VALUE (arglist));
5981      return const0_rtx;
5982
5983    case BUILT_IN_FFS:
5984    case BUILT_IN_FFSL:
5985    case BUILT_IN_FFSLL:
5986    case BUILT_IN_FFSIMAX:
5987      target = expand_builtin_unop (target_mode, arglist, target,
5988				    subtarget, ffs_optab);
5989      if (target)
5990	return target;
5991      break;
5992
5993    case BUILT_IN_CLZ:
5994    case BUILT_IN_CLZL:
5995    case BUILT_IN_CLZLL:
5996    case BUILT_IN_CLZIMAX:
5997      target = expand_builtin_unop (target_mode, arglist, target,
5998				    subtarget, clz_optab);
5999      if (target)
6000	return target;
6001      break;
6002
6003    case BUILT_IN_CTZ:
6004    case BUILT_IN_CTZL:
6005    case BUILT_IN_CTZLL:
6006    case BUILT_IN_CTZIMAX:
6007      target = expand_builtin_unop (target_mode, arglist, target,
6008				    subtarget, ctz_optab);
6009      if (target)
6010	return target;
6011      break;
6012
6013    case BUILT_IN_POPCOUNT:
6014    case BUILT_IN_POPCOUNTL:
6015    case BUILT_IN_POPCOUNTLL:
6016    case BUILT_IN_POPCOUNTIMAX:
6017      target = expand_builtin_unop (target_mode, arglist, target,
6018				    subtarget, popcount_optab);
6019      if (target)
6020	return target;
6021      break;
6022
6023    case BUILT_IN_PARITY:
6024    case BUILT_IN_PARITYL:
6025    case BUILT_IN_PARITYLL:
6026    case BUILT_IN_PARITYIMAX:
6027      target = expand_builtin_unop (target_mode, arglist, target,
6028				    subtarget, parity_optab);
6029      if (target)
6030	return target;
6031      break;
6032
6033    case BUILT_IN_STRLEN:
6034      target = expand_builtin_strlen (arglist, target, target_mode);
6035      if (target)
6036	return target;
6037      break;
6038
6039    case BUILT_IN_STRCPY:
6040      target = expand_builtin_strcpy (fndecl, arglist, target, mode);
6041      if (target)
6042	return target;
6043      break;
6044
6045    case BUILT_IN_STRNCPY:
6046      target = expand_builtin_strncpy (exp, target, mode);
6047      if (target)
6048	return target;
6049      break;
6050
6051    case BUILT_IN_STPCPY:
6052      target = expand_builtin_stpcpy (exp, target, mode);
6053      if (target)
6054	return target;
6055      break;
6056
6057    case BUILT_IN_STRCAT:
6058      target = expand_builtin_strcat (fndecl, arglist, target, mode);
6059      if (target)
6060	return target;
6061      break;
6062
6063    case BUILT_IN_STRNCAT:
6064      target = expand_builtin_strncat (arglist, target, mode);
6065      if (target)
6066	return target;
6067      break;
6068
6069    case BUILT_IN_STRSPN:
6070      target = expand_builtin_strspn (arglist, target, mode);
6071      if (target)
6072	return target;
6073      break;
6074
6075    case BUILT_IN_STRCSPN:
6076      target = expand_builtin_strcspn (arglist, target, mode);
6077      if (target)
6078	return target;
6079      break;
6080
6081    case BUILT_IN_STRSTR:
6082      target = expand_builtin_strstr (arglist, TREE_TYPE (exp), target, mode);
6083      if (target)
6084	return target;
6085      break;
6086
6087    case BUILT_IN_STRPBRK:
6088      target = expand_builtin_strpbrk (arglist, TREE_TYPE (exp), target, mode);
6089      if (target)
6090	return target;
6091      break;
6092
6093    case BUILT_IN_INDEX:
6094    case BUILT_IN_STRCHR:
6095      target = expand_builtin_strchr (arglist, TREE_TYPE (exp), target, mode);
6096      if (target)
6097	return target;
6098      break;
6099
6100    case BUILT_IN_RINDEX:
6101    case BUILT_IN_STRRCHR:
6102      target = expand_builtin_strrchr (arglist, TREE_TYPE (exp), target, mode);
6103      if (target)
6104	return target;
6105      break;
6106
6107    case BUILT_IN_MEMCPY:
6108      target = expand_builtin_memcpy (exp, target, mode);
6109      if (target)
6110	return target;
6111      break;
6112
6113    case BUILT_IN_MEMPCPY:
6114      target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
6115      if (target)
6116	return target;
6117      break;
6118
6119    case BUILT_IN_MEMMOVE:
6120      target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target,
6121				       mode, exp);
6122      if (target)
6123	return target;
6124      break;
6125
6126    case BUILT_IN_BCOPY:
6127      target = expand_builtin_bcopy (exp);
6128      if (target)
6129	return target;
6130      break;
6131
6132    case BUILT_IN_MEMSET:
6133      target = expand_builtin_memset (arglist, target, mode, exp);
6134      if (target)
6135	return target;
6136      break;
6137
6138    case BUILT_IN_BZERO:
6139      target = expand_builtin_bzero (exp);
6140      if (target)
6141	return target;
6142      break;
6143
6144    case BUILT_IN_STRCMP:
6145      target = expand_builtin_strcmp (exp, target, mode);
6146      if (target)
6147	return target;
6148      break;
6149
6150    case BUILT_IN_STRNCMP:
6151      target = expand_builtin_strncmp (exp, target, mode);
6152      if (target)
6153	return target;
6154      break;
6155
6156    case BUILT_IN_BCMP:
6157    case BUILT_IN_MEMCMP:
6158      target = expand_builtin_memcmp (exp, arglist, target, mode);
6159      if (target)
6160	return target;
6161      break;
6162
6163    case BUILT_IN_SETJMP:
6164      target = expand_builtin_setjmp (arglist, target);
6165      if (target)
6166	return target;
6167      break;
6168
6169      /* __builtin_longjmp is passed a pointer to an array of five words.
6170	 It's similar to the C library longjmp function but works with
6171	 __builtin_setjmp above.  */
6172    case BUILT_IN_LONGJMP:
6173      if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
6174	break;
6175      else
6176	{
6177	  rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
6178				      VOIDmode, 0);
6179	  rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
6180				   NULL_RTX, VOIDmode, 0);
6181
6182	  if (value != const1_rtx)
6183	    {
6184	      error ("%<__builtin_longjmp%> second argument must be 1");
6185	      return const0_rtx;
6186	    }
6187
6188	  expand_builtin_longjmp (buf_addr, value);
6189	  return const0_rtx;
6190	}
6191
6192    case BUILT_IN_NONLOCAL_GOTO:
6193      target = expand_builtin_nonlocal_goto (arglist);
6194      if (target)
6195	return target;
6196      break;
6197
6198      /* This updates the setjmp buffer that is its argument with the value
6199	 of the current stack pointer.  */
6200    case BUILT_IN_UPDATE_SETJMP_BUF:
6201      if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6202	{
6203	  rtx buf_addr
6204	    = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
6205
6206	  expand_builtin_update_setjmp_buf (buf_addr);
6207	  return const0_rtx;
6208	}
6209      break;
6210
6211    case BUILT_IN_TRAP:
6212      expand_builtin_trap ();
6213      return const0_rtx;
6214
6215    case BUILT_IN_PRINTF:
6216      target = expand_builtin_printf (exp, target, mode, false);
6217      if (target)
6218	return target;
6219      break;
6220
6221    case BUILT_IN_PRINTF_UNLOCKED:
6222      target = expand_builtin_printf (exp, target, mode, true);
6223      if (target)
6224	return target;
6225      break;
6226
6227    case BUILT_IN_FPUTS:
6228      target = expand_builtin_fputs (arglist, target, false);
6229      if (target)
6230	return target;
6231      break;
6232    case BUILT_IN_FPUTS_UNLOCKED:
6233      target = expand_builtin_fputs (arglist, target, true);
6234      if (target)
6235	return target;
6236      break;
6237
6238    case BUILT_IN_FPRINTF:
6239      target = expand_builtin_fprintf (exp, target, mode, false);
6240      if (target)
6241	return target;
6242      break;
6243
6244    case BUILT_IN_FPRINTF_UNLOCKED:
6245      target = expand_builtin_fprintf (exp, target, mode, true);
6246      if (target)
6247	return target;
6248      break;
6249
6250    case BUILT_IN_SPRINTF:
6251      target = expand_builtin_sprintf (arglist, target, mode);
6252      if (target)
6253	return target;
6254      break;
6255
6256    case BUILT_IN_SIGNBIT:
6257    case BUILT_IN_SIGNBITF:
6258    case BUILT_IN_SIGNBITL:
6259      target = expand_builtin_signbit (exp, target);
6260      if (target)
6261	return target;
6262      break;
6263
6264      /* Various hooks for the DWARF 2 __throw routine.  */
6265    case BUILT_IN_UNWIND_INIT:
6266      expand_builtin_unwind_init ();
6267      return const0_rtx;
6268    case BUILT_IN_DWARF_CFA:
6269      return virtual_cfa_rtx;
6270#ifdef DWARF2_UNWIND_INFO
6271    case BUILT_IN_DWARF_SP_COLUMN:
6272      return expand_builtin_dwarf_sp_column ();
6273    case BUILT_IN_INIT_DWARF_REG_SIZES:
6274      expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
6275      return const0_rtx;
6276#endif
6277    case BUILT_IN_FROB_RETURN_ADDR:
6278      return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
6279    case BUILT_IN_EXTRACT_RETURN_ADDR:
6280      return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
6281    case BUILT_IN_EH_RETURN:
6282      expand_builtin_eh_return (TREE_VALUE (arglist),
6283				TREE_VALUE (TREE_CHAIN (arglist)));
6284      return const0_rtx;
6285#ifdef EH_RETURN_DATA_REGNO
6286    case BUILT_IN_EH_RETURN_DATA_REGNO:
6287      return expand_builtin_eh_return_data_regno (arglist);
6288#endif
6289    case BUILT_IN_EXTEND_POINTER:
6290      return expand_builtin_extend_pointer (TREE_VALUE (arglist));
6291
6292    case BUILT_IN_VA_START:
6293    case BUILT_IN_STDARG_START:
6294      return expand_builtin_va_start (arglist);
6295    case BUILT_IN_VA_END:
6296      return expand_builtin_va_end (arglist);
6297    case BUILT_IN_VA_COPY:
6298      return expand_builtin_va_copy (arglist);
6299    case BUILT_IN_EXPECT:
6300      return expand_builtin_expect (arglist, target);
6301    case BUILT_IN_PREFETCH:
6302      expand_builtin_prefetch (arglist);
6303      return const0_rtx;
6304
6305    case BUILT_IN_PROFILE_FUNC_ENTER:
6306      return expand_builtin_profile_func (false);
6307    case BUILT_IN_PROFILE_FUNC_EXIT:
6308      return expand_builtin_profile_func (true);
6309
6310    case BUILT_IN_INIT_TRAMPOLINE:
6311      return expand_builtin_init_trampoline (arglist);
6312    case BUILT_IN_ADJUST_TRAMPOLINE:
6313      return expand_builtin_adjust_trampoline (arglist);
6314
6315    case BUILT_IN_FORK:
6316    case BUILT_IN_EXECL:
6317    case BUILT_IN_EXECV:
6318    case BUILT_IN_EXECLP:
6319    case BUILT_IN_EXECLE:
6320    case BUILT_IN_EXECVP:
6321    case BUILT_IN_EXECVE:
6322      target = expand_builtin_fork_or_exec (fndecl, arglist, target, ignore);
6323      if (target)
6324	return target;
6325      break;
6326
6327    case BUILT_IN_FETCH_AND_ADD_1:
6328    case BUILT_IN_FETCH_AND_ADD_2:
6329    case BUILT_IN_FETCH_AND_ADD_4:
6330    case BUILT_IN_FETCH_AND_ADD_8:
6331      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
6332      target = expand_builtin_sync_operation (mode, arglist, PLUS,
6333					      false, target, ignore);
6334      if (target)
6335	return target;
6336      break;
6337
6338    case BUILT_IN_FETCH_AND_SUB_1:
6339    case BUILT_IN_FETCH_AND_SUB_2:
6340    case BUILT_IN_FETCH_AND_SUB_4:
6341    case BUILT_IN_FETCH_AND_SUB_8:
6342      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
6343      target = expand_builtin_sync_operation (mode, arglist, MINUS,
6344					      false, target, ignore);
6345      if (target)
6346	return target;
6347      break;
6348
6349    case BUILT_IN_FETCH_AND_OR_1:
6350    case BUILT_IN_FETCH_AND_OR_2:
6351    case BUILT_IN_FETCH_AND_OR_4:
6352    case BUILT_IN_FETCH_AND_OR_8:
6353      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
6354      target = expand_builtin_sync_operation (mode, arglist, IOR,
6355					      false, target, ignore);
6356      if (target)
6357	return target;
6358      break;
6359
6360    case BUILT_IN_FETCH_AND_AND_1:
6361    case BUILT_IN_FETCH_AND_AND_2:
6362    case BUILT_IN_FETCH_AND_AND_4:
6363    case BUILT_IN_FETCH_AND_AND_8:
6364      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
6365      target = expand_builtin_sync_operation (mode, arglist, AND,
6366					      false, target, ignore);
6367      if (target)
6368	return target;
6369      break;
6370
6371    case BUILT_IN_FETCH_AND_XOR_1:
6372    case BUILT_IN_FETCH_AND_XOR_2:
6373    case BUILT_IN_FETCH_AND_XOR_4:
6374    case BUILT_IN_FETCH_AND_XOR_8:
6375      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
6376      target = expand_builtin_sync_operation (mode, arglist, XOR,
6377					      false, target, ignore);
6378      if (target)
6379	return target;
6380      break;
6381
6382    case BUILT_IN_FETCH_AND_NAND_1:
6383    case BUILT_IN_FETCH_AND_NAND_2:
6384    case BUILT_IN_FETCH_AND_NAND_4:
6385    case BUILT_IN_FETCH_AND_NAND_8:
6386      mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
6387      target = expand_builtin_sync_operation (mode, arglist, NOT,
6388					      false, target, ignore);
6389      if (target)
6390	return target;
6391      break;
6392
6393    case BUILT_IN_ADD_AND_FETCH_1:
6394    case BUILT_IN_ADD_AND_FETCH_2:
6395    case BUILT_IN_ADD_AND_FETCH_4:
6396    case BUILT_IN_ADD_AND_FETCH_8:
6397      mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
6398      target = expand_builtin_sync_operation (mode, arglist, PLUS,
6399					      true, target, ignore);
6400      if (target)
6401	return target;
6402      break;
6403
6404    case BUILT_IN_SUB_AND_FETCH_1:
6405    case BUILT_IN_SUB_AND_FETCH_2:
6406    case BUILT_IN_SUB_AND_FETCH_4:
6407    case BUILT_IN_SUB_AND_FETCH_8:
6408      mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
6409      target = expand_builtin_sync_operation (mode, arglist, MINUS,
6410					      true, target, ignore);
6411      if (target)
6412	return target;
6413      break;
6414
6415    case BUILT_IN_OR_AND_FETCH_1:
6416    case BUILT_IN_OR_AND_FETCH_2:
6417    case BUILT_IN_OR_AND_FETCH_4:
6418    case BUILT_IN_OR_AND_FETCH_8:
6419      mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
6420      target = expand_builtin_sync_operation (mode, arglist, IOR,
6421					      true, target, ignore);
6422      if (target)
6423	return target;
6424      break;
6425
6426    case BUILT_IN_AND_AND_FETCH_1:
6427    case BUILT_IN_AND_AND_FETCH_2:
6428    case BUILT_IN_AND_AND_FETCH_4:
6429    case BUILT_IN_AND_AND_FETCH_8:
6430      mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
6431      target = expand_builtin_sync_operation (mode, arglist, AND,
6432					      true, target, ignore);
6433      if (target)
6434	return target;
6435      break;
6436
6437    case BUILT_IN_XOR_AND_FETCH_1:
6438    case BUILT_IN_XOR_AND_FETCH_2:
6439    case BUILT_IN_XOR_AND_FETCH_4:
6440    case BUILT_IN_XOR_AND_FETCH_8:
6441      mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
6442      target = expand_builtin_sync_operation (mode, arglist, XOR,
6443					      true, target, ignore);
6444      if (target)
6445	return target;
6446      break;
6447
6448    case BUILT_IN_NAND_AND_FETCH_1:
6449    case BUILT_IN_NAND_AND_FETCH_2:
6450    case BUILT_IN_NAND_AND_FETCH_4:
6451    case BUILT_IN_NAND_AND_FETCH_8:
6452      mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
6453      target = expand_builtin_sync_operation (mode, arglist, NOT,
6454					      true, target, ignore);
6455      if (target)
6456	return target;
6457      break;
6458
6459    case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6460    case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6461    case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6462    case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
6463      if (mode == VOIDmode)
6464	mode = TYPE_MODE (boolean_type_node);
6465      if (!target || !register_operand (target, mode))
6466	target = gen_reg_rtx (mode);
6467
6468      mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
6469      target = expand_builtin_compare_and_swap (mode, arglist, true, target);
6470      if (target)
6471	return target;
6472      break;
6473
6474    case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6475    case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6476    case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6477    case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
6478      mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
6479      target = expand_builtin_compare_and_swap (mode, arglist, false, target);
6480      if (target)
6481	return target;
6482      break;
6483
6484    case BUILT_IN_LOCK_TEST_AND_SET_1:
6485    case BUILT_IN_LOCK_TEST_AND_SET_2:
6486    case BUILT_IN_LOCK_TEST_AND_SET_4:
6487    case BUILT_IN_LOCK_TEST_AND_SET_8:
6488      mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
6489      target = expand_builtin_lock_test_and_set (mode, arglist, target);
6490      if (target)
6491	return target;
6492      break;
6493
6494    case BUILT_IN_LOCK_RELEASE_1:
6495    case BUILT_IN_LOCK_RELEASE_2:
6496    case BUILT_IN_LOCK_RELEASE_4:
6497    case BUILT_IN_LOCK_RELEASE_8:
6498      mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
6499      expand_builtin_lock_release (mode, arglist);
6500      return const0_rtx;
6501
6502    case BUILT_IN_SYNCHRONIZE:
6503      expand_builtin_synchronize ();
6504      return const0_rtx;
6505
6506    case BUILT_IN_OBJECT_SIZE:
6507      return expand_builtin_object_size (exp);
6508
6509    case BUILT_IN_MEMCPY_CHK:
6510    case BUILT_IN_MEMPCPY_CHK:
6511    case BUILT_IN_MEMMOVE_CHK:
6512    case BUILT_IN_MEMSET_CHK:
6513      target = expand_builtin_memory_chk (exp, target, mode, fcode);
6514      if (target)
6515	return target;
6516      break;
6517
6518    case BUILT_IN_STRCPY_CHK:
6519    case BUILT_IN_STPCPY_CHK:
6520    case BUILT_IN_STRNCPY_CHK:
6521    case BUILT_IN_STRCAT_CHK:
6522    case BUILT_IN_SNPRINTF_CHK:
6523    case BUILT_IN_VSNPRINTF_CHK:
6524      maybe_emit_chk_warning (exp, fcode);
6525      break;
6526
6527    case BUILT_IN_SPRINTF_CHK:
6528    case BUILT_IN_VSPRINTF_CHK:
6529      maybe_emit_sprintf_chk_warning (exp, fcode);
6530      break;
6531
6532    default:	/* just do library call, if unknown builtin */
6533      break;
6534    }
6535
6536  /* The switch statement above can drop through to cause the function
6537     to be called normally.  */
6538  return expand_call (exp, target, ignore);
6539}
6540
6541/* Determine whether a tree node represents a call to a built-in
6542   function.  If the tree T is a call to a built-in function with
6543   the right number of arguments of the appropriate types, return
6544   the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6545   Otherwise the return value is END_BUILTINS.  */
6546
6547enum built_in_function
6548builtin_mathfn_code (tree t)
6549{
6550  tree fndecl, arglist, parmlist;
6551  tree argtype, parmtype;
6552
6553  if (TREE_CODE (t) != CALL_EXPR
6554      || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
6555    return END_BUILTINS;
6556
6557  fndecl = get_callee_fndecl (t);
6558  if (fndecl == NULL_TREE
6559      || TREE_CODE (fndecl) != FUNCTION_DECL
6560      || ! DECL_BUILT_IN (fndecl)
6561      || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6562    return END_BUILTINS;
6563
6564  arglist = TREE_OPERAND (t, 1);
6565  parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
6566  for (; parmlist; parmlist = TREE_CHAIN (parmlist))
6567    {
6568      /* If a function doesn't take a variable number of arguments,
6569	 the last element in the list will have type `void'.  */
6570      parmtype = TREE_VALUE (parmlist);
6571      if (VOID_TYPE_P (parmtype))
6572	{
6573	  if (arglist)
6574	    return END_BUILTINS;
6575	  return DECL_FUNCTION_CODE (fndecl);
6576	}
6577
6578      if (! arglist)
6579	return END_BUILTINS;
6580
6581      argtype = TREE_TYPE (TREE_VALUE (arglist));
6582
6583      if (SCALAR_FLOAT_TYPE_P (parmtype))
6584	{
6585	  if (! SCALAR_FLOAT_TYPE_P (argtype))
6586	    return END_BUILTINS;
6587	}
6588      else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6589	{
6590	  if (! COMPLEX_FLOAT_TYPE_P (argtype))
6591	    return END_BUILTINS;
6592	}
6593      else if (POINTER_TYPE_P (parmtype))
6594	{
6595	  if (! POINTER_TYPE_P (argtype))
6596	    return END_BUILTINS;
6597	}
6598      else if (INTEGRAL_TYPE_P (parmtype))
6599	{
6600	  if (! INTEGRAL_TYPE_P (argtype))
6601	    return END_BUILTINS;
6602	}
6603      else
6604	return END_BUILTINS;
6605
6606      arglist = TREE_CHAIN (arglist);
6607    }
6608
6609  /* Variable-length argument list.  */
6610  return DECL_FUNCTION_CODE (fndecl);
6611}
6612
6613/* Fold a call to __builtin_constant_p, if we know it will evaluate to a
6614   constant.  ARGLIST is the argument list of the call.  */
6615
6616static tree
6617fold_builtin_constant_p (tree arglist)
6618{
6619  if (arglist == 0)
6620    return 0;
6621
6622  arglist = TREE_VALUE (arglist);
6623
6624  /* We return 1 for a numeric type that's known to be a constant
6625     value at compile-time or for an aggregate type that's a
6626     literal constant.  */
6627  STRIP_NOPS (arglist);
6628
6629  /* If we know this is a constant, emit the constant of one.  */
6630  if (CONSTANT_CLASS_P (arglist)
6631      || (TREE_CODE (arglist) == CONSTRUCTOR
6632	  && TREE_CONSTANT (arglist)))
6633    return integer_one_node;
6634  if (TREE_CODE (arglist) == ADDR_EXPR)
6635    {
6636       tree op = TREE_OPERAND (arglist, 0);
6637       if (TREE_CODE (op) == STRING_CST
6638	   || (TREE_CODE (op) == ARRAY_REF
6639	       && integer_zerop (TREE_OPERAND (op, 1))
6640	       && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6641	 return integer_one_node;
6642    }
6643
6644  /* If this expression has side effects, show we don't know it to be a
6645     constant.  Likewise if it's a pointer or aggregate type since in
6646     those case we only want literals, since those are only optimized
6647     when generating RTL, not later.
6648     And finally, if we are compiling an initializer, not code, we
6649     need to return a definite result now; there's not going to be any
6650     more optimization done.  */
6651  if (TREE_SIDE_EFFECTS (arglist)
6652      || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
6653      || POINTER_TYPE_P (TREE_TYPE (arglist))
6654      || cfun == 0)
6655    return integer_zero_node;
6656
6657  return 0;
6658}
6659
6660/* Fold a call to __builtin_expect, if we expect that a comparison against
6661   the argument will fold to a constant.  In practice, this means a true
6662   constant or the address of a non-weak symbol.  ARGLIST is the argument
6663   list of the call.  */
6664
6665static tree
6666fold_builtin_expect (tree arglist)
6667{
6668  tree arg, inner;
6669
6670  if (arglist == 0)
6671    return 0;
6672
6673  arg = TREE_VALUE (arglist);
6674
6675  /* If the argument isn't invariant, then there's nothing we can do.  */
6676  if (!TREE_INVARIANT (arg))
6677    return 0;
6678
6679  /* If we're looking at an address of a weak decl, then do not fold.  */
6680  inner = arg;
6681  STRIP_NOPS (inner);
6682  if (TREE_CODE (inner) == ADDR_EXPR)
6683    {
6684      do
6685	{
6686	  inner = TREE_OPERAND (inner, 0);
6687	}
6688      while (TREE_CODE (inner) == COMPONENT_REF
6689	     || TREE_CODE (inner) == ARRAY_REF);
6690      if (DECL_P (inner) && DECL_WEAK (inner))
6691	return 0;
6692    }
6693
6694  /* Otherwise, ARG already has the proper type for the return value.  */
6695  return arg;
6696}
6697
6698/* Fold a call to __builtin_classify_type.  */
6699
6700static tree
6701fold_builtin_classify_type (tree arglist)
6702{
6703  if (arglist == 0)
6704    return build_int_cst (NULL_TREE, no_type_class);
6705
6706  return build_int_cst (NULL_TREE,
6707			type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
6708}
6709
6710/* Fold a call to __builtin_strlen.  */
6711
6712static tree
6713fold_builtin_strlen (tree arglist)
6714{
6715  if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6716    return NULL_TREE;
6717  else
6718    {
6719      tree len = c_strlen (TREE_VALUE (arglist), 0);
6720
6721      if (len)
6722	{
6723	  /* Convert from the internal "sizetype" type to "size_t".  */
6724	  if (size_type_node)
6725	    len = fold_convert (size_type_node, len);
6726	  return len;
6727	}
6728
6729      return NULL_TREE;
6730    }
6731}
6732
6733/* Fold a call to __builtin_inf or __builtin_huge_val.  */
6734
6735static tree
6736fold_builtin_inf (tree type, int warn)
6737{
6738  REAL_VALUE_TYPE real;
6739
6740  /* __builtin_inff is intended to be usable to define INFINITY on all
6741     targets.  If an infinity is not available, INFINITY expands "to a
6742     positive constant of type float that overflows at translation
6743     time", footnote "In this case, using INFINITY will violate the
6744     constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
6745     Thus we pedwarn to ensure this constraint violation is
6746     diagnosed.  */
6747  if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
6748    pedwarn ("target format does not support infinity");
6749
6750  real_inf (&real);
6751  return build_real (type, real);
6752}
6753
6754/* Fold a call to __builtin_nan or __builtin_nans.  */
6755
6756static tree
6757fold_builtin_nan (tree arglist, tree type, int quiet)
6758{
6759  REAL_VALUE_TYPE real;
6760  const char *str;
6761
6762  if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6763    return 0;
6764  str = c_getstr (TREE_VALUE (arglist));
6765  if (!str)
6766    return 0;
6767
6768  if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
6769    return 0;
6770
6771  return build_real (type, real);
6772}
6773
6774/* Return true if the floating point expression T has an integer value.
6775   We also allow +Inf, -Inf and NaN to be considered integer values.  */
6776
6777static bool
6778integer_valued_real_p (tree t)
6779{
6780  switch (TREE_CODE (t))
6781    {
6782    case FLOAT_EXPR:
6783      return true;
6784
6785    case ABS_EXPR:
6786    case SAVE_EXPR:
6787    case NON_LVALUE_EXPR:
6788      return integer_valued_real_p (TREE_OPERAND (t, 0));
6789
6790    case COMPOUND_EXPR:
6791    case MODIFY_EXPR:
6792    case BIND_EXPR:
6793      return integer_valued_real_p (TREE_OPERAND (t, 1));
6794
6795    case PLUS_EXPR:
6796    case MINUS_EXPR:
6797    case MULT_EXPR:
6798    case MIN_EXPR:
6799    case MAX_EXPR:
6800      return integer_valued_real_p (TREE_OPERAND (t, 0))
6801	     && integer_valued_real_p (TREE_OPERAND (t, 1));
6802
6803    case COND_EXPR:
6804      return integer_valued_real_p (TREE_OPERAND (t, 1))
6805	     && integer_valued_real_p (TREE_OPERAND (t, 2));
6806
6807    case REAL_CST:
6808      if (! TREE_CONSTANT_OVERFLOW (t))
6809      {
6810        REAL_VALUE_TYPE c, cint;
6811
6812	c = TREE_REAL_CST (t);
6813	real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
6814	return real_identical (&c, &cint);
6815      }
6816      break;
6817
6818    case NOP_EXPR:
6819      {
6820	tree type = TREE_TYPE (TREE_OPERAND (t, 0));
6821	if (TREE_CODE (type) == INTEGER_TYPE)
6822	  return true;
6823	if (TREE_CODE (type) == REAL_TYPE)
6824	  return integer_valued_real_p (TREE_OPERAND (t, 0));
6825	break;
6826      }
6827
6828    case CALL_EXPR:
6829      switch (builtin_mathfn_code (t))
6830	{
6831	case BUILT_IN_CEIL:
6832	case BUILT_IN_CEILF:
6833	case BUILT_IN_CEILL:
6834	case BUILT_IN_FLOOR:
6835	case BUILT_IN_FLOORF:
6836	case BUILT_IN_FLOORL:
6837	case BUILT_IN_NEARBYINT:
6838	case BUILT_IN_NEARBYINTF:
6839	case BUILT_IN_NEARBYINTL:
6840	case BUILT_IN_RINT:
6841	case BUILT_IN_RINTF:
6842	case BUILT_IN_RINTL:
6843	case BUILT_IN_ROUND:
6844	case BUILT_IN_ROUNDF:
6845	case BUILT_IN_ROUNDL:
6846	case BUILT_IN_TRUNC:
6847	case BUILT_IN_TRUNCF:
6848	case BUILT_IN_TRUNCL:
6849	  return true;
6850
6851	default:
6852	  break;
6853	}
6854      break;
6855
6856    default:
6857      break;
6858    }
6859  return false;
6860}
6861
6862/* EXP is assumed to be builtin call where truncation can be propagated
6863   across (for instance floor((double)f) == (double)floorf (f).
6864   Do the transformation.  */
6865
6866static tree
6867fold_trunc_transparent_mathfn (tree fndecl, tree arglist)
6868{
6869  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
6870  tree arg;
6871
6872  if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6873    return 0;
6874
6875  arg = TREE_VALUE (arglist);
6876  /* Integer rounding functions are idempotent.  */
6877  if (fcode == builtin_mathfn_code (arg))
6878    return arg;
6879
6880  /* If argument is already integer valued, and we don't need to worry
6881     about setting errno, there's no need to perform rounding.  */
6882  if (! flag_errno_math && integer_valued_real_p (arg))
6883    return arg;
6884
6885  if (optimize)
6886    {
6887      tree arg0 = strip_float_extensions (arg);
6888      tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6889      tree newtype = TREE_TYPE (arg0);
6890      tree decl;
6891
6892      if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6893	  && (decl = mathfn_built_in (newtype, fcode)))
6894	{
6895	  arglist =
6896	    build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
6897	  return fold_convert (ftype,
6898			       build_function_call_expr (decl, arglist));
6899	}
6900    }
6901  return 0;
6902}
6903
6904/* EXP is assumed to be builtin call which can narrow the FP type of
6905   the argument, for instance lround((double)f) -> lroundf (f).  */
6906
6907static tree
6908fold_fixed_mathfn (tree fndecl, tree arglist)
6909{
6910  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
6911  tree arg;
6912
6913  if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6914    return 0;
6915
6916  arg = TREE_VALUE (arglist);
6917
6918  /* If argument is already integer valued, and we don't need to worry
6919     about setting errno, there's no need to perform rounding.  */
6920  if (! flag_errno_math && integer_valued_real_p (arg))
6921    return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
6922
6923  if (optimize)
6924    {
6925      tree ftype = TREE_TYPE (arg);
6926      tree arg0 = strip_float_extensions (arg);
6927      tree newtype = TREE_TYPE (arg0);
6928      tree decl;
6929
6930      if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6931	  && (decl = mathfn_built_in (newtype, fcode)))
6932	{
6933	  arglist =
6934	    build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
6935	  return build_function_call_expr (decl, arglist);
6936	}
6937    }
6938
6939  /* Canonicalize llround (x) to lround (x) on LP64 targets where
6940     sizeof (long long) == sizeof (long).  */
6941  if (TYPE_PRECISION (long_long_integer_type_node)
6942      == TYPE_PRECISION (long_integer_type_node))
6943    {
6944      tree newfn = NULL_TREE;
6945      switch (fcode)
6946	{
6947	case BUILT_IN_LLCEIL:
6948	case BUILT_IN_LLCEILF:
6949	case BUILT_IN_LLCEILL:
6950	  newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
6951	  break;
6952
6953	case BUILT_IN_LLFLOOR:
6954	case BUILT_IN_LLFLOORF:
6955	case BUILT_IN_LLFLOORL:
6956	  newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
6957	  break;
6958
6959	case BUILT_IN_LLROUND:
6960	case BUILT_IN_LLROUNDF:
6961	case BUILT_IN_LLROUNDL:
6962	  newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
6963	  break;
6964
6965	case BUILT_IN_LLRINT:
6966	case BUILT_IN_LLRINTF:
6967	case BUILT_IN_LLRINTL:
6968	  newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
6969	  break;
6970
6971	default:
6972	  break;
6973	}
6974
6975      if (newfn)
6976	{
6977	  tree newcall = build_function_call_expr (newfn, arglist);
6978	  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall);
6979	}
6980    }
6981
6982  return 0;
6983}
6984
6985/* Fold function call to builtin cabs, cabsf or cabsl.  ARGLIST
6986   is the argument list and TYPE is the return type.  Return
6987   NULL_TREE if no if no simplification can be made.  */
6988
6989static tree
6990fold_builtin_cabs (tree arglist, tree type)
6991{
6992  tree arg;
6993
6994  if (!arglist || TREE_CHAIN (arglist))
6995    return NULL_TREE;
6996
6997  arg = TREE_VALUE (arglist);
6998  if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
6999      || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
7000    return NULL_TREE;
7001
7002  /* Evaluate cabs of a constant at compile-time.  */
7003  if (flag_unsafe_math_optimizations
7004      && TREE_CODE (arg) == COMPLEX_CST
7005      && TREE_CODE (TREE_REALPART (arg)) == REAL_CST
7006      && TREE_CODE (TREE_IMAGPART (arg)) == REAL_CST
7007      && ! TREE_CONSTANT_OVERFLOW (TREE_REALPART (arg))
7008      && ! TREE_CONSTANT_OVERFLOW (TREE_IMAGPART (arg)))
7009    {
7010      REAL_VALUE_TYPE r, i;
7011
7012      r = TREE_REAL_CST (TREE_REALPART (arg));
7013      i = TREE_REAL_CST (TREE_IMAGPART (arg));
7014
7015      real_arithmetic (&r, MULT_EXPR, &r, &r);
7016      real_arithmetic (&i, MULT_EXPR, &i, &i);
7017      real_arithmetic (&r, PLUS_EXPR, &r, &i);
7018      if (real_sqrt (&r, TYPE_MODE (type), &r)
7019	  || ! flag_trapping_math)
7020	return build_real (type, r);
7021    }
7022
7023  /* If either part is zero, cabs is fabs of the other.  */
7024  if (TREE_CODE (arg) == COMPLEX_EXPR
7025      && real_zerop (TREE_OPERAND (arg, 0)))
7026    return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1));
7027  if (TREE_CODE (arg) == COMPLEX_EXPR
7028      && real_zerop (TREE_OPERAND (arg, 1)))
7029    return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0));
7030
7031  /* Don't do this when optimizing for size.  */
7032  if (flag_unsafe_math_optimizations
7033      && optimize && !optimize_size)
7034    {
7035      tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
7036
7037      if (sqrtfn != NULL_TREE)
7038	{
7039	  tree rpart, ipart, result, arglist;
7040
7041	  arg = builtin_save_expr (arg);
7042
7043	  rpart = fold_build1 (REALPART_EXPR, type, arg);
7044	  ipart = fold_build1 (IMAGPART_EXPR, type, arg);
7045
7046	  rpart = builtin_save_expr (rpart);
7047	  ipart = builtin_save_expr (ipart);
7048
7049	  result = fold_build2 (PLUS_EXPR, type,
7050				fold_build2 (MULT_EXPR, type,
7051					     rpart, rpart),
7052				fold_build2 (MULT_EXPR, type,
7053					     ipart, ipart));
7054
7055	  arglist = build_tree_list (NULL_TREE, result);
7056	  return build_function_call_expr (sqrtfn, arglist);
7057	}
7058    }
7059
7060  return NULL_TREE;
7061}
7062
7063/* Fold a builtin function call to sqrt, sqrtf, or sqrtl.  Return
7064   NULL_TREE if no simplification can be made.  */
7065
7066static tree
7067fold_builtin_sqrt (tree arglist, tree type)
7068{
7069
7070  enum built_in_function fcode;
7071  tree arg = TREE_VALUE (arglist);
7072
7073  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7074    return NULL_TREE;
7075
7076  /* Optimize sqrt of constant value.  */
7077  if (TREE_CODE (arg) == REAL_CST
7078      && ! TREE_CONSTANT_OVERFLOW (arg))
7079    {
7080      REAL_VALUE_TYPE r, x;
7081
7082      x = TREE_REAL_CST (arg);
7083      if (real_sqrt (&r, TYPE_MODE (type), &x)
7084	  || (!flag_trapping_math && !flag_errno_math))
7085	return build_real (type, r);
7086    }
7087
7088  /* Optimize sqrt(expN(x)) = expN(x*0.5).  */
7089  fcode = builtin_mathfn_code (arg);
7090  if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7091    {
7092      tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7093      arg = fold_build2 (MULT_EXPR, type,
7094			 TREE_VALUE (TREE_OPERAND (arg, 1)),
7095			 build_real (type, dconsthalf));
7096      arglist = build_tree_list (NULL_TREE, arg);
7097      return build_function_call_expr (expfn, arglist);
7098    }
7099
7100  /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)).  */
7101  if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7102    {
7103      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7104
7105      if (powfn)
7106	{
7107	  tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7108	  tree tree_root;
7109	  /* The inner root was either sqrt or cbrt.  */
7110	  REAL_VALUE_TYPE dconstroot =
7111	    BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
7112
7113	  /* Adjust for the outer root.  */
7114	  SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7115	  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7116	  tree_root = build_real (type, dconstroot);
7117	  arglist = tree_cons (NULL_TREE, arg0,
7118			       build_tree_list (NULL_TREE, tree_root));
7119	  return build_function_call_expr (powfn, arglist);
7120	}
7121    }
7122
7123  /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5).  */
7124  if (flag_unsafe_math_optimizations
7125      && (fcode == BUILT_IN_POW
7126	  || fcode == BUILT_IN_POWF
7127	  || fcode == BUILT_IN_POWL))
7128    {
7129      tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7130      tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7131      tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7132      tree narg1;
7133      if (!tree_expr_nonnegative_p (arg0))
7134	arg0 = build1 (ABS_EXPR, type, arg0);
7135      narg1 = fold_build2 (MULT_EXPR, type, arg1,
7136			   build_real (type, dconsthalf));
7137      arglist = tree_cons (NULL_TREE, arg0,
7138			   build_tree_list (NULL_TREE, narg1));
7139      return build_function_call_expr (powfn, arglist);
7140    }
7141
7142  return NULL_TREE;
7143}
7144
7145/* Fold a builtin function call to cbrt, cbrtf, or cbrtl.  Return
7146   NULL_TREE if no simplification can be made.  */
7147static tree
7148fold_builtin_cbrt (tree arglist, tree type)
7149{
7150  tree arg = TREE_VALUE (arglist);
7151  const enum built_in_function fcode = builtin_mathfn_code (arg);
7152
7153  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7154    return NULL_TREE;
7155
7156  /* Optimize cbrt of constant value.  */
7157  if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg))
7158    return arg;
7159
7160  if (flag_unsafe_math_optimizations)
7161    {
7162      /* Optimize cbrt(expN(x)) -> expN(x/3).  */
7163      if (BUILTIN_EXPONENT_P (fcode))
7164        {
7165	  tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7166	  const REAL_VALUE_TYPE third_trunc =
7167	    real_value_truncate (TYPE_MODE (type), dconstthird);
7168	  arg = fold_build2 (MULT_EXPR, type,
7169			     TREE_VALUE (TREE_OPERAND (arg, 1)),
7170			     build_real (type, third_trunc));
7171	  arglist = build_tree_list (NULL_TREE, arg);
7172	  return build_function_call_expr (expfn, arglist);
7173	}
7174
7175      /* Optimize cbrt(sqrt(x)) -> pow(x,1/6).  */
7176      if (BUILTIN_SQRT_P (fcode))
7177        {
7178	  tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7179
7180	  if (powfn)
7181	    {
7182	      tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7183	      tree tree_root;
7184	      REAL_VALUE_TYPE dconstroot = dconstthird;
7185
7186	      SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7187	      dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7188	      tree_root = build_real (type, dconstroot);
7189	      arglist = tree_cons (NULL_TREE, arg0,
7190				   build_tree_list (NULL_TREE, tree_root));
7191	      return build_function_call_expr (powfn, arglist);
7192	    }
7193	}
7194
7195      /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative.  */
7196      if (BUILTIN_CBRT_P (fcode))
7197        {
7198	  tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7199	  if (tree_expr_nonnegative_p (arg0))
7200	    {
7201	      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7202
7203	      if (powfn)
7204	        {
7205		  tree tree_root;
7206		  REAL_VALUE_TYPE dconstroot;
7207
7208		  real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
7209		  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7210		  tree_root = build_real (type, dconstroot);
7211		  arglist = tree_cons (NULL_TREE, arg0,
7212				       build_tree_list (NULL_TREE, tree_root));
7213		  return build_function_call_expr (powfn, arglist);
7214		}
7215	    }
7216	}
7217
7218      /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative.  */
7219      if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
7220	  || fcode == BUILT_IN_POWL)
7221        {
7222	  tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1));
7223	  tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7224	  if (tree_expr_nonnegative_p (arg00))
7225	    {
7226	      tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7227	      const REAL_VALUE_TYPE dconstroot
7228		= real_value_truncate (TYPE_MODE (type), dconstthird);
7229	      tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
7230					 build_real (type, dconstroot));
7231	      arglist = tree_cons (NULL_TREE, arg00,
7232				   build_tree_list (NULL_TREE, narg01));
7233	      return build_function_call_expr (powfn, arglist);
7234	    }
7235	}
7236    }
7237  return NULL_TREE;
7238}
7239
7240/* Fold function call to builtin sin, sinf, or sinl.  Return
7241   NULL_TREE if no simplification can be made.  */
7242static tree
7243fold_builtin_sin (tree arglist)
7244{
7245  tree arg = TREE_VALUE (arglist);
7246
7247  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7248    return NULL_TREE;
7249
7250  /* Optimize sin (0.0) = 0.0.  */
7251  if (real_zerop (arg))
7252    return arg;
7253
7254  return NULL_TREE;
7255}
7256
7257/* Fold function call to builtin cos, cosf, or cosl.  Return
7258   NULL_TREE if no simplification can be made.  */
7259static tree
7260fold_builtin_cos (tree arglist, tree type, tree fndecl)
7261{
7262  tree arg = TREE_VALUE (arglist);
7263
7264  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7265    return NULL_TREE;
7266
7267  /* Optimize cos (0.0) = 1.0.  */
7268  if (real_zerop (arg))
7269    return build_real (type, dconst1);
7270
7271  /* Optimize cos(-x) into cos (x).  */
7272  if (TREE_CODE (arg) == NEGATE_EXPR)
7273    {
7274      tree args = build_tree_list (NULL_TREE,
7275				   TREE_OPERAND (arg, 0));
7276      return build_function_call_expr (fndecl, args);
7277    }
7278
7279  return NULL_TREE;
7280}
7281
7282/* Fold function call to builtin tan, tanf, or tanl.  Return
7283   NULL_TREE if no simplification can be made.  */
7284static tree
7285fold_builtin_tan (tree arglist)
7286{
7287  enum built_in_function fcode;
7288  tree arg = TREE_VALUE (arglist);
7289
7290  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7291    return NULL_TREE;
7292
7293  /* Optimize tan(0.0) = 0.0.  */
7294  if (real_zerop (arg))
7295    return arg;
7296
7297  /* Optimize tan(atan(x)) = x.  */
7298  fcode = builtin_mathfn_code (arg);
7299  if (flag_unsafe_math_optimizations
7300      && (fcode == BUILT_IN_ATAN
7301	  || fcode == BUILT_IN_ATANF
7302	  || fcode == BUILT_IN_ATANL))
7303    return TREE_VALUE (TREE_OPERAND (arg, 1));
7304
7305  return NULL_TREE;
7306}
7307
7308/* Fold function call to builtin atan, atanf, or atanl.  Return
7309   NULL_TREE if no simplification can be made.  */
7310
7311static tree
7312fold_builtin_atan (tree arglist, tree type)
7313{
7314
7315  tree arg = TREE_VALUE (arglist);
7316
7317  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7318    return NULL_TREE;
7319
7320  /* Optimize atan(0.0) = 0.0.  */
7321  if (real_zerop (arg))
7322    return arg;
7323
7324  /* Optimize atan(1.0) = pi/4.  */
7325  if (real_onep (arg))
7326    {
7327      REAL_VALUE_TYPE cst;
7328
7329      real_convert (&cst, TYPE_MODE (type), &dconstpi);
7330      SET_REAL_EXP (&cst, REAL_EXP (&cst) - 2);
7331      return build_real (type, cst);
7332    }
7333
7334  return NULL_TREE;
7335}
7336
7337/* Fold function call to builtin trunc, truncf or truncl.  Return
7338   NULL_TREE if no simplification can be made.  */
7339
7340static tree
7341fold_builtin_trunc (tree fndecl, tree arglist)
7342{
7343  tree arg;
7344
7345  if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7346    return 0;
7347
7348  /* Optimize trunc of constant value.  */
7349  arg = TREE_VALUE (arglist);
7350  if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7351    {
7352      REAL_VALUE_TYPE r, x;
7353      tree type = TREE_TYPE (TREE_TYPE (fndecl));
7354
7355      x = TREE_REAL_CST (arg);
7356      real_trunc (&r, TYPE_MODE (type), &x);
7357      return build_real (type, r);
7358    }
7359
7360  return fold_trunc_transparent_mathfn (fndecl, arglist);
7361}
7362
7363/* Fold function call to builtin floor, floorf or floorl.  Return
7364   NULL_TREE if no simplification can be made.  */
7365
7366static tree
7367fold_builtin_floor (tree fndecl, tree arglist)
7368{
7369  tree arg;
7370
7371  if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7372    return 0;
7373
7374  /* Optimize floor of constant value.  */
7375  arg = TREE_VALUE (arglist);
7376  if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7377    {
7378      REAL_VALUE_TYPE x;
7379
7380      x = TREE_REAL_CST (arg);
7381      if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7382	{
7383	  tree type = TREE_TYPE (TREE_TYPE (fndecl));
7384	  REAL_VALUE_TYPE r;
7385
7386	  real_floor (&r, TYPE_MODE (type), &x);
7387	  return build_real (type, r);
7388	}
7389    }
7390
7391  return fold_trunc_transparent_mathfn (fndecl, arglist);
7392}
7393
7394/* Fold function call to builtin ceil, ceilf or ceill.  Return
7395   NULL_TREE if no simplification can be made.  */
7396
7397static tree
7398fold_builtin_ceil (tree fndecl, tree arglist)
7399{
7400  tree arg;
7401
7402  if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7403    return 0;
7404
7405  /* Optimize ceil of constant value.  */
7406  arg = TREE_VALUE (arglist);
7407  if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7408    {
7409      REAL_VALUE_TYPE x;
7410
7411      x = TREE_REAL_CST (arg);
7412      if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7413	{
7414	  tree type = TREE_TYPE (TREE_TYPE (fndecl));
7415	  REAL_VALUE_TYPE r;
7416
7417	  real_ceil (&r, TYPE_MODE (type), &x);
7418	  return build_real (type, r);
7419	}
7420    }
7421
7422  return fold_trunc_transparent_mathfn (fndecl, arglist);
7423}
7424
7425/* Fold function call to builtin round, roundf or roundl.  Return
7426   NULL_TREE if no simplification can be made.  */
7427
7428static tree
7429fold_builtin_round (tree fndecl, tree arglist)
7430{
7431  tree arg;
7432
7433  if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7434    return 0;
7435
7436  /* Optimize round of constant value.  */
7437  arg = TREE_VALUE (arglist);
7438  if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7439    {
7440      REAL_VALUE_TYPE x;
7441
7442      x = TREE_REAL_CST (arg);
7443      if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7444	{
7445	  tree type = TREE_TYPE (TREE_TYPE (fndecl));
7446	  REAL_VALUE_TYPE r;
7447
7448	  real_round (&r, TYPE_MODE (type), &x);
7449	  return build_real (type, r);
7450	}
7451    }
7452
7453  return fold_trunc_transparent_mathfn (fndecl, arglist);
7454}
7455
7456/* Fold function call to builtin lround, lroundf or lroundl (or the
7457   corresponding long long versions) and other rounding functions.
7458   Return NULL_TREE if no simplification can be made.  */
7459
7460static tree
7461fold_builtin_int_roundingfn (tree fndecl, tree arglist)
7462{
7463  tree arg;
7464
7465  if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7466    return 0;
7467
7468  /* Optimize lround of constant value.  */
7469  arg = TREE_VALUE (arglist);
7470  if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7471    {
7472      const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7473
7474      if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
7475	{
7476	  tree itype = TREE_TYPE (TREE_TYPE (fndecl));
7477	  tree ftype = TREE_TYPE (arg), result;
7478	  HOST_WIDE_INT hi, lo;
7479	  REAL_VALUE_TYPE r;
7480
7481	  switch (DECL_FUNCTION_CODE (fndecl))
7482	    {
7483	    case BUILT_IN_LFLOOR:
7484	    case BUILT_IN_LFLOORF:
7485	    case BUILT_IN_LFLOORL:
7486	    case BUILT_IN_LLFLOOR:
7487	    case BUILT_IN_LLFLOORF:
7488	    case BUILT_IN_LLFLOORL:
7489	      real_floor (&r, TYPE_MODE (ftype), &x);
7490	      break;
7491
7492	    case BUILT_IN_LCEIL:
7493	    case BUILT_IN_LCEILF:
7494	    case BUILT_IN_LCEILL:
7495	    case BUILT_IN_LLCEIL:
7496	    case BUILT_IN_LLCEILF:
7497	    case BUILT_IN_LLCEILL:
7498	      real_ceil (&r, TYPE_MODE (ftype), &x);
7499	      break;
7500
7501	    case BUILT_IN_LROUND:
7502	    case BUILT_IN_LROUNDF:
7503	    case BUILT_IN_LROUNDL:
7504	    case BUILT_IN_LLROUND:
7505	    case BUILT_IN_LLROUNDF:
7506	    case BUILT_IN_LLROUNDL:
7507	      real_round (&r, TYPE_MODE (ftype), &x);
7508	      break;
7509
7510	    default:
7511	      gcc_unreachable ();
7512	    }
7513
7514	  REAL_VALUE_TO_INT (&lo, &hi, r);
7515	  result = build_int_cst_wide (NULL_TREE, lo, hi);
7516	  if (int_fits_type_p (result, itype))
7517	    return fold_convert (itype, result);
7518	}
7519    }
7520
7521  return fold_fixed_mathfn (fndecl, arglist);
7522}
7523
7524/* Fold function call to builtin ffs, clz, ctz, popcount and parity
7525   and their long and long long variants (i.e. ffsl and ffsll).
7526   Return NULL_TREE if no simplification can be made.  */
7527
7528static tree
7529fold_builtin_bitop (tree fndecl, tree arglist)
7530{
7531  tree arg;
7532
7533  if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
7534    return NULL_TREE;
7535
7536  /* Optimize for constant argument.  */
7537  arg = TREE_VALUE (arglist);
7538  if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7539    {
7540      HOST_WIDE_INT hi, width, result;
7541      unsigned HOST_WIDE_INT lo;
7542      tree type;
7543
7544      type = TREE_TYPE (arg);
7545      width = TYPE_PRECISION (type);
7546      lo = TREE_INT_CST_LOW (arg);
7547
7548      /* Clear all the bits that are beyond the type's precision.  */
7549      if (width > HOST_BITS_PER_WIDE_INT)
7550	{
7551	  hi = TREE_INT_CST_HIGH (arg);
7552	  if (width < 2 * HOST_BITS_PER_WIDE_INT)
7553	    hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
7554	}
7555      else
7556	{
7557	  hi = 0;
7558	  if (width < HOST_BITS_PER_WIDE_INT)
7559	    lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
7560	}
7561
7562      switch (DECL_FUNCTION_CODE (fndecl))
7563	{
7564	case BUILT_IN_FFS:
7565	case BUILT_IN_FFSL:
7566	case BUILT_IN_FFSLL:
7567	  if (lo != 0)
7568	    result = exact_log2 (lo & -lo) + 1;
7569	  else if (hi != 0)
7570	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
7571	  else
7572	    result = 0;
7573	  break;
7574
7575	case BUILT_IN_CLZ:
7576	case BUILT_IN_CLZL:
7577	case BUILT_IN_CLZLL:
7578	  if (hi != 0)
7579	    result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
7580	  else if (lo != 0)
7581	    result = width - floor_log2 (lo) - 1;
7582	  else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7583	    result = width;
7584	  break;
7585
7586	case BUILT_IN_CTZ:
7587	case BUILT_IN_CTZL:
7588	case BUILT_IN_CTZLL:
7589	  if (lo != 0)
7590	    result = exact_log2 (lo & -lo);
7591	  else if (hi != 0)
7592	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
7593	  else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7594	    result = width;
7595	  break;
7596
7597	case BUILT_IN_POPCOUNT:
7598	case BUILT_IN_POPCOUNTL:
7599	case BUILT_IN_POPCOUNTLL:
7600	  result = 0;
7601	  while (lo)
7602	    result++, lo &= lo - 1;
7603	  while (hi)
7604	    result++, hi &= hi - 1;
7605	  break;
7606
7607	case BUILT_IN_PARITY:
7608	case BUILT_IN_PARITYL:
7609	case BUILT_IN_PARITYLL:
7610	  result = 0;
7611	  while (lo)
7612	    result++, lo &= lo - 1;
7613	  while (hi)
7614	    result++, hi &= hi - 1;
7615	  result &= 1;
7616	  break;
7617
7618	default:
7619	  gcc_unreachable ();
7620	}
7621
7622      return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
7623    }
7624
7625  return NULL_TREE;
7626}
7627
7628/* Return true if EXPR is the real constant contained in VALUE.  */
7629
7630static bool
7631real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
7632{
7633  STRIP_NOPS (expr);
7634
7635  return ((TREE_CODE (expr) == REAL_CST
7636           && ! TREE_CONSTANT_OVERFLOW (expr)
7637           && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
7638          || (TREE_CODE (expr) == COMPLEX_CST
7639              && real_dconstp (TREE_REALPART (expr), value)
7640              && real_zerop (TREE_IMAGPART (expr))));
7641}
7642
7643/* A subroutine of fold_builtin to fold the various logarithmic
7644   functions.  EXP is the CALL_EXPR of a call to a builtin logN
7645   function.  VALUE is the base of the logN function.  */
7646
7647static tree
7648fold_builtin_logarithm (tree fndecl, tree arglist,
7649			const REAL_VALUE_TYPE *value)
7650{
7651  if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7652    {
7653      tree type = TREE_TYPE (TREE_TYPE (fndecl));
7654      tree arg = TREE_VALUE (arglist);
7655      const enum built_in_function fcode = builtin_mathfn_code (arg);
7656
7657      /* Optimize logN(1.0) = 0.0.  */
7658      if (real_onep (arg))
7659	return build_real (type, dconst0);
7660
7661      /* Optimize logN(N) = 1.0.  If N can't be truncated to MODE
7662         exactly, then only do this if flag_unsafe_math_optimizations.  */
7663      if (exact_real_truncate (TYPE_MODE (type), value)
7664	  || flag_unsafe_math_optimizations)
7665        {
7666	  const REAL_VALUE_TYPE value_truncate =
7667	    real_value_truncate (TYPE_MODE (type), *value);
7668	  if (real_dconstp (arg, &value_truncate))
7669	    return build_real (type, dconst1);
7670	}
7671
7672      /* Special case, optimize logN(expN(x)) = x.  */
7673      if (flag_unsafe_math_optimizations
7674	  && ((value == &dconste
7675	       && (fcode == BUILT_IN_EXP
7676		   || fcode == BUILT_IN_EXPF
7677		   || fcode == BUILT_IN_EXPL))
7678	      || (value == &dconst2
7679		  && (fcode == BUILT_IN_EXP2
7680		      || fcode == BUILT_IN_EXP2F
7681		      || fcode == BUILT_IN_EXP2L))
7682	      || (value == &dconst10 && (BUILTIN_EXP10_P (fcode)))))
7683	return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
7684
7685      /* Optimize logN(func()) for various exponential functions.  We
7686         want to determine the value "x" and the power "exponent" in
7687         order to transform logN(x**exponent) into exponent*logN(x).  */
7688      if (flag_unsafe_math_optimizations)
7689        {
7690	  tree exponent = 0, x = 0;
7691
7692	  switch (fcode)
7693	  {
7694	  case BUILT_IN_EXP:
7695	  case BUILT_IN_EXPF:
7696	  case BUILT_IN_EXPL:
7697	    /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
7698	    x = build_real (type,
7699			    real_value_truncate (TYPE_MODE (type), dconste));
7700	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7701	    break;
7702	  case BUILT_IN_EXP2:
7703	  case BUILT_IN_EXP2F:
7704	  case BUILT_IN_EXP2L:
7705	    /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
7706	    x = build_real (type, dconst2);
7707	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7708	    break;
7709	  case BUILT_IN_EXP10:
7710	  case BUILT_IN_EXP10F:
7711	  case BUILT_IN_EXP10L:
7712	  case BUILT_IN_POW10:
7713	  case BUILT_IN_POW10F:
7714	  case BUILT_IN_POW10L:
7715	    /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
7716	    x = build_real (type, dconst10);
7717	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7718	    break;
7719	  case BUILT_IN_SQRT:
7720	  case BUILT_IN_SQRTF:
7721	  case BUILT_IN_SQRTL:
7722	    /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
7723	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
7724	    exponent = build_real (type, dconsthalf);
7725	    break;
7726	  case BUILT_IN_CBRT:
7727	  case BUILT_IN_CBRTF:
7728	  case BUILT_IN_CBRTL:
7729	    /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
7730	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
7731	    exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7732							      dconstthird));
7733	    break;
7734	  case BUILT_IN_POW:
7735	  case BUILT_IN_POWF:
7736	  case BUILT_IN_POWL:
7737	    /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
7738	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
7739	    exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7740	    break;
7741	  default:
7742	    break;
7743	  }
7744
7745	  /* Now perform the optimization.  */
7746	  if (x && exponent)
7747	    {
7748	      tree logfn;
7749	      arglist = build_tree_list (NULL_TREE, x);
7750	      logfn = build_function_call_expr (fndecl, arglist);
7751	      return fold_build2 (MULT_EXPR, type, exponent, logfn);
7752	    }
7753	}
7754    }
7755
7756  return 0;
7757}
7758
7759/* Fold a builtin function call to pow, powf, or powl.  Return
7760   NULL_TREE if no simplification can be made.  */
7761static tree
7762fold_builtin_pow (tree fndecl, tree arglist, tree type)
7763{
7764  tree arg0 = TREE_VALUE (arglist);
7765  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
7766
7767  if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
7768    return NULL_TREE;
7769
7770  /* Optimize pow(1.0,y) = 1.0.  */
7771  if (real_onep (arg0))
7772    return omit_one_operand (type, build_real (type, dconst1), arg1);
7773
7774  if (TREE_CODE (arg1) == REAL_CST
7775      && ! TREE_CONSTANT_OVERFLOW (arg1))
7776    {
7777      REAL_VALUE_TYPE cint;
7778      REAL_VALUE_TYPE c;
7779      HOST_WIDE_INT n;
7780
7781      c = TREE_REAL_CST (arg1);
7782
7783      /* Optimize pow(x,0.0) = 1.0.  */
7784      if (REAL_VALUES_EQUAL (c, dconst0))
7785	return omit_one_operand (type, build_real (type, dconst1),
7786				 arg0);
7787
7788      /* Optimize pow(x,1.0) = x.  */
7789      if (REAL_VALUES_EQUAL (c, dconst1))
7790	return arg0;
7791
7792      /* Optimize pow(x,-1.0) = 1.0/x.  */
7793      if (REAL_VALUES_EQUAL (c, dconstm1))
7794	return fold_build2 (RDIV_EXPR, type,
7795			    build_real (type, dconst1), arg0);
7796
7797      /* Optimize pow(x,0.5) = sqrt(x).  */
7798      if (flag_unsafe_math_optimizations
7799	  && REAL_VALUES_EQUAL (c, dconsthalf))
7800	{
7801	  tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
7802
7803	  if (sqrtfn != NULL_TREE)
7804	    {
7805	      tree arglist = build_tree_list (NULL_TREE, arg0);
7806	      return build_function_call_expr (sqrtfn, arglist);
7807	    }
7808	}
7809
7810      /* Check for an integer exponent.  */
7811      n = real_to_integer (&c);
7812      real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
7813      if (real_identical (&c, &cint))
7814	{
7815	  /* Attempt to evaluate pow at compile-time.  */
7816	  if (TREE_CODE (arg0) == REAL_CST
7817	      && ! TREE_CONSTANT_OVERFLOW (arg0))
7818	    {
7819	      REAL_VALUE_TYPE x;
7820	      bool inexact;
7821
7822	      x = TREE_REAL_CST (arg0);
7823	      inexact = real_powi (&x, TYPE_MODE (type), &x, n);
7824	      if (flag_unsafe_math_optimizations || !inexact)
7825		return build_real (type, x);
7826	    }
7827
7828	  /* Strip sign ops from even integer powers.  */
7829	  if ((n & 1) == 0 && flag_unsafe_math_optimizations)
7830	    {
7831	      tree narg0 = fold_strip_sign_ops (arg0);
7832	      if (narg0)
7833		{
7834		  arglist = build_tree_list (NULL_TREE, arg1);
7835		  arglist = tree_cons (NULL_TREE, narg0, arglist);
7836		  return build_function_call_expr (fndecl, arglist);
7837		}
7838	    }
7839	}
7840    }
7841
7842  if (flag_unsafe_math_optimizations)
7843    {
7844      const enum built_in_function fcode = builtin_mathfn_code (arg0);
7845
7846      /* Optimize pow(expN(x),y) = expN(x*y).  */
7847      if (BUILTIN_EXPONENT_P (fcode))
7848        {
7849	  tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
7850	  tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
7851	  arg = fold_build2 (MULT_EXPR, type, arg, arg1);
7852	  arglist = build_tree_list (NULL_TREE, arg);
7853	  return build_function_call_expr (expfn, arglist);
7854	}
7855
7856      /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
7857      if (BUILTIN_SQRT_P (fcode))
7858        {
7859	  tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
7860	  tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
7861				    build_real (type, dconsthalf));
7862
7863	  arglist = tree_cons (NULL_TREE, narg0,
7864			       build_tree_list (NULL_TREE, narg1));
7865	  return build_function_call_expr (fndecl, arglist);
7866	}
7867
7868      /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative.  */
7869      if (BUILTIN_CBRT_P (fcode))
7870        {
7871	  tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
7872	  if (tree_expr_nonnegative_p (arg))
7873	    {
7874	      const REAL_VALUE_TYPE dconstroot
7875		= real_value_truncate (TYPE_MODE (type), dconstthird);
7876	      tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
7877					build_real (type, dconstroot));
7878	      arglist = tree_cons (NULL_TREE, arg,
7879				   build_tree_list (NULL_TREE, narg1));
7880	      return build_function_call_expr (fndecl, arglist);
7881	    }
7882	}
7883
7884      /* Optimize pow(pow(x,y),z) = pow(x,y*z).  */
7885      if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
7886	   || fcode == BUILT_IN_POWL)
7887        {
7888	  tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
7889	  tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
7890	  tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
7891	  arglist = tree_cons (NULL_TREE, arg00,
7892			       build_tree_list (NULL_TREE, narg1));
7893	  return build_function_call_expr (fndecl, arglist);
7894	}
7895    }
7896
7897  return NULL_TREE;
7898}
7899
7900/* Fold a builtin function call to powi, powif, or powil.  Return
7901   NULL_TREE if no simplification can be made.  */
7902static tree
7903fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type)
7904{
7905  tree arg0 = TREE_VALUE (arglist);
7906  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
7907
7908  if (!validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
7909    return NULL_TREE;
7910
7911  /* Optimize pow(1.0,y) = 1.0.  */
7912  if (real_onep (arg0))
7913    return omit_one_operand (type, build_real (type, dconst1), arg1);
7914
7915  if (host_integerp (arg1, 0))
7916    {
7917      HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
7918
7919      /* Evaluate powi at compile-time.  */
7920      if (TREE_CODE (arg0) == REAL_CST
7921	  && ! TREE_CONSTANT_OVERFLOW (arg0))
7922	{
7923	  REAL_VALUE_TYPE x;
7924	  x = TREE_REAL_CST (arg0);
7925	  real_powi (&x, TYPE_MODE (type), &x, c);
7926	  return build_real (type, x);
7927	}
7928
7929      /* Optimize pow(x,0) = 1.0.  */
7930      if (c == 0)
7931	return omit_one_operand (type, build_real (type, dconst1),
7932				 arg0);
7933
7934      /* Optimize pow(x,1) = x.  */
7935      if (c == 1)
7936	return arg0;
7937
7938      /* Optimize pow(x,-1) = 1.0/x.  */
7939      if (c == -1)
7940	return fold_build2 (RDIV_EXPR, type,
7941			   build_real (type, dconst1), arg0);
7942    }
7943
7944  return NULL_TREE;
7945}
7946
7947/* A subroutine of fold_builtin to fold the various exponent
7948   functions.  EXP is the CALL_EXPR of a call to a builtin function.
7949   VALUE is the value which will be raised to a power.  */
7950
7951static tree
7952fold_builtin_exponent (tree fndecl, tree arglist,
7953		       const REAL_VALUE_TYPE *value)
7954{
7955  if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7956    {
7957      tree type = TREE_TYPE (TREE_TYPE (fndecl));
7958      tree arg = TREE_VALUE (arglist);
7959
7960      /* Optimize exp*(0.0) = 1.0.  */
7961      if (real_zerop (arg))
7962	return build_real (type, dconst1);
7963
7964      /* Optimize expN(1.0) = N.  */
7965      if (real_onep (arg))
7966        {
7967	  REAL_VALUE_TYPE cst;
7968
7969	  real_convert (&cst, TYPE_MODE (type), value);
7970	  return build_real (type, cst);
7971	}
7972
7973      /* Attempt to evaluate expN(integer) at compile-time.  */
7974      if (flag_unsafe_math_optimizations
7975	  && TREE_CODE (arg) == REAL_CST
7976	  && ! TREE_CONSTANT_OVERFLOW (arg))
7977        {
7978	  REAL_VALUE_TYPE cint;
7979	  REAL_VALUE_TYPE c;
7980	  HOST_WIDE_INT n;
7981
7982	  c = TREE_REAL_CST (arg);
7983	  n = real_to_integer (&c);
7984	  real_from_integer (&cint, VOIDmode, n,
7985			     n < 0 ? -1 : 0, 0);
7986	  if (real_identical (&c, &cint))
7987	    {
7988	      REAL_VALUE_TYPE x;
7989
7990	      real_powi (&x, TYPE_MODE (type), value, n);
7991	      return build_real (type, x);
7992	    }
7993	}
7994
7995      /* Optimize expN(logN(x)) = x.  */
7996      if (flag_unsafe_math_optimizations)
7997        {
7998	  const enum built_in_function fcode = builtin_mathfn_code (arg);
7999
8000	  if ((value == &dconste
8001	       && (fcode == BUILT_IN_LOG
8002		   || fcode == BUILT_IN_LOGF
8003		   || fcode == BUILT_IN_LOGL))
8004	      || (value == &dconst2
8005		  && (fcode == BUILT_IN_LOG2
8006		      || fcode == BUILT_IN_LOG2F
8007		      || fcode == BUILT_IN_LOG2L))
8008	      || (value == &dconst10
8009		  && (fcode == BUILT_IN_LOG10
8010		      || fcode == BUILT_IN_LOG10F
8011		      || fcode == BUILT_IN_LOG10L)))
8012	    return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
8013	}
8014    }
8015
8016  return 0;
8017}
8018
8019/* Fold function call to builtin memcpy.  Return
8020   NULL_TREE if no simplification can be made.  */
8021
8022static tree
8023fold_builtin_memcpy (tree fndecl, tree arglist)
8024{
8025  tree dest, src, len;
8026
8027  if (!validate_arglist (arglist,
8028			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8029    return 0;
8030
8031  dest = TREE_VALUE (arglist);
8032  src = TREE_VALUE (TREE_CHAIN (arglist));
8033  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8034
8035  /* If the LEN parameter is zero, return DEST.  */
8036  if (integer_zerop (len))
8037    return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
8038
8039  /* If SRC and DEST are the same (and not volatile), return DEST.  */
8040  if (operand_equal_p (src, dest, 0))
8041    return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
8042
8043  return 0;
8044}
8045
8046/* Fold function call to builtin mempcpy.  Return
8047   NULL_TREE if no simplification can be made.  */
8048
8049static tree
8050fold_builtin_mempcpy (tree arglist, tree type, int endp)
8051{
8052  if (validate_arglist (arglist,
8053			POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8054    {
8055      tree dest = TREE_VALUE (arglist);
8056      tree src = TREE_VALUE (TREE_CHAIN (arglist));
8057      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8058
8059      /* If the LEN parameter is zero, return DEST.  */
8060      if (integer_zerop (len))
8061	return omit_one_operand (type, dest, src);
8062
8063      /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
8064      if (operand_equal_p (src, dest, 0))
8065        {
8066	  if (endp == 0)
8067	    return omit_one_operand (type, dest, len);
8068
8069	  if (endp == 2)
8070	    len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
8071			       ssize_int (1));
8072
8073	  len = fold_convert (TREE_TYPE (dest), len);
8074	  len = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
8075	  return fold_convert (type, len);
8076	}
8077    }
8078  return 0;
8079}
8080
8081/* Fold function call to builtin memmove.  Return
8082   NULL_TREE if no simplification can be made.  */
8083
8084static tree
8085fold_builtin_memmove (tree arglist, tree type)
8086{
8087  tree dest, src, len;
8088
8089  if (!validate_arglist (arglist,
8090			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8091    return 0;
8092
8093  dest = TREE_VALUE (arglist);
8094  src = TREE_VALUE (TREE_CHAIN (arglist));
8095  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8096
8097  /* If the LEN parameter is zero, return DEST.  */
8098  if (integer_zerop (len))
8099    return omit_one_operand (type, dest, src);
8100
8101  /* If SRC and DEST are the same (and not volatile), return DEST.  */
8102  if (operand_equal_p (src, dest, 0))
8103    return omit_one_operand (type, dest, len);
8104
8105  return 0;
8106}
8107
8108/* Fold function call to builtin strcpy.  If LEN is not NULL, it represents
8109   the length of the string to be copied.  Return NULL_TREE if no
8110   simplification can be made.  */
8111
8112tree
8113fold_builtin_strcpy (tree fndecl, tree arglist, tree len)
8114{
8115  tree dest, src, fn;
8116
8117  if (!validate_arglist (arglist,
8118			 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8119    return 0;
8120
8121  dest = TREE_VALUE (arglist);
8122  src = TREE_VALUE (TREE_CHAIN (arglist));
8123
8124  /* If SRC and DEST are the same (and not volatile), return DEST.  */
8125  if (operand_equal_p (src, dest, 0))
8126    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
8127
8128  if (optimize_size)
8129    return 0;
8130
8131  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8132  if (!fn)
8133    return 0;
8134
8135  if (!len)
8136    {
8137      len = c_strlen (src, 1);
8138      if (! len || TREE_SIDE_EFFECTS (len))
8139	return 0;
8140    }
8141
8142  len = size_binop (PLUS_EXPR, len, ssize_int (1));
8143  arglist = build_tree_list (NULL_TREE, len);
8144  arglist = tree_cons (NULL_TREE, src, arglist);
8145  arglist = tree_cons (NULL_TREE, dest, arglist);
8146  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
8147		       build_function_call_expr (fn, arglist));
8148}
8149
8150/* Fold function call to builtin strncpy.  If SLEN is not NULL, it represents
8151   the length of the source string.  Return NULL_TREE if no simplification
8152   can be made.  */
8153
8154tree
8155fold_builtin_strncpy (tree fndecl, tree arglist, tree slen)
8156{
8157  tree dest, src, len, fn;
8158
8159  if (!validate_arglist (arglist,
8160			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8161    return 0;
8162
8163  dest = TREE_VALUE (arglist);
8164  src = TREE_VALUE (TREE_CHAIN (arglist));
8165  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8166
8167  /* If the LEN parameter is zero, return DEST.  */
8168  if (integer_zerop (len))
8169    return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
8170
8171  /* We can't compare slen with len as constants below if len is not a
8172     constant.  */
8173  if (len == 0 || TREE_CODE (len) != INTEGER_CST)
8174    return 0;
8175
8176  if (!slen)
8177    slen = c_strlen (src, 1);
8178
8179  /* Now, we must be passed a constant src ptr parameter.  */
8180  if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
8181    return 0;
8182
8183  slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
8184
8185  /* We do not support simplification of this case, though we do
8186     support it when expanding trees into RTL.  */
8187  /* FIXME: generate a call to __builtin_memset.  */
8188  if (tree_int_cst_lt (slen, len))
8189    return 0;
8190
8191  /* OK transform into builtin memcpy.  */
8192  fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8193  if (!fn)
8194    return 0;
8195  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
8196		       build_function_call_expr (fn, arglist));
8197}
8198
8199/* Fold function call to builtin memcmp.  Return
8200   NULL_TREE if no simplification can be made.  */
8201
8202static tree
8203fold_builtin_memcmp (tree arglist)
8204{
8205  tree arg1, arg2, len;
8206  const char *p1, *p2;
8207
8208  if (!validate_arglist (arglist,
8209			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8210    return 0;
8211
8212  arg1 = TREE_VALUE (arglist);
8213  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8214  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8215
8216  /* If the LEN parameter is zero, return zero.  */
8217  if (integer_zerop (len))
8218    return omit_two_operands (integer_type_node, integer_zero_node,
8219			      arg1, arg2);
8220
8221  /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
8222  if (operand_equal_p (arg1, arg2, 0))
8223    return omit_one_operand (integer_type_node, integer_zero_node, len);
8224
8225  p1 = c_getstr (arg1);
8226  p2 = c_getstr (arg2);
8227
8228  /* If all arguments are constant, and the value of len is not greater
8229     than the lengths of arg1 and arg2, evaluate at compile-time.  */
8230  if (host_integerp (len, 1) && p1 && p2
8231      && compare_tree_int (len, strlen (p1) + 1) <= 0
8232      && compare_tree_int (len, strlen (p2) + 1) <= 0)
8233    {
8234      const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8235
8236      if (r > 0)
8237	return integer_one_node;
8238      else if (r < 0)
8239	return integer_minus_one_node;
8240      else
8241	return integer_zero_node;
8242    }
8243
8244  /* If len parameter is one, return an expression corresponding to
8245     (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
8246  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8247    {
8248      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8249      tree cst_uchar_ptr_node
8250	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8251
8252      tree ind1 = fold_convert (integer_type_node,
8253				build1 (INDIRECT_REF, cst_uchar_node,
8254					fold_convert (cst_uchar_ptr_node,
8255						      arg1)));
8256      tree ind2 = fold_convert (integer_type_node,
8257				build1 (INDIRECT_REF, cst_uchar_node,
8258					fold_convert (cst_uchar_ptr_node,
8259						      arg2)));
8260      return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
8261    }
8262
8263  return 0;
8264}
8265
8266/* Fold function call to builtin strcmp.  Return
8267   NULL_TREE if no simplification can be made.  */
8268
8269static tree
8270fold_builtin_strcmp (tree arglist)
8271{
8272  tree arg1, arg2;
8273  const char *p1, *p2;
8274
8275  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8276    return 0;
8277
8278  arg1 = TREE_VALUE (arglist);
8279  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8280
8281  /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
8282  if (operand_equal_p (arg1, arg2, 0))
8283    return integer_zero_node;
8284
8285  p1 = c_getstr (arg1);
8286  p2 = c_getstr (arg2);
8287
8288  if (p1 && p2)
8289    {
8290      const int i = strcmp (p1, p2);
8291      if (i < 0)
8292	return integer_minus_one_node;
8293      else if (i > 0)
8294	return integer_one_node;
8295      else
8296	return integer_zero_node;
8297    }
8298
8299  /* If the second arg is "", return *(const unsigned char*)arg1.  */
8300  if (p2 && *p2 == '\0')
8301    {
8302      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8303      tree cst_uchar_ptr_node
8304	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8305
8306      return fold_convert (integer_type_node,
8307			   build1 (INDIRECT_REF, cst_uchar_node,
8308				   fold_convert (cst_uchar_ptr_node,
8309						 arg1)));
8310    }
8311
8312  /* If the first arg is "", return -*(const unsigned char*)arg2.  */
8313  if (p1 && *p1 == '\0')
8314    {
8315      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8316      tree cst_uchar_ptr_node
8317	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8318
8319      tree temp = fold_convert (integer_type_node,
8320				build1 (INDIRECT_REF, cst_uchar_node,
8321					fold_convert (cst_uchar_ptr_node,
8322						      arg2)));
8323      return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
8324    }
8325
8326  return 0;
8327}
8328
8329/* Fold function call to builtin strncmp.  Return
8330   NULL_TREE if no simplification can be made.  */
8331
8332static tree
8333fold_builtin_strncmp (tree arglist)
8334{
8335  tree arg1, arg2, len;
8336  const char *p1, *p2;
8337
8338  if (!validate_arglist (arglist,
8339			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8340    return 0;
8341
8342  arg1 = TREE_VALUE (arglist);
8343  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8344  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8345
8346  /* If the LEN parameter is zero, return zero.  */
8347  if (integer_zerop (len))
8348    return omit_two_operands (integer_type_node, integer_zero_node,
8349			      arg1, arg2);
8350
8351  /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
8352  if (operand_equal_p (arg1, arg2, 0))
8353    return omit_one_operand (integer_type_node, integer_zero_node, len);
8354
8355  p1 = c_getstr (arg1);
8356  p2 = c_getstr (arg2);
8357
8358  if (host_integerp (len, 1) && p1 && p2)
8359    {
8360      const int i = strncmp (p1, p2, tree_low_cst (len, 1));
8361      if (i > 0)
8362	return integer_one_node;
8363      else if (i < 0)
8364	return integer_minus_one_node;
8365      else
8366	return integer_zero_node;
8367    }
8368
8369  /* If the second arg is "", and the length is greater than zero,
8370     return *(const unsigned char*)arg1.  */
8371  if (p2 && *p2 == '\0'
8372      && TREE_CODE (len) == INTEGER_CST
8373      && tree_int_cst_sgn (len) == 1)
8374    {
8375      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8376      tree cst_uchar_ptr_node
8377	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8378
8379      return fold_convert (integer_type_node,
8380			   build1 (INDIRECT_REF, cst_uchar_node,
8381				   fold_convert (cst_uchar_ptr_node,
8382						 arg1)));
8383    }
8384
8385  /* If the first arg is "", and the length is greater than zero,
8386     return -*(const unsigned char*)arg2.  */
8387  if (p1 && *p1 == '\0'
8388      && TREE_CODE (len) == INTEGER_CST
8389      && tree_int_cst_sgn (len) == 1)
8390    {
8391      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8392      tree cst_uchar_ptr_node
8393	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8394
8395      tree temp = fold_convert (integer_type_node,
8396				build1 (INDIRECT_REF, cst_uchar_node,
8397					fold_convert (cst_uchar_ptr_node,
8398						      arg2)));
8399      return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
8400    }
8401
8402  /* If len parameter is one, return an expression corresponding to
8403     (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
8404  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8405    {
8406      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8407      tree cst_uchar_ptr_node
8408	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8409
8410      tree ind1 = fold_convert (integer_type_node,
8411				build1 (INDIRECT_REF, cst_uchar_node,
8412					fold_convert (cst_uchar_ptr_node,
8413						      arg1)));
8414      tree ind2 = fold_convert (integer_type_node,
8415				build1 (INDIRECT_REF, cst_uchar_node,
8416					fold_convert (cst_uchar_ptr_node,
8417						      arg2)));
8418      return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
8419    }
8420
8421  return 0;
8422}
8423
8424/* Fold function call to builtin signbit, signbitf or signbitl.  Return
8425   NULL_TREE if no simplification can be made.  */
8426
8427static tree
8428fold_builtin_signbit (tree fndecl, tree arglist)
8429{
8430  tree type = TREE_TYPE (TREE_TYPE (fndecl));
8431  tree arg, temp;
8432
8433  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8434    return NULL_TREE;
8435
8436  arg = TREE_VALUE (arglist);
8437
8438  /* If ARG is a compile-time constant, determine the result.  */
8439  if (TREE_CODE (arg) == REAL_CST
8440      && !TREE_CONSTANT_OVERFLOW (arg))
8441    {
8442      REAL_VALUE_TYPE c;
8443
8444      c = TREE_REAL_CST (arg);
8445      temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
8446      return fold_convert (type, temp);
8447    }
8448
8449  /* If ARG is non-negative, the result is always zero.  */
8450  if (tree_expr_nonnegative_p (arg))
8451    return omit_one_operand (type, integer_zero_node, arg);
8452
8453  /* If ARG's format doesn't have signed zeros, return "arg < 0.0".  */
8454  if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
8455    return fold_build2 (LT_EXPR, type, arg,
8456			build_real (TREE_TYPE (arg), dconst0));
8457
8458  return NULL_TREE;
8459}
8460
8461/* Fold function call to builtin copysign, copysignf or copysignl.
8462   Return NULL_TREE if no simplification can be made.  */
8463
8464static tree
8465fold_builtin_copysign (tree fndecl, tree arglist, tree type)
8466{
8467  tree arg1, arg2, tem;
8468
8469  if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
8470    return NULL_TREE;
8471
8472  arg1 = TREE_VALUE (arglist);
8473  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8474
8475  /* copysign(X,X) is X.  */
8476  if (operand_equal_p (arg1, arg2, 0))
8477    return fold_convert (type, arg1);
8478
8479  /* If ARG1 and ARG2 are compile-time constants, determine the result.  */
8480  if (TREE_CODE (arg1) == REAL_CST
8481      && TREE_CODE (arg2) == REAL_CST
8482      && !TREE_CONSTANT_OVERFLOW (arg1)
8483      && !TREE_CONSTANT_OVERFLOW (arg2))
8484    {
8485      REAL_VALUE_TYPE c1, c2;
8486
8487      c1 = TREE_REAL_CST (arg1);
8488      c2 = TREE_REAL_CST (arg2);
8489      real_copysign (&c1, &c2);
8490      return build_real (type, c1);
8491      c1.sign = c2.sign;
8492    }
8493
8494  /* copysign(X, Y) is fabs(X) when Y is always non-negative.
8495     Remember to evaluate Y for side-effects.  */
8496  if (tree_expr_nonnegative_p (arg2))
8497    return omit_one_operand (type,
8498			     fold_build1 (ABS_EXPR, type, arg1),
8499			     arg2);
8500
8501  /* Strip sign changing operations for the first argument.  */
8502  tem = fold_strip_sign_ops (arg1);
8503  if (tem)
8504    {
8505      arglist = tree_cons (NULL_TREE, tem, TREE_CHAIN (arglist));
8506      return build_function_call_expr (fndecl, arglist);
8507    }
8508
8509  return NULL_TREE;
8510}
8511
8512/* Fold a call to builtin isascii.  */
8513
8514static tree
8515fold_builtin_isascii (tree arglist)
8516{
8517  if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8518    return 0;
8519  else
8520    {
8521      /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
8522      tree arg = TREE_VALUE (arglist);
8523
8524      arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
8525		    build_int_cst (NULL_TREE,
8526				   ~ (unsigned HOST_WIDE_INT) 0x7f));
8527      arg = fold_build2 (EQ_EXPR, integer_type_node,
8528			 arg, integer_zero_node);
8529
8530      if (in_gimple_form && !TREE_CONSTANT (arg))
8531        return NULL_TREE;
8532      else
8533        return arg;
8534    }
8535}
8536
8537/* Fold a call to builtin toascii.  */
8538
8539static tree
8540fold_builtin_toascii (tree arglist)
8541{
8542  if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8543    return 0;
8544  else
8545    {
8546      /* Transform toascii(c) -> (c & 0x7f).  */
8547      tree arg = TREE_VALUE (arglist);
8548
8549      return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
8550			  build_int_cst (NULL_TREE, 0x7f));
8551    }
8552}
8553
8554/* Fold a call to builtin isdigit.  */
8555
8556static tree
8557fold_builtin_isdigit (tree arglist)
8558{
8559  if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8560    return 0;
8561  else
8562    {
8563      /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9.  */
8564      /* According to the C standard, isdigit is unaffected by locale.
8565	 However, it definitely is affected by the target character set.  */
8566      tree arg;
8567      unsigned HOST_WIDE_INT target_digit0
8568	= lang_hooks.to_target_charset ('0');
8569
8570      if (target_digit0 == 0)
8571	return NULL_TREE;
8572
8573      arg = fold_convert (unsigned_type_node, TREE_VALUE (arglist));
8574      arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
8575		    build_int_cst (unsigned_type_node, target_digit0));
8576      arg = fold_build2 (LE_EXPR, integer_type_node, arg,
8577			 build_int_cst (unsigned_type_node, 9));
8578      if (in_gimple_form && !TREE_CONSTANT (arg))
8579        return NULL_TREE;
8580      else
8581        return arg;
8582    }
8583}
8584
8585/* Fold a call to fabs, fabsf or fabsl.  */
8586
8587static tree
8588fold_builtin_fabs (tree arglist, tree type)
8589{
8590  tree arg;
8591
8592  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8593    return 0;
8594
8595  arg = TREE_VALUE (arglist);
8596  arg = fold_convert (type, arg);
8597  if (TREE_CODE (arg) == REAL_CST)
8598    return fold_abs_const (arg, type);
8599  return fold_build1 (ABS_EXPR, type, arg);
8600}
8601
8602/* Fold a call to abs, labs, llabs or imaxabs.  */
8603
8604static tree
8605fold_builtin_abs (tree arglist, tree type)
8606{
8607  tree arg;
8608
8609  if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8610    return 0;
8611
8612  arg = TREE_VALUE (arglist);
8613  arg = fold_convert (type, arg);
8614  if (TREE_CODE (arg) == INTEGER_CST)
8615    return fold_abs_const (arg, type);
8616  return fold_build1 (ABS_EXPR, type, arg);
8617}
8618
8619/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
8620   EXP is the CALL_EXPR for the call.  */
8621
8622static tree
8623fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
8624{
8625  tree type = TREE_TYPE (TREE_TYPE (fndecl));
8626  tree arg;
8627  REAL_VALUE_TYPE r;
8628
8629  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8630    {
8631      /* Check that we have exactly one argument.  */
8632      if (arglist == 0)
8633	{
8634	  error ("too few arguments to function %qs",
8635		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8636	  return error_mark_node;
8637	}
8638      else if (TREE_CHAIN (arglist) != 0)
8639	{
8640	  error ("too many arguments to function %qs",
8641		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8642	  return error_mark_node;
8643	}
8644      else
8645	{
8646	  error ("non-floating-point argument to function %qs",
8647		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8648	  return error_mark_node;
8649	}
8650    }
8651
8652  arg = TREE_VALUE (arglist);
8653  switch (builtin_index)
8654    {
8655    case BUILT_IN_ISINF:
8656      if (!MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
8657        return omit_one_operand (type, integer_zero_node, arg);
8658
8659      if (TREE_CODE (arg) == REAL_CST)
8660	{
8661	  r = TREE_REAL_CST (arg);
8662	  if (real_isinf (&r))
8663	    return real_compare (GT_EXPR, &r, &dconst0)
8664		   ? integer_one_node : integer_minus_one_node;
8665	  else
8666	    return integer_zero_node;
8667	}
8668
8669      return NULL_TREE;
8670
8671    case BUILT_IN_FINITE:
8672      if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg)))
8673          && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
8674        return omit_one_operand (type, integer_one_node, arg);
8675
8676      if (TREE_CODE (arg) == REAL_CST)
8677	{
8678	  r = TREE_REAL_CST (arg);
8679	  return real_isinf (&r) || real_isnan (&r)
8680		 ? integer_zero_node : integer_one_node;
8681	}
8682
8683      return NULL_TREE;
8684
8685    case BUILT_IN_ISNAN:
8686      if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg))))
8687        return omit_one_operand (type, integer_zero_node, arg);
8688
8689      if (TREE_CODE (arg) == REAL_CST)
8690	{
8691	  r = TREE_REAL_CST (arg);
8692	  return real_isnan (&r) ? integer_one_node : integer_zero_node;
8693	}
8694
8695      arg = builtin_save_expr (arg);
8696      return fold_build2 (UNORDERED_EXPR, type, arg, arg);
8697
8698    default:
8699      gcc_unreachable ();
8700    }
8701}
8702
8703/* Fold a call to an unordered comparison function such as
8704   __builtin_isgreater().  FNDECL is the FUNCTION_DECL for the function
8705   being called and ARGLIST is the argument list for the call.
8706   UNORDERED_CODE and ORDERED_CODE are comparison codes that give
8707   the opposite of the desired result.  UNORDERED_CODE is used
8708   for modes that can hold NaNs and ORDERED_CODE is used for
8709   the rest.  */
8710
8711static tree
8712fold_builtin_unordered_cmp (tree fndecl, tree arglist,
8713			    enum tree_code unordered_code,
8714			    enum tree_code ordered_code)
8715{
8716  tree type = TREE_TYPE (TREE_TYPE (fndecl));
8717  enum tree_code code;
8718  tree arg0, arg1;
8719  tree type0, type1;
8720  enum tree_code code0, code1;
8721  tree cmp_type = NULL_TREE;
8722
8723  if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
8724    {
8725      /* Check that we have exactly two arguments.  */
8726      if (arglist == 0 || TREE_CHAIN (arglist) == 0)
8727	{
8728	  error ("too few arguments to function %qs",
8729		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8730	  return error_mark_node;
8731	}
8732      else if (TREE_CHAIN (TREE_CHAIN (arglist)) != 0)
8733	{
8734	  error ("too many arguments to function %qs",
8735		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8736	  return error_mark_node;
8737	}
8738    }
8739
8740  arg0 = TREE_VALUE (arglist);
8741  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
8742
8743  type0 = TREE_TYPE (arg0);
8744  type1 = TREE_TYPE (arg1);
8745
8746  code0 = TREE_CODE (type0);
8747  code1 = TREE_CODE (type1);
8748
8749  if (code0 == REAL_TYPE && code1 == REAL_TYPE)
8750    /* Choose the wider of two real types.  */
8751    cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
8752      ? type0 : type1;
8753  else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
8754    cmp_type = type0;
8755  else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
8756    cmp_type = type1;
8757  else
8758    {
8759      error ("non-floating-point argument to function %qs",
8760		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8761      return error_mark_node;
8762    }
8763
8764  arg0 = fold_convert (cmp_type, arg0);
8765  arg1 = fold_convert (cmp_type, arg1);
8766
8767  if (unordered_code == UNORDERED_EXPR)
8768    {
8769      if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))))
8770	return omit_two_operands (type, integer_zero_node, arg0, arg1);
8771      return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
8772    }
8773
8774  code = MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
8775						      : ordered_code;
8776  return fold_build1 (TRUTH_NOT_EXPR, type,
8777		      fold_build2 (code, type, arg0, arg1));
8778}
8779
8780/* Used by constant folding to simplify calls to builtin functions.  EXP is
8781   the CALL_EXPR of a call to a builtin function.  IGNORE is true if the
8782   result of the function call is ignored.  This function returns NULL_TREE
8783   if no simplification was possible.  */
8784
8785static tree
8786fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
8787{
8788  tree type = TREE_TYPE (TREE_TYPE (fndecl));
8789  enum built_in_function fcode;
8790
8791  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
8792    return targetm.fold_builtin (fndecl, arglist, ignore);
8793
8794  fcode = DECL_FUNCTION_CODE (fndecl);
8795  switch (fcode)
8796    {
8797    case BUILT_IN_FPUTS:
8798      return fold_builtin_fputs (arglist, ignore, false, NULL_TREE);
8799
8800    case BUILT_IN_FPUTS_UNLOCKED:
8801      return fold_builtin_fputs (arglist, ignore, true, NULL_TREE);
8802
8803    case BUILT_IN_STRSTR:
8804      return fold_builtin_strstr (arglist, type);
8805
8806    case BUILT_IN_STRCAT:
8807      return fold_builtin_strcat (arglist);
8808
8809    case BUILT_IN_STRNCAT:
8810      return fold_builtin_strncat (arglist);
8811
8812    case BUILT_IN_STRSPN:
8813      return fold_builtin_strspn (arglist);
8814
8815    case BUILT_IN_STRCSPN:
8816      return fold_builtin_strcspn (arglist);
8817
8818    case BUILT_IN_STRCHR:
8819    case BUILT_IN_INDEX:
8820      return fold_builtin_strchr (arglist, type);
8821
8822    case BUILT_IN_STRRCHR:
8823    case BUILT_IN_RINDEX:
8824      return fold_builtin_strrchr (arglist, type);
8825
8826    case BUILT_IN_STRCPY:
8827      return fold_builtin_strcpy (fndecl, arglist, NULL_TREE);
8828
8829    case BUILT_IN_STRNCPY:
8830      return fold_builtin_strncpy (fndecl, arglist, NULL_TREE);
8831
8832    case BUILT_IN_STRCMP:
8833      return fold_builtin_strcmp (arglist);
8834
8835    case BUILT_IN_STRNCMP:
8836      return fold_builtin_strncmp (arglist);
8837
8838    case BUILT_IN_STRPBRK:
8839      return fold_builtin_strpbrk (arglist, type);
8840
8841    case BUILT_IN_BCMP:
8842    case BUILT_IN_MEMCMP:
8843      return fold_builtin_memcmp (arglist);
8844
8845    case BUILT_IN_SPRINTF:
8846      return fold_builtin_sprintf (arglist, ignore);
8847
8848    case BUILT_IN_CONSTANT_P:
8849      {
8850	tree val;
8851
8852	val = fold_builtin_constant_p (arglist);
8853	/* Gimplification will pull the CALL_EXPR for the builtin out of
8854	   an if condition.  When not optimizing, we'll not CSE it back.
8855	   To avoid link error types of regressions, return false now.  */
8856	if (!val && !optimize)
8857	  val = integer_zero_node;
8858
8859	return val;
8860      }
8861
8862    case BUILT_IN_EXPECT:
8863      return fold_builtin_expect (arglist);
8864
8865    case BUILT_IN_CLASSIFY_TYPE:
8866      return fold_builtin_classify_type (arglist);
8867
8868    case BUILT_IN_STRLEN:
8869      return fold_builtin_strlen (arglist);
8870
8871    case BUILT_IN_FABS:
8872    case BUILT_IN_FABSF:
8873    case BUILT_IN_FABSL:
8874      return fold_builtin_fabs (arglist, type);
8875
8876    case BUILT_IN_ABS:
8877    case BUILT_IN_LABS:
8878    case BUILT_IN_LLABS:
8879    case BUILT_IN_IMAXABS:
8880      return fold_builtin_abs (arglist, type);
8881
8882    case BUILT_IN_CONJ:
8883    case BUILT_IN_CONJF:
8884    case BUILT_IN_CONJL:
8885      if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
8886	return fold_build1 (CONJ_EXPR, type, TREE_VALUE (arglist));
8887      break;
8888
8889    case BUILT_IN_CREAL:
8890    case BUILT_IN_CREALF:
8891    case BUILT_IN_CREALL:
8892      if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
8893        return non_lvalue (fold_build1 (REALPART_EXPR, type,
8894					TREE_VALUE (arglist)));
8895      break;
8896
8897    case BUILT_IN_CIMAG:
8898    case BUILT_IN_CIMAGF:
8899    case BUILT_IN_CIMAGL:
8900      if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
8901        return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
8902					TREE_VALUE (arglist)));
8903      break;
8904
8905    case BUILT_IN_CABS:
8906    case BUILT_IN_CABSF:
8907    case BUILT_IN_CABSL:
8908      return fold_builtin_cabs (arglist, type);
8909
8910    case BUILT_IN_SQRT:
8911    case BUILT_IN_SQRTF:
8912    case BUILT_IN_SQRTL:
8913      return fold_builtin_sqrt (arglist, type);
8914
8915    case BUILT_IN_CBRT:
8916    case BUILT_IN_CBRTF:
8917    case BUILT_IN_CBRTL:
8918      return fold_builtin_cbrt (arglist, type);
8919
8920    case BUILT_IN_SIN:
8921    case BUILT_IN_SINF:
8922    case BUILT_IN_SINL:
8923      return fold_builtin_sin (arglist);
8924
8925    case BUILT_IN_COS:
8926    case BUILT_IN_COSF:
8927    case BUILT_IN_COSL:
8928      return fold_builtin_cos (arglist, type, fndecl);
8929
8930    case BUILT_IN_EXP:
8931    case BUILT_IN_EXPF:
8932    case BUILT_IN_EXPL:
8933      return fold_builtin_exponent (fndecl, arglist, &dconste);
8934
8935    case BUILT_IN_EXP2:
8936    case BUILT_IN_EXP2F:
8937    case BUILT_IN_EXP2L:
8938      return fold_builtin_exponent (fndecl, arglist, &dconst2);
8939
8940    case BUILT_IN_EXP10:
8941    case BUILT_IN_EXP10F:
8942    case BUILT_IN_EXP10L:
8943    case BUILT_IN_POW10:
8944    case BUILT_IN_POW10F:
8945    case BUILT_IN_POW10L:
8946      return fold_builtin_exponent (fndecl, arglist, &dconst10);
8947
8948    case BUILT_IN_LOG:
8949    case BUILT_IN_LOGF:
8950    case BUILT_IN_LOGL:
8951      return fold_builtin_logarithm (fndecl, arglist, &dconste);
8952
8953    case BUILT_IN_LOG2:
8954    case BUILT_IN_LOG2F:
8955    case BUILT_IN_LOG2L:
8956      return fold_builtin_logarithm (fndecl, arglist, &dconst2);
8957
8958    case BUILT_IN_LOG10:
8959    case BUILT_IN_LOG10F:
8960    case BUILT_IN_LOG10L:
8961      return fold_builtin_logarithm (fndecl, arglist, &dconst10);
8962
8963    case BUILT_IN_TAN:
8964    case BUILT_IN_TANF:
8965    case BUILT_IN_TANL:
8966      return fold_builtin_tan (arglist);
8967
8968    case BUILT_IN_ATAN:
8969    case BUILT_IN_ATANF:
8970    case BUILT_IN_ATANL:
8971      return fold_builtin_atan (arglist, type);
8972
8973    case BUILT_IN_POW:
8974    case BUILT_IN_POWF:
8975    case BUILT_IN_POWL:
8976      return fold_builtin_pow (fndecl, arglist, type);
8977
8978    case BUILT_IN_POWI:
8979    case BUILT_IN_POWIF:
8980    case BUILT_IN_POWIL:
8981      return fold_builtin_powi (fndecl, arglist, type);
8982
8983    case BUILT_IN_INF:
8984    case BUILT_IN_INFF:
8985    case BUILT_IN_INFL:
8986      return fold_builtin_inf (type, true);
8987
8988    case BUILT_IN_HUGE_VAL:
8989    case BUILT_IN_HUGE_VALF:
8990    case BUILT_IN_HUGE_VALL:
8991      return fold_builtin_inf (type, false);
8992
8993    case BUILT_IN_NAN:
8994    case BUILT_IN_NANF:
8995    case BUILT_IN_NANL:
8996      return fold_builtin_nan (arglist, type, true);
8997
8998    case BUILT_IN_NANS:
8999    case BUILT_IN_NANSF:
9000    case BUILT_IN_NANSL:
9001      return fold_builtin_nan (arglist, type, false);
9002
9003    case BUILT_IN_FLOOR:
9004    case BUILT_IN_FLOORF:
9005    case BUILT_IN_FLOORL:
9006      return fold_builtin_floor (fndecl, arglist);
9007
9008    case BUILT_IN_CEIL:
9009    case BUILT_IN_CEILF:
9010    case BUILT_IN_CEILL:
9011      return fold_builtin_ceil (fndecl, arglist);
9012
9013    case BUILT_IN_TRUNC:
9014    case BUILT_IN_TRUNCF:
9015    case BUILT_IN_TRUNCL:
9016      return fold_builtin_trunc (fndecl, arglist);
9017
9018    case BUILT_IN_ROUND:
9019    case BUILT_IN_ROUNDF:
9020    case BUILT_IN_ROUNDL:
9021      return fold_builtin_round (fndecl, arglist);
9022
9023    case BUILT_IN_NEARBYINT:
9024    case BUILT_IN_NEARBYINTF:
9025    case BUILT_IN_NEARBYINTL:
9026    case BUILT_IN_RINT:
9027    case BUILT_IN_RINTF:
9028    case BUILT_IN_RINTL:
9029      return fold_trunc_transparent_mathfn (fndecl, arglist);
9030
9031    case BUILT_IN_LCEIL:
9032    case BUILT_IN_LCEILF:
9033    case BUILT_IN_LCEILL:
9034    case BUILT_IN_LLCEIL:
9035    case BUILT_IN_LLCEILF:
9036    case BUILT_IN_LLCEILL:
9037    case BUILT_IN_LFLOOR:
9038    case BUILT_IN_LFLOORF:
9039    case BUILT_IN_LFLOORL:
9040    case BUILT_IN_LLFLOOR:
9041    case BUILT_IN_LLFLOORF:
9042    case BUILT_IN_LLFLOORL:
9043    case BUILT_IN_LROUND:
9044    case BUILT_IN_LROUNDF:
9045    case BUILT_IN_LROUNDL:
9046    case BUILT_IN_LLROUND:
9047    case BUILT_IN_LLROUNDF:
9048    case BUILT_IN_LLROUNDL:
9049      return fold_builtin_int_roundingfn (fndecl, arglist);
9050
9051    case BUILT_IN_LRINT:
9052    case BUILT_IN_LRINTF:
9053    case BUILT_IN_LRINTL:
9054    case BUILT_IN_LLRINT:
9055    case BUILT_IN_LLRINTF:
9056    case BUILT_IN_LLRINTL:
9057      return fold_fixed_mathfn (fndecl, arglist);
9058
9059    case BUILT_IN_FFS:
9060    case BUILT_IN_FFSL:
9061    case BUILT_IN_FFSLL:
9062    case BUILT_IN_CLZ:
9063    case BUILT_IN_CLZL:
9064    case BUILT_IN_CLZLL:
9065    case BUILT_IN_CTZ:
9066    case BUILT_IN_CTZL:
9067    case BUILT_IN_CTZLL:
9068    case BUILT_IN_POPCOUNT:
9069    case BUILT_IN_POPCOUNTL:
9070    case BUILT_IN_POPCOUNTLL:
9071    case BUILT_IN_PARITY:
9072    case BUILT_IN_PARITYL:
9073    case BUILT_IN_PARITYLL:
9074      return fold_builtin_bitop (fndecl, arglist);
9075
9076    case BUILT_IN_MEMCPY:
9077      return fold_builtin_memcpy (fndecl, arglist);
9078
9079    case BUILT_IN_MEMPCPY:
9080      return fold_builtin_mempcpy (arglist, type, /*endp=*/1);
9081
9082    case BUILT_IN_MEMMOVE:
9083      return fold_builtin_memmove (arglist, type);
9084
9085    case BUILT_IN_SIGNBIT:
9086    case BUILT_IN_SIGNBITF:
9087    case BUILT_IN_SIGNBITL:
9088      return fold_builtin_signbit (fndecl, arglist);
9089
9090    case BUILT_IN_ISASCII:
9091      return fold_builtin_isascii (arglist);
9092
9093    case BUILT_IN_TOASCII:
9094      return fold_builtin_toascii (arglist);
9095
9096    case BUILT_IN_ISDIGIT:
9097      return fold_builtin_isdigit (arglist);
9098
9099    case BUILT_IN_COPYSIGN:
9100    case BUILT_IN_COPYSIGNF:
9101    case BUILT_IN_COPYSIGNL:
9102      return fold_builtin_copysign (fndecl, arglist, type);
9103
9104    case BUILT_IN_FINITE:
9105    case BUILT_IN_FINITEF:
9106    case BUILT_IN_FINITEL:
9107      return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE);
9108
9109    case BUILT_IN_ISINF:
9110    case BUILT_IN_ISINFF:
9111    case BUILT_IN_ISINFL:
9112      return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF);
9113
9114    case BUILT_IN_ISNAN:
9115    case BUILT_IN_ISNANF:
9116    case BUILT_IN_ISNANL:
9117      return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN);
9118
9119    case BUILT_IN_ISGREATER:
9120      return fold_builtin_unordered_cmp (fndecl, arglist, UNLE_EXPR, LE_EXPR);
9121    case BUILT_IN_ISGREATEREQUAL:
9122      return fold_builtin_unordered_cmp (fndecl, arglist, UNLT_EXPR, LT_EXPR);
9123    case BUILT_IN_ISLESS:
9124      return fold_builtin_unordered_cmp (fndecl, arglist, UNGE_EXPR, GE_EXPR);
9125    case BUILT_IN_ISLESSEQUAL:
9126      return fold_builtin_unordered_cmp (fndecl, arglist, UNGT_EXPR, GT_EXPR);
9127    case BUILT_IN_ISLESSGREATER:
9128      return fold_builtin_unordered_cmp (fndecl, arglist, UNEQ_EXPR, EQ_EXPR);
9129    case BUILT_IN_ISUNORDERED:
9130      return fold_builtin_unordered_cmp (fndecl, arglist, UNORDERED_EXPR,
9131					 NOP_EXPR);
9132
9133      /* We do the folding for va_start in the expander.  */
9134    case BUILT_IN_VA_START:
9135      break;
9136
9137    case BUILT_IN_OBJECT_SIZE:
9138      return fold_builtin_object_size (arglist);
9139    case BUILT_IN_MEMCPY_CHK:
9140    case BUILT_IN_MEMPCPY_CHK:
9141    case BUILT_IN_MEMMOVE_CHK:
9142    case BUILT_IN_MEMSET_CHK:
9143      return fold_builtin_memory_chk (fndecl, arglist, NULL_TREE, ignore,
9144				      DECL_FUNCTION_CODE (fndecl));
9145    case BUILT_IN_STRCPY_CHK:
9146    case BUILT_IN_STPCPY_CHK:
9147      return fold_builtin_stxcpy_chk (fndecl, arglist, NULL_TREE, ignore,
9148				      DECL_FUNCTION_CODE (fndecl));
9149    case BUILT_IN_STRNCPY_CHK:
9150      return fold_builtin_strncpy_chk (arglist, NULL_TREE);
9151    case BUILT_IN_STRCAT_CHK:
9152      return fold_builtin_strcat_chk (fndecl, arglist);
9153    case BUILT_IN_STRNCAT_CHK:
9154      return fold_builtin_strncat_chk (fndecl, arglist);
9155    case BUILT_IN_SPRINTF_CHK:
9156    case BUILT_IN_VSPRINTF_CHK:
9157      return fold_builtin_sprintf_chk (arglist, DECL_FUNCTION_CODE (fndecl));
9158    case BUILT_IN_SNPRINTF_CHK:
9159    case BUILT_IN_VSNPRINTF_CHK:
9160      return fold_builtin_snprintf_chk (arglist, NULL_TREE,
9161					DECL_FUNCTION_CODE (fndecl));
9162
9163    case BUILT_IN_PRINTF:
9164    case BUILT_IN_PRINTF_UNLOCKED:
9165    case BUILT_IN_VPRINTF:
9166    case BUILT_IN_PRINTF_CHK:
9167    case BUILT_IN_VPRINTF_CHK:
9168      return fold_builtin_printf (fndecl, arglist, ignore,
9169				  DECL_FUNCTION_CODE (fndecl));
9170
9171    case BUILT_IN_FPRINTF:
9172    case BUILT_IN_FPRINTF_UNLOCKED:
9173    case BUILT_IN_VFPRINTF:
9174    case BUILT_IN_FPRINTF_CHK:
9175    case BUILT_IN_VFPRINTF_CHK:
9176      return fold_builtin_fprintf (fndecl, arglist, ignore,
9177				   DECL_FUNCTION_CODE (fndecl));
9178
9179    default:
9180      break;
9181    }
9182
9183  return 0;
9184}
9185
9186/* A wrapper function for builtin folding that prevents warnings for
9187   "statement without effect" and the like, caused by removing the
9188   call node earlier than the warning is generated.  */
9189
9190tree
9191fold_builtin (tree fndecl, tree arglist, bool ignore)
9192{
9193  tree exp = fold_builtin_1 (fndecl, arglist, ignore);
9194  if (exp)
9195    {
9196      exp = build1 (NOP_EXPR, TREE_TYPE (exp), exp);
9197      TREE_NO_WARNING (exp) = 1;
9198    }
9199
9200  return exp;
9201}
9202
9203/* Conveniently construct a function call expression.  */
9204
9205tree
9206build_function_call_expr (tree fn, tree arglist)
9207{
9208  tree call_expr;
9209
9210  call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
9211  return fold_build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
9212		      call_expr, arglist, NULL_TREE);
9213}
9214
9215/* This function validates the types of a function call argument list
9216   represented as a tree chain of parameters against a specified list
9217   of tree_codes.  If the last specifier is a 0, that represents an
9218   ellipses, otherwise the last specifier must be a VOID_TYPE.  */
9219
9220static int
9221validate_arglist (tree arglist, ...)
9222{
9223  enum tree_code code;
9224  int res = 0;
9225  va_list ap;
9226
9227  va_start (ap, arglist);
9228
9229  do
9230    {
9231      code = va_arg (ap, enum tree_code);
9232      switch (code)
9233	{
9234	case 0:
9235	  /* This signifies an ellipses, any further arguments are all ok.  */
9236	  res = 1;
9237	  goto end;
9238	case VOID_TYPE:
9239	  /* This signifies an endlink, if no arguments remain, return
9240	     true, otherwise return false.  */
9241	  res = arglist == 0;
9242	  goto end;
9243	default:
9244	  /* If no parameters remain or the parameter's code does not
9245	     match the specified code, return false.  Otherwise continue
9246	     checking any remaining arguments.  */
9247	  if (arglist == 0)
9248	    goto end;
9249	  if (code == POINTER_TYPE)
9250	    {
9251	      if (! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))))
9252		goto end;
9253	    }
9254	  else if (code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
9255	    goto end;
9256	  break;
9257	}
9258      arglist = TREE_CHAIN (arglist);
9259    }
9260  while (1);
9261
9262  /* We need gotos here since we can only have one VA_CLOSE in a
9263     function.  */
9264 end: ;
9265  va_end (ap);
9266
9267  return res;
9268}
9269
9270/* Default target-specific builtin expander that does nothing.  */
9271
9272rtx
9273default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
9274			rtx target ATTRIBUTE_UNUSED,
9275			rtx subtarget ATTRIBUTE_UNUSED,
9276			enum machine_mode mode ATTRIBUTE_UNUSED,
9277			int ignore ATTRIBUTE_UNUSED)
9278{
9279  return NULL_RTX;
9280}
9281
9282/* Returns true is EXP represents data that would potentially reside
9283   in a readonly section.  */
9284
9285static bool
9286readonly_data_expr (tree exp)
9287{
9288  STRIP_NOPS (exp);
9289
9290  if (TREE_CODE (exp) != ADDR_EXPR)
9291    return false;
9292
9293  exp = get_base_address (TREE_OPERAND (exp, 0));
9294  if (!exp)
9295    return false;
9296
9297  /* Make sure we call decl_readonly_section only for trees it
9298     can handle (since it returns true for everything it doesn't
9299     understand).  */
9300  if (TREE_CODE (exp) == STRING_CST
9301      || TREE_CODE (exp) == CONSTRUCTOR
9302      || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
9303    return decl_readonly_section (exp, 0);
9304  else
9305    return false;
9306}
9307
9308/* Simplify a call to the strstr builtin.
9309
9310   Return 0 if no simplification was possible, otherwise return the
9311   simplified form of the call as a tree.
9312
9313   The simplified form may be a constant or other expression which
9314   computes the same value, but in a more efficient manner (including
9315   calls to other builtin functions).
9316
9317   The call may contain arguments which need to be evaluated, but
9318   which are not useful to determine the result of the call.  In
9319   this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9320   COMPOUND_EXPR will be an argument which must be evaluated.
9321   COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9322   COMPOUND_EXPR in the chain will contain the tree for the simplified
9323   form of the builtin function call.  */
9324
9325static tree
9326fold_builtin_strstr (tree arglist, tree type)
9327{
9328  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9329    return 0;
9330  else
9331    {
9332      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9333      tree fn;
9334      const char *p1, *p2;
9335
9336      p2 = c_getstr (s2);
9337      if (p2 == NULL)
9338	return 0;
9339
9340      p1 = c_getstr (s1);
9341      if (p1 != NULL)
9342	{
9343	  const char *r = strstr (p1, p2);
9344	  tree tem;
9345
9346	  if (r == NULL)
9347	    return build_int_cst (TREE_TYPE (s1), 0);
9348
9349	  /* Return an offset into the constant string argument.  */
9350	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9351			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9352	  return fold_convert (type, tem);
9353	}
9354
9355      /* The argument is const char *, and the result is char *, so we need
9356	 a type conversion here to avoid a warning.  */
9357      if (p2[0] == '\0')
9358	return fold_convert (type, s1);
9359
9360      if (p2[1] != '\0')
9361	return 0;
9362
9363      fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9364      if (!fn)
9365	return 0;
9366
9367      /* New argument list transforming strstr(s1, s2) to
9368	 strchr(s1, s2[0]).  */
9369      arglist = build_tree_list (NULL_TREE,
9370				 build_int_cst (NULL_TREE, p2[0]));
9371      arglist = tree_cons (NULL_TREE, s1, arglist);
9372      return build_function_call_expr (fn, arglist);
9373    }
9374}
9375
9376/* Simplify a call to the strchr builtin.
9377
9378   Return 0 if no simplification was possible, otherwise return the
9379   simplified form of the call as a tree.
9380
9381   The simplified form may be a constant or other expression which
9382   computes the same value, but in a more efficient manner (including
9383   calls to other builtin functions).
9384
9385   The call may contain arguments which need to be evaluated, but
9386   which are not useful to determine the result of the call.  In
9387   this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9388   COMPOUND_EXPR will be an argument which must be evaluated.
9389   COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9390   COMPOUND_EXPR in the chain will contain the tree for the simplified
9391   form of the builtin function call.  */
9392
9393static tree
9394fold_builtin_strchr (tree arglist, tree type)
9395{
9396  if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9397    return 0;
9398  else
9399    {
9400      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9401      const char *p1;
9402
9403      if (TREE_CODE (s2) != INTEGER_CST)
9404	return 0;
9405
9406      p1 = c_getstr (s1);
9407      if (p1 != NULL)
9408	{
9409	  char c;
9410	  const char *r;
9411	  tree tem;
9412
9413	  if (target_char_cast (s2, &c))
9414	    return 0;
9415
9416	  r = strchr (p1, c);
9417
9418	  if (r == NULL)
9419	    return build_int_cst (TREE_TYPE (s1), 0);
9420
9421	  /* Return an offset into the constant string argument.  */
9422	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9423			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9424	  return fold_convert (type, tem);
9425	}
9426      return 0;
9427    }
9428}
9429
9430/* Simplify a call to the strrchr builtin.
9431
9432   Return 0 if no simplification was possible, otherwise return the
9433   simplified form of the call as a tree.
9434
9435   The simplified form may be a constant or other expression which
9436   computes the same value, but in a more efficient manner (including
9437   calls to other builtin functions).
9438
9439   The call may contain arguments which need to be evaluated, but
9440   which are not useful to determine the result of the call.  In
9441   this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9442   COMPOUND_EXPR will be an argument which must be evaluated.
9443   COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9444   COMPOUND_EXPR in the chain will contain the tree for the simplified
9445   form of the builtin function call.  */
9446
9447static tree
9448fold_builtin_strrchr (tree arglist, tree type)
9449{
9450  if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9451    return 0;
9452  else
9453    {
9454      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9455      tree fn;
9456      const char *p1;
9457
9458      if (TREE_CODE (s2) != INTEGER_CST)
9459	return 0;
9460
9461      p1 = c_getstr (s1);
9462      if (p1 != NULL)
9463	{
9464	  char c;
9465	  const char *r;
9466	  tree tem;
9467
9468	  if (target_char_cast (s2, &c))
9469	    return 0;
9470
9471	  r = strrchr (p1, c);
9472
9473	  if (r == NULL)
9474	    return build_int_cst (TREE_TYPE (s1), 0);
9475
9476	  /* Return an offset into the constant string argument.  */
9477	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9478			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9479	  return fold_convert (type, tem);
9480	}
9481
9482      if (! integer_zerop (s2))
9483	return 0;
9484
9485      fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9486      if (!fn)
9487	return 0;
9488
9489      /* Transform strrchr(s1, '\0') to strchr(s1, '\0').  */
9490      return build_function_call_expr (fn, arglist);
9491    }
9492}
9493
9494/* Simplify a call to the strpbrk builtin.
9495
9496   Return 0 if no simplification was possible, otherwise return the
9497   simplified form of the call as a tree.
9498
9499   The simplified form may be a constant or other expression which
9500   computes the same value, but in a more efficient manner (including
9501   calls to other builtin functions).
9502
9503   The call may contain arguments which need to be evaluated, but
9504   which are not useful to determine the result of the call.  In
9505   this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9506   COMPOUND_EXPR will be an argument which must be evaluated.
9507   COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9508   COMPOUND_EXPR in the chain will contain the tree for the simplified
9509   form of the builtin function call.  */
9510
9511static tree
9512fold_builtin_strpbrk (tree arglist, tree type)
9513{
9514  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9515    return 0;
9516  else
9517    {
9518      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9519      tree fn;
9520      const char *p1, *p2;
9521
9522      p2 = c_getstr (s2);
9523      if (p2 == NULL)
9524	return 0;
9525
9526      p1 = c_getstr (s1);
9527      if (p1 != NULL)
9528	{
9529	  const char *r = strpbrk (p1, p2);
9530	  tree tem;
9531
9532	  if (r == NULL)
9533	    return build_int_cst (TREE_TYPE (s1), 0);
9534
9535	  /* Return an offset into the constant string argument.  */
9536	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9537			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9538	  return fold_convert (type, tem);
9539	}
9540
9541      if (p2[0] == '\0')
9542	/* strpbrk(x, "") == NULL.
9543	   Evaluate and ignore s1 in case it had side-effects.  */
9544	return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1);
9545
9546      if (p2[1] != '\0')
9547	return 0;  /* Really call strpbrk.  */
9548
9549      fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9550      if (!fn)
9551	return 0;
9552
9553      /* New argument list transforming strpbrk(s1, s2) to
9554	 strchr(s1, s2[0]).  */
9555      arglist = build_tree_list (NULL_TREE,
9556				 build_int_cst (NULL_TREE, p2[0]));
9557      arglist = tree_cons (NULL_TREE, s1, arglist);
9558      return build_function_call_expr (fn, arglist);
9559    }
9560}
9561
9562/* Simplify a call to the strcat builtin.
9563
9564   Return 0 if no simplification was possible, otherwise return the
9565   simplified form of the call as a tree.
9566
9567   The simplified form may be a constant or other expression which
9568   computes the same value, but in a more efficient manner (including
9569   calls to other builtin functions).
9570
9571   The call may contain arguments which need to be evaluated, but
9572   which are not useful to determine the result of the call.  In
9573   this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9574   COMPOUND_EXPR will be an argument which must be evaluated.
9575   COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9576   COMPOUND_EXPR in the chain will contain the tree for the simplified
9577   form of the builtin function call.  */
9578
9579static tree
9580fold_builtin_strcat (tree arglist)
9581{
9582  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9583    return 0;
9584  else
9585    {
9586      tree dst = TREE_VALUE (arglist),
9587	src = TREE_VALUE (TREE_CHAIN (arglist));
9588      const char *p = c_getstr (src);
9589
9590      /* If the string length is zero, return the dst parameter.  */
9591      if (p && *p == '\0')
9592	return dst;
9593
9594      return 0;
9595    }
9596}
9597
9598/* Simplify a call to the strncat builtin.
9599
9600   Return 0 if no simplification was possible, otherwise return the
9601   simplified form of the call as a tree.
9602
9603   The simplified form may be a constant or other expression which
9604   computes the same value, but in a more efficient manner (including
9605   calls to other builtin functions).
9606
9607   The call may contain arguments which need to be evaluated, but
9608   which are not useful to determine the result of the call.  In
9609   this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9610   COMPOUND_EXPR will be an argument which must be evaluated.
9611   COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9612   COMPOUND_EXPR in the chain will contain the tree for the simplified
9613   form of the builtin function call.  */
9614
9615static tree
9616fold_builtin_strncat (tree arglist)
9617{
9618  if (!validate_arglist (arglist,
9619			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9620    return 0;
9621  else
9622    {
9623      tree dst = TREE_VALUE (arglist);
9624      tree src = TREE_VALUE (TREE_CHAIN (arglist));
9625      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
9626      const char *p = c_getstr (src);
9627
9628      /* If the requested length is zero, or the src parameter string
9629	 length is zero, return the dst parameter.  */
9630      if (integer_zerop (len) || (p && *p == '\0'))
9631        return omit_two_operands (TREE_TYPE (dst), dst, src, len);
9632
9633      /* If the requested len is greater than or equal to the string
9634         length, call strcat.  */
9635      if (TREE_CODE (len) == INTEGER_CST && p
9636	  && compare_tree_int (len, strlen (p)) >= 0)
9637	{
9638	  tree newarglist
9639	    = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
9640	  tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
9641
9642	  /* If the replacement _DECL isn't initialized, don't do the
9643	     transformation.  */
9644	  if (!fn)
9645	    return 0;
9646
9647	  return build_function_call_expr (fn, newarglist);
9648	}
9649      return 0;
9650    }
9651}
9652
9653/* Simplify a call to the strspn builtin.
9654
9655   Return 0 if no simplification was possible, otherwise return the
9656   simplified form of the call as a tree.
9657
9658   The simplified form may be a constant or other expression which
9659   computes the same value, but in a more efficient manner (including
9660   calls to other builtin functions).
9661
9662   The call may contain arguments which need to be evaluated, but
9663   which are not useful to determine the result of the call.  In
9664   this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9665   COMPOUND_EXPR will be an argument which must be evaluated.
9666   COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9667   COMPOUND_EXPR in the chain will contain the tree for the simplified
9668   form of the builtin function call.  */
9669
9670static tree
9671fold_builtin_strspn (tree arglist)
9672{
9673  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9674    return 0;
9675  else
9676    {
9677      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9678      const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
9679
9680      /* If both arguments are constants, evaluate at compile-time.  */
9681      if (p1 && p2)
9682	{
9683	  const size_t r = strspn (p1, p2);
9684	  return size_int (r);
9685	}
9686
9687      /* If either argument is "", return 0.  */
9688      if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9689	/* Evaluate and ignore both arguments in case either one has
9690	   side-effects.  */
9691	return omit_two_operands (integer_type_node, integer_zero_node,
9692				  s1, s2);
9693      return 0;
9694    }
9695}
9696
9697/* Simplify a call to the strcspn builtin.
9698
9699   Return 0 if no simplification was possible, otherwise return the
9700   simplified form of the call as a tree.
9701
9702   The simplified form may be a constant or other expression which
9703   computes the same value, but in a more efficient manner (including
9704   calls to other builtin functions).
9705
9706   The call may contain arguments which need to be evaluated, but
9707   which are not useful to determine the result of the call.  In
9708   this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9709   COMPOUND_EXPR will be an argument which must be evaluated.
9710   COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9711   COMPOUND_EXPR in the chain will contain the tree for the simplified
9712   form of the builtin function call.  */
9713
9714static tree
9715fold_builtin_strcspn (tree arglist)
9716{
9717  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9718    return 0;
9719  else
9720    {
9721      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9722      const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
9723
9724      /* If both arguments are constants, evaluate at compile-time.  */
9725      if (p1 && p2)
9726	{
9727	  const size_t r = strcspn (p1, p2);
9728	  return size_int (r);
9729	}
9730
9731      /* If the first argument is "", return 0.  */
9732      if (p1 && *p1 == '\0')
9733	{
9734	  /* Evaluate and ignore argument s2 in case it has
9735	     side-effects.  */
9736	  return omit_one_operand (integer_type_node,
9737				   integer_zero_node, s2);
9738	}
9739
9740      /* If the second argument is "", return __builtin_strlen(s1).  */
9741      if (p2 && *p2 == '\0')
9742	{
9743	  tree newarglist = build_tree_list (NULL_TREE, s1),
9744	    fn = implicit_built_in_decls[BUILT_IN_STRLEN];
9745
9746	  /* If the replacement _DECL isn't initialized, don't do the
9747	     transformation.  */
9748	  if (!fn)
9749	    return 0;
9750
9751	  return build_function_call_expr (fn, newarglist);
9752	}
9753      return 0;
9754    }
9755}
9756
9757/* Fold a call to the fputs builtin.  IGNORE is true if the value returned
9758   by the builtin will be ignored.  UNLOCKED is true is true if this
9759   actually a call to fputs_unlocked.  If LEN in non-NULL, it represents
9760   the known length of the string.  Return NULL_TREE if no simplification
9761   was possible.  */
9762
9763tree
9764fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
9765{
9766  tree fn;
9767  /* If we're using an unlocked function, assume the other unlocked
9768     functions exist explicitly.  */
9769  tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
9770    : implicit_built_in_decls[BUILT_IN_FPUTC];
9771  tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
9772    : implicit_built_in_decls[BUILT_IN_FWRITE];
9773
9774  /* If the return value is used, don't do the transformation.  */
9775  if (!ignore)
9776    return 0;
9777
9778  /* Verify the arguments in the original call.  */
9779  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9780    return 0;
9781
9782  if (! len)
9783    len = c_strlen (TREE_VALUE (arglist), 0);
9784
9785  /* Get the length of the string passed to fputs.  If the length
9786     can't be determined, punt.  */
9787  if (!len
9788      || TREE_CODE (len) != INTEGER_CST)
9789    return 0;
9790
9791  switch (compare_tree_int (len, 1))
9792    {
9793    case -1: /* length is 0, delete the call entirely .  */
9794      return omit_one_operand (integer_type_node, integer_zero_node,
9795			       TREE_VALUE (TREE_CHAIN (arglist)));
9796
9797    case 0: /* length is 1, call fputc.  */
9798      {
9799	const char *p = c_getstr (TREE_VALUE (arglist));
9800
9801	if (p != NULL)
9802	  {
9803	    /* New argument list transforming fputs(string, stream) to
9804	       fputc(string[0], stream).  */
9805	    arglist = build_tree_list (NULL_TREE,
9806				       TREE_VALUE (TREE_CHAIN (arglist)));
9807	    arglist = tree_cons (NULL_TREE,
9808				 build_int_cst (NULL_TREE, p[0]),
9809				 arglist);
9810	    fn = fn_fputc;
9811	    break;
9812	  }
9813      }
9814      /* FALLTHROUGH */
9815    case 1: /* length is greater than 1, call fwrite.  */
9816      {
9817	tree string_arg;
9818
9819	/* If optimizing for size keep fputs.  */
9820	if (optimize_size)
9821	  return 0;
9822	string_arg = TREE_VALUE (arglist);
9823	/* New argument list transforming fputs(string, stream) to
9824	   fwrite(string, 1, len, stream).  */
9825	arglist = build_tree_list (NULL_TREE,
9826				   TREE_VALUE (TREE_CHAIN (arglist)));
9827	arglist = tree_cons (NULL_TREE, len, arglist);
9828	arglist = tree_cons (NULL_TREE, size_one_node, arglist);
9829	arglist = tree_cons (NULL_TREE, string_arg, arglist);
9830	fn = fn_fwrite;
9831	break;
9832      }
9833    default:
9834      gcc_unreachable ();
9835    }
9836
9837  /* If the replacement _DECL isn't initialized, don't do the
9838     transformation.  */
9839  if (!fn)
9840    return 0;
9841
9842  /* These optimizations are only performed when the result is ignored,
9843     hence there's no need to cast the result to integer_type_node.  */
9844  return build_function_call_expr (fn, arglist);
9845}
9846
9847/* Fold the new_arg's arguments (ARGLIST). Returns true if there was an error
9848   produced.  False otherwise.  This is done so that we don't output the error
9849   or warning twice or three times.  */
9850bool
9851fold_builtin_next_arg (tree arglist)
9852{
9853  tree fntype = TREE_TYPE (current_function_decl);
9854
9855  if (TYPE_ARG_TYPES (fntype) == 0
9856      || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
9857	  == void_type_node))
9858    {
9859      error ("%<va_start%> used in function with fixed args");
9860      return true;
9861    }
9862  else if (!arglist)
9863    {
9864      /* Evidently an out of date version of <stdarg.h>; can't validate
9865	 va_start's second argument, but can still work as intended.  */
9866      warning (0, "%<__builtin_next_arg%> called without an argument");
9867      return true;
9868    }
9869  /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
9870     when we checked the arguments and if needed issued a warning.  */
9871  else if (!TREE_CHAIN (arglist)
9872           || !integer_zerop (TREE_VALUE (arglist))
9873           || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist)))
9874           || TREE_CHAIN (TREE_CHAIN (arglist)))
9875    {
9876      tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
9877      tree arg = TREE_VALUE (arglist);
9878
9879      if (TREE_CHAIN (arglist))
9880        {
9881          error ("%<va_start%> used with too many arguments");
9882          return true;
9883        }
9884
9885      /* Strip off all nops for the sake of the comparison.  This
9886	 is not quite the same as STRIP_NOPS.  It does more.
9887	 We must also strip off INDIRECT_EXPR for C++ reference
9888	 parameters.  */
9889      while (TREE_CODE (arg) == NOP_EXPR
9890	     || TREE_CODE (arg) == CONVERT_EXPR
9891	     || TREE_CODE (arg) == NON_LVALUE_EXPR
9892	     || TREE_CODE (arg) == INDIRECT_REF)
9893	arg = TREE_OPERAND (arg, 0);
9894      if (arg != last_parm)
9895        {
9896#if 0
9897	  /* FIXME: Sometimes with the tree optimizers we can get the
9898	     not the last argument even though the user used the last
9899	     argument.  We just warn and set the arg to be the last
9900	     argument so that we will get wrong-code because of
9901	     it.  */
9902	  warning (0, "second parameter of %<va_start%> not last named argument");
9903#endif
9904	}
9905      /* We want to verify the second parameter just once before the tree
9906         optimizers are run and then avoid keeping it in the tree,
9907         as otherwise we could warn even for correct code like:
9908         void foo (int i, ...)
9909         { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
9910      TREE_VALUE (arglist) = integer_zero_node;
9911      TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node);
9912    }
9913  return false;
9914}
9915
9916
9917/* Simplify a call to the sprintf builtin.
9918
9919   Return 0 if no simplification was possible, otherwise return the
9920   simplified form of the call as a tree.  If IGNORED is true, it means that
9921   the caller does not use the returned value of the function.  */
9922
9923static tree
9924fold_builtin_sprintf (tree arglist, int ignored)
9925{
9926  tree call, retval, dest, fmt;
9927  const char *fmt_str = NULL;
9928
9929  /* Verify the required arguments in the original call.  We deal with two
9930     types of sprintf() calls: 'sprintf (str, fmt)' and
9931     'sprintf (dest, "%s", orig)'.  */
9932  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
9933      && !validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
9934			    VOID_TYPE))
9935    return NULL_TREE;
9936
9937  /* Get the destination string and the format specifier.  */
9938  dest = TREE_VALUE (arglist);
9939  fmt = TREE_VALUE (TREE_CHAIN (arglist));
9940  arglist = TREE_CHAIN (TREE_CHAIN (arglist));
9941
9942  /* Check whether the format is a literal string constant.  */
9943  fmt_str = c_getstr (fmt);
9944  if (fmt_str == NULL)
9945    return NULL_TREE;
9946
9947  call = NULL_TREE;
9948  retval = NULL_TREE;
9949
9950  if (!init_target_chars())
9951    return 0;
9952
9953  /* If the format doesn't contain % args or %%, use strcpy.  */
9954  if (strchr (fmt_str, target_percent) == NULL)
9955    {
9956      tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
9957
9958      if (!fn)
9959	return NULL_TREE;
9960
9961      /* Don't optimize sprintf (buf, "abc", ptr++).  */
9962      if (arglist)
9963	return NULL_TREE;
9964
9965      /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
9966	 'format' is known to contain no % formats.  */
9967      arglist = build_tree_list (NULL_TREE, fmt);
9968      arglist = tree_cons (NULL_TREE, dest, arglist);
9969      call = build_function_call_expr (fn, arglist);
9970      if (!ignored)
9971	retval = build_int_cst (NULL_TREE, strlen (fmt_str));
9972    }
9973
9974  /* If the format is "%s", use strcpy if the result isn't used.  */
9975  else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
9976    {
9977      tree fn, orig;
9978      fn = implicit_built_in_decls[BUILT_IN_STRCPY];
9979
9980      if (!fn)
9981	return NULL_TREE;
9982
9983      /* Don't crash on sprintf (str1, "%s").  */
9984      if (!arglist)
9985	return NULL_TREE;
9986
9987      /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2).  */
9988      orig = TREE_VALUE (arglist);
9989      arglist = build_tree_list (NULL_TREE, orig);
9990      arglist = tree_cons (NULL_TREE, dest, arglist);
9991      if (!ignored)
9992	{
9993	  retval = c_strlen (orig, 1);
9994	  if (!retval || TREE_CODE (retval) != INTEGER_CST)
9995	    return NULL_TREE;
9996	}
9997      call = build_function_call_expr (fn, arglist);
9998    }
9999
10000  if (call && retval)
10001    {
10002      retval = convert
10003	(TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
10004	 retval);
10005      return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
10006    }
10007  else
10008    return call;
10009}
10010
10011/* Expand a call to __builtin_object_size.  */
10012
10013rtx
10014expand_builtin_object_size (tree exp)
10015{
10016  tree ost;
10017  int object_size_type;
10018  tree fndecl = get_callee_fndecl (exp);
10019  tree arglist = TREE_OPERAND (exp, 1);
10020  location_t locus = EXPR_LOCATION (exp);
10021
10022  if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
10023    {
10024      error ("%Hfirst argument of %D must be a pointer, second integer constant",
10025	     &locus, fndecl);
10026      expand_builtin_trap ();
10027      return const0_rtx;
10028    }
10029
10030  ost = TREE_VALUE (TREE_CHAIN (arglist));
10031  STRIP_NOPS (ost);
10032
10033  if (TREE_CODE (ost) != INTEGER_CST
10034      || tree_int_cst_sgn (ost) < 0
10035      || compare_tree_int (ost, 3) > 0)
10036    {
10037      error ("%Hlast argument of %D is not integer constant between 0 and 3",
10038	     &locus, fndecl);
10039      expand_builtin_trap ();
10040      return const0_rtx;
10041    }
10042
10043  object_size_type = tree_low_cst (ost, 0);
10044
10045  return object_size_type < 2 ? constm1_rtx : const0_rtx;
10046}
10047
10048/* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
10049   FCODE is the BUILT_IN_* to use.
10050   Return 0 if we failed; the caller should emit a normal call,
10051   otherwise try to get the result in TARGET, if convenient (and in
10052   mode MODE if that's convenient).  */
10053
10054static rtx
10055expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
10056			   enum built_in_function fcode)
10057{
10058  tree arglist = TREE_OPERAND (exp, 1);
10059  tree dest, src, len, size;
10060
10061  if (!validate_arglist (arglist,
10062			 POINTER_TYPE,
10063			 fcode == BUILT_IN_MEMSET_CHK
10064			 ? INTEGER_TYPE : POINTER_TYPE,
10065			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
10066    return 0;
10067
10068  dest = TREE_VALUE (arglist);
10069  src = TREE_VALUE (TREE_CHAIN (arglist));
10070  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10071  size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10072
10073  if (! host_integerp (size, 1))
10074    return 0;
10075
10076  if (host_integerp (len, 1) || integer_all_onesp (size))
10077    {
10078      tree fn;
10079
10080      if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
10081	{
10082	  location_t locus = EXPR_LOCATION (exp);
10083	  warning (0, "%Hcall to %D will always overflow destination buffer",
10084		   &locus, get_callee_fndecl (exp));
10085	  return 0;
10086	}
10087
10088      arglist = build_tree_list (NULL_TREE, len);
10089      arglist = tree_cons (NULL_TREE, src, arglist);
10090      arglist = tree_cons (NULL_TREE, dest, arglist);
10091
10092      fn = NULL_TREE;
10093      /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
10094	 mem{cpy,pcpy,move,set} is available.  */
10095      switch (fcode)
10096	{
10097	case BUILT_IN_MEMCPY_CHK:
10098	  fn = built_in_decls[BUILT_IN_MEMCPY];
10099	  break;
10100	case BUILT_IN_MEMPCPY_CHK:
10101	  fn = built_in_decls[BUILT_IN_MEMPCPY];
10102	  break;
10103	case BUILT_IN_MEMMOVE_CHK:
10104	  fn = built_in_decls[BUILT_IN_MEMMOVE];
10105	  break;
10106	case BUILT_IN_MEMSET_CHK:
10107	  fn = built_in_decls[BUILT_IN_MEMSET];
10108	  break;
10109	default:
10110	  break;
10111	}
10112
10113      if (! fn)
10114	return 0;
10115
10116      fn = build_function_call_expr (fn, arglist);
10117      if (TREE_CODE (fn) == CALL_EXPR)
10118	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10119      return expand_expr (fn, target, mode, EXPAND_NORMAL);
10120    }
10121  else if (fcode == BUILT_IN_MEMSET_CHK)
10122    return 0;
10123  else
10124    {
10125      unsigned int dest_align
10126	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
10127
10128      /* If DEST is not a pointer type, call the normal function.  */
10129      if (dest_align == 0)
10130	return 0;
10131
10132      /* If SRC and DEST are the same (and not volatile), do nothing.  */
10133      if (operand_equal_p (src, dest, 0))
10134	{
10135	  tree expr;
10136
10137	  if (fcode != BUILT_IN_MEMPCPY_CHK)
10138	    {
10139	      /* Evaluate and ignore LEN in case it has side-effects.  */
10140	      expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
10141	      return expand_expr (dest, target, mode, EXPAND_NORMAL);
10142	    }
10143
10144	  len = fold_convert (TREE_TYPE (dest), len);
10145	  expr = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
10146	  return expand_expr (expr, target, mode, EXPAND_NORMAL);
10147	}
10148
10149      /* __memmove_chk special case.  */
10150      if (fcode == BUILT_IN_MEMMOVE_CHK)
10151	{
10152	  unsigned int src_align
10153	    = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
10154
10155	  if (src_align == 0)
10156	    return 0;
10157
10158	  /* If src is categorized for a readonly section we can use
10159	     normal __memcpy_chk.  */
10160	  if (readonly_data_expr (src))
10161	    {
10162	      tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10163	      if (!fn)
10164		return 0;
10165	      fn = build_function_call_expr (fn, arglist);
10166	      if (TREE_CODE (fn) == CALL_EXPR)
10167		CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10168	      return expand_expr (fn, target, mode, EXPAND_NORMAL);
10169	    }
10170	}
10171      return 0;
10172    }
10173}
10174
10175/* Emit warning if a buffer overflow is detected at compile time.  */
10176
10177static void
10178maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
10179{
10180  int arg_mask, is_strlen = 0;
10181  tree arglist = TREE_OPERAND (exp, 1), a;
10182  tree len, size;
10183  location_t locus;
10184
10185  switch (fcode)
10186    {
10187    case BUILT_IN_STRCPY_CHK:
10188    case BUILT_IN_STPCPY_CHK:
10189    /* For __strcat_chk the warning will be emitted only if overflowing
10190       by at least strlen (dest) + 1 bytes.  */
10191    case BUILT_IN_STRCAT_CHK:
10192      arg_mask = 6;
10193      is_strlen = 1;
10194      break;
10195    case BUILT_IN_STRNCPY_CHK:
10196      arg_mask = 12;
10197      break;
10198    case BUILT_IN_SNPRINTF_CHK:
10199    case BUILT_IN_VSNPRINTF_CHK:
10200      arg_mask = 10;
10201      break;
10202    default:
10203      gcc_unreachable ();
10204    }
10205
10206  len = NULL_TREE;
10207  size = NULL_TREE;
10208  for (a = arglist; a && arg_mask; a = TREE_CHAIN (a), arg_mask >>= 1)
10209    if (arg_mask & 1)
10210      {
10211	if (len)
10212	  size = a;
10213	else
10214	  len = a;
10215      }
10216
10217  if (!len || !size)
10218    return;
10219
10220  len = TREE_VALUE (len);
10221  size = TREE_VALUE (size);
10222
10223  if (! host_integerp (size, 1) || integer_all_onesp (size))
10224    return;
10225
10226  if (is_strlen)
10227    {
10228      len = c_strlen (len, 1);
10229      if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
10230	return;
10231    }
10232  else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
10233    return;
10234
10235  locus = EXPR_LOCATION (exp);
10236  warning (0, "%Hcall to %D will always overflow destination buffer",
10237	   &locus, get_callee_fndecl (exp));
10238}
10239
10240/* Emit warning if a buffer overflow is detected at compile time
10241   in __sprintf_chk/__vsprintf_chk calls.  */
10242
10243static void
10244maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
10245{
10246  tree arglist = TREE_OPERAND (exp, 1);
10247  tree dest, size, len, fmt, flag;
10248  const char *fmt_str;
10249
10250  /* Verify the required arguments in the original call.  */
10251  if (! arglist)
10252    return;
10253  dest = TREE_VALUE (arglist);
10254  arglist = TREE_CHAIN (arglist);
10255  if (! arglist)
10256    return;
10257  flag = TREE_VALUE (arglist);
10258  arglist = TREE_CHAIN (arglist);
10259  if (! arglist)
10260    return;
10261  size = TREE_VALUE (arglist);
10262  arglist = TREE_CHAIN (arglist);
10263  if (! arglist)
10264    return;
10265  fmt = TREE_VALUE (arglist);
10266  arglist = TREE_CHAIN (arglist);
10267
10268  if (! host_integerp (size, 1) || integer_all_onesp (size))
10269    return;
10270
10271  /* Check whether the format is a literal string constant.  */
10272  fmt_str = c_getstr (fmt);
10273  if (fmt_str == NULL)
10274    return;
10275
10276  if (!init_target_chars())
10277    return;
10278
10279  /* If the format doesn't contain % args or %%, we know its size.  */
10280  if (strchr (fmt_str, target_percent) == 0)
10281    len = build_int_cstu (size_type_node, strlen (fmt_str));
10282  /* If the format is "%s" and first ... argument is a string literal,
10283     we know it too.  */
10284  else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
10285    {
10286      tree arg;
10287
10288      if (! arglist)
10289	return;
10290      arg = TREE_VALUE (arglist);
10291      if (! POINTER_TYPE_P (TREE_TYPE (arg)))
10292	return;
10293
10294      len = c_strlen (arg, 1);
10295      if (!len || ! host_integerp (len, 1))
10296	return;
10297    }
10298  else
10299    return;
10300
10301  if (! tree_int_cst_lt (len, size))
10302    {
10303      location_t locus = EXPR_LOCATION (exp);
10304      warning (0, "%Hcall to %D will always overflow destination buffer",
10305	       &locus, get_callee_fndecl (exp));
10306    }
10307}
10308
10309/* Fold a call to __builtin_object_size, if possible.  */
10310
10311tree
10312fold_builtin_object_size (tree arglist)
10313{
10314  tree ptr, ost, ret = 0;
10315  int object_size_type;
10316
10317  if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
10318    return 0;
10319
10320  ptr = TREE_VALUE (arglist);
10321  ost = TREE_VALUE (TREE_CHAIN (arglist));
10322  STRIP_NOPS (ost);
10323
10324  if (TREE_CODE (ost) != INTEGER_CST
10325      || tree_int_cst_sgn (ost) < 0
10326      || compare_tree_int (ost, 3) > 0)
10327    return 0;
10328
10329  object_size_type = tree_low_cst (ost, 0);
10330
10331  /* __builtin_object_size doesn't evaluate side-effects in its arguments;
10332     if there are any side-effects, it returns (size_t) -1 for types 0 and 1
10333     and (size_t) 0 for types 2 and 3.  */
10334  if (TREE_SIDE_EFFECTS (ptr))
10335    return fold_convert (size_type_node,
10336			 object_size_type < 2
10337			 ? integer_minus_one_node : integer_zero_node);
10338
10339  if (TREE_CODE (ptr) == ADDR_EXPR)
10340    ret = build_int_cstu (size_type_node,
10341			compute_builtin_object_size (ptr, object_size_type));
10342
10343  else if (TREE_CODE (ptr) == SSA_NAME)
10344    {
10345      unsigned HOST_WIDE_INT bytes;
10346
10347      /* If object size is not known yet, delay folding until
10348       later.  Maybe subsequent passes will help determining
10349       it.  */
10350      bytes = compute_builtin_object_size (ptr, object_size_type);
10351      if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
10352					     ? -1 : 0))
10353	ret = build_int_cstu (size_type_node, bytes);
10354    }
10355
10356  if (ret)
10357    {
10358      ret = force_fit_type (ret, -1, false, false);
10359      if (TREE_CONSTANT_OVERFLOW (ret))
10360	ret = 0;
10361    }
10362
10363  return ret;
10364}
10365
10366/* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
10367   IGNORE is true, if return value can be ignored.  FCODE is the BUILT_IN_*
10368   code of the builtin.  If MAXLEN is not NULL, it is maximum length
10369   passed as third argument.  */
10370
10371tree
10372fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
10373			 enum built_in_function fcode)
10374{
10375  tree dest, src, len, size, fn;
10376
10377  if (!validate_arglist (arglist,
10378			 POINTER_TYPE,
10379			 fcode == BUILT_IN_MEMSET_CHK
10380			 ? INTEGER_TYPE : POINTER_TYPE,
10381			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
10382    return 0;
10383
10384  dest = TREE_VALUE (arglist);
10385  /* Actually val for __memset_chk, but it doesn't matter.  */
10386  src = TREE_VALUE (TREE_CHAIN (arglist));
10387  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10388  size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10389
10390  /* If SRC and DEST are the same (and not volatile), return DEST
10391     (resp. DEST+LEN for __mempcpy_chk).  */
10392  if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
10393    {
10394      if (fcode != BUILT_IN_MEMPCPY_CHK)
10395	return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
10396      else
10397	{
10398	  tree temp = fold_convert (TREE_TYPE (dest), len);
10399	  temp = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp);
10400	  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
10401	}
10402    }
10403
10404  if (! host_integerp (size, 1))
10405    return 0;
10406
10407  if (! integer_all_onesp (size))
10408    {
10409      if (! host_integerp (len, 1))
10410	{
10411	  /* If LEN is not constant, try MAXLEN too.
10412	     For MAXLEN only allow optimizing into non-_ocs function
10413	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10414	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10415	    {
10416	      if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
10417		{
10418		  /* (void) __mempcpy_chk () can be optimized into
10419		     (void) __memcpy_chk ().  */
10420		  fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10421		  if (!fn)
10422		    return 0;
10423
10424		  return build_function_call_expr (fn, arglist);
10425		}
10426	      return 0;
10427	    }
10428	}
10429      else
10430	maxlen = len;
10431
10432      if (tree_int_cst_lt (size, maxlen))
10433	return 0;
10434    }
10435
10436  arglist = build_tree_list (NULL_TREE, len);
10437  arglist = tree_cons (NULL_TREE, src, arglist);
10438  arglist = tree_cons (NULL_TREE, dest, arglist);
10439
10440  fn = NULL_TREE;
10441  /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
10442     mem{cpy,pcpy,move,set} is available.  */
10443  switch (fcode)
10444    {
10445    case BUILT_IN_MEMCPY_CHK:
10446      fn = built_in_decls[BUILT_IN_MEMCPY];
10447      break;
10448    case BUILT_IN_MEMPCPY_CHK:
10449      fn = built_in_decls[BUILT_IN_MEMPCPY];
10450      break;
10451    case BUILT_IN_MEMMOVE_CHK:
10452      fn = built_in_decls[BUILT_IN_MEMMOVE];
10453      break;
10454    case BUILT_IN_MEMSET_CHK:
10455      fn = built_in_decls[BUILT_IN_MEMSET];
10456      break;
10457    default:
10458      break;
10459    }
10460
10461  if (!fn)
10462    return 0;
10463
10464  return build_function_call_expr (fn, arglist);
10465}
10466
10467/* Fold a call to the __st[rp]cpy_chk builtin.
10468   IGNORE is true, if return value can be ignored.  FCODE is the BUILT_IN_*
10469   code of the builtin.  If MAXLEN is not NULL, it is maximum length of
10470   strings passed as second argument.  */
10471
10472tree
10473fold_builtin_stxcpy_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
10474			 enum built_in_function fcode)
10475{
10476  tree dest, src, size, len, fn;
10477
10478  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10479			 VOID_TYPE))
10480    return 0;
10481
10482  dest = TREE_VALUE (arglist);
10483  src = TREE_VALUE (TREE_CHAIN (arglist));
10484  size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10485
10486  /* If SRC and DEST are the same (and not volatile), return DEST.  */
10487  if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
10488    return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
10489
10490  if (! host_integerp (size, 1))
10491    return 0;
10492
10493  if (! integer_all_onesp (size))
10494    {
10495      len = c_strlen (src, 1);
10496      if (! len || ! host_integerp (len, 1))
10497	{
10498	  /* If LEN is not constant, try MAXLEN too.
10499	     For MAXLEN only allow optimizing into non-_ocs function
10500	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10501	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10502	    {
10503	      if (fcode == BUILT_IN_STPCPY_CHK)
10504		{
10505		  if (! ignore)
10506		    return 0;
10507
10508		  /* If return value of __stpcpy_chk is ignored,
10509		     optimize into __strcpy_chk.  */
10510		  fn = built_in_decls[BUILT_IN_STRCPY_CHK];
10511		  if (!fn)
10512		    return 0;
10513
10514		  return build_function_call_expr (fn, arglist);
10515		}
10516
10517	      if (! len || TREE_SIDE_EFFECTS (len))
10518		return 0;
10519
10520	      /* If c_strlen returned something, but not a constant,
10521		 transform __strcpy_chk into __memcpy_chk.  */
10522	      fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10523	      if (!fn)
10524		return 0;
10525
10526	      len = size_binop (PLUS_EXPR, len, ssize_int (1));
10527	      arglist = build_tree_list (NULL_TREE, size);
10528	      arglist = tree_cons (NULL_TREE, len, arglist);
10529	      arglist = tree_cons (NULL_TREE, src, arglist);
10530	      arglist = tree_cons (NULL_TREE, dest, arglist);
10531	      return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
10532				   build_function_call_expr (fn, arglist));
10533	    }
10534	}
10535      else
10536	maxlen = len;
10537
10538      if (! tree_int_cst_lt (maxlen, size))
10539	return 0;
10540    }
10541
10542  arglist = build_tree_list (NULL_TREE, src);
10543  arglist = tree_cons (NULL_TREE, dest, arglist);
10544
10545  /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available.  */
10546  fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
10547		      ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
10548  if (!fn)
10549    return 0;
10550
10551  return build_function_call_expr (fn, arglist);
10552}
10553
10554/* Fold a call to the __strncpy_chk builtin.
10555   If MAXLEN is not NULL, it is maximum length passed as third argument.  */
10556
10557tree
10558fold_builtin_strncpy_chk (tree arglist, tree maxlen)
10559{
10560  tree dest, src, size, len, fn;
10561
10562  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10563			 INTEGER_TYPE, VOID_TYPE))
10564    return 0;
10565
10566  dest = TREE_VALUE (arglist);
10567  src = TREE_VALUE (TREE_CHAIN (arglist));
10568  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10569  size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10570
10571  if (! host_integerp (size, 1))
10572    return 0;
10573
10574  if (! integer_all_onesp (size))
10575    {
10576      if (! host_integerp (len, 1))
10577	{
10578	  /* If LEN is not constant, try MAXLEN too.
10579	     For MAXLEN only allow optimizing into non-_ocs function
10580	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10581	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10582	    return 0;
10583	}
10584      else
10585	maxlen = len;
10586
10587      if (tree_int_cst_lt (size, maxlen))
10588	return 0;
10589    }
10590
10591  arglist = build_tree_list (NULL_TREE, len);
10592  arglist = tree_cons (NULL_TREE, src, arglist);
10593  arglist = tree_cons (NULL_TREE, dest, arglist);
10594
10595  /* If __builtin_strncpy_chk is used, assume strncpy is available.  */
10596  fn = built_in_decls[BUILT_IN_STRNCPY];
10597  if (!fn)
10598    return 0;
10599
10600  return build_function_call_expr (fn, arglist);
10601}
10602
10603/* Fold a call to the __strcat_chk builtin FNDECL with ARGLIST.  */
10604
10605static tree
10606fold_builtin_strcat_chk (tree fndecl, tree arglist)
10607{
10608  tree dest, src, size, fn;
10609  const char *p;
10610
10611  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10612			 VOID_TYPE))
10613    return 0;
10614
10615  dest = TREE_VALUE (arglist);
10616  src = TREE_VALUE (TREE_CHAIN (arglist));
10617  size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10618
10619  p = c_getstr (src);
10620  /* If the SRC parameter is "", return DEST.  */
10621  if (p && *p == '\0')
10622    return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
10623
10624  if (! host_integerp (size, 1) || ! integer_all_onesp (size))
10625    return 0;
10626
10627  arglist = build_tree_list (NULL_TREE, src);
10628  arglist = tree_cons (NULL_TREE, dest, arglist);
10629
10630  /* If __builtin_strcat_chk is used, assume strcat is available.  */
10631  fn = built_in_decls[BUILT_IN_STRCAT];
10632  if (!fn)
10633    return 0;
10634
10635  return build_function_call_expr (fn, arglist);
10636}
10637
10638/* Fold a call to the __strncat_chk builtin EXP.  */
10639
10640static tree
10641fold_builtin_strncat_chk (tree fndecl, tree arglist)
10642{
10643  tree dest, src, size, len, fn;
10644  const char *p;
10645
10646  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10647			 INTEGER_TYPE, VOID_TYPE))
10648    return 0;
10649
10650  dest = TREE_VALUE (arglist);
10651  src = TREE_VALUE (TREE_CHAIN (arglist));
10652  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10653  size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10654
10655  p = c_getstr (src);
10656  /* If the SRC parameter is "" or if LEN is 0, return DEST.  */
10657  if (p && *p == '\0')
10658    return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
10659  else if (integer_zerop (len))
10660    return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
10661
10662  if (! host_integerp (size, 1))
10663    return 0;
10664
10665  if (! integer_all_onesp (size))
10666    {
10667      tree src_len = c_strlen (src, 1);
10668      if (src_len
10669	  && host_integerp (src_len, 1)
10670	  && host_integerp (len, 1)
10671	  && ! tree_int_cst_lt (len, src_len))
10672	{
10673	  /* If LEN >= strlen (SRC), optimize into __strcat_chk.  */
10674	  fn = built_in_decls[BUILT_IN_STRCAT_CHK];
10675	  if (!fn)
10676	    return 0;
10677
10678	  arglist = build_tree_list (NULL_TREE, size);
10679	  arglist = tree_cons (NULL_TREE, src, arglist);
10680	  arglist = tree_cons (NULL_TREE, dest, arglist);
10681	  return build_function_call_expr (fn, arglist);
10682	}
10683      return 0;
10684    }
10685
10686  arglist = build_tree_list (NULL_TREE, len);
10687  arglist = tree_cons (NULL_TREE, src, arglist);
10688  arglist = tree_cons (NULL_TREE, dest, arglist);
10689
10690  /* If __builtin_strncat_chk is used, assume strncat is available.  */
10691  fn = built_in_decls[BUILT_IN_STRNCAT];
10692  if (!fn)
10693    return 0;
10694
10695  return build_function_call_expr (fn, arglist);
10696}
10697
10698/* Fold a call to __{,v}sprintf_chk with argument list ARGLIST.  Return 0 if
10699   a normal call should be emitted rather than expanding the function
10700   inline.  FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK.  */
10701
10702static tree
10703fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode)
10704{
10705  tree dest, size, len, fn, fmt, flag;
10706  const char *fmt_str;
10707
10708  /* Verify the required arguments in the original call.  */
10709  if (! arglist)
10710    return 0;
10711  dest = TREE_VALUE (arglist);
10712  if (! POINTER_TYPE_P (TREE_TYPE (dest)))
10713    return 0;
10714  arglist = TREE_CHAIN (arglist);
10715  if (! arglist)
10716    return 0;
10717  flag = TREE_VALUE (arglist);
10718  if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE)
10719    return 0;
10720  arglist = TREE_CHAIN (arglist);
10721  if (! arglist)
10722    return 0;
10723  size = TREE_VALUE (arglist);
10724  if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
10725    return 0;
10726  arglist = TREE_CHAIN (arglist);
10727  if (! arglist)
10728    return 0;
10729  fmt = TREE_VALUE (arglist);
10730  if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10731    return 0;
10732  arglist = TREE_CHAIN (arglist);
10733
10734  if (! host_integerp (size, 1))
10735    return 0;
10736
10737  len = NULL_TREE;
10738
10739  if (!init_target_chars())
10740    return 0;
10741
10742  /* Check whether the format is a literal string constant.  */
10743  fmt_str = c_getstr (fmt);
10744  if (fmt_str != NULL)
10745    {
10746      /* If the format doesn't contain % args or %%, we know the size.  */
10747      if (strchr (fmt_str, target_percent) == 0)
10748	{
10749	  if (fcode != BUILT_IN_SPRINTF_CHK || arglist == NULL_TREE)
10750	    len = build_int_cstu (size_type_node, strlen (fmt_str));
10751	}
10752      /* If the format is "%s" and first ... argument is a string literal,
10753	 we know the size too.  */
10754      else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
10755	{
10756	  tree arg;
10757
10758	  if (arglist && !TREE_CHAIN (arglist))
10759	    {
10760	      arg = TREE_VALUE (arglist);
10761	      if (POINTER_TYPE_P (TREE_TYPE (arg)))
10762		{
10763		  len = c_strlen (arg, 1);
10764		  if (! len || ! host_integerp (len, 1))
10765		    len = NULL_TREE;
10766		}
10767	    }
10768	}
10769    }
10770
10771  if (! integer_all_onesp (size))
10772    {
10773      if (! len || ! tree_int_cst_lt (len, size))
10774	return 0;
10775    }
10776
10777  /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
10778     or if format doesn't contain % chars or is "%s".  */
10779  if (! integer_zerop (flag))
10780    {
10781      if (fmt_str == NULL)
10782	return 0;
10783      if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
10784	return 0;
10785    }
10786
10787  arglist = tree_cons (NULL_TREE, fmt, arglist);
10788  arglist = tree_cons (NULL_TREE, dest, arglist);
10789
10790  /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available.  */
10791  fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
10792		      ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
10793  if (!fn)
10794    return 0;
10795
10796  return build_function_call_expr (fn, arglist);
10797}
10798
10799/* Fold a call to {,v}snprintf with argument list ARGLIST.  Return 0 if
10800   a normal call should be emitted rather than expanding the function
10801   inline.  FCODE is either BUILT_IN_SNPRINTF_CHK or
10802   BUILT_IN_VSNPRINTF_CHK.  If MAXLEN is not NULL, it is maximum length
10803   passed as second argument.  */
10804
10805tree
10806fold_builtin_snprintf_chk (tree arglist, tree maxlen,
10807			   enum built_in_function fcode)
10808{
10809  tree dest, size, len, fn, fmt, flag;
10810  const char *fmt_str;
10811
10812  /* Verify the required arguments in the original call.  */
10813  if (! arglist)
10814    return 0;
10815  dest = TREE_VALUE (arglist);
10816  if (! POINTER_TYPE_P (TREE_TYPE (dest)))
10817    return 0;
10818  arglist = TREE_CHAIN (arglist);
10819  if (! arglist)
10820    return 0;
10821  len = TREE_VALUE (arglist);
10822  if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
10823    return 0;
10824  arglist = TREE_CHAIN (arglist);
10825  if (! arglist)
10826    return 0;
10827  flag = TREE_VALUE (arglist);
10828  if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
10829    return 0;
10830  arglist = TREE_CHAIN (arglist);
10831  if (! arglist)
10832    return 0;
10833  size = TREE_VALUE (arglist);
10834  if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
10835    return 0;
10836  arglist = TREE_CHAIN (arglist);
10837  if (! arglist)
10838    return 0;
10839  fmt = TREE_VALUE (arglist);
10840  if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10841    return 0;
10842  arglist = TREE_CHAIN (arglist);
10843
10844  if (! host_integerp (size, 1))
10845    return 0;
10846
10847  if (! integer_all_onesp (size))
10848    {
10849      if (! host_integerp (len, 1))
10850	{
10851	  /* If LEN is not constant, try MAXLEN too.
10852	     For MAXLEN only allow optimizing into non-_ocs function
10853	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10854	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10855	    return 0;
10856	}
10857      else
10858	maxlen = len;
10859
10860      if (tree_int_cst_lt (size, maxlen))
10861	return 0;
10862    }
10863
10864  if (!init_target_chars())
10865    return 0;
10866
10867  /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
10868     or if format doesn't contain % chars or is "%s".  */
10869  if (! integer_zerop (flag))
10870    {
10871      fmt_str = c_getstr (fmt);
10872      if (fmt_str == NULL)
10873	return 0;
10874      if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
10875	return 0;
10876    }
10877
10878  arglist = tree_cons (NULL_TREE, fmt, arglist);
10879  arglist = tree_cons (NULL_TREE, len, arglist);
10880  arglist = tree_cons (NULL_TREE, dest, arglist);
10881
10882  /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
10883     available.  */
10884  fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
10885		      ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
10886  if (!fn)
10887    return 0;
10888
10889  return build_function_call_expr (fn, arglist);
10890}
10891
10892/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
10893
10894   Return 0 if no simplification was possible, otherwise return the
10895   simplified form of the call as a tree.  FCODE is the BUILT_IN_*
10896   code of the function to be simplified.  */
10897
10898static tree
10899fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
10900		     enum built_in_function fcode)
10901{
10902  tree fmt, fn = NULL_TREE, fn_putchar, fn_puts, arg, call;
10903  const char *fmt_str = NULL;
10904
10905  /* If the return value is used, don't do the transformation.  */
10906  if (! ignore)
10907    return 0;
10908
10909  /* Verify the required arguments in the original call.  */
10910  if (fcode == BUILT_IN_PRINTF_CHK || fcode == BUILT_IN_VPRINTF_CHK)
10911    {
10912      tree flag;
10913
10914      if (! arglist)
10915	return 0;
10916      flag = TREE_VALUE (arglist);
10917      if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
10918	  || TREE_SIDE_EFFECTS (flag))
10919	return 0;
10920      arglist = TREE_CHAIN (arglist);
10921    }
10922
10923  if (! arglist)
10924    return 0;
10925  fmt = TREE_VALUE (arglist);
10926  if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10927    return 0;
10928  arglist = TREE_CHAIN (arglist);
10929
10930  /* Check whether the format is a literal string constant.  */
10931  fmt_str = c_getstr (fmt);
10932  if (fmt_str == NULL)
10933    return NULL_TREE;
10934
10935  if (fcode == BUILT_IN_PRINTF_UNLOCKED)
10936    {
10937      /* If we're using an unlocked function, assume the other
10938	 unlocked functions exist explicitly.  */
10939      fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
10940      fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
10941    }
10942  else
10943    {
10944      fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
10945      fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
10946    }
10947
10948  if (!init_target_chars())
10949    return 0;
10950
10951  if (strcmp (fmt_str, target_percent_s) == 0 || strchr (fmt_str, target_percent) == NULL)
10952    {
10953      const char *str;
10954
10955      if (strcmp (fmt_str, target_percent_s) == 0)
10956	{
10957	  if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
10958	    return 0;
10959
10960	  if (! arglist
10961	      || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
10962	      || TREE_CHAIN (arglist))
10963	    return 0;
10964
10965	  str = c_getstr (TREE_VALUE (arglist));
10966	  if (str == NULL)
10967	    return 0;
10968	}
10969      else
10970	{
10971	  /* The format specifier doesn't contain any '%' characters.  */
10972	  if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
10973	      && arglist)
10974	    return 0;
10975	  str = fmt_str;
10976	}
10977
10978      /* If the string was "", printf does nothing.  */
10979      if (str[0] == '\0')
10980	return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
10981
10982      /* If the string has length of 1, call putchar.  */
10983      if (str[1] == '\0')
10984	{
10985	  /* Given printf("c"), (where c is any one character,)
10986	     convert "c"[0] to an int and pass that to the replacement
10987	     function.  */
10988	  arg = build_int_cst (NULL_TREE, str[0]);
10989	  arglist = build_tree_list (NULL_TREE, arg);
10990	  fn = fn_putchar;
10991	}
10992      else
10993	{
10994	  /* If the string was "string\n", call puts("string").  */
10995	  size_t len = strlen (str);
10996	  if ((unsigned char)str[len - 1] == target_newline)
10997	    {
10998	      /* Create a NUL-terminated string that's one char shorter
10999		 than the original, stripping off the trailing '\n'.  */
11000	      char *newstr = alloca (len);
11001	      memcpy (newstr, str, len - 1);
11002	      newstr[len - 1] = 0;
11003
11004	      arg = build_string_literal (len, newstr);
11005	      arglist = build_tree_list (NULL_TREE, arg);
11006	      fn = fn_puts;
11007	    }
11008	  else
11009	    /* We'd like to arrange to call fputs(string,stdout) here,
11010	       but we need stdout and don't have a way to get it yet.  */
11011	    return 0;
11012	}
11013    }
11014
11015  /* The other optimizations can be done only on the non-va_list variants.  */
11016  else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
11017    return 0;
11018
11019  /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
11020  else if (strcmp (fmt_str, target_percent_s_newline) == 0)
11021    {
11022      if (! arglist
11023	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
11024	  || TREE_CHAIN (arglist))
11025	return 0;
11026      fn = fn_puts;
11027    }
11028
11029  /* If the format specifier was "%c", call __builtin_putchar(arg).  */
11030  else if (strcmp (fmt_str, target_percent_c) == 0)
11031    {
11032      if (! arglist
11033	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
11034	  || TREE_CHAIN (arglist))
11035	return 0;
11036      fn = fn_putchar;
11037    }
11038
11039  if (!fn)
11040    return 0;
11041
11042  call = build_function_call_expr (fn, arglist);
11043  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
11044}
11045
11046/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
11047
11048   Return 0 if no simplification was possible, otherwise return the
11049   simplified form of the call as a tree.  FCODE is the BUILT_IN_*
11050   code of the function to be simplified.  */
11051
11052static tree
11053fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
11054		      enum built_in_function fcode)
11055{
11056  tree fp, fmt, fn = NULL_TREE, fn_fputc, fn_fputs, arg, call;
11057  const char *fmt_str = NULL;
11058
11059  /* If the return value is used, don't do the transformation.  */
11060  if (! ignore)
11061    return 0;
11062
11063  /* Verify the required arguments in the original call.  */
11064  if (! arglist)
11065    return 0;
11066  fp = TREE_VALUE (arglist);
11067  if (! POINTER_TYPE_P (TREE_TYPE (fp)))
11068    return 0;
11069  arglist = TREE_CHAIN (arglist);
11070
11071  if (fcode == BUILT_IN_FPRINTF_CHK || fcode == BUILT_IN_VFPRINTF_CHK)
11072    {
11073      tree flag;
11074
11075      if (! arglist)
11076	return 0;
11077      flag = TREE_VALUE (arglist);
11078      if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
11079	  || TREE_SIDE_EFFECTS (flag))
11080	return 0;
11081      arglist = TREE_CHAIN (arglist);
11082    }
11083
11084  if (! arglist)
11085    return 0;
11086  fmt = TREE_VALUE (arglist);
11087  if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
11088    return 0;
11089  arglist = TREE_CHAIN (arglist);
11090
11091  /* Check whether the format is a literal string constant.  */
11092  fmt_str = c_getstr (fmt);
11093  if (fmt_str == NULL)
11094    return NULL_TREE;
11095
11096  if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
11097    {
11098      /* If we're using an unlocked function, assume the other
11099	 unlocked functions exist explicitly.  */
11100      fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
11101      fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
11102    }
11103  else
11104    {
11105      fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
11106      fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
11107    }
11108
11109  if (!init_target_chars())
11110    return 0;
11111
11112  /* If the format doesn't contain % args or %%, use strcpy.  */
11113  if (strchr (fmt_str, target_percent) == NULL)
11114    {
11115      if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
11116	  && arglist)
11117	return 0;
11118
11119      /* If the format specifier was "", fprintf does nothing.  */
11120      if (fmt_str[0] == '\0')
11121	{
11122	  /* If FP has side-effects, just wait until gimplification is
11123	     done.  */
11124	  if (TREE_SIDE_EFFECTS (fp))
11125	    return 0;
11126
11127	  return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
11128	}
11129
11130      /* When "string" doesn't contain %, replace all cases of
11131	 fprintf (fp, string) with fputs (string, fp).  The fputs
11132	 builtin will take care of special cases like length == 1.  */
11133      arglist = build_tree_list (NULL_TREE, fp);
11134      arglist = tree_cons (NULL_TREE, fmt, arglist);
11135      fn = fn_fputs;
11136    }
11137
11138  /* The other optimizations can be done only on the non-va_list variants.  */
11139  else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
11140    return 0;
11141
11142  /* If the format specifier was "%s", call __builtin_fputs (arg, fp).  */
11143  else if (strcmp (fmt_str, target_percent_s) == 0)
11144    {
11145      if (! arglist
11146	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
11147	  || TREE_CHAIN (arglist))
11148	return 0;
11149      arg = TREE_VALUE (arglist);
11150      arglist = build_tree_list (NULL_TREE, fp);
11151      arglist = tree_cons (NULL_TREE, arg, arglist);
11152      fn = fn_fputs;
11153    }
11154
11155  /* If the format specifier was "%c", call __builtin_fputc (arg, fp).  */
11156  else if (strcmp (fmt_str, target_percent_c) == 0)
11157    {
11158      if (! arglist
11159	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
11160	  || TREE_CHAIN (arglist))
11161	return 0;
11162      arg = TREE_VALUE (arglist);
11163      arglist = build_tree_list (NULL_TREE, fp);
11164      arglist = tree_cons (NULL_TREE, arg, arglist);
11165      fn = fn_fputc;
11166    }
11167
11168  if (!fn)
11169    return 0;
11170
11171  call = build_function_call_expr (fn, arglist);
11172  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
11173}
11174
11175/* Initialize format string characters in the target charset.  */
11176
11177static bool
11178init_target_chars (void)
11179{
11180  static bool init;
11181  if (!init)
11182    {
11183      target_newline = lang_hooks.to_target_charset ('\n');
11184      target_percent = lang_hooks.to_target_charset ('%');
11185      target_c = lang_hooks.to_target_charset ('c');
11186      target_s = lang_hooks.to_target_charset ('s');
11187      if (target_newline == 0 || target_percent == 0 || target_c == 0
11188	  || target_s == 0)
11189	return false;
11190
11191      target_percent_c[0] = target_percent;
11192      target_percent_c[1] = target_c;
11193      target_percent_c[2] = '\0';
11194
11195      target_percent_s[0] = target_percent;
11196      target_percent_s[1] = target_s;
11197      target_percent_s[2] = '\0';
11198
11199      target_percent_s_newline[0] = target_percent;
11200      target_percent_s_newline[1] = target_s;
11201      target_percent_s_newline[2] = target_newline;
11202      target_percent_s_newline[3] = '\0';
11203
11204      init = true;
11205    }
11206  return true;
11207}
11208