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