xref: /freebsd-12.1/contrib/gcc/builtins.c (revision 5b167459)
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 bswap builtin.  The arguments are in ARGLIST.  MODE
4591    is the mode to expand with.  */
4592 
4593 static rtx
expand_builtin_bswap(tree arglist,rtx target,rtx subtarget)4594 expand_builtin_bswap (tree arglist, rtx target, rtx subtarget)
4595 {
4596   enum machine_mode mode;
4597   tree arg;
4598   rtx op0;
4599 
4600   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
4601     return 0;
4602 
4603   arg = TREE_VALUE (arglist);
4604   mode = TYPE_MODE (TREE_TYPE (arg));
4605   op0 = expand_expr (arg, subtarget, VOIDmode, 0);
4606 
4607   target = expand_unop (mode, bswap_optab, op0, target, 1);
4608 
4609   gcc_assert (target);
4610 
4611   return convert_to_mode (mode, target, 0);
4612 }
4613 
4614 /* Expand a call to a unary builtin.  The arguments are in ARGLIST.
4615    Return 0 if a normal call should be emitted rather than expanding the
4616    function in-line.  If convenient, the result should be placed in TARGET.
4617    SUBTARGET may be used as the target for computing one of EXP's operands.  */
4618 
4619 static rtx
expand_builtin_unop(enum machine_mode target_mode,tree arglist,rtx target,rtx subtarget,optab op_optab)4620 expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target,
4621 		     rtx subtarget, optab op_optab)
4622 {
4623   rtx op0;
4624   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
4625     return 0;
4626 
4627   /* Compute the argument.  */
4628   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
4629   /* Compute op, into TARGET if possible.
4630      Set TARGET to wherever the result comes back.  */
4631   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
4632 			op_optab, op0, target, 1);
4633   gcc_assert (target);
4634 
4635   return convert_to_mode (target_mode, target, 0);
4636 }
4637 
4638 /* If the string passed to fputs is a constant and is one character
4639    long, we attempt to transform this call into __builtin_fputc().  */
4640 
4641 static rtx
expand_builtin_fputs(tree arglist,rtx target,bool unlocked)4642 expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
4643 {
4644   /* Verify the arguments in the original call.  */
4645   if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
4646     {
4647       tree result = fold_builtin_fputs (arglist, (target == const0_rtx),
4648 					unlocked, NULL_TREE);
4649       if (result)
4650 	return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
4651     }
4652   return 0;
4653 }
4654 
4655 /* Expand a call to __builtin_expect.  We return our argument and emit a
4656    NOTE_INSN_EXPECTED_VALUE note.  This is the expansion of __builtin_expect in
4657    a non-jump context.  */
4658 
4659 static rtx
expand_builtin_expect(tree arglist,rtx target)4660 expand_builtin_expect (tree arglist, rtx target)
4661 {
4662   tree exp, c;
4663   rtx note, rtx_c;
4664 
4665   if (arglist == NULL_TREE
4666       || TREE_CHAIN (arglist) == NULL_TREE)
4667     return const0_rtx;
4668   exp = TREE_VALUE (arglist);
4669   c = TREE_VALUE (TREE_CHAIN (arglist));
4670 
4671   if (TREE_CODE (c) != INTEGER_CST)
4672     {
4673       error ("second argument to %<__builtin_expect%> must be a constant");
4674       c = integer_zero_node;
4675     }
4676 
4677   target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
4678 
4679   /* Don't bother with expected value notes for integral constants.  */
4680   if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
4681     {
4682       /* We do need to force this into a register so that we can be
4683 	 moderately sure to be able to correctly interpret the branch
4684 	 condition later.  */
4685       target = force_reg (GET_MODE (target), target);
4686 
4687       rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
4688 
4689       note = emit_note (NOTE_INSN_EXPECTED_VALUE);
4690       NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
4691     }
4692 
4693   return target;
4694 }
4695 
4696 /* Like expand_builtin_expect, except do this in a jump context.  This is
4697    called from do_jump if the conditional is a __builtin_expect.  Return either
4698    a list of insns to emit the jump or NULL if we cannot optimize
4699    __builtin_expect.  We need to optimize this at jump time so that machines
4700    like the PowerPC don't turn the test into a SCC operation, and then jump
4701    based on the test being 0/1.  */
4702 
4703 rtx
expand_builtin_expect_jump(tree exp,rtx if_false_label,rtx if_true_label)4704 expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
4705 {
4706   tree arglist = TREE_OPERAND (exp, 1);
4707   tree arg0 = TREE_VALUE (arglist);
4708   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4709   rtx ret = NULL_RTX;
4710 
4711   /* Only handle __builtin_expect (test, 0) and
4712      __builtin_expect (test, 1).  */
4713   if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
4714       && (integer_zerop (arg1) || integer_onep (arg1)))
4715     {
4716       rtx insn, drop_through_label, temp;
4717 
4718       /* Expand the jump insns.  */
4719       start_sequence ();
4720       do_jump (arg0, if_false_label, if_true_label);
4721       ret = get_insns ();
4722 
4723       drop_through_label = get_last_insn ();
4724       if (drop_through_label && NOTE_P (drop_through_label))
4725 	drop_through_label = prev_nonnote_insn (drop_through_label);
4726       if (drop_through_label && !LABEL_P (drop_through_label))
4727 	drop_through_label = NULL_RTX;
4728       end_sequence ();
4729 
4730       if (! if_true_label)
4731 	if_true_label = drop_through_label;
4732       if (! if_false_label)
4733 	if_false_label = drop_through_label;
4734 
4735       /* Go through and add the expect's to each of the conditional jumps.  */
4736       insn = ret;
4737       while (insn != NULL_RTX)
4738 	{
4739 	  rtx next = NEXT_INSN (insn);
4740 
4741 	  if (JUMP_P (insn) && any_condjump_p (insn))
4742 	    {
4743 	      rtx ifelse = SET_SRC (pc_set (insn));
4744 	      rtx then_dest = XEXP (ifelse, 1);
4745 	      rtx else_dest = XEXP (ifelse, 2);
4746 	      int taken = -1;
4747 
4748 	      /* First check if we recognize any of the labels.  */
4749 	      if (GET_CODE (then_dest) == LABEL_REF
4750 		  && XEXP (then_dest, 0) == if_true_label)
4751 		taken = 1;
4752 	      else if (GET_CODE (then_dest) == LABEL_REF
4753 		       && XEXP (then_dest, 0) == if_false_label)
4754 		taken = 0;
4755 	      else if (GET_CODE (else_dest) == LABEL_REF
4756 		       && XEXP (else_dest, 0) == if_false_label)
4757 		taken = 1;
4758 	      else if (GET_CODE (else_dest) == LABEL_REF
4759 		       && XEXP (else_dest, 0) == if_true_label)
4760 		taken = 0;
4761 	      /* Otherwise check where we drop through.  */
4762 	      else if (else_dest == pc_rtx)
4763 		{
4764 		  if (next && NOTE_P (next))
4765 		    next = next_nonnote_insn (next);
4766 
4767 		  if (next && JUMP_P (next)
4768 		      && any_uncondjump_p (next))
4769 		    temp = XEXP (SET_SRC (pc_set (next)), 0);
4770 		  else
4771 		    temp = next;
4772 
4773 		  /* TEMP is either a CODE_LABEL, NULL_RTX or something
4774 		     else that can't possibly match either target label.  */
4775 		  if (temp == if_false_label)
4776 		    taken = 1;
4777 		  else if (temp == if_true_label)
4778 		    taken = 0;
4779 		}
4780 	      else if (then_dest == pc_rtx)
4781 		{
4782 		  if (next && NOTE_P (next))
4783 		    next = next_nonnote_insn (next);
4784 
4785 		  if (next && JUMP_P (next)
4786 		      && any_uncondjump_p (next))
4787 		    temp = XEXP (SET_SRC (pc_set (next)), 0);
4788 		  else
4789 		    temp = next;
4790 
4791 		  if (temp == if_false_label)
4792 		    taken = 0;
4793 		  else if (temp == if_true_label)
4794 		    taken = 1;
4795 		}
4796 
4797 	      if (taken != -1)
4798 		{
4799 		  /* If the test is expected to fail, reverse the
4800 		     probabilities.  */
4801 		  if (integer_zerop (arg1))
4802 		    taken = 1 - taken;
4803 		  predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
4804 		}
4805 	    }
4806 
4807 	  insn = next;
4808 	}
4809     }
4810 
4811   return ret;
4812 }
4813 
4814 void
expand_builtin_trap(void)4815 expand_builtin_trap (void)
4816 {
4817 #ifdef HAVE_trap
4818   if (HAVE_trap)
4819     emit_insn (gen_trap ());
4820   else
4821 #endif
4822     emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4823   emit_barrier ();
4824 }
4825 
4826 /* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST.
4827    Return 0 if a normal call should be emitted rather than expanding
4828    the function inline.  If convenient, the result should be placed
4829    in TARGET.  SUBTARGET may be used as the target for computing
4830    the operand.  */
4831 
4832 static rtx
expand_builtin_fabs(tree arglist,rtx target,rtx subtarget)4833 expand_builtin_fabs (tree arglist, rtx target, rtx subtarget)
4834 {
4835   enum machine_mode mode;
4836   tree arg;
4837   rtx op0;
4838 
4839   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
4840     return 0;
4841 
4842   arg = TREE_VALUE (arglist);
4843   mode = TYPE_MODE (TREE_TYPE (arg));
4844   op0 = expand_expr (arg, subtarget, VOIDmode, 0);
4845   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
4846 }
4847 
4848 /* Expand a call to copysign, copysignf, or copysignl with arguments ARGLIST.
4849    Return NULL is a normal call should be emitted rather than expanding the
4850    function inline.  If convenient, the result should be placed in TARGET.
4851    SUBTARGET may be used as the target for computing the operand.  */
4852 
4853 static rtx
expand_builtin_copysign(tree arglist,rtx target,rtx subtarget)4854 expand_builtin_copysign (tree arglist, rtx target, rtx subtarget)
4855 {
4856   rtx op0, op1;
4857   tree arg;
4858 
4859   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
4860     return 0;
4861 
4862   arg = TREE_VALUE (arglist);
4863   op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
4864 
4865   arg = TREE_VALUE (TREE_CHAIN (arglist));
4866   op1 = expand_normal (arg);
4867 
4868   return expand_copysign (op0, op1, target);
4869 }
4870 
4871 /* Create a new constant string literal and return a char* pointer to it.
4872    The STRING_CST value is the LEN characters at STR.  */
4873 tree
build_string_literal(int len,const char * str)4874 build_string_literal (int len, const char *str)
4875 {
4876   tree t, elem, index, type;
4877 
4878   t = build_string (len, str);
4879   elem = build_type_variant (char_type_node, 1, 0);
4880   index = build_index_type (build_int_cst (NULL_TREE, len - 1));
4881   type = build_array_type (elem, index);
4882   TREE_TYPE (t) = type;
4883   TREE_CONSTANT (t) = 1;
4884   TREE_INVARIANT (t) = 1;
4885   TREE_READONLY (t) = 1;
4886   TREE_STATIC (t) = 1;
4887 
4888   type = build_pointer_type (type);
4889   t = build1 (ADDR_EXPR, type, t);
4890 
4891   type = build_pointer_type (elem);
4892   t = build1 (NOP_EXPR, type, t);
4893   return t;
4894 }
4895 
4896 /* Expand EXP, a call to printf or printf_unlocked.
4897    Return 0 if a normal call should be emitted rather than transforming
4898    the function inline.  If convenient, the result should be placed in
4899    TARGET with mode MODE.  UNLOCKED indicates this is a printf_unlocked
4900    call.  */
4901 static rtx
expand_builtin_printf(tree exp,rtx target,enum machine_mode mode,bool unlocked)4902 expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
4903 		       bool unlocked)
4904 {
4905   tree arglist = TREE_OPERAND (exp, 1);
4906   /* If we're using an unlocked function, assume the other unlocked
4907      functions exist explicitly.  */
4908   tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
4909     : implicit_built_in_decls[BUILT_IN_PUTCHAR];
4910   tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
4911     : implicit_built_in_decls[BUILT_IN_PUTS];
4912   const char *fmt_str;
4913   tree fn, fmt, arg;
4914 
4915   /* If the return value is used, don't do the transformation.  */
4916   if (target != const0_rtx)
4917     return 0;
4918 
4919   /* Verify the required arguments in the original call.  */
4920   if (! arglist)
4921     return 0;
4922   fmt = TREE_VALUE (arglist);
4923   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
4924     return 0;
4925   arglist = TREE_CHAIN (arglist);
4926 
4927   /* Check whether the format is a literal string constant.  */
4928   fmt_str = c_getstr (fmt);
4929   if (fmt_str == NULL)
4930     return 0;
4931 
4932   if (!init_target_chars())
4933     return 0;
4934 
4935   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
4936   if (strcmp (fmt_str, target_percent_s_newline) == 0)
4937     {
4938       if (! arglist
4939 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
4940 	  || TREE_CHAIN (arglist))
4941 	return 0;
4942       fn = fn_puts;
4943     }
4944   /* If the format specifier was "%c", call __builtin_putchar(arg).  */
4945   else if (strcmp (fmt_str, target_percent_c) == 0)
4946     {
4947       if (! arglist
4948 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
4949 	  || TREE_CHAIN (arglist))
4950 	return 0;
4951       fn = fn_putchar;
4952     }
4953   else
4954     {
4955       /* We can't handle anything else with % args or %% ... yet.  */
4956       if (strchr (fmt_str, target_percent))
4957 	return 0;
4958 
4959       if (arglist)
4960 	return 0;
4961 
4962       /* If the format specifier was "", printf does nothing.  */
4963       if (fmt_str[0] == '\0')
4964 	return const0_rtx;
4965       /* If the format specifier has length of 1, call putchar.  */
4966       if (fmt_str[1] == '\0')
4967 	{
4968 	  /* Given printf("c"), (where c is any one character,)
4969 	     convert "c"[0] to an int and pass that to the replacement
4970 	     function.  */
4971 	  arg = build_int_cst (NULL_TREE, fmt_str[0]);
4972 	  arglist = build_tree_list (NULL_TREE, arg);
4973 	  fn = fn_putchar;
4974 	}
4975       else
4976 	{
4977 	  /* If the format specifier was "string\n", call puts("string").  */
4978 	  size_t len = strlen (fmt_str);
4979 	  if ((unsigned char)fmt_str[len - 1] == target_newline)
4980 	    {
4981 	      /* Create a NUL-terminated string that's one char shorter
4982 		 than the original, stripping off the trailing '\n'.  */
4983 	      char *newstr = alloca (len);
4984 	      memcpy (newstr, fmt_str, len - 1);
4985 	      newstr[len - 1] = 0;
4986 
4987 	      arg = build_string_literal (len, newstr);
4988 	      arglist = build_tree_list (NULL_TREE, arg);
4989 	      fn = fn_puts;
4990 	    }
4991 	  else
4992 	    /* We'd like to arrange to call fputs(string,stdout) here,
4993 	       but we need stdout and don't have a way to get it yet.  */
4994 	    return 0;
4995 	}
4996     }
4997 
4998   if (!fn)
4999     return 0;
5000   fn = build_function_call_expr (fn, arglist);
5001   if (TREE_CODE (fn) == CALL_EXPR)
5002     CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5003   return expand_expr (fn, target, mode, EXPAND_NORMAL);
5004 }
5005 
5006 /* Expand EXP, a call to fprintf or fprintf_unlocked.
5007    Return 0 if a normal call should be emitted rather than transforming
5008    the function inline.  If convenient, the result should be placed in
5009    TARGET with mode MODE.  UNLOCKED indicates this is a fprintf_unlocked
5010    call.  */
5011 static rtx
expand_builtin_fprintf(tree exp,rtx target,enum machine_mode mode,bool unlocked)5012 expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
5013 			bool unlocked)
5014 {
5015   tree arglist = TREE_OPERAND (exp, 1);
5016   /* If we're using an unlocked function, assume the other unlocked
5017      functions exist explicitly.  */
5018   tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
5019     : implicit_built_in_decls[BUILT_IN_FPUTC];
5020   tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
5021     : implicit_built_in_decls[BUILT_IN_FPUTS];
5022   const char *fmt_str;
5023   tree fn, fmt, fp, arg;
5024 
5025   /* If the return value is used, don't do the transformation.  */
5026   if (target != const0_rtx)
5027     return 0;
5028 
5029   /* Verify the required arguments in the original call.  */
5030   if (! arglist)
5031     return 0;
5032   fp = TREE_VALUE (arglist);
5033   if (! POINTER_TYPE_P (TREE_TYPE (fp)))
5034     return 0;
5035   arglist = TREE_CHAIN (arglist);
5036   if (! arglist)
5037     return 0;
5038   fmt = TREE_VALUE (arglist);
5039   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
5040     return 0;
5041   arglist = TREE_CHAIN (arglist);
5042 
5043   /* Check whether the format is a literal string constant.  */
5044   fmt_str = c_getstr (fmt);
5045   if (fmt_str == NULL)
5046     return 0;
5047 
5048   if (!init_target_chars())
5049     return 0;
5050 
5051   /* If the format specifier was "%s", call __builtin_fputs(arg,fp).  */
5052   if (strcmp (fmt_str, target_percent_s) == 0)
5053     {
5054       if (! arglist
5055 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
5056 	  || TREE_CHAIN (arglist))
5057 	return 0;
5058       arg = TREE_VALUE (arglist);
5059       arglist = build_tree_list (NULL_TREE, fp);
5060       arglist = tree_cons (NULL_TREE, arg, arglist);
5061       fn = fn_fputs;
5062     }
5063   /* If the format specifier was "%c", call __builtin_fputc(arg,fp).  */
5064   else if (strcmp (fmt_str, target_percent_c) == 0)
5065     {
5066       if (! arglist
5067 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
5068 	  || TREE_CHAIN (arglist))
5069 	return 0;
5070       arg = TREE_VALUE (arglist);
5071       arglist = build_tree_list (NULL_TREE, fp);
5072       arglist = tree_cons (NULL_TREE, arg, arglist);
5073       fn = fn_fputc;
5074     }
5075   else
5076     {
5077       /* We can't handle anything else with % args or %% ... yet.  */
5078       if (strchr (fmt_str, target_percent))
5079 	return 0;
5080 
5081       if (arglist)
5082 	return 0;
5083 
5084       /* If the format specifier was "", fprintf does nothing.  */
5085       if (fmt_str[0] == '\0')
5086 	{
5087 	  /* Evaluate and ignore FILE* argument for side-effects.  */
5088 	  expand_expr (fp, const0_rtx, VOIDmode, EXPAND_NORMAL);
5089 	  return const0_rtx;
5090 	}
5091 
5092       /* When "string" doesn't contain %, replace all cases of
5093 	 fprintf(stream,string) with fputs(string,stream).  The fputs
5094 	 builtin will take care of special cases like length == 1.  */
5095       arglist = build_tree_list (NULL_TREE, fp);
5096       arglist = tree_cons (NULL_TREE, fmt, arglist);
5097       fn = fn_fputs;
5098     }
5099 
5100   if (!fn)
5101     return 0;
5102   fn = build_function_call_expr (fn, arglist);
5103   if (TREE_CODE (fn) == CALL_EXPR)
5104     CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
5105   return expand_expr (fn, target, mode, EXPAND_NORMAL);
5106 }
5107 
5108 /* Expand a call to sprintf with argument list ARGLIST.  Return 0 if
5109    a normal call should be emitted rather than expanding the function
5110    inline.  If convenient, the result should be placed in TARGET with
5111    mode MODE.  */
5112 
5113 static rtx
expand_builtin_sprintf(tree arglist,rtx target,enum machine_mode mode)5114 expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
5115 {
5116   tree orig_arglist, dest, fmt;
5117   const char *fmt_str;
5118 
5119   orig_arglist = arglist;
5120 
5121   /* Verify the required arguments in the original call.  */
5122   if (! arglist)
5123     return 0;
5124   dest = TREE_VALUE (arglist);
5125   if (! POINTER_TYPE_P (TREE_TYPE (dest)))
5126     return 0;
5127   arglist = TREE_CHAIN (arglist);
5128   if (! arglist)
5129     return 0;
5130   fmt = TREE_VALUE (arglist);
5131   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
5132     return 0;
5133   arglist = TREE_CHAIN (arglist);
5134 
5135   /* Check whether the format is a literal string constant.  */
5136   fmt_str = c_getstr (fmt);
5137   if (fmt_str == NULL)
5138     return 0;
5139 
5140   if (!init_target_chars())
5141     return 0;
5142 
5143   /* If the format doesn't contain % args or %%, use strcpy.  */
5144   if (strchr (fmt_str, target_percent) == 0)
5145     {
5146       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5147       tree exp;
5148 
5149       if (arglist || ! fn)
5150 	return 0;
5151       expand_expr (build_function_call_expr (fn, orig_arglist),
5152 		   const0_rtx, VOIDmode, EXPAND_NORMAL);
5153       if (target == const0_rtx)
5154 	return const0_rtx;
5155       exp = build_int_cst (NULL_TREE, strlen (fmt_str));
5156       return expand_expr (exp, target, mode, EXPAND_NORMAL);
5157     }
5158   /* If the format is "%s", use strcpy if the result isn't used.  */
5159   else if (strcmp (fmt_str, target_percent_s) == 0)
5160     {
5161       tree fn, arg, len;
5162       fn = implicit_built_in_decls[BUILT_IN_STRCPY];
5163 
5164       if (! fn)
5165 	return 0;
5166 
5167       if (! arglist || TREE_CHAIN (arglist))
5168 	return 0;
5169       arg = TREE_VALUE (arglist);
5170       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
5171 	return 0;
5172 
5173       if (target != const0_rtx)
5174 	{
5175 	  len = c_strlen (arg, 1);
5176 	  if (! len || TREE_CODE (len) != INTEGER_CST)
5177 	    return 0;
5178 	}
5179       else
5180 	len = NULL_TREE;
5181 
5182       arglist = build_tree_list (NULL_TREE, arg);
5183       arglist = tree_cons (NULL_TREE, dest, arglist);
5184       expand_expr (build_function_call_expr (fn, arglist),
5185 		   const0_rtx, VOIDmode, EXPAND_NORMAL);
5186 
5187       if (target == const0_rtx)
5188 	return const0_rtx;
5189       return expand_expr (len, target, mode, EXPAND_NORMAL);
5190     }
5191 
5192   return 0;
5193 }
5194 
5195 /* Expand a call to either the entry or exit function profiler.  */
5196 
5197 static rtx
expand_builtin_profile_func(bool exitp)5198 expand_builtin_profile_func (bool exitp)
5199 {
5200   rtx this, which;
5201 
5202   this = DECL_RTL (current_function_decl);
5203   gcc_assert (MEM_P (this));
5204   this = XEXP (this, 0);
5205 
5206   if (exitp)
5207     which = profile_function_exit_libfunc;
5208   else
5209     which = profile_function_entry_libfunc;
5210 
5211   emit_library_call (which, LCT_NORMAL, VOIDmode, 2, this, Pmode,
5212 		     expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
5213 						 0),
5214 		     Pmode);
5215 
5216   return const0_rtx;
5217 }
5218 
5219 /* Given a trampoline address, make sure it satisfies TRAMPOLINE_ALIGNMENT.  */
5220 
5221 static rtx
round_trampoline_addr(rtx tramp)5222 round_trampoline_addr (rtx tramp)
5223 {
5224   rtx temp, addend, mask;
5225 
5226   /* If we don't need too much alignment, we'll have been guaranteed
5227      proper alignment by get_trampoline_type.  */
5228   if (TRAMPOLINE_ALIGNMENT <= STACK_BOUNDARY)
5229     return tramp;
5230 
5231   /* Round address up to desired boundary.  */
5232   temp = gen_reg_rtx (Pmode);
5233   addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
5234   mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
5235 
5236   temp  = expand_simple_binop (Pmode, PLUS, tramp, addend,
5237 			       temp, 0, OPTAB_LIB_WIDEN);
5238   tramp = expand_simple_binop (Pmode, AND, temp, mask,
5239 			       temp, 0, OPTAB_LIB_WIDEN);
5240 
5241   return tramp;
5242 }
5243 
5244 static rtx
expand_builtin_init_trampoline(tree arglist)5245 expand_builtin_init_trampoline (tree arglist)
5246 {
5247   tree t_tramp, t_func, t_chain;
5248   rtx r_tramp, r_func, r_chain;
5249 #ifdef TRAMPOLINE_TEMPLATE
5250   rtx blktramp;
5251 #endif
5252 
5253   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE,
5254 			 POINTER_TYPE, VOID_TYPE))
5255     return NULL_RTX;
5256 
5257   t_tramp = TREE_VALUE (arglist);
5258   arglist = TREE_CHAIN (arglist);
5259   t_func = TREE_VALUE (arglist);
5260   arglist = TREE_CHAIN (arglist);
5261   t_chain = TREE_VALUE (arglist);
5262 
5263   r_tramp = expand_normal (t_tramp);
5264   r_func = expand_normal (t_func);
5265   r_chain = expand_normal (t_chain);
5266 
5267   /* Generate insns to initialize the trampoline.  */
5268   r_tramp = round_trampoline_addr (r_tramp);
5269 #ifdef TRAMPOLINE_TEMPLATE
5270   blktramp = gen_rtx_MEM (BLKmode, r_tramp);
5271   set_mem_align (blktramp, TRAMPOLINE_ALIGNMENT);
5272   emit_block_move (blktramp, assemble_trampoline_template (),
5273 		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
5274 #endif
5275   trampolines_created = 1;
5276   INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain);
5277 
5278   return const0_rtx;
5279 }
5280 
5281 static rtx
expand_builtin_adjust_trampoline(tree arglist)5282 expand_builtin_adjust_trampoline (tree arglist)
5283 {
5284   rtx tramp;
5285 
5286   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5287     return NULL_RTX;
5288 
5289   tramp = expand_normal (TREE_VALUE (arglist));
5290   tramp = round_trampoline_addr (tramp);
5291 #ifdef TRAMPOLINE_ADJUST_ADDRESS
5292   TRAMPOLINE_ADJUST_ADDRESS (tramp);
5293 #endif
5294 
5295   return tramp;
5296 }
5297 
5298 /* Expand a call to the built-in signbit, signbitf or signbitl function.
5299    Return NULL_RTX if a normal call should be emitted rather than expanding
5300    the function in-line.  EXP is the expression that is a call to the builtin
5301    function; if convenient, the result should be placed in TARGET.  */
5302 
5303 static rtx
expand_builtin_signbit(tree exp,rtx target)5304 expand_builtin_signbit (tree exp, rtx target)
5305 {
5306   const struct real_format *fmt;
5307   enum machine_mode fmode, imode, rmode;
5308   HOST_WIDE_INT hi, lo;
5309   tree arg, arglist;
5310   int word, bitpos;
5311   rtx temp;
5312 
5313   arglist = TREE_OPERAND (exp, 1);
5314   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5315     return 0;
5316 
5317   arg = TREE_VALUE (arglist);
5318   fmode = TYPE_MODE (TREE_TYPE (arg));
5319   rmode = TYPE_MODE (TREE_TYPE (exp));
5320   fmt = REAL_MODE_FORMAT (fmode);
5321 
5322   /* For floating point formats without a sign bit, implement signbit
5323      as "ARG < 0.0".  */
5324   bitpos = fmt->signbit_ro;
5325   if (bitpos < 0)
5326   {
5327     /* But we can't do this if the format supports signed zero.  */
5328     if (fmt->has_signed_zero && HONOR_SIGNED_ZEROS (fmode))
5329       return 0;
5330 
5331     arg = fold_build2 (LT_EXPR, TREE_TYPE (exp), arg,
5332 		       build_real (TREE_TYPE (arg), dconst0));
5333     return expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
5334   }
5335 
5336   temp = expand_normal (arg);
5337   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
5338     {
5339       imode = int_mode_for_mode (fmode);
5340       if (imode == BLKmode)
5341 	return 0;
5342       temp = gen_lowpart (imode, temp);
5343     }
5344   else
5345     {
5346       imode = word_mode;
5347       /* Handle targets with different FP word orders.  */
5348       if (FLOAT_WORDS_BIG_ENDIAN)
5349 	word = (GET_MODE_BITSIZE (fmode) - bitpos) / BITS_PER_WORD;
5350       else
5351 	word = bitpos / BITS_PER_WORD;
5352       temp = operand_subword_force (temp, word, fmode);
5353       bitpos = bitpos % BITS_PER_WORD;
5354     }
5355 
5356   /* Force the intermediate word_mode (or narrower) result into a
5357      register.  This avoids attempting to create paradoxical SUBREGs
5358      of floating point modes below.  */
5359   temp = force_reg (imode, temp);
5360 
5361   /* If the bitpos is within the "result mode" lowpart, the operation
5362      can be implement with a single bitwise AND.  Otherwise, we need
5363      a right shift and an AND.  */
5364 
5365   if (bitpos < GET_MODE_BITSIZE (rmode))
5366     {
5367       if (bitpos < HOST_BITS_PER_WIDE_INT)
5368 	{
5369 	  hi = 0;
5370 	  lo = (HOST_WIDE_INT) 1 << bitpos;
5371 	}
5372       else
5373 	{
5374 	  hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
5375 	  lo = 0;
5376 	}
5377 
5378       if (imode != rmode)
5379 	temp = gen_lowpart (rmode, temp);
5380       temp = expand_binop (rmode, and_optab, temp,
5381 			   immed_double_const (lo, hi, rmode),
5382 			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
5383     }
5384   else
5385     {
5386       /* Perform a logical right shift to place the signbit in the least
5387 	 significant bit, then truncate the result to the desired mode
5388 	 and mask just this bit.  */
5389       temp = expand_shift (RSHIFT_EXPR, imode, temp,
5390 			   build_int_cst (NULL_TREE, bitpos), NULL_RTX, 1);
5391       temp = gen_lowpart (rmode, temp);
5392       temp = expand_binop (rmode, and_optab, temp, const1_rtx,
5393 			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
5394     }
5395 
5396   return temp;
5397 }
5398 
5399 /* Expand fork or exec calls.  TARGET is the desired target of the
5400    call.  ARGLIST is the list of arguments of the call.  FN is the
5401    identificator of the actual function.  IGNORE is nonzero if the
5402    value is to be ignored.  */
5403 
5404 static rtx
expand_builtin_fork_or_exec(tree fn,tree arglist,rtx target,int ignore)5405 expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
5406 {
5407   tree id, decl;
5408   tree call;
5409 
5410   /* If we are not profiling, just call the function.  */
5411   if (!profile_arc_flag)
5412     return NULL_RTX;
5413 
5414   /* Otherwise call the wrapper.  This should be equivalent for the rest of
5415      compiler, so the code does not diverge, and the wrapper may run the
5416      code necessary for keeping the profiling sane.  */
5417 
5418   switch (DECL_FUNCTION_CODE (fn))
5419     {
5420     case BUILT_IN_FORK:
5421       id = get_identifier ("__gcov_fork");
5422       break;
5423 
5424     case BUILT_IN_EXECL:
5425       id = get_identifier ("__gcov_execl");
5426       break;
5427 
5428     case BUILT_IN_EXECV:
5429       id = get_identifier ("__gcov_execv");
5430       break;
5431 
5432     case BUILT_IN_EXECLP:
5433       id = get_identifier ("__gcov_execlp");
5434       break;
5435 
5436     case BUILT_IN_EXECLE:
5437       id = get_identifier ("__gcov_execle");
5438       break;
5439 
5440     case BUILT_IN_EXECVP:
5441       id = get_identifier ("__gcov_execvp");
5442       break;
5443 
5444     case BUILT_IN_EXECVE:
5445       id = get_identifier ("__gcov_execve");
5446       break;
5447 
5448     default:
5449       gcc_unreachable ();
5450     }
5451 
5452   decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
5453   DECL_EXTERNAL (decl) = 1;
5454   TREE_PUBLIC (decl) = 1;
5455   DECL_ARTIFICIAL (decl) = 1;
5456   TREE_NOTHROW (decl) = 1;
5457   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
5458   DECL_VISIBILITY_SPECIFIED (decl) = 1;
5459   call = build_function_call_expr (decl, arglist);
5460 
5461   return expand_call (call, target, ignore);
5462 }
5463 
5464 
5465 /* Reconstitute a mode for a __sync intrinsic operation.  Since the type of
5466    the pointer in these functions is void*, the tree optimizers may remove
5467    casts.  The mode computed in expand_builtin isn't reliable either, due
5468    to __sync_bool_compare_and_swap.
5469 
5470    FCODE_DIFF should be fcode - base, where base is the FOO_1 code for the
5471    group of builtins.  This gives us log2 of the mode size.  */
5472 
5473 static inline enum machine_mode
get_builtin_sync_mode(int fcode_diff)5474 get_builtin_sync_mode (int fcode_diff)
5475 {
5476   /* The size is not negotiable, so ask not to get BLKmode in return
5477      if the target indicates that a smaller size would be better.  */
5478   return mode_for_size (BITS_PER_UNIT << fcode_diff, MODE_INT, 0);
5479 }
5480 
5481 /* Expand the memory expression LOC and return the appropriate memory operand
5482    for the builtin_sync operations.  */
5483 
5484 static rtx
get_builtin_sync_mem(tree loc,enum machine_mode mode)5485 get_builtin_sync_mem (tree loc, enum machine_mode mode)
5486 {
5487   rtx addr, mem;
5488 
5489   addr = expand_expr (loc, NULL, Pmode, EXPAND_SUM);
5490 
5491   /* Note that we explicitly do not want any alias information for this
5492      memory, so that we kill all other live memories.  Otherwise we don't
5493      satisfy the full barrier semantics of the intrinsic.  */
5494   mem = validize_mem (gen_rtx_MEM (mode, addr));
5495 
5496   set_mem_align (mem, get_pointer_alignment (loc, BIGGEST_ALIGNMENT));
5497   set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
5498   MEM_VOLATILE_P (mem) = 1;
5499 
5500   return mem;
5501 }
5502 
5503 /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
5504    ARGLIST is the operands list to the function.  CODE is the rtx code
5505    that corresponds to the arithmetic or logical operation from the name;
5506    an exception here is that NOT actually means NAND.  TARGET is an optional
5507    place for us to store the results; AFTER is true if this is the
5508    fetch_and_xxx form.  IGNORE is true if we don't actually care about
5509    the result of the operation at all.  */
5510 
5511 static rtx
expand_builtin_sync_operation(enum machine_mode mode,tree arglist,enum rtx_code code,bool after,rtx target,bool ignore)5512 expand_builtin_sync_operation (enum machine_mode mode, tree arglist,
5513 			       enum rtx_code code, bool after,
5514 			       rtx target, bool ignore)
5515 {
5516   rtx val, mem;
5517   enum machine_mode old_mode;
5518 
5519   /* Expand the operands.  */
5520   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5521 
5522   arglist = TREE_CHAIN (arglist);
5523   val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5524   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
5525      of CONST_INTs, where we know the old_mode only from the call argument.  */
5526   old_mode = GET_MODE (val);
5527   if (old_mode == VOIDmode)
5528     old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
5529   val = convert_modes (mode, old_mode, val, 1);
5530 
5531   if (ignore)
5532     return expand_sync_operation (mem, val, code);
5533   else
5534     return expand_sync_fetch_operation (mem, val, code, after, target);
5535 }
5536 
5537 /* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
5538    intrinsics.  ARGLIST is the operands list to the function.  IS_BOOL is
5539    true if this is the boolean form.  TARGET is a place for us to store the
5540    results; this is NOT optional if IS_BOOL is true.  */
5541 
5542 static rtx
expand_builtin_compare_and_swap(enum machine_mode mode,tree arglist,bool is_bool,rtx target)5543 expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
5544 				 bool is_bool, rtx target)
5545 {
5546   rtx old_val, new_val, mem;
5547   enum machine_mode old_mode;
5548 
5549   /* Expand the operands.  */
5550   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5551 
5552   arglist = TREE_CHAIN (arglist);
5553   old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5554   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
5555      of CONST_INTs, where we know the old_mode only from the call argument.  */
5556   old_mode = GET_MODE (old_val);
5557   if (old_mode == VOIDmode)
5558     old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
5559   old_val = convert_modes (mode, old_mode, old_val, 1);
5560 
5561   arglist = TREE_CHAIN (arglist);
5562   new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5563   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
5564      of CONST_INTs, where we know the old_mode only from the call argument.  */
5565   old_mode = GET_MODE (new_val);
5566   if (old_mode == VOIDmode)
5567     old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
5568   new_val = convert_modes (mode, old_mode, new_val, 1);
5569 
5570   if (is_bool)
5571     return expand_bool_compare_and_swap (mem, old_val, new_val, target);
5572   else
5573     return expand_val_compare_and_swap (mem, old_val, new_val, target);
5574 }
5575 
5576 /* Expand the __sync_lock_test_and_set intrinsic.  Note that the most
5577    general form is actually an atomic exchange, and some targets only
5578    support a reduced form with the second argument being a constant 1.
5579    ARGLIST is the operands list to the function; TARGET is an optional
5580    place for us to store the results.  */
5581 
5582 static rtx
expand_builtin_lock_test_and_set(enum machine_mode mode,tree arglist,rtx target)5583 expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
5584 				  rtx target)
5585 {
5586   rtx val, mem;
5587   enum machine_mode old_mode;
5588 
5589   /* Expand the operands.  */
5590   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5591 
5592   arglist = TREE_CHAIN (arglist);
5593   val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
5594   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
5595      of CONST_INTs, where we know the old_mode only from the call argument.  */
5596   old_mode = GET_MODE (val);
5597   if (old_mode == VOIDmode)
5598     old_mode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
5599   val = convert_modes (mode, old_mode, val, 1);
5600 
5601   return expand_sync_lock_test_and_set (mem, val, target);
5602 }
5603 
5604 /* Expand the __sync_synchronize intrinsic.  */
5605 
5606 static void
expand_builtin_synchronize(void)5607 expand_builtin_synchronize (void)
5608 {
5609   tree x;
5610 
5611 #ifdef HAVE_memory_barrier
5612   if (HAVE_memory_barrier)
5613     {
5614       emit_insn (gen_memory_barrier ());
5615       return;
5616     }
5617 #endif
5618 
5619   /* If no explicit memory barrier instruction is available, create an
5620      empty asm stmt with a memory clobber.  */
5621   x = build4 (ASM_EXPR, void_type_node, build_string (0, ""), NULL, NULL,
5622 	      tree_cons (NULL, build_string (6, "memory"), NULL));
5623   ASM_VOLATILE_P (x) = 1;
5624   expand_asm_expr (x);
5625 }
5626 
5627 /* Expand the __sync_lock_release intrinsic.  ARGLIST is the operands list
5628    to the function.  */
5629 
5630 static void
expand_builtin_lock_release(enum machine_mode mode,tree arglist)5631 expand_builtin_lock_release (enum machine_mode mode, tree arglist)
5632 {
5633   enum insn_code icode;
5634   rtx mem, insn;
5635   rtx val = const0_rtx;
5636 
5637   /* Expand the operands.  */
5638   mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
5639 
5640   /* If there is an explicit operation in the md file, use it.  */
5641   icode = sync_lock_release[mode];
5642   if (icode != CODE_FOR_nothing)
5643     {
5644       if (!insn_data[icode].operand[1].predicate (val, mode))
5645 	val = force_reg (mode, val);
5646 
5647       insn = GEN_FCN (icode) (mem, val);
5648       if (insn)
5649 	{
5650 	  emit_insn (insn);
5651 	  return;
5652 	}
5653     }
5654 
5655   /* Otherwise we can implement this operation by emitting a barrier
5656      followed by a store of zero.  */
5657   expand_builtin_synchronize ();
5658   emit_move_insn (mem, val);
5659 }
5660 
5661 /* Expand an expression EXP that calls a built-in function,
5662    with result going to TARGET if that's convenient
5663    (and in mode MODE if that's convenient).
5664    SUBTARGET may be used as the target for computing one of EXP's operands.
5665    IGNORE is nonzero if the value is to be ignored.  */
5666 
5667 rtx
expand_builtin(tree exp,rtx target,rtx subtarget,enum machine_mode mode,int ignore)5668 expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
5669 		int ignore)
5670 {
5671   tree fndecl = get_callee_fndecl (exp);
5672   tree arglist = TREE_OPERAND (exp, 1);
5673   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
5674   enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
5675 
5676   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
5677     return targetm.expand_builtin (exp, target, subtarget, mode, ignore);
5678 
5679   /* When not optimizing, generate calls to library functions for a certain
5680      set of builtins.  */
5681   if (!optimize
5682       && !called_as_built_in (fndecl)
5683       && DECL_ASSEMBLER_NAME_SET_P (fndecl)
5684       && fcode != BUILT_IN_ALLOCA)
5685     return expand_call (exp, target, ignore);
5686 
5687   /* The built-in function expanders test for target == const0_rtx
5688      to determine whether the function's result will be ignored.  */
5689   if (ignore)
5690     target = const0_rtx;
5691 
5692   /* If the result of a pure or const built-in function is ignored, and
5693      none of its arguments are volatile, we can avoid expanding the
5694      built-in call and just evaluate the arguments for side-effects.  */
5695   if (target == const0_rtx
5696       && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
5697     {
5698       bool volatilep = false;
5699       tree arg;
5700 
5701       for (arg = arglist; arg; arg = TREE_CHAIN (arg))
5702 	if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
5703 	  {
5704 	    volatilep = true;
5705 	    break;
5706 	  }
5707 
5708       if (! volatilep)
5709 	{
5710 	  for (arg = arglist; arg; arg = TREE_CHAIN (arg))
5711 	    expand_expr (TREE_VALUE (arg), const0_rtx,
5712 			 VOIDmode, EXPAND_NORMAL);
5713 	  return const0_rtx;
5714 	}
5715     }
5716 
5717   switch (fcode)
5718     {
5719     CASE_FLT_FN (BUILT_IN_FABS):
5720       target = expand_builtin_fabs (arglist, target, subtarget);
5721       if (target)
5722 	return target;
5723       break;
5724 
5725     CASE_FLT_FN (BUILT_IN_COPYSIGN):
5726       target = expand_builtin_copysign (arglist, target, subtarget);
5727       if (target)
5728 	return target;
5729       break;
5730 
5731       /* Just do a normal library call if we were unable to fold
5732 	 the values.  */
5733     CASE_FLT_FN (BUILT_IN_CABS):
5734       break;
5735 
5736     CASE_FLT_FN (BUILT_IN_EXP):
5737     CASE_FLT_FN (BUILT_IN_EXP10):
5738     CASE_FLT_FN (BUILT_IN_POW10):
5739     CASE_FLT_FN (BUILT_IN_EXP2):
5740     CASE_FLT_FN (BUILT_IN_EXPM1):
5741     CASE_FLT_FN (BUILT_IN_LOGB):
5742     CASE_FLT_FN (BUILT_IN_ILOGB):
5743     CASE_FLT_FN (BUILT_IN_LOG):
5744     CASE_FLT_FN (BUILT_IN_LOG10):
5745     CASE_FLT_FN (BUILT_IN_LOG2):
5746     CASE_FLT_FN (BUILT_IN_LOG1P):
5747     CASE_FLT_FN (BUILT_IN_TAN):
5748     CASE_FLT_FN (BUILT_IN_ASIN):
5749     CASE_FLT_FN (BUILT_IN_ACOS):
5750     CASE_FLT_FN (BUILT_IN_ATAN):
5751       /* Treat these like sqrt only if unsafe math optimizations are allowed,
5752 	 because of possible accuracy problems.  */
5753       if (! flag_unsafe_math_optimizations)
5754 	break;
5755     CASE_FLT_FN (BUILT_IN_SQRT):
5756     CASE_FLT_FN (BUILT_IN_FLOOR):
5757     CASE_FLT_FN (BUILT_IN_CEIL):
5758     CASE_FLT_FN (BUILT_IN_TRUNC):
5759     CASE_FLT_FN (BUILT_IN_ROUND):
5760     CASE_FLT_FN (BUILT_IN_NEARBYINT):
5761     CASE_FLT_FN (BUILT_IN_RINT):
5762     CASE_FLT_FN (BUILT_IN_LRINT):
5763     CASE_FLT_FN (BUILT_IN_LLRINT):
5764       target = expand_builtin_mathfn (exp, target, subtarget);
5765       if (target)
5766 	return target;
5767       break;
5768 
5769     CASE_FLT_FN (BUILT_IN_LCEIL):
5770     CASE_FLT_FN (BUILT_IN_LLCEIL):
5771     CASE_FLT_FN (BUILT_IN_LFLOOR):
5772     CASE_FLT_FN (BUILT_IN_LLFLOOR):
5773       target = expand_builtin_int_roundingfn (exp, target, subtarget);
5774       if (target)
5775 	return target;
5776       break;
5777 
5778     CASE_FLT_FN (BUILT_IN_POW):
5779       target = expand_builtin_pow (exp, target, subtarget);
5780       if (target)
5781 	return target;
5782       break;
5783 
5784     CASE_FLT_FN (BUILT_IN_POWI):
5785       target = expand_builtin_powi (exp, target, subtarget);
5786       if (target)
5787 	return target;
5788       break;
5789 
5790     CASE_FLT_FN (BUILT_IN_ATAN2):
5791     CASE_FLT_FN (BUILT_IN_LDEXP):
5792     CASE_FLT_FN (BUILT_IN_FMOD):
5793     CASE_FLT_FN (BUILT_IN_DREM):
5794       if (! flag_unsafe_math_optimizations)
5795 	break;
5796       target = expand_builtin_mathfn_2 (exp, target, subtarget);
5797       if (target)
5798 	return target;
5799       break;
5800 
5801     CASE_FLT_FN (BUILT_IN_SIN):
5802     CASE_FLT_FN (BUILT_IN_COS):
5803       if (! flag_unsafe_math_optimizations)
5804 	break;
5805       target = expand_builtin_mathfn_3 (exp, target, subtarget);
5806       if (target)
5807 	return target;
5808       break;
5809 
5810     CASE_FLT_FN (BUILT_IN_SINCOS):
5811       if (! flag_unsafe_math_optimizations)
5812 	break;
5813       target = expand_builtin_sincos (exp);
5814       if (target)
5815 	return target;
5816       break;
5817 
5818     case BUILT_IN_APPLY_ARGS:
5819       return expand_builtin_apply_args ();
5820 
5821       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
5822 	 FUNCTION with a copy of the parameters described by
5823 	 ARGUMENTS, and ARGSIZE.  It returns a block of memory
5824 	 allocated on the stack into which is stored all the registers
5825 	 that might possibly be used for returning the result of a
5826 	 function.  ARGUMENTS is the value returned by
5827 	 __builtin_apply_args.  ARGSIZE is the number of bytes of
5828 	 arguments that must be copied.  ??? How should this value be
5829 	 computed?  We'll also need a safe worst case value for varargs
5830 	 functions.  */
5831     case BUILT_IN_APPLY:
5832       if (!validate_arglist (arglist, POINTER_TYPE,
5833 			     POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
5834 	  && !validate_arglist (arglist, REFERENCE_TYPE,
5835 				POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
5836 	return const0_rtx;
5837       else
5838 	{
5839 	  int i;
5840 	  tree t;
5841 	  rtx ops[3];
5842 
5843 	  for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
5844 	    ops[i] = expand_normal (TREE_VALUE (t));
5845 
5846 	  return expand_builtin_apply (ops[0], ops[1], ops[2]);
5847 	}
5848 
5849       /* __builtin_return (RESULT) causes the function to return the
5850 	 value described by RESULT.  RESULT is address of the block of
5851 	 memory returned by __builtin_apply.  */
5852     case BUILT_IN_RETURN:
5853       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
5854 	expand_builtin_return (expand_normal (TREE_VALUE (arglist)));
5855       return const0_rtx;
5856 
5857     case BUILT_IN_SAVEREGS:
5858       return expand_builtin_saveregs ();
5859 
5860     case BUILT_IN_ARGS_INFO:
5861       return expand_builtin_args_info (arglist);
5862 
5863       /* Return the address of the first anonymous stack arg.  */
5864     case BUILT_IN_NEXT_ARG:
5865       if (fold_builtin_next_arg (arglist))
5866 	return const0_rtx;
5867       return expand_builtin_next_arg ();
5868 
5869     case BUILT_IN_CLASSIFY_TYPE:
5870       return expand_builtin_classify_type (arglist);
5871 
5872     case BUILT_IN_CONSTANT_P:
5873       return const0_rtx;
5874 
5875     case BUILT_IN_FRAME_ADDRESS:
5876     case BUILT_IN_RETURN_ADDRESS:
5877       return expand_builtin_frame_address (fndecl, arglist);
5878 
5879     /* Returns the address of the area where the structure is returned.
5880        0 otherwise.  */
5881     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
5882       if (arglist != 0
5883 	  || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
5884 	  || !MEM_P (DECL_RTL (DECL_RESULT (current_function_decl))))
5885 	return const0_rtx;
5886       else
5887 	return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
5888 
5889     case BUILT_IN_ALLOCA:
5890       target = expand_builtin_alloca (arglist, target);
5891       if (target)
5892 	return target;
5893       break;
5894 
5895     case BUILT_IN_STACK_SAVE:
5896       return expand_stack_save ();
5897 
5898     case BUILT_IN_STACK_RESTORE:
5899       expand_stack_restore (TREE_VALUE (arglist));
5900       return const0_rtx;
5901 
5902     case BUILT_IN_BSWAP32:
5903     case BUILT_IN_BSWAP64:
5904       target = expand_builtin_bswap (arglist, target, subtarget);
5905 
5906       if (target)
5907 	return target;
5908       break;
5909 
5910     CASE_INT_FN (BUILT_IN_FFS):
5911     case BUILT_IN_FFSIMAX:
5912       target = expand_builtin_unop (target_mode, arglist, target,
5913 				    subtarget, ffs_optab);
5914       if (target)
5915 	return target;
5916       break;
5917 
5918     CASE_INT_FN (BUILT_IN_CLZ):
5919     case BUILT_IN_CLZIMAX:
5920       target = expand_builtin_unop (target_mode, arglist, target,
5921 				    subtarget, clz_optab);
5922       if (target)
5923 	return target;
5924       break;
5925 
5926     CASE_INT_FN (BUILT_IN_CTZ):
5927     case BUILT_IN_CTZIMAX:
5928       target = expand_builtin_unop (target_mode, arglist, target,
5929 				    subtarget, ctz_optab);
5930       if (target)
5931 	return target;
5932       break;
5933 
5934     CASE_INT_FN (BUILT_IN_POPCOUNT):
5935     case BUILT_IN_POPCOUNTIMAX:
5936       target = expand_builtin_unop (target_mode, arglist, target,
5937 				    subtarget, popcount_optab);
5938       if (target)
5939 	return target;
5940       break;
5941 
5942     CASE_INT_FN (BUILT_IN_PARITY):
5943     case BUILT_IN_PARITYIMAX:
5944       target = expand_builtin_unop (target_mode, arglist, target,
5945 				    subtarget, parity_optab);
5946       if (target)
5947 	return target;
5948       break;
5949 
5950     case BUILT_IN_STRLEN:
5951       target = expand_builtin_strlen (arglist, target, target_mode);
5952       if (target)
5953 	return target;
5954       break;
5955 
5956     case BUILT_IN_STRCPY:
5957       target = expand_builtin_strcpy (fndecl, arglist, target, mode);
5958       if (target)
5959 	return target;
5960       break;
5961 
5962     case BUILT_IN_STRNCPY:
5963       target = expand_builtin_strncpy (exp, target, mode);
5964       if (target)
5965 	return target;
5966       break;
5967 
5968     case BUILT_IN_STPCPY:
5969       target = expand_builtin_stpcpy (exp, target, mode);
5970       if (target)
5971 	return target;
5972       break;
5973 
5974     case BUILT_IN_STRCAT:
5975       target = expand_builtin_strcat (fndecl, arglist, target, mode);
5976       if (target)
5977 	return target;
5978       break;
5979 
5980     case BUILT_IN_STRNCAT:
5981       target = expand_builtin_strncat (arglist, target, mode);
5982       if (target)
5983 	return target;
5984       break;
5985 
5986     case BUILT_IN_STRSPN:
5987       target = expand_builtin_strspn (arglist, target, mode);
5988       if (target)
5989 	return target;
5990       break;
5991 
5992     case BUILT_IN_STRCSPN:
5993       target = expand_builtin_strcspn (arglist, target, mode);
5994       if (target)
5995 	return target;
5996       break;
5997 
5998     case BUILT_IN_STRSTR:
5999       target = expand_builtin_strstr (arglist, TREE_TYPE (exp), target, mode);
6000       if (target)
6001 	return target;
6002       break;
6003 
6004     case BUILT_IN_STRPBRK:
6005       target = expand_builtin_strpbrk (arglist, TREE_TYPE (exp), target, mode);
6006       if (target)
6007 	return target;
6008       break;
6009 
6010     case BUILT_IN_INDEX:
6011     case BUILT_IN_STRCHR:
6012       target = expand_builtin_strchr (arglist, TREE_TYPE (exp), target, mode);
6013       if (target)
6014 	return target;
6015       break;
6016 
6017     case BUILT_IN_RINDEX:
6018     case BUILT_IN_STRRCHR:
6019       target = expand_builtin_strrchr (arglist, TREE_TYPE (exp), target, mode);
6020       if (target)
6021 	return target;
6022       break;
6023 
6024     case BUILT_IN_MEMCPY:
6025       target = expand_builtin_memcpy (exp, target, mode);
6026       if (target)
6027 	return target;
6028       break;
6029 
6030     case BUILT_IN_MEMPCPY:
6031       target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
6032       if (target)
6033 	return target;
6034       break;
6035 
6036     case BUILT_IN_MEMMOVE:
6037       target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target,
6038 				       mode, exp);
6039       if (target)
6040 	return target;
6041       break;
6042 
6043     case BUILT_IN_BCOPY:
6044       target = expand_builtin_bcopy (exp);
6045       if (target)
6046 	return target;
6047       break;
6048 
6049     case BUILT_IN_MEMSET:
6050       target = expand_builtin_memset (arglist, target, mode, exp);
6051       if (target)
6052 	return target;
6053       break;
6054 
6055     case BUILT_IN_BZERO:
6056       target = expand_builtin_bzero (exp);
6057       if (target)
6058 	return target;
6059       break;
6060 
6061     case BUILT_IN_STRCMP:
6062       target = expand_builtin_strcmp (exp, target, mode);
6063       if (target)
6064 	return target;
6065       break;
6066 
6067     case BUILT_IN_STRNCMP:
6068       target = expand_builtin_strncmp (exp, target, mode);
6069       if (target)
6070 	return target;
6071       break;
6072 
6073     case BUILT_IN_BCMP:
6074     case BUILT_IN_MEMCMP:
6075       target = expand_builtin_memcmp (exp, arglist, target, mode);
6076       if (target)
6077 	return target;
6078       break;
6079 
6080     case BUILT_IN_SETJMP:
6081       /* This should have been lowered to the builtins below.  */
6082       gcc_unreachable ();
6083 
6084     case BUILT_IN_SETJMP_SETUP:
6085       /* __builtin_setjmp_setup is passed a pointer to an array of five words
6086           and the receiver label.  */
6087       if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
6088 	{
6089 	  rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
6090 				      VOIDmode, EXPAND_NORMAL);
6091 	  tree label = TREE_OPERAND (TREE_VALUE (TREE_CHAIN (arglist)), 0);
6092 	  rtx label_r = label_rtx (label);
6093 
6094 	  /* This is copied from the handling of non-local gotos.  */
6095 	  expand_builtin_setjmp_setup (buf_addr, label_r);
6096 	  nonlocal_goto_handler_labels
6097 	    = gen_rtx_EXPR_LIST (VOIDmode, label_r,
6098 				 nonlocal_goto_handler_labels);
6099 	  /* ??? Do not let expand_label treat us as such since we would
6100 	     not want to be both on the list of non-local labels and on
6101 	     the list of forced labels.  */
6102 	  FORCED_LABEL (label) = 0;
6103 	  return const0_rtx;
6104 	}
6105       break;
6106 
6107     case BUILT_IN_SETJMP_DISPATCHER:
6108        /* __builtin_setjmp_dispatcher is passed the dispatcher label.  */
6109       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6110 	{
6111 	  tree label = TREE_OPERAND (TREE_VALUE (arglist), 0);
6112 	  rtx label_r = label_rtx (label);
6113 
6114 	  /* Remove the dispatcher label from the list of non-local labels
6115 	     since the receiver labels have been added to it above.  */
6116 	  remove_node_from_expr_list (label_r, &nonlocal_goto_handler_labels);
6117 	  return const0_rtx;
6118 	}
6119       break;
6120 
6121     case BUILT_IN_SETJMP_RECEIVER:
6122        /* __builtin_setjmp_receiver is passed the receiver label.  */
6123       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6124 	{
6125 	  tree label = TREE_OPERAND (TREE_VALUE (arglist), 0);
6126 	  rtx label_r = label_rtx (label);
6127 
6128 	  expand_builtin_setjmp_receiver (label_r);
6129 	  return const0_rtx;
6130 	}
6131       break;
6132 
6133       /* __builtin_longjmp is passed a pointer to an array of five words.
6134 	 It's similar to the C library longjmp function but works with
6135 	 __builtin_setjmp above.  */
6136     case BUILT_IN_LONGJMP:
6137       if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
6138 	{
6139 	  rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
6140 				      VOIDmode, EXPAND_NORMAL);
6141 	  rtx value = expand_normal (TREE_VALUE (TREE_CHAIN (arglist)));
6142 
6143 	  if (value != const1_rtx)
6144 	    {
6145 	      error ("%<__builtin_longjmp%> second argument must be 1");
6146 	      return const0_rtx;
6147 	    }
6148 
6149 	  expand_builtin_longjmp (buf_addr, value);
6150 	  return const0_rtx;
6151 	}
6152       break;
6153 
6154     case BUILT_IN_NONLOCAL_GOTO:
6155       target = expand_builtin_nonlocal_goto (arglist);
6156       if (target)
6157 	return target;
6158       break;
6159 
6160       /* This updates the setjmp buffer that is its argument with the value
6161 	 of the current stack pointer.  */
6162     case BUILT_IN_UPDATE_SETJMP_BUF:
6163       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6164 	{
6165 	  rtx buf_addr
6166 	    = expand_normal (TREE_VALUE (arglist));
6167 
6168 	  expand_builtin_update_setjmp_buf (buf_addr);
6169 	  return const0_rtx;
6170 	}
6171       break;
6172 
6173     case BUILT_IN_TRAP:
6174       expand_builtin_trap ();
6175       return const0_rtx;
6176 
6177     case BUILT_IN_PRINTF:
6178       target = expand_builtin_printf (exp, target, mode, false);
6179       if (target)
6180 	return target;
6181       break;
6182 
6183     case BUILT_IN_PRINTF_UNLOCKED:
6184       target = expand_builtin_printf (exp, target, mode, true);
6185       if (target)
6186 	return target;
6187       break;
6188 
6189     case BUILT_IN_FPUTS:
6190       target = expand_builtin_fputs (arglist, target, false);
6191       if (target)
6192 	return target;
6193       break;
6194     case BUILT_IN_FPUTS_UNLOCKED:
6195       target = expand_builtin_fputs (arglist, target, true);
6196       if (target)
6197 	return target;
6198       break;
6199 
6200     case BUILT_IN_FPRINTF:
6201       target = expand_builtin_fprintf (exp, target, mode, false);
6202       if (target)
6203 	return target;
6204       break;
6205 
6206     case BUILT_IN_FPRINTF_UNLOCKED:
6207       target = expand_builtin_fprintf (exp, target, mode, true);
6208       if (target)
6209 	return target;
6210       break;
6211 
6212     case BUILT_IN_SPRINTF:
6213       target = expand_builtin_sprintf (arglist, target, mode);
6214       if (target)
6215 	return target;
6216       break;
6217 
6218     CASE_FLT_FN (BUILT_IN_SIGNBIT):
6219       target = expand_builtin_signbit (exp, target);
6220       if (target)
6221 	return target;
6222       break;
6223 
6224       /* Various hooks for the DWARF 2 __throw routine.  */
6225     case BUILT_IN_UNWIND_INIT:
6226       expand_builtin_unwind_init ();
6227       return const0_rtx;
6228     case BUILT_IN_DWARF_CFA:
6229       return virtual_cfa_rtx;
6230 #ifdef DWARF2_UNWIND_INFO
6231     case BUILT_IN_DWARF_SP_COLUMN:
6232       return expand_builtin_dwarf_sp_column ();
6233     case BUILT_IN_INIT_DWARF_REG_SIZES:
6234       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
6235       return const0_rtx;
6236 #endif
6237     case BUILT_IN_FROB_RETURN_ADDR:
6238       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
6239     case BUILT_IN_EXTRACT_RETURN_ADDR:
6240       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
6241     case BUILT_IN_EH_RETURN:
6242       expand_builtin_eh_return (TREE_VALUE (arglist),
6243 				TREE_VALUE (TREE_CHAIN (arglist)));
6244       return const0_rtx;
6245 #ifdef EH_RETURN_DATA_REGNO
6246     case BUILT_IN_EH_RETURN_DATA_REGNO:
6247       return expand_builtin_eh_return_data_regno (arglist);
6248 #endif
6249     case BUILT_IN_EXTEND_POINTER:
6250       return expand_builtin_extend_pointer (TREE_VALUE (arglist));
6251 
6252     case BUILT_IN_VA_START:
6253     case BUILT_IN_STDARG_START:
6254       return expand_builtin_va_start (arglist);
6255     case BUILT_IN_VA_END:
6256       return expand_builtin_va_end (arglist);
6257     case BUILT_IN_VA_COPY:
6258       return expand_builtin_va_copy (arglist);
6259     case BUILT_IN_EXPECT:
6260       return expand_builtin_expect (arglist, target);
6261     case BUILT_IN_PREFETCH:
6262       expand_builtin_prefetch (arglist);
6263       return const0_rtx;
6264 
6265     case BUILT_IN_PROFILE_FUNC_ENTER:
6266       return expand_builtin_profile_func (false);
6267     case BUILT_IN_PROFILE_FUNC_EXIT:
6268       return expand_builtin_profile_func (true);
6269 
6270     case BUILT_IN_INIT_TRAMPOLINE:
6271       return expand_builtin_init_trampoline (arglist);
6272     case BUILT_IN_ADJUST_TRAMPOLINE:
6273       return expand_builtin_adjust_trampoline (arglist);
6274 
6275     case BUILT_IN_FORK:
6276     case BUILT_IN_EXECL:
6277     case BUILT_IN_EXECV:
6278     case BUILT_IN_EXECLP:
6279     case BUILT_IN_EXECLE:
6280     case BUILT_IN_EXECVP:
6281     case BUILT_IN_EXECVE:
6282       target = expand_builtin_fork_or_exec (fndecl, arglist, target, ignore);
6283       if (target)
6284 	return target;
6285       break;
6286 
6287     case BUILT_IN_FETCH_AND_ADD_1:
6288     case BUILT_IN_FETCH_AND_ADD_2:
6289     case BUILT_IN_FETCH_AND_ADD_4:
6290     case BUILT_IN_FETCH_AND_ADD_8:
6291     case BUILT_IN_FETCH_AND_ADD_16:
6292       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_ADD_1);
6293       target = expand_builtin_sync_operation (mode, arglist, PLUS,
6294 					      false, target, ignore);
6295       if (target)
6296 	return target;
6297       break;
6298 
6299     case BUILT_IN_FETCH_AND_SUB_1:
6300     case BUILT_IN_FETCH_AND_SUB_2:
6301     case BUILT_IN_FETCH_AND_SUB_4:
6302     case BUILT_IN_FETCH_AND_SUB_8:
6303     case BUILT_IN_FETCH_AND_SUB_16:
6304       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_SUB_1);
6305       target = expand_builtin_sync_operation (mode, arglist, MINUS,
6306 					      false, target, ignore);
6307       if (target)
6308 	return target;
6309       break;
6310 
6311     case BUILT_IN_FETCH_AND_OR_1:
6312     case BUILT_IN_FETCH_AND_OR_2:
6313     case BUILT_IN_FETCH_AND_OR_4:
6314     case BUILT_IN_FETCH_AND_OR_8:
6315     case BUILT_IN_FETCH_AND_OR_16:
6316       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_OR_1);
6317       target = expand_builtin_sync_operation (mode, arglist, IOR,
6318 					      false, target, ignore);
6319       if (target)
6320 	return target;
6321       break;
6322 
6323     case BUILT_IN_FETCH_AND_AND_1:
6324     case BUILT_IN_FETCH_AND_AND_2:
6325     case BUILT_IN_FETCH_AND_AND_4:
6326     case BUILT_IN_FETCH_AND_AND_8:
6327     case BUILT_IN_FETCH_AND_AND_16:
6328       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_AND_1);
6329       target = expand_builtin_sync_operation (mode, arglist, AND,
6330 					      false, target, ignore);
6331       if (target)
6332 	return target;
6333       break;
6334 
6335     case BUILT_IN_FETCH_AND_XOR_1:
6336     case BUILT_IN_FETCH_AND_XOR_2:
6337     case BUILT_IN_FETCH_AND_XOR_4:
6338     case BUILT_IN_FETCH_AND_XOR_8:
6339     case BUILT_IN_FETCH_AND_XOR_16:
6340       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_XOR_1);
6341       target = expand_builtin_sync_operation (mode, arglist, XOR,
6342 					      false, target, ignore);
6343       if (target)
6344 	return target;
6345       break;
6346 
6347     case BUILT_IN_FETCH_AND_NAND_1:
6348     case BUILT_IN_FETCH_AND_NAND_2:
6349     case BUILT_IN_FETCH_AND_NAND_4:
6350     case BUILT_IN_FETCH_AND_NAND_8:
6351     case BUILT_IN_FETCH_AND_NAND_16:
6352       mode = get_builtin_sync_mode (fcode - BUILT_IN_FETCH_AND_NAND_1);
6353       target = expand_builtin_sync_operation (mode, arglist, NOT,
6354 					      false, target, ignore);
6355       if (target)
6356 	return target;
6357       break;
6358 
6359     case BUILT_IN_ADD_AND_FETCH_1:
6360     case BUILT_IN_ADD_AND_FETCH_2:
6361     case BUILT_IN_ADD_AND_FETCH_4:
6362     case BUILT_IN_ADD_AND_FETCH_8:
6363     case BUILT_IN_ADD_AND_FETCH_16:
6364       mode = get_builtin_sync_mode (fcode - BUILT_IN_ADD_AND_FETCH_1);
6365       target = expand_builtin_sync_operation (mode, arglist, PLUS,
6366 					      true, target, ignore);
6367       if (target)
6368 	return target;
6369       break;
6370 
6371     case BUILT_IN_SUB_AND_FETCH_1:
6372     case BUILT_IN_SUB_AND_FETCH_2:
6373     case BUILT_IN_SUB_AND_FETCH_4:
6374     case BUILT_IN_SUB_AND_FETCH_8:
6375     case BUILT_IN_SUB_AND_FETCH_16:
6376       mode = get_builtin_sync_mode (fcode - BUILT_IN_SUB_AND_FETCH_1);
6377       target = expand_builtin_sync_operation (mode, arglist, MINUS,
6378 					      true, target, ignore);
6379       if (target)
6380 	return target;
6381       break;
6382 
6383     case BUILT_IN_OR_AND_FETCH_1:
6384     case BUILT_IN_OR_AND_FETCH_2:
6385     case BUILT_IN_OR_AND_FETCH_4:
6386     case BUILT_IN_OR_AND_FETCH_8:
6387     case BUILT_IN_OR_AND_FETCH_16:
6388       mode = get_builtin_sync_mode (fcode - BUILT_IN_OR_AND_FETCH_1);
6389       target = expand_builtin_sync_operation (mode, arglist, IOR,
6390 					      true, target, ignore);
6391       if (target)
6392 	return target;
6393       break;
6394 
6395     case BUILT_IN_AND_AND_FETCH_1:
6396     case BUILT_IN_AND_AND_FETCH_2:
6397     case BUILT_IN_AND_AND_FETCH_4:
6398     case BUILT_IN_AND_AND_FETCH_8:
6399     case BUILT_IN_AND_AND_FETCH_16:
6400       mode = get_builtin_sync_mode (fcode - BUILT_IN_AND_AND_FETCH_1);
6401       target = expand_builtin_sync_operation (mode, arglist, AND,
6402 					      true, target, ignore);
6403       if (target)
6404 	return target;
6405       break;
6406 
6407     case BUILT_IN_XOR_AND_FETCH_1:
6408     case BUILT_IN_XOR_AND_FETCH_2:
6409     case BUILT_IN_XOR_AND_FETCH_4:
6410     case BUILT_IN_XOR_AND_FETCH_8:
6411     case BUILT_IN_XOR_AND_FETCH_16:
6412       mode = get_builtin_sync_mode (fcode - BUILT_IN_XOR_AND_FETCH_1);
6413       target = expand_builtin_sync_operation (mode, arglist, XOR,
6414 					      true, target, ignore);
6415       if (target)
6416 	return target;
6417       break;
6418 
6419     case BUILT_IN_NAND_AND_FETCH_1:
6420     case BUILT_IN_NAND_AND_FETCH_2:
6421     case BUILT_IN_NAND_AND_FETCH_4:
6422     case BUILT_IN_NAND_AND_FETCH_8:
6423     case BUILT_IN_NAND_AND_FETCH_16:
6424       mode = get_builtin_sync_mode (fcode - BUILT_IN_NAND_AND_FETCH_1);
6425       target = expand_builtin_sync_operation (mode, arglist, NOT,
6426 					      true, target, ignore);
6427       if (target)
6428 	return target;
6429       break;
6430 
6431     case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
6432     case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
6433     case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
6434     case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
6435     case BUILT_IN_BOOL_COMPARE_AND_SWAP_16:
6436       if (mode == VOIDmode)
6437 	mode = TYPE_MODE (boolean_type_node);
6438       if (!target || !register_operand (target, mode))
6439 	target = gen_reg_rtx (mode);
6440 
6441       mode = get_builtin_sync_mode (fcode - BUILT_IN_BOOL_COMPARE_AND_SWAP_1);
6442       target = expand_builtin_compare_and_swap (mode, arglist, true, target);
6443       if (target)
6444 	return target;
6445       break;
6446 
6447     case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
6448     case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
6449     case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
6450     case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
6451     case BUILT_IN_VAL_COMPARE_AND_SWAP_16:
6452       mode = get_builtin_sync_mode (fcode - BUILT_IN_VAL_COMPARE_AND_SWAP_1);
6453       target = expand_builtin_compare_and_swap (mode, arglist, false, target);
6454       if (target)
6455 	return target;
6456       break;
6457 
6458     case BUILT_IN_LOCK_TEST_AND_SET_1:
6459     case BUILT_IN_LOCK_TEST_AND_SET_2:
6460     case BUILT_IN_LOCK_TEST_AND_SET_4:
6461     case BUILT_IN_LOCK_TEST_AND_SET_8:
6462     case BUILT_IN_LOCK_TEST_AND_SET_16:
6463       mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_TEST_AND_SET_1);
6464       target = expand_builtin_lock_test_and_set (mode, arglist, target);
6465       if (target)
6466 	return target;
6467       break;
6468 
6469     case BUILT_IN_LOCK_RELEASE_1:
6470     case BUILT_IN_LOCK_RELEASE_2:
6471     case BUILT_IN_LOCK_RELEASE_4:
6472     case BUILT_IN_LOCK_RELEASE_8:
6473     case BUILT_IN_LOCK_RELEASE_16:
6474       mode = get_builtin_sync_mode (fcode - BUILT_IN_LOCK_RELEASE_1);
6475       expand_builtin_lock_release (mode, arglist);
6476       return const0_rtx;
6477 
6478     case BUILT_IN_SYNCHRONIZE:
6479       expand_builtin_synchronize ();
6480       return const0_rtx;
6481 
6482     case BUILT_IN_OBJECT_SIZE:
6483       return expand_builtin_object_size (exp);
6484 
6485     case BUILT_IN_MEMCPY_CHK:
6486     case BUILT_IN_MEMPCPY_CHK:
6487     case BUILT_IN_MEMMOVE_CHK:
6488     case BUILT_IN_MEMSET_CHK:
6489       target = expand_builtin_memory_chk (exp, target, mode, fcode);
6490       if (target)
6491 	return target;
6492       break;
6493 
6494     case BUILT_IN_STRCPY_CHK:
6495     case BUILT_IN_STPCPY_CHK:
6496     case BUILT_IN_STRNCPY_CHK:
6497     case BUILT_IN_STRCAT_CHK:
6498     case BUILT_IN_SNPRINTF_CHK:
6499     case BUILT_IN_VSNPRINTF_CHK:
6500       maybe_emit_chk_warning (exp, fcode);
6501       break;
6502 
6503     case BUILT_IN_SPRINTF_CHK:
6504     case BUILT_IN_VSPRINTF_CHK:
6505       maybe_emit_sprintf_chk_warning (exp, fcode);
6506       break;
6507 
6508     default:	/* just do library call, if unknown builtin */
6509       break;
6510     }
6511 
6512   /* The switch statement above can drop through to cause the function
6513      to be called normally.  */
6514   return expand_call (exp, target, ignore);
6515 }
6516 
6517 /* Determine whether a tree node represents a call to a built-in
6518    function.  If the tree T is a call to a built-in function with
6519    the right number of arguments of the appropriate types, return
6520    the DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.
6521    Otherwise the return value is END_BUILTINS.  */
6522 
6523 enum built_in_function
builtin_mathfn_code(tree t)6524 builtin_mathfn_code (tree t)
6525 {
6526   tree fndecl, arglist, parmlist;
6527   tree argtype, parmtype;
6528 
6529   if (TREE_CODE (t) != CALL_EXPR
6530       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
6531     return END_BUILTINS;
6532 
6533   fndecl = get_callee_fndecl (t);
6534   if (fndecl == NULL_TREE
6535       || TREE_CODE (fndecl) != FUNCTION_DECL
6536       || ! DECL_BUILT_IN (fndecl)
6537       || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
6538     return END_BUILTINS;
6539 
6540   arglist = TREE_OPERAND (t, 1);
6541   parmlist = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
6542   for (; parmlist; parmlist = TREE_CHAIN (parmlist))
6543     {
6544       /* If a function doesn't take a variable number of arguments,
6545 	 the last element in the list will have type `void'.  */
6546       parmtype = TREE_VALUE (parmlist);
6547       if (VOID_TYPE_P (parmtype))
6548 	{
6549 	  if (arglist)
6550 	    return END_BUILTINS;
6551 	  return DECL_FUNCTION_CODE (fndecl);
6552 	}
6553 
6554       if (! arglist)
6555 	return END_BUILTINS;
6556 
6557       argtype = TREE_TYPE (TREE_VALUE (arglist));
6558 
6559       if (SCALAR_FLOAT_TYPE_P (parmtype))
6560 	{
6561 	  if (! SCALAR_FLOAT_TYPE_P (argtype))
6562 	    return END_BUILTINS;
6563 	}
6564       else if (COMPLEX_FLOAT_TYPE_P (parmtype))
6565 	{
6566 	  if (! COMPLEX_FLOAT_TYPE_P (argtype))
6567 	    return END_BUILTINS;
6568 	}
6569       else if (POINTER_TYPE_P (parmtype))
6570 	{
6571 	  if (! POINTER_TYPE_P (argtype))
6572 	    return END_BUILTINS;
6573 	}
6574       else if (INTEGRAL_TYPE_P (parmtype))
6575 	{
6576 	  if (! INTEGRAL_TYPE_P (argtype))
6577 	    return END_BUILTINS;
6578 	}
6579       else
6580 	return END_BUILTINS;
6581 
6582       arglist = TREE_CHAIN (arglist);
6583     }
6584 
6585   /* Variable-length argument list.  */
6586   return DECL_FUNCTION_CODE (fndecl);
6587 }
6588 
6589 /* Fold a call to __builtin_constant_p, if we know it will evaluate to a
6590    constant.  ARGLIST is the argument list of the call.  */
6591 
6592 static tree
fold_builtin_constant_p(tree arglist)6593 fold_builtin_constant_p (tree arglist)
6594 {
6595   if (arglist == 0)
6596     return 0;
6597 
6598   arglist = TREE_VALUE (arglist);
6599 
6600   /* We return 1 for a numeric type that's known to be a constant
6601      value at compile-time or for an aggregate type that's a
6602      literal constant.  */
6603   STRIP_NOPS (arglist);
6604 
6605   /* If we know this is a constant, emit the constant of one.  */
6606   if (CONSTANT_CLASS_P (arglist)
6607       || (TREE_CODE (arglist) == CONSTRUCTOR
6608 	  && TREE_CONSTANT (arglist)))
6609     return integer_one_node;
6610   if (TREE_CODE (arglist) == ADDR_EXPR)
6611     {
6612        tree op = TREE_OPERAND (arglist, 0);
6613        if (TREE_CODE (op) == STRING_CST
6614 	   || (TREE_CODE (op) == ARRAY_REF
6615 	       && integer_zerop (TREE_OPERAND (op, 1))
6616 	       && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST))
6617 	 return integer_one_node;
6618     }
6619 
6620   /* If this expression has side effects, show we don't know it to be a
6621      constant.  Likewise if it's a pointer or aggregate type since in
6622      those case we only want literals, since those are only optimized
6623      when generating RTL, not later.
6624      And finally, if we are compiling an initializer, not code, we
6625      need to return a definite result now; there's not going to be any
6626      more optimization done.  */
6627   if (TREE_SIDE_EFFECTS (arglist)
6628       || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
6629       || POINTER_TYPE_P (TREE_TYPE (arglist))
6630       || cfun == 0
6631       || folding_initializer)
6632     return integer_zero_node;
6633 
6634   return 0;
6635 }
6636 
6637 /* Fold a call to __builtin_expect, if we expect that a comparison against
6638    the argument will fold to a constant.  In practice, this means a true
6639    constant or the address of a non-weak symbol.  ARGLIST is the argument
6640    list of the call.  */
6641 
6642 static tree
fold_builtin_expect(tree arglist)6643 fold_builtin_expect (tree arglist)
6644 {
6645   tree arg, inner;
6646 
6647   if (arglist == 0)
6648     return 0;
6649 
6650   arg = TREE_VALUE (arglist);
6651 
6652   /* If the argument isn't invariant, then there's nothing we can do.  */
6653   if (!TREE_INVARIANT (arg))
6654     return 0;
6655 
6656   /* If we're looking at an address of a weak decl, then do not fold.  */
6657   inner = arg;
6658   STRIP_NOPS (inner);
6659   if (TREE_CODE (inner) == ADDR_EXPR)
6660     {
6661       do
6662 	{
6663 	  inner = TREE_OPERAND (inner, 0);
6664 	}
6665       while (TREE_CODE (inner) == COMPONENT_REF
6666 	     || TREE_CODE (inner) == ARRAY_REF);
6667       if (DECL_P (inner) && DECL_WEAK (inner))
6668 	return 0;
6669     }
6670 
6671   /* Otherwise, ARG already has the proper type for the return value.  */
6672   return arg;
6673 }
6674 
6675 /* Fold a call to __builtin_classify_type.  */
6676 
6677 static tree
fold_builtin_classify_type(tree arglist)6678 fold_builtin_classify_type (tree arglist)
6679 {
6680   if (arglist == 0)
6681     return build_int_cst (NULL_TREE, no_type_class);
6682 
6683   return build_int_cst (NULL_TREE,
6684 			type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
6685 }
6686 
6687 /* Fold a call to __builtin_strlen.  */
6688 
6689 static tree
fold_builtin_strlen(tree arglist)6690 fold_builtin_strlen (tree arglist)
6691 {
6692   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6693     return NULL_TREE;
6694   else
6695     {
6696       tree len = c_strlen (TREE_VALUE (arglist), 0);
6697 
6698       if (len)
6699 	{
6700 	  /* Convert from the internal "sizetype" type to "size_t".  */
6701 	  if (size_type_node)
6702 	    len = fold_convert (size_type_node, len);
6703 	  return len;
6704 	}
6705 
6706       return NULL_TREE;
6707     }
6708 }
6709 
6710 /* Fold a call to __builtin_inf or __builtin_huge_val.  */
6711 
6712 static tree
fold_builtin_inf(tree type,int warn)6713 fold_builtin_inf (tree type, int warn)
6714 {
6715   REAL_VALUE_TYPE real;
6716 
6717   /* __builtin_inff is intended to be usable to define INFINITY on all
6718      targets.  If an infinity is not available, INFINITY expands "to a
6719      positive constant of type float that overflows at translation
6720      time", footnote "In this case, using INFINITY will violate the
6721      constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
6722      Thus we pedwarn to ensure this constraint violation is
6723      diagnosed.  */
6724   if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
6725     pedwarn ("target format does not support infinity");
6726 
6727   real_inf (&real);
6728   return build_real (type, real);
6729 }
6730 
6731 /* Fold a call to __builtin_nan or __builtin_nans.  */
6732 
6733 static tree
fold_builtin_nan(tree arglist,tree type,int quiet)6734 fold_builtin_nan (tree arglist, tree type, int quiet)
6735 {
6736   REAL_VALUE_TYPE real;
6737   const char *str;
6738 
6739   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6740     return 0;
6741   str = c_getstr (TREE_VALUE (arglist));
6742   if (!str)
6743     return 0;
6744 
6745   if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
6746     return 0;
6747 
6748   return build_real (type, real);
6749 }
6750 
6751 /* Return true if the floating point expression T has an integer value.
6752    We also allow +Inf, -Inf and NaN to be considered integer values.  */
6753 
6754 static bool
integer_valued_real_p(tree t)6755 integer_valued_real_p (tree t)
6756 {
6757   switch (TREE_CODE (t))
6758     {
6759     case FLOAT_EXPR:
6760       return true;
6761 
6762     case ABS_EXPR:
6763     case SAVE_EXPR:
6764     case NON_LVALUE_EXPR:
6765       return integer_valued_real_p (TREE_OPERAND (t, 0));
6766 
6767     case COMPOUND_EXPR:
6768     case MODIFY_EXPR:
6769     case BIND_EXPR:
6770       return integer_valued_real_p (TREE_OPERAND (t, 1));
6771 
6772     case PLUS_EXPR:
6773     case MINUS_EXPR:
6774     case MULT_EXPR:
6775     case MIN_EXPR:
6776     case MAX_EXPR:
6777       return integer_valued_real_p (TREE_OPERAND (t, 0))
6778 	     && integer_valued_real_p (TREE_OPERAND (t, 1));
6779 
6780     case COND_EXPR:
6781       return integer_valued_real_p (TREE_OPERAND (t, 1))
6782 	     && integer_valued_real_p (TREE_OPERAND (t, 2));
6783 
6784     case REAL_CST:
6785       if (! TREE_CONSTANT_OVERFLOW (t))
6786       {
6787 	REAL_VALUE_TYPE c, cint;
6788 
6789 	c = TREE_REAL_CST (t);
6790 	real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c);
6791 	return real_identical (&c, &cint);
6792       }
6793       break;
6794 
6795     case NOP_EXPR:
6796       {
6797 	tree type = TREE_TYPE (TREE_OPERAND (t, 0));
6798 	if (TREE_CODE (type) == INTEGER_TYPE)
6799 	  return true;
6800 	if (TREE_CODE (type) == REAL_TYPE)
6801 	  return integer_valued_real_p (TREE_OPERAND (t, 0));
6802 	break;
6803       }
6804 
6805     case CALL_EXPR:
6806       switch (builtin_mathfn_code (t))
6807 	{
6808 	CASE_FLT_FN (BUILT_IN_CEIL):
6809 	CASE_FLT_FN (BUILT_IN_FLOOR):
6810 	CASE_FLT_FN (BUILT_IN_NEARBYINT):
6811 	CASE_FLT_FN (BUILT_IN_RINT):
6812 	CASE_FLT_FN (BUILT_IN_ROUND):
6813 	CASE_FLT_FN (BUILT_IN_TRUNC):
6814 	  return true;
6815 
6816 	default:
6817 	  break;
6818 	}
6819       break;
6820 
6821     default:
6822       break;
6823     }
6824   return false;
6825 }
6826 
6827 /* EXP is assumed to be builtin call where truncation can be propagated
6828    across (for instance floor((double)f) == (double)floorf (f).
6829    Do the transformation.  */
6830 
6831 static tree
fold_trunc_transparent_mathfn(tree fndecl,tree arglist)6832 fold_trunc_transparent_mathfn (tree fndecl, tree arglist)
6833 {
6834   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
6835   tree arg;
6836 
6837   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6838     return 0;
6839 
6840   arg = TREE_VALUE (arglist);
6841   /* Integer rounding functions are idempotent.  */
6842   if (fcode == builtin_mathfn_code (arg))
6843     return arg;
6844 
6845   /* If argument is already integer valued, and we don't need to worry
6846      about setting errno, there's no need to perform rounding.  */
6847   if (! flag_errno_math && integer_valued_real_p (arg))
6848     return arg;
6849 
6850   if (optimize)
6851     {
6852       tree arg0 = strip_float_extensions (arg);
6853       tree ftype = TREE_TYPE (TREE_TYPE (fndecl));
6854       tree newtype = TREE_TYPE (arg0);
6855       tree decl;
6856 
6857       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6858 	  && (decl = mathfn_built_in (newtype, fcode)))
6859 	{
6860 	  arglist =
6861 	    build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
6862 	  return fold_convert (ftype,
6863 			       build_function_call_expr (decl, arglist));
6864 	}
6865     }
6866   return 0;
6867 }
6868 
6869 /* EXP is assumed to be builtin call which can narrow the FP type of
6870    the argument, for instance lround((double)f) -> lroundf (f).  */
6871 
6872 static tree
fold_fixed_mathfn(tree fndecl,tree arglist)6873 fold_fixed_mathfn (tree fndecl, tree arglist)
6874 {
6875   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
6876   tree arg;
6877 
6878   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
6879     return 0;
6880 
6881   arg = TREE_VALUE (arglist);
6882 
6883   /* If argument is already integer valued, and we don't need to worry
6884      about setting errno, there's no need to perform rounding.  */
6885   if (! flag_errno_math && integer_valued_real_p (arg))
6886     return fold_build1 (FIX_TRUNC_EXPR, TREE_TYPE (TREE_TYPE (fndecl)), arg);
6887 
6888   if (optimize)
6889     {
6890       tree ftype = TREE_TYPE (arg);
6891       tree arg0 = strip_float_extensions (arg);
6892       tree newtype = TREE_TYPE (arg0);
6893       tree decl;
6894 
6895       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
6896 	  && (decl = mathfn_built_in (newtype, fcode)))
6897 	{
6898 	  arglist =
6899 	    build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
6900 	  return build_function_call_expr (decl, arglist);
6901 	}
6902     }
6903 
6904   /* Canonicalize llround (x) to lround (x) on LP64 targets where
6905      sizeof (long long) == sizeof (long).  */
6906   if (TYPE_PRECISION (long_long_integer_type_node)
6907       == TYPE_PRECISION (long_integer_type_node))
6908     {
6909       tree newfn = NULL_TREE;
6910       switch (fcode)
6911 	{
6912 	CASE_FLT_FN (BUILT_IN_LLCEIL):
6913 	  newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
6914 	  break;
6915 
6916 	CASE_FLT_FN (BUILT_IN_LLFLOOR):
6917 	  newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
6918 	  break;
6919 
6920 	CASE_FLT_FN (BUILT_IN_LLROUND):
6921 	  newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
6922 	  break;
6923 
6924 	CASE_FLT_FN (BUILT_IN_LLRINT):
6925 	  newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
6926 	  break;
6927 
6928 	default:
6929 	  break;
6930 	}
6931 
6932       if (newfn)
6933 	{
6934 	  tree newcall = build_function_call_expr (newfn, arglist);
6935 	  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), newcall);
6936 	}
6937     }
6938 
6939   return 0;
6940 }
6941 
6942 /* Fold function call to builtin cabs, cabsf or cabsl.  ARGLIST
6943    is the argument list, TYPE is the return type and FNDECL is the
6944    original function DECL.  Return NULL_TREE if no if no simplification
6945    can be made.  */
6946 
6947 static tree
fold_builtin_cabs(tree arglist,tree type,tree fndecl)6948 fold_builtin_cabs (tree arglist, tree type, tree fndecl)
6949 {
6950   tree arg;
6951 
6952   if (!arglist || TREE_CHAIN (arglist))
6953     return NULL_TREE;
6954 
6955   arg = TREE_VALUE (arglist);
6956   if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
6957       || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
6958     return NULL_TREE;
6959 
6960   /* Evaluate cabs of a constant at compile-time.  */
6961   if (flag_unsafe_math_optimizations
6962       && TREE_CODE (arg) == COMPLEX_CST
6963       && TREE_CODE (TREE_REALPART (arg)) == REAL_CST
6964       && TREE_CODE (TREE_IMAGPART (arg)) == REAL_CST
6965       && ! TREE_CONSTANT_OVERFLOW (TREE_REALPART (arg))
6966       && ! TREE_CONSTANT_OVERFLOW (TREE_IMAGPART (arg)))
6967     {
6968       REAL_VALUE_TYPE r, i;
6969 
6970       r = TREE_REAL_CST (TREE_REALPART (arg));
6971       i = TREE_REAL_CST (TREE_IMAGPART (arg));
6972 
6973       real_arithmetic (&r, MULT_EXPR, &r, &r);
6974       real_arithmetic (&i, MULT_EXPR, &i, &i);
6975       real_arithmetic (&r, PLUS_EXPR, &r, &i);
6976       if (real_sqrt (&r, TYPE_MODE (type), &r)
6977 	  || ! flag_trapping_math)
6978 	return build_real (type, r);
6979     }
6980 
6981   /* If either part is zero, cabs is fabs of the other.  */
6982   if (TREE_CODE (arg) == COMPLEX_EXPR
6983       && real_zerop (TREE_OPERAND (arg, 0)))
6984     return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 1));
6985   if (TREE_CODE (arg) == COMPLEX_EXPR
6986       && real_zerop (TREE_OPERAND (arg, 1)))
6987     return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0));
6988 
6989   /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z).  */
6990   if (TREE_CODE (arg) == NEGATE_EXPR
6991       || TREE_CODE (arg) == CONJ_EXPR)
6992     {
6993       tree arglist = build_tree_list (NULL_TREE, TREE_OPERAND (arg, 0));
6994       return build_function_call_expr (fndecl, arglist);
6995     }
6996 
6997   /* Don't do this when optimizing for size.  */
6998   if (flag_unsafe_math_optimizations
6999       && optimize && !optimize_size)
7000     {
7001       tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
7002 
7003       if (sqrtfn != NULL_TREE)
7004 	{
7005 	  tree rpart, ipart, result, arglist;
7006 
7007 	  arg = builtin_save_expr (arg);
7008 
7009 	  rpart = fold_build1 (REALPART_EXPR, type, arg);
7010 	  ipart = fold_build1 (IMAGPART_EXPR, type, arg);
7011 
7012 	  rpart = builtin_save_expr (rpart);
7013 	  ipart = builtin_save_expr (ipart);
7014 
7015 	  result = fold_build2 (PLUS_EXPR, type,
7016 				fold_build2 (MULT_EXPR, type,
7017 					     rpart, rpart),
7018 				fold_build2 (MULT_EXPR, type,
7019 					     ipart, ipart));
7020 
7021 	  arglist = build_tree_list (NULL_TREE, result);
7022 	  return build_function_call_expr (sqrtfn, arglist);
7023 	}
7024     }
7025 
7026   return NULL_TREE;
7027 }
7028 
7029 /* Fold a builtin function call to sqrt, sqrtf, or sqrtl.  Return
7030    NULL_TREE if no simplification can be made.  */
7031 
7032 static tree
fold_builtin_sqrt(tree arglist,tree type)7033 fold_builtin_sqrt (tree arglist, tree type)
7034 {
7035 
7036   enum built_in_function fcode;
7037   tree arg = TREE_VALUE (arglist);
7038 
7039   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7040     return NULL_TREE;
7041 
7042   /* Optimize sqrt of constant value.  */
7043   if (TREE_CODE (arg) == REAL_CST
7044       && ! TREE_CONSTANT_OVERFLOW (arg))
7045     {
7046       REAL_VALUE_TYPE r, x;
7047 
7048       x = TREE_REAL_CST (arg);
7049       if (real_sqrt (&r, TYPE_MODE (type), &x)
7050 	  || (!flag_trapping_math && !flag_errno_math))
7051 	return build_real (type, r);
7052     }
7053 
7054   /* Optimize sqrt(expN(x)) = expN(x*0.5).  */
7055   fcode = builtin_mathfn_code (arg);
7056   if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
7057     {
7058       tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7059       arg = fold_build2 (MULT_EXPR, type,
7060 			 TREE_VALUE (TREE_OPERAND (arg, 1)),
7061 			 build_real (type, dconsthalf));
7062       arglist = build_tree_list (NULL_TREE, arg);
7063       return build_function_call_expr (expfn, arglist);
7064     }
7065 
7066   /* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)).  */
7067   if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
7068     {
7069       tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7070 
7071       if (powfn)
7072 	{
7073 	  tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7074 	  tree tree_root;
7075 	  /* The inner root was either sqrt or cbrt.  */
7076 	  REAL_VALUE_TYPE dconstroot =
7077 	    BUILTIN_SQRT_P (fcode) ? dconsthalf : dconstthird;
7078 
7079 	  /* Adjust for the outer root.  */
7080 	  SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7081 	  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7082 	  tree_root = build_real (type, dconstroot);
7083 	  arglist = tree_cons (NULL_TREE, arg0,
7084 			       build_tree_list (NULL_TREE, tree_root));
7085 	  return build_function_call_expr (powfn, arglist);
7086 	}
7087     }
7088 
7089   /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5).  */
7090   if (flag_unsafe_math_optimizations
7091       && (fcode == BUILT_IN_POW
7092 	  || fcode == BUILT_IN_POWF
7093 	  || fcode == BUILT_IN_POWL))
7094     {
7095       tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7096       tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7097       tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7098       tree narg1;
7099       if (!tree_expr_nonnegative_p (arg0))
7100 	arg0 = build1 (ABS_EXPR, type, arg0);
7101       narg1 = fold_build2 (MULT_EXPR, type, arg1,
7102 			   build_real (type, dconsthalf));
7103       arglist = tree_cons (NULL_TREE, arg0,
7104 			   build_tree_list (NULL_TREE, narg1));
7105       return build_function_call_expr (powfn, arglist);
7106     }
7107 
7108   return NULL_TREE;
7109 }
7110 
7111 /* Fold a builtin function call to cbrt, cbrtf, or cbrtl.  Return
7112    NULL_TREE if no simplification can be made.  */
7113 static tree
fold_builtin_cbrt(tree arglist,tree type)7114 fold_builtin_cbrt (tree arglist, tree type)
7115 {
7116   tree arg = TREE_VALUE (arglist);
7117   const enum built_in_function fcode = builtin_mathfn_code (arg);
7118 
7119   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7120     return NULL_TREE;
7121 
7122   /* Optimize cbrt of constant value.  */
7123   if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg))
7124     return arg;
7125 
7126   if (flag_unsafe_math_optimizations)
7127     {
7128       /* Optimize cbrt(expN(x)) -> expN(x/3).  */
7129       if (BUILTIN_EXPONENT_P (fcode))
7130 	{
7131 	  tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7132 	  const REAL_VALUE_TYPE third_trunc =
7133 	    real_value_truncate (TYPE_MODE (type), dconstthird);
7134 	  arg = fold_build2 (MULT_EXPR, type,
7135 			     TREE_VALUE (TREE_OPERAND (arg, 1)),
7136 			     build_real (type, third_trunc));
7137 	  arglist = build_tree_list (NULL_TREE, arg);
7138 	  return build_function_call_expr (expfn, arglist);
7139 	}
7140 
7141       /* Optimize cbrt(sqrt(x)) -> pow(x,1/6).  */
7142       if (BUILTIN_SQRT_P (fcode))
7143 	{
7144 	  tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7145 
7146 	  if (powfn)
7147 	    {
7148 	      tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7149 	      tree tree_root;
7150 	      REAL_VALUE_TYPE dconstroot = dconstthird;
7151 
7152 	      SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1);
7153 	      dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7154 	      tree_root = build_real (type, dconstroot);
7155 	      arglist = tree_cons (NULL_TREE, arg0,
7156 				   build_tree_list (NULL_TREE, tree_root));
7157 	      return build_function_call_expr (powfn, arglist);
7158 	    }
7159 	}
7160 
7161       /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative.  */
7162       if (BUILTIN_CBRT_P (fcode))
7163 	{
7164 	  tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
7165 	  if (tree_expr_nonnegative_p (arg0))
7166 	    {
7167 	      tree powfn = mathfn_built_in (type, BUILT_IN_POW);
7168 
7169 	      if (powfn)
7170 		{
7171 		  tree tree_root;
7172 		  REAL_VALUE_TYPE dconstroot;
7173 
7174 		  real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird);
7175 		  dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot);
7176 		  tree_root = build_real (type, dconstroot);
7177 		  arglist = tree_cons (NULL_TREE, arg0,
7178 				       build_tree_list (NULL_TREE, tree_root));
7179 		  return build_function_call_expr (powfn, arglist);
7180 		}
7181 	    }
7182 	}
7183 
7184       /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative.  */
7185       if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
7186 	  || fcode == BUILT_IN_POWL)
7187 	{
7188 	  tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1));
7189 	  tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7190 	  if (tree_expr_nonnegative_p (arg00))
7191 	    {
7192 	      tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
7193 	      const REAL_VALUE_TYPE dconstroot
7194 		= real_value_truncate (TYPE_MODE (type), dconstthird);
7195 	      tree narg01 = fold_build2 (MULT_EXPR, type, arg01,
7196 					 build_real (type, dconstroot));
7197 	      arglist = tree_cons (NULL_TREE, arg00,
7198 				   build_tree_list (NULL_TREE, narg01));
7199 	      return build_function_call_expr (powfn, arglist);
7200 	    }
7201 	}
7202     }
7203   return NULL_TREE;
7204 }
7205 
7206 /* Fold function call to builtin sin, sinf, or sinl.  Return
7207    NULL_TREE if no simplification can be made.  */
7208 static tree
fold_builtin_sin(tree arglist)7209 fold_builtin_sin (tree arglist)
7210 {
7211   tree arg = TREE_VALUE (arglist);
7212 
7213   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7214     return NULL_TREE;
7215 
7216   /* Optimize sin (0.0) = 0.0.  */
7217   if (real_zerop (arg))
7218     return arg;
7219 
7220   return NULL_TREE;
7221 }
7222 
7223 /* Fold function call to builtin cos, cosf, or cosl.  Return
7224    NULL_TREE if no simplification can be made.  */
7225 static tree
fold_builtin_cos(tree arglist,tree type,tree fndecl)7226 fold_builtin_cos (tree arglist, tree type, tree fndecl)
7227 {
7228   tree arg = TREE_VALUE (arglist);
7229 
7230   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7231     return NULL_TREE;
7232 
7233   /* Optimize cos (0.0) = 1.0.  */
7234   if (real_zerop (arg))
7235     return build_real (type, dconst1);
7236 
7237   /* Optimize cos(-x) into cos (x).  */
7238   if (TREE_CODE (arg) == NEGATE_EXPR)
7239     {
7240       tree args = build_tree_list (NULL_TREE,
7241 				   TREE_OPERAND (arg, 0));
7242       return build_function_call_expr (fndecl, args);
7243     }
7244 
7245   return NULL_TREE;
7246 }
7247 
7248 /* Fold function call to builtin tan, tanf, or tanl.  Return
7249    NULL_TREE if no simplification can be made.  */
7250 static tree
fold_builtin_tan(tree arglist)7251 fold_builtin_tan (tree arglist)
7252 {
7253   enum built_in_function fcode;
7254   tree arg = TREE_VALUE (arglist);
7255 
7256   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7257     return NULL_TREE;
7258 
7259   /* Optimize tan(0.0) = 0.0.  */
7260   if (real_zerop (arg))
7261     return arg;
7262 
7263   /* Optimize tan(atan(x)) = x.  */
7264   fcode = builtin_mathfn_code (arg);
7265   if (flag_unsafe_math_optimizations
7266       && (fcode == BUILT_IN_ATAN
7267 	  || fcode == BUILT_IN_ATANF
7268 	  || fcode == BUILT_IN_ATANL))
7269     return TREE_VALUE (TREE_OPERAND (arg, 1));
7270 
7271   return NULL_TREE;
7272 }
7273 
7274 /* Fold function call to builtin atan, atanf, or atanl.  Return
7275    NULL_TREE if no simplification can be made.  */
7276 
7277 static tree
fold_builtin_atan(tree arglist,tree type)7278 fold_builtin_atan (tree arglist, tree type)
7279 {
7280 
7281   tree arg = TREE_VALUE (arglist);
7282 
7283   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7284     return NULL_TREE;
7285 
7286   /* Optimize atan(0.0) = 0.0.  */
7287   if (real_zerop (arg))
7288     return arg;
7289 
7290   /* Optimize atan(1.0) = pi/4.  */
7291   if (real_onep (arg))
7292     {
7293       REAL_VALUE_TYPE cst;
7294 
7295       real_convert (&cst, TYPE_MODE (type), &dconstpi);
7296       SET_REAL_EXP (&cst, REAL_EXP (&cst) - 2);
7297       return build_real (type, cst);
7298     }
7299 
7300   return NULL_TREE;
7301 }
7302 
7303 /* Fold function call to builtin trunc, truncf or truncl.  Return
7304    NULL_TREE if no simplification can be made.  */
7305 
7306 static tree
fold_builtin_trunc(tree fndecl,tree arglist)7307 fold_builtin_trunc (tree fndecl, tree arglist)
7308 {
7309   tree arg;
7310 
7311   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7312     return 0;
7313 
7314   /* Optimize trunc of constant value.  */
7315   arg = TREE_VALUE (arglist);
7316   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7317     {
7318       REAL_VALUE_TYPE r, x;
7319       tree type = TREE_TYPE (TREE_TYPE (fndecl));
7320 
7321       x = TREE_REAL_CST (arg);
7322       real_trunc (&r, TYPE_MODE (type), &x);
7323       return build_real (type, r);
7324     }
7325 
7326   return fold_trunc_transparent_mathfn (fndecl, arglist);
7327 }
7328 
7329 /* Fold function call to builtin floor, floorf or floorl.  Return
7330    NULL_TREE if no simplification can be made.  */
7331 
7332 static tree
fold_builtin_floor(tree fndecl,tree arglist)7333 fold_builtin_floor (tree fndecl, tree arglist)
7334 {
7335   tree arg;
7336 
7337   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7338     return 0;
7339 
7340   /* Optimize floor of constant value.  */
7341   arg = TREE_VALUE (arglist);
7342   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7343     {
7344       REAL_VALUE_TYPE x;
7345 
7346       x = TREE_REAL_CST (arg);
7347       if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7348 	{
7349 	  tree type = TREE_TYPE (TREE_TYPE (fndecl));
7350 	  REAL_VALUE_TYPE r;
7351 
7352 	  real_floor (&r, TYPE_MODE (type), &x);
7353 	  return build_real (type, r);
7354 	}
7355     }
7356 
7357   return fold_trunc_transparent_mathfn (fndecl, arglist);
7358 }
7359 
7360 /* Fold function call to builtin ceil, ceilf or ceill.  Return
7361    NULL_TREE if no simplification can be made.  */
7362 
7363 static tree
fold_builtin_ceil(tree fndecl,tree arglist)7364 fold_builtin_ceil (tree fndecl, tree arglist)
7365 {
7366   tree arg;
7367 
7368   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7369     return 0;
7370 
7371   /* Optimize ceil of constant value.  */
7372   arg = TREE_VALUE (arglist);
7373   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7374     {
7375       REAL_VALUE_TYPE x;
7376 
7377       x = TREE_REAL_CST (arg);
7378       if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7379 	{
7380 	  tree type = TREE_TYPE (TREE_TYPE (fndecl));
7381 	  REAL_VALUE_TYPE r;
7382 
7383 	  real_ceil (&r, TYPE_MODE (type), &x);
7384 	  return build_real (type, r);
7385 	}
7386     }
7387 
7388   return fold_trunc_transparent_mathfn (fndecl, arglist);
7389 }
7390 
7391 /* Fold function call to builtin round, roundf or roundl.  Return
7392    NULL_TREE if no simplification can be made.  */
7393 
7394 static tree
fold_builtin_round(tree fndecl,tree arglist)7395 fold_builtin_round (tree fndecl, tree arglist)
7396 {
7397   tree arg;
7398 
7399   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7400     return 0;
7401 
7402   /* Optimize round of constant value.  */
7403   arg = TREE_VALUE (arglist);
7404   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7405     {
7406       REAL_VALUE_TYPE x;
7407 
7408       x = TREE_REAL_CST (arg);
7409       if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
7410 	{
7411 	  tree type = TREE_TYPE (TREE_TYPE (fndecl));
7412 	  REAL_VALUE_TYPE r;
7413 
7414 	  real_round (&r, TYPE_MODE (type), &x);
7415 	  return build_real (type, r);
7416 	}
7417     }
7418 
7419   return fold_trunc_transparent_mathfn (fndecl, arglist);
7420 }
7421 
7422 /* Fold function call to builtin lround, lroundf or lroundl (or the
7423    corresponding long long versions) and other rounding functions.
7424    Return NULL_TREE if no simplification can be made.  */
7425 
7426 static tree
fold_builtin_int_roundingfn(tree fndecl,tree arglist)7427 fold_builtin_int_roundingfn (tree fndecl, tree arglist)
7428 {
7429   tree arg;
7430 
7431   if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7432     return 0;
7433 
7434   /* Optimize lround of constant value.  */
7435   arg = TREE_VALUE (arglist);
7436   if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7437     {
7438       const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
7439 
7440       if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
7441 	{
7442 	  tree itype = TREE_TYPE (TREE_TYPE (fndecl));
7443 	  tree ftype = TREE_TYPE (arg), result;
7444 	  HOST_WIDE_INT hi, lo;
7445 	  REAL_VALUE_TYPE r;
7446 
7447 	  switch (DECL_FUNCTION_CODE (fndecl))
7448 	    {
7449 	    CASE_FLT_FN (BUILT_IN_LFLOOR):
7450 	    CASE_FLT_FN (BUILT_IN_LLFLOOR):
7451 	      real_floor (&r, TYPE_MODE (ftype), &x);
7452 	      break;
7453 
7454 	    CASE_FLT_FN (BUILT_IN_LCEIL):
7455 	    CASE_FLT_FN (BUILT_IN_LLCEIL):
7456 	      real_ceil (&r, TYPE_MODE (ftype), &x);
7457 	      break;
7458 
7459 	    CASE_FLT_FN (BUILT_IN_LROUND):
7460 	    CASE_FLT_FN (BUILT_IN_LLROUND):
7461 	      real_round (&r, TYPE_MODE (ftype), &x);
7462 	      break;
7463 
7464 	    default:
7465 	      gcc_unreachable ();
7466 	    }
7467 
7468 	  REAL_VALUE_TO_INT (&lo, &hi, r);
7469 	  result = build_int_cst_wide (NULL_TREE, lo, hi);
7470 	  if (int_fits_type_p (result, itype))
7471 	    return fold_convert (itype, result);
7472 	}
7473     }
7474 
7475   return fold_fixed_mathfn (fndecl, arglist);
7476 }
7477 
7478 /* Fold function call to builtin ffs, clz, ctz, popcount and parity
7479    and their long and long long variants (i.e. ffsl and ffsll).
7480    Return NULL_TREE if no simplification can be made.  */
7481 
7482 static tree
fold_builtin_bitop(tree fndecl,tree arglist)7483 fold_builtin_bitop (tree fndecl, tree arglist)
7484 {
7485   tree arg;
7486 
7487   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
7488     return NULL_TREE;
7489 
7490   /* Optimize for constant argument.  */
7491   arg = TREE_VALUE (arglist);
7492   if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7493     {
7494       HOST_WIDE_INT hi, width, result;
7495       unsigned HOST_WIDE_INT lo;
7496       tree type;
7497 
7498       type = TREE_TYPE (arg);
7499       width = TYPE_PRECISION (type);
7500       lo = TREE_INT_CST_LOW (arg);
7501 
7502       /* Clear all the bits that are beyond the type's precision.  */
7503       if (width > HOST_BITS_PER_WIDE_INT)
7504 	{
7505 	  hi = TREE_INT_CST_HIGH (arg);
7506 	  if (width < 2 * HOST_BITS_PER_WIDE_INT)
7507 	    hi &= ~((HOST_WIDE_INT) (-1) >> (width - HOST_BITS_PER_WIDE_INT));
7508 	}
7509       else
7510 	{
7511 	  hi = 0;
7512 	  if (width < HOST_BITS_PER_WIDE_INT)
7513 	    lo &= ~((unsigned HOST_WIDE_INT) (-1) << width);
7514 	}
7515 
7516       switch (DECL_FUNCTION_CODE (fndecl))
7517 	{
7518 	CASE_INT_FN (BUILT_IN_FFS):
7519 	  if (lo != 0)
7520 	    result = exact_log2 (lo & -lo) + 1;
7521 	  else if (hi != 0)
7522 	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
7523 	  else
7524 	    result = 0;
7525 	  break;
7526 
7527 	CASE_INT_FN (BUILT_IN_CLZ):
7528 	  if (hi != 0)
7529 	    result = width - floor_log2 (hi) - 1 - HOST_BITS_PER_WIDE_INT;
7530 	  else if (lo != 0)
7531 	    result = width - floor_log2 (lo) - 1;
7532 	  else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7533 	    result = width;
7534 	  break;
7535 
7536 	CASE_INT_FN (BUILT_IN_CTZ):
7537 	  if (lo != 0)
7538 	    result = exact_log2 (lo & -lo);
7539 	  else if (hi != 0)
7540 	    result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
7541 	  else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
7542 	    result = width;
7543 	  break;
7544 
7545 	CASE_INT_FN (BUILT_IN_POPCOUNT):
7546 	  result = 0;
7547 	  while (lo)
7548 	    result++, lo &= lo - 1;
7549 	  while (hi)
7550 	    result++, hi &= hi - 1;
7551 	  break;
7552 
7553 	CASE_INT_FN (BUILT_IN_PARITY):
7554 	  result = 0;
7555 	  while (lo)
7556 	    result++, lo &= lo - 1;
7557 	  while (hi)
7558 	    result++, hi &= hi - 1;
7559 	  result &= 1;
7560 	  break;
7561 
7562 	default:
7563 	  gcc_unreachable ();
7564 	}
7565 
7566       return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
7567     }
7568 
7569   return NULL_TREE;
7570 }
7571 
7572 /* Fold function call to builtin_bswap and the long and long long
7573    variants.  Return NULL_TREE if no simplification can be made.  */
7574 static tree
fold_builtin_bswap(tree fndecl,tree arglist)7575 fold_builtin_bswap (tree fndecl, tree arglist)
7576 {
7577   tree arg;
7578 
7579   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
7580     return 0;
7581 
7582   /* Optimize constant value.  */
7583   arg = TREE_VALUE (arglist);
7584   if (TREE_CODE (arg) == INTEGER_CST && ! TREE_CONSTANT_OVERFLOW (arg))
7585     {
7586       HOST_WIDE_INT hi, width, r_hi = 0;
7587       unsigned HOST_WIDE_INT lo, r_lo = 0;
7588       tree type;
7589 
7590       type = TREE_TYPE (arg);
7591       width = TYPE_PRECISION (type);
7592       lo = TREE_INT_CST_LOW (arg);
7593       hi = TREE_INT_CST_HIGH (arg);
7594 
7595       switch (DECL_FUNCTION_CODE (fndecl))
7596 	{
7597 	  case BUILT_IN_BSWAP32:
7598 	  case BUILT_IN_BSWAP64:
7599 	    {
7600 	      int s;
7601 
7602 	      for (s = 0; s < width; s += 8)
7603 		{
7604 		  int d = width - s - 8;
7605 		  unsigned HOST_WIDE_INT byte;
7606 
7607 		  if (s < HOST_BITS_PER_WIDE_INT)
7608 		    byte = (lo >> s) & 0xff;
7609 		  else
7610 		    byte = (hi >> (s - HOST_BITS_PER_WIDE_INT)) & 0xff;
7611 
7612 		  if (d < HOST_BITS_PER_WIDE_INT)
7613 		    r_lo |= byte << d;
7614 		  else
7615 		    r_hi |= byte << (d - HOST_BITS_PER_WIDE_INT);
7616 		}
7617 	    }
7618 
7619 	    break;
7620 
7621 	default:
7622 	  gcc_unreachable ();
7623 	}
7624 
7625       if (width < HOST_BITS_PER_WIDE_INT)
7626 	return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), r_lo);
7627       else
7628 	return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), r_lo, r_hi);
7629     }
7630 
7631   return NULL_TREE;
7632 }
7633 /* Return true if EXPR is the real constant contained in VALUE.  */
7634 
7635 static bool
real_dconstp(tree expr,const REAL_VALUE_TYPE * value)7636 real_dconstp (tree expr, const REAL_VALUE_TYPE *value)
7637 {
7638   STRIP_NOPS (expr);
7639 
7640   return ((TREE_CODE (expr) == REAL_CST
7641 	   && ! TREE_CONSTANT_OVERFLOW (expr)
7642 	   && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), *value))
7643 	  || (TREE_CODE (expr) == COMPLEX_CST
7644 	      && real_dconstp (TREE_REALPART (expr), value)
7645 	      && real_zerop (TREE_IMAGPART (expr))));
7646 }
7647 
7648 /* A subroutine of fold_builtin to fold the various logarithmic
7649    functions.  EXP is the CALL_EXPR of a call to a builtin logN
7650    function.  VALUE is the base of the logN function.  */
7651 
7652 static tree
fold_builtin_logarithm(tree fndecl,tree arglist,const REAL_VALUE_TYPE * value)7653 fold_builtin_logarithm (tree fndecl, tree arglist,
7654 			const REAL_VALUE_TYPE *value)
7655 {
7656   if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7657     {
7658       tree type = TREE_TYPE (TREE_TYPE (fndecl));
7659       tree arg = TREE_VALUE (arglist);
7660       const enum built_in_function fcode = builtin_mathfn_code (arg);
7661 
7662       /* Optimize logN(1.0) = 0.0.  */
7663       if (real_onep (arg))
7664 	return build_real (type, dconst0);
7665 
7666       /* Optimize logN(N) = 1.0.  If N can't be truncated to MODE
7667 	 exactly, then only do this if flag_unsafe_math_optimizations.  */
7668       if (exact_real_truncate (TYPE_MODE (type), value)
7669 	  || flag_unsafe_math_optimizations)
7670 	{
7671 	  const REAL_VALUE_TYPE value_truncate =
7672 	    real_value_truncate (TYPE_MODE (type), *value);
7673 	  if (real_dconstp (arg, &value_truncate))
7674 	    return build_real (type, dconst1);
7675 	}
7676 
7677       /* Special case, optimize logN(expN(x)) = x.  */
7678       if (flag_unsafe_math_optimizations
7679 	  && ((value == &dconste
7680 	       && (fcode == BUILT_IN_EXP
7681 		   || fcode == BUILT_IN_EXPF
7682 		   || fcode == BUILT_IN_EXPL))
7683 	      || (value == &dconst2
7684 		  && (fcode == BUILT_IN_EXP2
7685 		      || fcode == BUILT_IN_EXP2F
7686 		      || fcode == BUILT_IN_EXP2L))
7687 	      || (value == &dconst10 && (BUILTIN_EXP10_P (fcode)))))
7688 	return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
7689 
7690       /* Optimize logN(func()) for various exponential functions.  We
7691 	 want to determine the value "x" and the power "exponent" in
7692 	 order to transform logN(x**exponent) into exponent*logN(x).  */
7693       if (flag_unsafe_math_optimizations)
7694 	{
7695 	  tree exponent = 0, x = 0;
7696 
7697 	  switch (fcode)
7698 	  {
7699 	  CASE_FLT_FN (BUILT_IN_EXP):
7700 	    /* Prepare to do logN(exp(exponent) -> exponent*logN(e).  */
7701 	    x = build_real (type,
7702 			    real_value_truncate (TYPE_MODE (type), dconste));
7703 	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7704 	    break;
7705 	  CASE_FLT_FN (BUILT_IN_EXP2):
7706 	    /* Prepare to do logN(exp2(exponent) -> exponent*logN(2).  */
7707 	    x = build_real (type, dconst2);
7708 	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7709 	    break;
7710 	  CASE_FLT_FN (BUILT_IN_EXP10):
7711 	  CASE_FLT_FN (BUILT_IN_POW10):
7712 	    /* Prepare to do logN(exp10(exponent) -> exponent*logN(10).  */
7713 	    x = build_real (type, dconst10);
7714 	    exponent = TREE_VALUE (TREE_OPERAND (arg, 1));
7715 	    break;
7716 	  CASE_FLT_FN (BUILT_IN_SQRT):
7717 	    /* Prepare to do logN(sqrt(x) -> 0.5*logN(x).  */
7718 	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
7719 	    exponent = build_real (type, dconsthalf);
7720 	    break;
7721 	  CASE_FLT_FN (BUILT_IN_CBRT):
7722 	    /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x).  */
7723 	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
7724 	    exponent = build_real (type, real_value_truncate (TYPE_MODE (type),
7725 							      dconstthird));
7726 	    break;
7727 	  CASE_FLT_FN (BUILT_IN_POW):
7728 	    /* Prepare to do logN(pow(x,exponent) -> exponent*logN(x).  */
7729 	    x = TREE_VALUE (TREE_OPERAND (arg, 1));
7730 	    exponent = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
7731 	    break;
7732 	  default:
7733 	    break;
7734 	  }
7735 
7736 	  /* Now perform the optimization.  */
7737 	  if (x && exponent)
7738 	    {
7739 	      tree logfn;
7740 	      arglist = build_tree_list (NULL_TREE, x);
7741 	      logfn = build_function_call_expr (fndecl, arglist);
7742 	      return fold_build2 (MULT_EXPR, type, exponent, logfn);
7743 	    }
7744 	}
7745     }
7746 
7747   return 0;
7748 }
7749 
7750 /* Fold a builtin function call to pow, powf, or powl.  Return
7751    NULL_TREE if no simplification can be made.  */
7752 static tree
fold_builtin_pow(tree fndecl,tree arglist,tree type)7753 fold_builtin_pow (tree fndecl, tree arglist, tree type)
7754 {
7755   tree arg0 = TREE_VALUE (arglist);
7756   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
7757 
7758   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
7759     return NULL_TREE;
7760 
7761   /* Optimize pow(1.0,y) = 1.0.  */
7762   if (real_onep (arg0))
7763     return omit_one_operand (type, build_real (type, dconst1), arg1);
7764 
7765   if (TREE_CODE (arg1) == REAL_CST
7766       && ! TREE_CONSTANT_OVERFLOW (arg1))
7767     {
7768       REAL_VALUE_TYPE cint;
7769       REAL_VALUE_TYPE c;
7770       HOST_WIDE_INT n;
7771 
7772       c = TREE_REAL_CST (arg1);
7773 
7774       /* Optimize pow(x,0.0) = 1.0.  */
7775       if (REAL_VALUES_EQUAL (c, dconst0))
7776 	return omit_one_operand (type, build_real (type, dconst1),
7777 				 arg0);
7778 
7779       /* Optimize pow(x,1.0) = x.  */
7780       if (REAL_VALUES_EQUAL (c, dconst1))
7781 	return arg0;
7782 
7783       /* Optimize pow(x,-1.0) = 1.0/x.  */
7784       if (REAL_VALUES_EQUAL (c, dconstm1))
7785 	return fold_build2 (RDIV_EXPR, type,
7786 			    build_real (type, dconst1), arg0);
7787 
7788       /* Optimize pow(x,0.5) = sqrt(x).  */
7789       if (flag_unsafe_math_optimizations
7790 	  && REAL_VALUES_EQUAL (c, dconsthalf))
7791 	{
7792 	  tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
7793 
7794 	  if (sqrtfn != NULL_TREE)
7795 	    {
7796 	      tree arglist = build_tree_list (NULL_TREE, arg0);
7797 	      return build_function_call_expr (sqrtfn, arglist);
7798 	    }
7799 	}
7800 
7801       /* Check for an integer exponent.  */
7802       n = real_to_integer (&c);
7803       real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
7804       if (real_identical (&c, &cint))
7805 	{
7806 	  /* Attempt to evaluate pow at compile-time.  */
7807 	  if (TREE_CODE (arg0) == REAL_CST
7808 	      && ! TREE_CONSTANT_OVERFLOW (arg0))
7809 	    {
7810 	      REAL_VALUE_TYPE x;
7811 	      bool inexact;
7812 
7813 	      x = TREE_REAL_CST (arg0);
7814 	      inexact = real_powi (&x, TYPE_MODE (type), &x, n);
7815 	      if (flag_unsafe_math_optimizations || !inexact)
7816 		return build_real (type, x);
7817 	    }
7818 
7819 	  /* Strip sign ops from even integer powers.  */
7820 	  if ((n & 1) == 0 && flag_unsafe_math_optimizations)
7821 	    {
7822 	      tree narg0 = fold_strip_sign_ops (arg0);
7823 	      if (narg0)
7824 		{
7825 		  arglist = build_tree_list (NULL_TREE, arg1);
7826 		  arglist = tree_cons (NULL_TREE, narg0, arglist);
7827 		  return build_function_call_expr (fndecl, arglist);
7828 		}
7829 	    }
7830 	}
7831     }
7832 
7833   if (flag_unsafe_math_optimizations)
7834     {
7835       const enum built_in_function fcode = builtin_mathfn_code (arg0);
7836 
7837       /* Optimize pow(expN(x),y) = expN(x*y).  */
7838       if (BUILTIN_EXPONENT_P (fcode))
7839 	{
7840 	  tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
7841 	  tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
7842 	  arg = fold_build2 (MULT_EXPR, type, arg, arg1);
7843 	  arglist = build_tree_list (NULL_TREE, arg);
7844 	  return build_function_call_expr (expfn, arglist);
7845 	}
7846 
7847       /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
7848       if (BUILTIN_SQRT_P (fcode))
7849 	{
7850 	  tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
7851 	  tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
7852 				    build_real (type, dconsthalf));
7853 
7854 	  arglist = tree_cons (NULL_TREE, narg0,
7855 			       build_tree_list (NULL_TREE, narg1));
7856 	  return build_function_call_expr (fndecl, arglist);
7857 	}
7858 
7859       /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative.  */
7860       if (BUILTIN_CBRT_P (fcode))
7861 	{
7862 	  tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
7863 	  if (tree_expr_nonnegative_p (arg))
7864 	    {
7865 	      const REAL_VALUE_TYPE dconstroot
7866 		= real_value_truncate (TYPE_MODE (type), dconstthird);
7867 	      tree narg1 = fold_build2 (MULT_EXPR, type, arg1,
7868 					build_real (type, dconstroot));
7869 	      arglist = tree_cons (NULL_TREE, arg,
7870 				   build_tree_list (NULL_TREE, narg1));
7871 	      return build_function_call_expr (fndecl, arglist);
7872 	    }
7873 	}
7874 
7875       /* Optimize pow(pow(x,y),z) = pow(x,y*z).  */
7876       if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
7877 	   || fcode == BUILT_IN_POWL)
7878 	{
7879 	  tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
7880 	  tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
7881 	  tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
7882 	  arglist = tree_cons (NULL_TREE, arg00,
7883 			       build_tree_list (NULL_TREE, narg1));
7884 	  return build_function_call_expr (fndecl, arglist);
7885 	}
7886     }
7887 
7888   return NULL_TREE;
7889 }
7890 
7891 /* Fold a builtin function call to powi, powif, or powil.  Return
7892    NULL_TREE if no simplification can be made.  */
7893 static tree
fold_builtin_powi(tree fndecl ATTRIBUTE_UNUSED,tree arglist,tree type)7894 fold_builtin_powi (tree fndecl ATTRIBUTE_UNUSED, tree arglist, tree type)
7895 {
7896   tree arg0 = TREE_VALUE (arglist);
7897   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
7898 
7899   if (!validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
7900     return NULL_TREE;
7901 
7902   /* Optimize pow(1.0,y) = 1.0.  */
7903   if (real_onep (arg0))
7904     return omit_one_operand (type, build_real (type, dconst1), arg1);
7905 
7906   if (host_integerp (arg1, 0))
7907     {
7908       HOST_WIDE_INT c = TREE_INT_CST_LOW (arg1);
7909 
7910       /* Evaluate powi at compile-time.  */
7911       if (TREE_CODE (arg0) == REAL_CST
7912 	  && ! TREE_CONSTANT_OVERFLOW (arg0))
7913 	{
7914 	  REAL_VALUE_TYPE x;
7915 	  x = TREE_REAL_CST (arg0);
7916 	  real_powi (&x, TYPE_MODE (type), &x, c);
7917 	  return build_real (type, x);
7918 	}
7919 
7920       /* Optimize pow(x,0) = 1.0.  */
7921       if (c == 0)
7922 	return omit_one_operand (type, build_real (type, dconst1),
7923 				 arg0);
7924 
7925       /* Optimize pow(x,1) = x.  */
7926       if (c == 1)
7927 	return arg0;
7928 
7929       /* Optimize pow(x,-1) = 1.0/x.  */
7930       if (c == -1)
7931 	return fold_build2 (RDIV_EXPR, type,
7932 			   build_real (type, dconst1), arg0);
7933     }
7934 
7935   return NULL_TREE;
7936 }
7937 
7938 /* A subroutine of fold_builtin to fold the various exponent
7939    functions.  EXP is the CALL_EXPR of a call to a builtin function.
7940    VALUE is the value which will be raised to a power.  */
7941 
7942 static tree
fold_builtin_exponent(tree fndecl,tree arglist,const REAL_VALUE_TYPE * value)7943 fold_builtin_exponent (tree fndecl, tree arglist,
7944 		       const REAL_VALUE_TYPE *value)
7945 {
7946   if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
7947     {
7948       tree type = TREE_TYPE (TREE_TYPE (fndecl));
7949       tree arg = TREE_VALUE (arglist);
7950 
7951       /* Optimize exp*(0.0) = 1.0.  */
7952       if (real_zerop (arg))
7953 	return build_real (type, dconst1);
7954 
7955       /* Optimize expN(1.0) = N.  */
7956       if (real_onep (arg))
7957 	{
7958 	  REAL_VALUE_TYPE cst;
7959 
7960 	  real_convert (&cst, TYPE_MODE (type), value);
7961 	  return build_real (type, cst);
7962 	}
7963 
7964       /* Attempt to evaluate expN(integer) at compile-time.  */
7965       if (flag_unsafe_math_optimizations
7966 	  && TREE_CODE (arg) == REAL_CST
7967 	  && ! TREE_CONSTANT_OVERFLOW (arg))
7968 	{
7969 	  REAL_VALUE_TYPE cint;
7970 	  REAL_VALUE_TYPE c;
7971 	  HOST_WIDE_INT n;
7972 
7973 	  c = TREE_REAL_CST (arg);
7974 	  n = real_to_integer (&c);
7975 	  real_from_integer (&cint, VOIDmode, n,
7976 			     n < 0 ? -1 : 0, 0);
7977 	  if (real_identical (&c, &cint))
7978 	    {
7979 	      REAL_VALUE_TYPE x;
7980 
7981 	      real_powi (&x, TYPE_MODE (type), value, n);
7982 	      return build_real (type, x);
7983 	    }
7984 	}
7985 
7986       /* Optimize expN(logN(x)) = x.  */
7987       if (flag_unsafe_math_optimizations)
7988 	{
7989 	  const enum built_in_function fcode = builtin_mathfn_code (arg);
7990 
7991 	  if ((value == &dconste
7992 	       && (fcode == BUILT_IN_LOG
7993 		   || fcode == BUILT_IN_LOGF
7994 		   || fcode == BUILT_IN_LOGL))
7995 	      || (value == &dconst2
7996 		  && (fcode == BUILT_IN_LOG2
7997 		      || fcode == BUILT_IN_LOG2F
7998 		      || fcode == BUILT_IN_LOG2L))
7999 	      || (value == &dconst10
8000 		  && (fcode == BUILT_IN_LOG10
8001 		      || fcode == BUILT_IN_LOG10F
8002 		      || fcode == BUILT_IN_LOG10L)))
8003 	    return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1)));
8004 	}
8005     }
8006 
8007   return 0;
8008 }
8009 
8010 /* Return true if VAR is a VAR_DECL or a component thereof.  */
8011 
8012 static bool
var_decl_component_p(tree var)8013 var_decl_component_p (tree var)
8014 {
8015   tree inner = var;
8016   while (handled_component_p (inner))
8017     inner = TREE_OPERAND (inner, 0);
8018   return SSA_VAR_P (inner);
8019 }
8020 
8021 /* Fold function call to builtin memset.  Return
8022    NULL_TREE if no simplification can be made.  */
8023 
8024 static tree
fold_builtin_memset(tree arglist,tree type,bool ignore)8025 fold_builtin_memset (tree arglist, tree type, bool ignore)
8026 {
8027   tree dest, c, len, var, ret;
8028   unsigned HOST_WIDE_INT length, cval;
8029 
8030   if (!validate_arglist (arglist,
8031 			 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
8032     return 0;
8033 
8034   dest = TREE_VALUE (arglist);
8035   c = TREE_VALUE (TREE_CHAIN (arglist));
8036   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8037 
8038   if (! host_integerp (len, 1))
8039     return 0;
8040 
8041   /* If the LEN parameter is zero, return DEST.  */
8042   if (integer_zerop (len))
8043     return omit_one_operand (type, dest, c);
8044 
8045   if (! host_integerp (c, 1) || TREE_SIDE_EFFECTS (dest))
8046     return 0;
8047 
8048   var = dest;
8049   STRIP_NOPS (var);
8050   if (TREE_CODE (var) != ADDR_EXPR)
8051     return 0;
8052 
8053   var = TREE_OPERAND (var, 0);
8054   if (TREE_THIS_VOLATILE (var))
8055     return 0;
8056 
8057   if (!INTEGRAL_TYPE_P (TREE_TYPE (var))
8058       && !POINTER_TYPE_P (TREE_TYPE (var)))
8059     return 0;
8060 
8061   if (! var_decl_component_p (var))
8062     return 0;
8063 
8064   length = tree_low_cst (len, 1);
8065   if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length
8066       || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8067 	 < (int) length)
8068     return 0;
8069 
8070   if (length > HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT)
8071     return 0;
8072 
8073   if (integer_zerop (c))
8074     cval = 0;
8075   else
8076     {
8077       if (CHAR_BIT != 8 || BITS_PER_UNIT != 8 || HOST_BITS_PER_WIDE_INT > 64)
8078 	return 0;
8079 
8080       cval = tree_low_cst (c, 1);
8081       cval &= 0xff;
8082       cval |= cval << 8;
8083       cval |= cval << 16;
8084       cval |= (cval << 31) << 1;
8085     }
8086 
8087   ret = build_int_cst_type (TREE_TYPE (var), cval);
8088   ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret);
8089   if (ignore)
8090     return ret;
8091 
8092   return omit_one_operand (type, dest, ret);
8093 }
8094 
8095 /* Fold function call to builtin memset.  Return
8096    NULL_TREE if no simplification can be made.  */
8097 
8098 static tree
fold_builtin_bzero(tree arglist,bool ignore)8099 fold_builtin_bzero (tree arglist, bool ignore)
8100 {
8101   tree dest, size, newarglist;
8102 
8103   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8104     return 0;
8105 
8106   if (!ignore)
8107     return 0;
8108 
8109   dest = TREE_VALUE (arglist);
8110   size = TREE_VALUE (TREE_CHAIN (arglist));
8111 
8112   /* New argument list transforming bzero(ptr x, int y) to
8113      memset(ptr x, int 0, size_t y).   This is done this way
8114      so that if it isn't expanded inline, we fallback to
8115      calling bzero instead of memset.  */
8116 
8117   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
8118   newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
8119   newarglist = tree_cons (NULL_TREE, dest, newarglist);
8120   return fold_builtin_memset (newarglist, void_type_node, ignore);
8121 }
8122 
8123 /* Fold function call to builtin mem{{,p}cpy,move}.  Return
8124    NULL_TREE if no simplification can be made.
8125    If ENDP is 0, return DEST (like memcpy).
8126    If ENDP is 1, return DEST+LEN (like mempcpy).
8127    If ENDP is 2, return DEST+LEN-1 (like stpcpy).
8128    If ENDP is 3, return DEST, additionally *SRC and *DEST may overlap
8129    (memmove).   */
8130 
8131 static tree
fold_builtin_memory_op(tree arglist,tree type,bool ignore,int endp)8132 fold_builtin_memory_op (tree arglist, tree type, bool ignore, int endp)
8133 {
8134   tree dest, src, len, destvar, srcvar, expr;
8135   unsigned HOST_WIDE_INT length;
8136 
8137   if (! validate_arglist (arglist,
8138 			  POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8139     return 0;
8140 
8141   dest = TREE_VALUE (arglist);
8142   src = TREE_VALUE (TREE_CHAIN (arglist));
8143   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8144 
8145   /* If the LEN parameter is zero, return DEST.  */
8146   if (integer_zerop (len))
8147     return omit_one_operand (type, dest, src);
8148 
8149   /* If SRC and DEST are the same (and not volatile), return
8150      DEST{,+LEN,+LEN-1}.  */
8151   if (operand_equal_p (src, dest, 0))
8152     expr = len;
8153   else
8154     {
8155       if (! host_integerp (len, 1))
8156 	return 0;
8157 
8158       if (TREE_SIDE_EFFECTS (dest) || TREE_SIDE_EFFECTS (src))
8159 	return 0;
8160 
8161       destvar = dest;
8162       STRIP_NOPS (destvar);
8163       if (TREE_CODE (destvar) != ADDR_EXPR)
8164 	return 0;
8165 
8166       destvar = TREE_OPERAND (destvar, 0);
8167       if (TREE_THIS_VOLATILE (destvar))
8168 	return 0;
8169 
8170       if (!INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8171 	  && !POINTER_TYPE_P (TREE_TYPE (destvar))
8172 	  && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (destvar)))
8173 	return 0;
8174 
8175       if (! var_decl_component_p (destvar))
8176 	return 0;
8177 
8178       srcvar = src;
8179       STRIP_NOPS (srcvar);
8180       if (TREE_CODE (srcvar) != ADDR_EXPR)
8181 	return 0;
8182 
8183       srcvar = TREE_OPERAND (srcvar, 0);
8184       if (TREE_THIS_VOLATILE (srcvar))
8185 	return 0;
8186 
8187       if (!INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
8188 	  && !POINTER_TYPE_P (TREE_TYPE (srcvar))
8189 	  && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (srcvar)))
8190 	return 0;
8191 
8192       if (! var_decl_component_p (srcvar))
8193 	return 0;
8194 
8195       length = tree_low_cst (len, 1);
8196       if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (destvar))) != length
8197 	  || get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8198 	     < (int) length
8199 	  || GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (srcvar))) != length
8200 	  || get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
8201 	     < (int) length)
8202 	return 0;
8203 
8204       if ((INTEGRAL_TYPE_P (TREE_TYPE (srcvar))
8205 	   || POINTER_TYPE_P (TREE_TYPE (srcvar)))
8206 	  && (INTEGRAL_TYPE_P (TREE_TYPE (destvar))
8207 	      || POINTER_TYPE_P (TREE_TYPE (destvar))))
8208 	expr = fold_convert (TREE_TYPE (destvar), srcvar);
8209       else
8210 	expr = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (destvar), srcvar);
8211       expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, expr);
8212     }
8213 
8214   if (ignore)
8215     return expr;
8216 
8217   if (endp == 0 || endp == 3)
8218     return omit_one_operand (type, dest, expr);
8219 
8220   if (expr == len)
8221     expr = 0;
8222 
8223   if (endp == 2)
8224     len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len,
8225 		       ssize_int (1));
8226 
8227   len = fold_convert (TREE_TYPE (dest), len);
8228   dest = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
8229   dest = fold_convert (type, dest);
8230   if (expr)
8231     dest = omit_one_operand (type, dest, expr);
8232   return dest;
8233 }
8234 
8235 /* Fold function call to builtin bcopy.  Return NULL_TREE if no
8236    simplification can be made.  */
8237 
8238 static tree
fold_builtin_bcopy(tree arglist,bool ignore)8239 fold_builtin_bcopy (tree arglist, bool ignore)
8240 {
8241   tree src, dest, size, newarglist;
8242 
8243   if (!validate_arglist (arglist,
8244 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8245     return 0;
8246 
8247   if (! ignore)
8248     return 0;
8249 
8250   src = TREE_VALUE (arglist);
8251   dest = TREE_VALUE (TREE_CHAIN (arglist));
8252   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8253 
8254   /* New argument list transforming bcopy(ptr x, ptr y, int z) to
8255      memmove(ptr y, ptr x, size_t z).   This is done this way
8256      so that if it isn't expanded inline, we fallback to
8257      calling bcopy instead of memmove.  */
8258 
8259   newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
8260   newarglist = tree_cons (NULL_TREE, src, newarglist);
8261   newarglist = tree_cons (NULL_TREE, dest, newarglist);
8262 
8263   return fold_builtin_memory_op (newarglist, void_type_node, true, /*endp=*/3);
8264 }
8265 
8266 /* Fold function call to builtin strcpy.  If LEN is not NULL, it represents
8267    the length of the string to be copied.  Return NULL_TREE if no
8268    simplification can be made.  */
8269 
8270 tree
fold_builtin_strcpy(tree fndecl,tree arglist,tree len)8271 fold_builtin_strcpy (tree fndecl, tree arglist, tree len)
8272 {
8273   tree dest, src, fn;
8274 
8275   if (!validate_arglist (arglist,
8276 			 POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8277     return 0;
8278 
8279   dest = TREE_VALUE (arglist);
8280   src = TREE_VALUE (TREE_CHAIN (arglist));
8281 
8282   /* If SRC and DEST are the same (and not volatile), return DEST.  */
8283   if (operand_equal_p (src, dest, 0))
8284     return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
8285 
8286   if (optimize_size)
8287     return 0;
8288 
8289   fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8290   if (!fn)
8291     return 0;
8292 
8293   if (!len)
8294     {
8295       len = c_strlen (src, 1);
8296       if (! len || TREE_SIDE_EFFECTS (len))
8297 	return 0;
8298     }
8299 
8300   len = size_binop (PLUS_EXPR, len, ssize_int (1));
8301   arglist = build_tree_list (NULL_TREE, len);
8302   arglist = tree_cons (NULL_TREE, src, arglist);
8303   arglist = tree_cons (NULL_TREE, dest, arglist);
8304   return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
8305 		       build_function_call_expr (fn, arglist));
8306 }
8307 
8308 /* Fold function call to builtin strncpy.  If SLEN is not NULL, it represents
8309    the length of the source string.  Return NULL_TREE if no simplification
8310    can be made.  */
8311 
8312 tree
fold_builtin_strncpy(tree fndecl,tree arglist,tree slen)8313 fold_builtin_strncpy (tree fndecl, tree arglist, tree slen)
8314 {
8315   tree dest, src, len, fn;
8316 
8317   if (!validate_arglist (arglist,
8318 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8319     return 0;
8320 
8321   dest = TREE_VALUE (arglist);
8322   src = TREE_VALUE (TREE_CHAIN (arglist));
8323   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8324 
8325   /* If the LEN parameter is zero, return DEST.  */
8326   if (integer_zerop (len))
8327     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
8328 
8329   /* We can't compare slen with len as constants below if len is not a
8330      constant.  */
8331   if (len == 0 || TREE_CODE (len) != INTEGER_CST)
8332     return 0;
8333 
8334   if (!slen)
8335     slen = c_strlen (src, 1);
8336 
8337   /* Now, we must be passed a constant src ptr parameter.  */
8338   if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
8339     return 0;
8340 
8341   slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
8342 
8343   /* We do not support simplification of this case, though we do
8344      support it when expanding trees into RTL.  */
8345   /* FIXME: generate a call to __builtin_memset.  */
8346   if (tree_int_cst_lt (slen, len))
8347     return 0;
8348 
8349   /* OK transform into builtin memcpy.  */
8350   fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
8351   if (!fn)
8352     return 0;
8353   return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
8354 		       build_function_call_expr (fn, arglist));
8355 }
8356 
8357 /* Fold function call to builtin memcmp.  Return
8358    NULL_TREE if no simplification can be made.  */
8359 
8360 static tree
fold_builtin_memcmp(tree arglist)8361 fold_builtin_memcmp (tree arglist)
8362 {
8363   tree arg1, arg2, len;
8364   const char *p1, *p2;
8365 
8366   if (!validate_arglist (arglist,
8367 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8368     return 0;
8369 
8370   arg1 = TREE_VALUE (arglist);
8371   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8372   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8373 
8374   /* If the LEN parameter is zero, return zero.  */
8375   if (integer_zerop (len))
8376     return omit_two_operands (integer_type_node, integer_zero_node,
8377 			      arg1, arg2);
8378 
8379   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
8380   if (operand_equal_p (arg1, arg2, 0))
8381     return omit_one_operand (integer_type_node, integer_zero_node, len);
8382 
8383   p1 = c_getstr (arg1);
8384   p2 = c_getstr (arg2);
8385 
8386   /* If all arguments are constant, and the value of len is not greater
8387      than the lengths of arg1 and arg2, evaluate at compile-time.  */
8388   if (host_integerp (len, 1) && p1 && p2
8389       && compare_tree_int (len, strlen (p1) + 1) <= 0
8390       && compare_tree_int (len, strlen (p2) + 1) <= 0)
8391     {
8392       const int r = memcmp (p1, p2, tree_low_cst (len, 1));
8393 
8394       if (r > 0)
8395 	return integer_one_node;
8396       else if (r < 0)
8397 	return integer_minus_one_node;
8398       else
8399 	return integer_zero_node;
8400     }
8401 
8402   /* If len parameter is one, return an expression corresponding to
8403      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
8404   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8405     {
8406       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8407       tree cst_uchar_ptr_node
8408 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8409 
8410       tree ind1 = fold_convert (integer_type_node,
8411 				build1 (INDIRECT_REF, cst_uchar_node,
8412 					fold_convert (cst_uchar_ptr_node,
8413 						      arg1)));
8414       tree ind2 = fold_convert (integer_type_node,
8415 				build1 (INDIRECT_REF, cst_uchar_node,
8416 					fold_convert (cst_uchar_ptr_node,
8417 						      arg2)));
8418       return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
8419     }
8420 
8421   return 0;
8422 }
8423 
8424 /* Fold function call to builtin strcmp.  Return
8425    NULL_TREE if no simplification can be made.  */
8426 
8427 static tree
fold_builtin_strcmp(tree arglist)8428 fold_builtin_strcmp (tree arglist)
8429 {
8430   tree arg1, arg2;
8431   const char *p1, *p2;
8432 
8433   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
8434     return 0;
8435 
8436   arg1 = TREE_VALUE (arglist);
8437   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8438 
8439   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
8440   if (operand_equal_p (arg1, arg2, 0))
8441     return integer_zero_node;
8442 
8443   p1 = c_getstr (arg1);
8444   p2 = c_getstr (arg2);
8445 
8446   if (p1 && p2)
8447     {
8448       const int i = strcmp (p1, p2);
8449       if (i < 0)
8450 	return integer_minus_one_node;
8451       else if (i > 0)
8452 	return integer_one_node;
8453       else
8454 	return integer_zero_node;
8455     }
8456 
8457   /* If the second arg is "", return *(const unsigned char*)arg1.  */
8458   if (p2 && *p2 == '\0')
8459     {
8460       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8461       tree cst_uchar_ptr_node
8462 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8463 
8464       return fold_convert (integer_type_node,
8465 			   build1 (INDIRECT_REF, cst_uchar_node,
8466 				   fold_convert (cst_uchar_ptr_node,
8467 						 arg1)));
8468     }
8469 
8470   /* If the first arg is "", return -*(const unsigned char*)arg2.  */
8471   if (p1 && *p1 == '\0')
8472     {
8473       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8474       tree cst_uchar_ptr_node
8475 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8476 
8477       tree temp = fold_convert (integer_type_node,
8478 				build1 (INDIRECT_REF, cst_uchar_node,
8479 					fold_convert (cst_uchar_ptr_node,
8480 						      arg2)));
8481       return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
8482     }
8483 
8484   return 0;
8485 }
8486 
8487 /* Fold function call to builtin strncmp.  Return
8488    NULL_TREE if no simplification can be made.  */
8489 
8490 static tree
fold_builtin_strncmp(tree arglist)8491 fold_builtin_strncmp (tree arglist)
8492 {
8493   tree arg1, arg2, len;
8494   const char *p1, *p2;
8495 
8496   if (!validate_arglist (arglist,
8497 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
8498     return 0;
8499 
8500   arg1 = TREE_VALUE (arglist);
8501   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8502   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
8503 
8504   /* If the LEN parameter is zero, return zero.  */
8505   if (integer_zerop (len))
8506     return omit_two_operands (integer_type_node, integer_zero_node,
8507 			      arg1, arg2);
8508 
8509   /* If ARG1 and ARG2 are the same (and not volatile), return zero.  */
8510   if (operand_equal_p (arg1, arg2, 0))
8511     return omit_one_operand (integer_type_node, integer_zero_node, len);
8512 
8513   p1 = c_getstr (arg1);
8514   p2 = c_getstr (arg2);
8515 
8516   if (host_integerp (len, 1) && p1 && p2)
8517     {
8518       const int i = strncmp (p1, p2, tree_low_cst (len, 1));
8519       if (i > 0)
8520 	return integer_one_node;
8521       else if (i < 0)
8522 	return integer_minus_one_node;
8523       else
8524 	return integer_zero_node;
8525     }
8526 
8527   /* If the second arg is "", and the length is greater than zero,
8528      return *(const unsigned char*)arg1.  */
8529   if (p2 && *p2 == '\0'
8530       && TREE_CODE (len) == INTEGER_CST
8531       && tree_int_cst_sgn (len) == 1)
8532     {
8533       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8534       tree cst_uchar_ptr_node
8535 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8536 
8537       return fold_convert (integer_type_node,
8538 			   build1 (INDIRECT_REF, cst_uchar_node,
8539 				   fold_convert (cst_uchar_ptr_node,
8540 						 arg1)));
8541     }
8542 
8543   /* If the first arg is "", and the length is greater than zero,
8544      return -*(const unsigned char*)arg2.  */
8545   if (p1 && *p1 == '\0'
8546       && TREE_CODE (len) == INTEGER_CST
8547       && tree_int_cst_sgn (len) == 1)
8548     {
8549       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8550       tree cst_uchar_ptr_node
8551 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8552 
8553       tree temp = fold_convert (integer_type_node,
8554 				build1 (INDIRECT_REF, cst_uchar_node,
8555 					fold_convert (cst_uchar_ptr_node,
8556 						      arg2)));
8557       return fold_build1 (NEGATE_EXPR, integer_type_node, temp);
8558     }
8559 
8560   /* If len parameter is one, return an expression corresponding to
8561      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
8562   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
8563     {
8564       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
8565       tree cst_uchar_ptr_node
8566 	= build_pointer_type_for_mode (cst_uchar_node, ptr_mode, true);
8567 
8568       tree ind1 = fold_convert (integer_type_node,
8569 				build1 (INDIRECT_REF, cst_uchar_node,
8570 					fold_convert (cst_uchar_ptr_node,
8571 						      arg1)));
8572       tree ind2 = fold_convert (integer_type_node,
8573 				build1 (INDIRECT_REF, cst_uchar_node,
8574 					fold_convert (cst_uchar_ptr_node,
8575 						      arg2)));
8576       return fold_build2 (MINUS_EXPR, integer_type_node, ind1, ind2);
8577     }
8578 
8579   return 0;
8580 }
8581 
8582 /* Fold function call to builtin signbit, signbitf or signbitl.  Return
8583    NULL_TREE if no simplification can be made.  */
8584 
8585 static tree
fold_builtin_signbit(tree fndecl,tree arglist)8586 fold_builtin_signbit (tree fndecl, tree arglist)
8587 {
8588   tree type = TREE_TYPE (TREE_TYPE (fndecl));
8589   tree arg, temp;
8590 
8591   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8592     return NULL_TREE;
8593 
8594   arg = TREE_VALUE (arglist);
8595 
8596   /* If ARG is a compile-time constant, determine the result.  */
8597   if (TREE_CODE (arg) == REAL_CST
8598       && !TREE_CONSTANT_OVERFLOW (arg))
8599     {
8600       REAL_VALUE_TYPE c;
8601 
8602       c = TREE_REAL_CST (arg);
8603       temp = REAL_VALUE_NEGATIVE (c) ? integer_one_node : integer_zero_node;
8604       return fold_convert (type, temp);
8605     }
8606 
8607   /* If ARG is non-negative, the result is always zero.  */
8608   if (tree_expr_nonnegative_p (arg))
8609     return omit_one_operand (type, integer_zero_node, arg);
8610 
8611   /* If ARG's format doesn't have signed zeros, return "arg < 0.0".  */
8612   if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg))))
8613     return fold_build2 (LT_EXPR, type, arg,
8614 			build_real (TREE_TYPE (arg), dconst0));
8615 
8616   return NULL_TREE;
8617 }
8618 
8619 /* Fold function call to builtin copysign, copysignf or copysignl.
8620    Return NULL_TREE if no simplification can be made.  */
8621 
8622 static tree
fold_builtin_copysign(tree fndecl,tree arglist,tree type)8623 fold_builtin_copysign (tree fndecl, tree arglist, tree type)
8624 {
8625   tree arg1, arg2, tem;
8626 
8627   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
8628     return NULL_TREE;
8629 
8630   arg1 = TREE_VALUE (arglist);
8631   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
8632 
8633   /* copysign(X,X) is X.  */
8634   if (operand_equal_p (arg1, arg2, 0))
8635     return fold_convert (type, arg1);
8636 
8637   /* If ARG1 and ARG2 are compile-time constants, determine the result.  */
8638   if (TREE_CODE (arg1) == REAL_CST
8639       && TREE_CODE (arg2) == REAL_CST
8640       && !TREE_CONSTANT_OVERFLOW (arg1)
8641       && !TREE_CONSTANT_OVERFLOW (arg2))
8642     {
8643       REAL_VALUE_TYPE c1, c2;
8644 
8645       c1 = TREE_REAL_CST (arg1);
8646       c2 = TREE_REAL_CST (arg2);
8647       /* c1.sign := c2.sign.  */
8648       real_copysign (&c1, &c2);
8649       return build_real (type, c1);
8650     }
8651 
8652   /* copysign(X, Y) is fabs(X) when Y is always non-negative.
8653      Remember to evaluate Y for side-effects.  */
8654   if (tree_expr_nonnegative_p (arg2))
8655     return omit_one_operand (type,
8656 			     fold_build1 (ABS_EXPR, type, arg1),
8657 			     arg2);
8658 
8659   /* Strip sign changing operations for the first argument.  */
8660   tem = fold_strip_sign_ops (arg1);
8661   if (tem)
8662     {
8663       arglist = tree_cons (NULL_TREE, tem, TREE_CHAIN (arglist));
8664       return build_function_call_expr (fndecl, arglist);
8665     }
8666 
8667   return NULL_TREE;
8668 }
8669 
8670 /* Fold a call to builtin isascii.  */
8671 
8672 static tree
fold_builtin_isascii(tree arglist)8673 fold_builtin_isascii (tree arglist)
8674 {
8675   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8676     return 0;
8677   else
8678     {
8679       /* Transform isascii(c) -> ((c & ~0x7f) == 0).  */
8680       tree arg = TREE_VALUE (arglist);
8681 
8682       arg = build2 (BIT_AND_EXPR, integer_type_node, arg,
8683 		    build_int_cst (NULL_TREE,
8684 				   ~ (unsigned HOST_WIDE_INT) 0x7f));
8685       arg = fold_build2 (EQ_EXPR, integer_type_node,
8686 			 arg, integer_zero_node);
8687 
8688       if (in_gimple_form && !TREE_CONSTANT (arg))
8689 	return NULL_TREE;
8690       else
8691 	return arg;
8692     }
8693 }
8694 
8695 /* Fold a call to builtin toascii.  */
8696 
8697 static tree
fold_builtin_toascii(tree arglist)8698 fold_builtin_toascii (tree arglist)
8699 {
8700   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8701     return 0;
8702   else
8703     {
8704       /* Transform toascii(c) -> (c & 0x7f).  */
8705       tree arg = TREE_VALUE (arglist);
8706 
8707       return fold_build2 (BIT_AND_EXPR, integer_type_node, arg,
8708 			  build_int_cst (NULL_TREE, 0x7f));
8709     }
8710 }
8711 
8712 /* Fold a call to builtin isdigit.  */
8713 
8714 static tree
fold_builtin_isdigit(tree arglist)8715 fold_builtin_isdigit (tree arglist)
8716 {
8717   if (! validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8718     return 0;
8719   else
8720     {
8721       /* Transform isdigit(c) -> (unsigned)(c) - '0' <= 9.  */
8722       /* According to the C standard, isdigit is unaffected by locale.
8723 	 However, it definitely is affected by the target character set.  */
8724       tree arg;
8725       unsigned HOST_WIDE_INT target_digit0
8726 	= lang_hooks.to_target_charset ('0');
8727 
8728       if (target_digit0 == 0)
8729 	return NULL_TREE;
8730 
8731       arg = fold_convert (unsigned_type_node, TREE_VALUE (arglist));
8732       arg = build2 (MINUS_EXPR, unsigned_type_node, arg,
8733 		    build_int_cst (unsigned_type_node, target_digit0));
8734       arg = fold_build2 (LE_EXPR, integer_type_node, arg,
8735 			 build_int_cst (unsigned_type_node, 9));
8736       if (in_gimple_form && !TREE_CONSTANT (arg))
8737 	return NULL_TREE;
8738       else
8739 	return arg;
8740     }
8741 }
8742 
8743 /* Fold a call to fabs, fabsf or fabsl.  */
8744 
8745 static tree
fold_builtin_fabs(tree arglist,tree type)8746 fold_builtin_fabs (tree arglist, tree type)
8747 {
8748   tree arg;
8749 
8750   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8751     return 0;
8752 
8753   arg = TREE_VALUE (arglist);
8754   arg = fold_convert (type, arg);
8755   if (TREE_CODE (arg) == REAL_CST)
8756     return fold_abs_const (arg, type);
8757   return fold_build1 (ABS_EXPR, type, arg);
8758 }
8759 
8760 /* Fold a call to abs, labs, llabs or imaxabs.  */
8761 
8762 static tree
fold_builtin_abs(tree arglist,tree type)8763 fold_builtin_abs (tree arglist, tree type)
8764 {
8765   tree arg;
8766 
8767   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
8768     return 0;
8769 
8770   arg = TREE_VALUE (arglist);
8771   arg = fold_convert (type, arg);
8772   if (TREE_CODE (arg) == INTEGER_CST)
8773     return fold_abs_const (arg, type);
8774   return fold_build1 (ABS_EXPR, type, arg);
8775 }
8776 
8777 /* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
8778    EXP is the CALL_EXPR for the call.  */
8779 
8780 static tree
fold_builtin_classify(tree fndecl,tree arglist,int builtin_index)8781 fold_builtin_classify (tree fndecl, tree arglist, int builtin_index)
8782 {
8783   tree type = TREE_TYPE (TREE_TYPE (fndecl));
8784   tree arg;
8785   REAL_VALUE_TYPE r;
8786 
8787   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
8788     {
8789       /* Check that we have exactly one argument.  */
8790       if (arglist == 0)
8791 	{
8792 	  error ("too few arguments to function %qs",
8793 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8794 	  return error_mark_node;
8795 	}
8796       else if (TREE_CHAIN (arglist) != 0)
8797 	{
8798 	  error ("too many arguments to function %qs",
8799 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8800 	  return error_mark_node;
8801 	}
8802       else
8803 	{
8804 	  error ("non-floating-point argument to function %qs",
8805 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8806 	  return error_mark_node;
8807 	}
8808     }
8809 
8810   arg = TREE_VALUE (arglist);
8811   switch (builtin_index)
8812     {
8813     case BUILT_IN_ISINF:
8814       if (!HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
8815 	return omit_one_operand (type, integer_zero_node, arg);
8816 
8817       if (TREE_CODE (arg) == REAL_CST)
8818 	{
8819 	  r = TREE_REAL_CST (arg);
8820 	  if (real_isinf (&r))
8821 	    return real_compare (GT_EXPR, &r, &dconst0)
8822 		   ? integer_one_node : integer_minus_one_node;
8823 	  else
8824 	    return integer_zero_node;
8825 	}
8826 
8827       return NULL_TREE;
8828 
8829     case BUILT_IN_FINITE:
8830       if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
8831 	  && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
8832 	return omit_one_operand (type, integer_one_node, arg);
8833 
8834       if (TREE_CODE (arg) == REAL_CST)
8835 	{
8836 	  r = TREE_REAL_CST (arg);
8837 	  return real_isinf (&r) || real_isnan (&r)
8838 		 ? integer_zero_node : integer_one_node;
8839 	}
8840 
8841       return NULL_TREE;
8842 
8843     case BUILT_IN_ISNAN:
8844       if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))))
8845 	return omit_one_operand (type, integer_zero_node, arg);
8846 
8847       if (TREE_CODE (arg) == REAL_CST)
8848 	{
8849 	  r = TREE_REAL_CST (arg);
8850 	  return real_isnan (&r) ? integer_one_node : integer_zero_node;
8851 	}
8852 
8853       arg = builtin_save_expr (arg);
8854       return fold_build2 (UNORDERED_EXPR, type, arg, arg);
8855 
8856     default:
8857       gcc_unreachable ();
8858     }
8859 }
8860 
8861 /* Fold a call to an unordered comparison function such as
8862    __builtin_isgreater().  FNDECL is the FUNCTION_DECL for the function
8863    being called and ARGLIST is the argument list for the call.
8864    UNORDERED_CODE and ORDERED_CODE are comparison codes that give
8865    the opposite of the desired result.  UNORDERED_CODE is used
8866    for modes that can hold NaNs and ORDERED_CODE is used for
8867    the rest.  */
8868 
8869 static tree
fold_builtin_unordered_cmp(tree fndecl,tree arglist,enum tree_code unordered_code,enum tree_code ordered_code)8870 fold_builtin_unordered_cmp (tree fndecl, tree arglist,
8871 			    enum tree_code unordered_code,
8872 			    enum tree_code ordered_code)
8873 {
8874   tree type = TREE_TYPE (TREE_TYPE (fndecl));
8875   enum tree_code code;
8876   tree arg0, arg1;
8877   tree type0, type1;
8878   enum tree_code code0, code1;
8879   tree cmp_type = NULL_TREE;
8880 
8881   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
8882     {
8883       /* Check that we have exactly two arguments.  */
8884       if (arglist == 0 || TREE_CHAIN (arglist) == 0)
8885 	{
8886 	  error ("too few arguments to function %qs",
8887 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8888 	  return error_mark_node;
8889 	}
8890       else if (TREE_CHAIN (TREE_CHAIN (arglist)) != 0)
8891 	{
8892 	  error ("too many arguments to function %qs",
8893 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8894 	  return error_mark_node;
8895 	}
8896     }
8897 
8898   arg0 = TREE_VALUE (arglist);
8899   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
8900 
8901   type0 = TREE_TYPE (arg0);
8902   type1 = TREE_TYPE (arg1);
8903 
8904   code0 = TREE_CODE (type0);
8905   code1 = TREE_CODE (type1);
8906 
8907   if (code0 == REAL_TYPE && code1 == REAL_TYPE)
8908     /* Choose the wider of two real types.  */
8909     cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
8910       ? type0 : type1;
8911   else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
8912     cmp_type = type0;
8913   else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
8914     cmp_type = type1;
8915   else
8916     {
8917       error ("non-floating-point argument to function %qs",
8918 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
8919       return error_mark_node;
8920     }
8921 
8922   arg0 = fold_convert (cmp_type, arg0);
8923   arg1 = fold_convert (cmp_type, arg1);
8924 
8925   if (unordered_code == UNORDERED_EXPR)
8926     {
8927       if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
8928 	return omit_two_operands (type, integer_zero_node, arg0, arg1);
8929       return fold_build2 (UNORDERED_EXPR, type, arg0, arg1);
8930     }
8931 
8932   code = HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
8933 						   : ordered_code;
8934   return fold_build1 (TRUTH_NOT_EXPR, type,
8935 		      fold_build2 (code, type, arg0, arg1));
8936 }
8937 
8938 /* Used by constant folding to simplify calls to builtin functions.  EXP is
8939    the CALL_EXPR of a call to a builtin function.  IGNORE is true if the
8940    result of the function call is ignored.  This function returns NULL_TREE
8941    if no simplification was possible.  */
8942 
8943 static tree
fold_builtin_1(tree fndecl,tree arglist,bool ignore)8944 fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
8945 {
8946   tree type = TREE_TYPE (TREE_TYPE (fndecl));
8947   enum built_in_function fcode;
8948 
8949   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
8950     return targetm.fold_builtin (fndecl, arglist, ignore);
8951 
8952   fcode = DECL_FUNCTION_CODE (fndecl);
8953   switch (fcode)
8954     {
8955     case BUILT_IN_FPUTS:
8956       return fold_builtin_fputs (arglist, ignore, false, NULL_TREE);
8957 
8958     case BUILT_IN_FPUTS_UNLOCKED:
8959       return fold_builtin_fputs (arglist, ignore, true, NULL_TREE);
8960 
8961     case BUILT_IN_STRSTR:
8962       return fold_builtin_strstr (arglist, type);
8963 
8964     case BUILT_IN_STRCAT:
8965       return fold_builtin_strcat (arglist);
8966 
8967     case BUILT_IN_STRNCAT:
8968       return fold_builtin_strncat (arglist);
8969 
8970     case BUILT_IN_STRSPN:
8971       return fold_builtin_strspn (arglist);
8972 
8973     case BUILT_IN_STRCSPN:
8974       return fold_builtin_strcspn (arglist);
8975 
8976     case BUILT_IN_STRCHR:
8977     case BUILT_IN_INDEX:
8978       return fold_builtin_strchr (arglist, type);
8979 
8980     case BUILT_IN_STRRCHR:
8981     case BUILT_IN_RINDEX:
8982       return fold_builtin_strrchr (arglist, type);
8983 
8984     case BUILT_IN_STRCPY:
8985       return fold_builtin_strcpy (fndecl, arglist, NULL_TREE);
8986 
8987     case BUILT_IN_STRNCPY:
8988       return fold_builtin_strncpy (fndecl, arglist, NULL_TREE);
8989 
8990     case BUILT_IN_STRCMP:
8991       return fold_builtin_strcmp (arglist);
8992 
8993     case BUILT_IN_STRNCMP:
8994       return fold_builtin_strncmp (arglist);
8995 
8996     case BUILT_IN_STRPBRK:
8997       return fold_builtin_strpbrk (arglist, type);
8998 
8999     case BUILT_IN_BCMP:
9000     case BUILT_IN_MEMCMP:
9001       return fold_builtin_memcmp (arglist);
9002 
9003     case BUILT_IN_SPRINTF:
9004       return fold_builtin_sprintf (arglist, ignore);
9005 
9006     case BUILT_IN_CONSTANT_P:
9007       {
9008 	tree val;
9009 
9010 	val = fold_builtin_constant_p (arglist);
9011 	/* Gimplification will pull the CALL_EXPR for the builtin out of
9012 	   an if condition.  When not optimizing, we'll not CSE it back.
9013 	   To avoid link error types of regressions, return false now.  */
9014 	if (!val && !optimize)
9015 	  val = integer_zero_node;
9016 
9017 	return val;
9018       }
9019 
9020     case BUILT_IN_EXPECT:
9021       return fold_builtin_expect (arglist);
9022 
9023     case BUILT_IN_CLASSIFY_TYPE:
9024       return fold_builtin_classify_type (arglist);
9025 
9026     case BUILT_IN_STRLEN:
9027       return fold_builtin_strlen (arglist);
9028 
9029     CASE_FLT_FN (BUILT_IN_FABS):
9030       return fold_builtin_fabs (arglist, type);
9031 
9032     case BUILT_IN_ABS:
9033     case BUILT_IN_LABS:
9034     case BUILT_IN_LLABS:
9035     case BUILT_IN_IMAXABS:
9036       return fold_builtin_abs (arglist, type);
9037 
9038     CASE_FLT_FN (BUILT_IN_CONJ):
9039       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
9040 	return fold_build1 (CONJ_EXPR, type, TREE_VALUE (arglist));
9041       break;
9042 
9043     CASE_FLT_FN (BUILT_IN_CREAL):
9044       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
9045 	return non_lvalue (fold_build1 (REALPART_EXPR, type,
9046 					TREE_VALUE (arglist)));
9047       break;
9048 
9049     CASE_FLT_FN (BUILT_IN_CIMAG):
9050       if (validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE))
9051 	return non_lvalue (fold_build1 (IMAGPART_EXPR, type,
9052 					TREE_VALUE (arglist)));
9053       break;
9054 
9055     CASE_FLT_FN (BUILT_IN_CABS):
9056       return fold_builtin_cabs (arglist, type, fndecl);
9057 
9058     CASE_FLT_FN (BUILT_IN_SQRT):
9059       return fold_builtin_sqrt (arglist, type);
9060 
9061     CASE_FLT_FN (BUILT_IN_CBRT):
9062       return fold_builtin_cbrt (arglist, type);
9063 
9064     CASE_FLT_FN (BUILT_IN_SIN):
9065       return fold_builtin_sin (arglist);
9066 
9067     CASE_FLT_FN (BUILT_IN_COS):
9068       return fold_builtin_cos (arglist, type, fndecl);
9069 
9070     CASE_FLT_FN (BUILT_IN_EXP):
9071       return fold_builtin_exponent (fndecl, arglist, &dconste);
9072 
9073     CASE_FLT_FN (BUILT_IN_EXP2):
9074       return fold_builtin_exponent (fndecl, arglist, &dconst2);
9075 
9076     CASE_FLT_FN (BUILT_IN_EXP10):
9077     CASE_FLT_FN (BUILT_IN_POW10):
9078       return fold_builtin_exponent (fndecl, arglist, &dconst10);
9079 
9080     CASE_FLT_FN (BUILT_IN_LOG):
9081       return fold_builtin_logarithm (fndecl, arglist, &dconste);
9082 
9083     CASE_FLT_FN (BUILT_IN_LOG2):
9084       return fold_builtin_logarithm (fndecl, arglist, &dconst2);
9085 
9086     CASE_FLT_FN (BUILT_IN_LOG10):
9087       return fold_builtin_logarithm (fndecl, arglist, &dconst10);
9088 
9089     CASE_FLT_FN (BUILT_IN_TAN):
9090       return fold_builtin_tan (arglist);
9091 
9092     CASE_FLT_FN (BUILT_IN_ATAN):
9093       return fold_builtin_atan (arglist, type);
9094 
9095     CASE_FLT_FN (BUILT_IN_POW):
9096       return fold_builtin_pow (fndecl, arglist, type);
9097 
9098     CASE_FLT_FN (BUILT_IN_POWI):
9099       return fold_builtin_powi (fndecl, arglist, type);
9100 
9101     CASE_FLT_FN (BUILT_IN_INF):
9102     case BUILT_IN_INFD32:
9103     case BUILT_IN_INFD64:
9104     case BUILT_IN_INFD128:
9105       return fold_builtin_inf (type, true);
9106 
9107     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
9108       return fold_builtin_inf (type, false);
9109 
9110     CASE_FLT_FN (BUILT_IN_NAN):
9111     case BUILT_IN_NAND32:
9112     case BUILT_IN_NAND64:
9113     case BUILT_IN_NAND128:
9114       return fold_builtin_nan (arglist, type, true);
9115 
9116     CASE_FLT_FN (BUILT_IN_NANS):
9117       return fold_builtin_nan (arglist, type, false);
9118 
9119     CASE_FLT_FN (BUILT_IN_FLOOR):
9120       return fold_builtin_floor (fndecl, arglist);
9121 
9122     CASE_FLT_FN (BUILT_IN_CEIL):
9123       return fold_builtin_ceil (fndecl, arglist);
9124 
9125     CASE_FLT_FN (BUILT_IN_TRUNC):
9126       return fold_builtin_trunc (fndecl, arglist);
9127 
9128     CASE_FLT_FN (BUILT_IN_ROUND):
9129       return fold_builtin_round (fndecl, arglist);
9130 
9131     CASE_FLT_FN (BUILT_IN_NEARBYINT):
9132     CASE_FLT_FN (BUILT_IN_RINT):
9133       return fold_trunc_transparent_mathfn (fndecl, arglist);
9134 
9135     CASE_FLT_FN (BUILT_IN_LCEIL):
9136     CASE_FLT_FN (BUILT_IN_LLCEIL):
9137     CASE_FLT_FN (BUILT_IN_LFLOOR):
9138     CASE_FLT_FN (BUILT_IN_LLFLOOR):
9139     CASE_FLT_FN (BUILT_IN_LROUND):
9140     CASE_FLT_FN (BUILT_IN_LLROUND):
9141       return fold_builtin_int_roundingfn (fndecl, arglist);
9142 
9143     CASE_FLT_FN (BUILT_IN_LRINT):
9144     CASE_FLT_FN (BUILT_IN_LLRINT):
9145       return fold_fixed_mathfn (fndecl, arglist);
9146 
9147     case BUILT_IN_BSWAP32:
9148     case BUILT_IN_BSWAP64:
9149       return fold_builtin_bswap (fndecl, arglist);
9150 
9151     CASE_INT_FN (BUILT_IN_FFS):
9152     CASE_INT_FN (BUILT_IN_CLZ):
9153     CASE_INT_FN (BUILT_IN_CTZ):
9154     CASE_INT_FN (BUILT_IN_POPCOUNT):
9155     CASE_INT_FN (BUILT_IN_PARITY):
9156       return fold_builtin_bitop (fndecl, arglist);
9157 
9158     case BUILT_IN_MEMSET:
9159       return fold_builtin_memset (arglist, type, ignore);
9160 
9161     case BUILT_IN_MEMCPY:
9162       return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/0);
9163 
9164     case BUILT_IN_MEMPCPY:
9165       return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/1);
9166 
9167     case BUILT_IN_MEMMOVE:
9168       return fold_builtin_memory_op (arglist, type, ignore, /*endp=*/3);
9169 
9170     case BUILT_IN_BZERO:
9171       return fold_builtin_bzero (arglist, ignore);
9172 
9173     case BUILT_IN_BCOPY:
9174       return fold_builtin_bcopy (arglist, ignore);
9175 
9176     CASE_FLT_FN (BUILT_IN_SIGNBIT):
9177       return fold_builtin_signbit (fndecl, arglist);
9178 
9179     case BUILT_IN_ISASCII:
9180       return fold_builtin_isascii (arglist);
9181 
9182     case BUILT_IN_TOASCII:
9183       return fold_builtin_toascii (arglist);
9184 
9185     case BUILT_IN_ISDIGIT:
9186       return fold_builtin_isdigit (arglist);
9187 
9188     CASE_FLT_FN (BUILT_IN_COPYSIGN):
9189       return fold_builtin_copysign (fndecl, arglist, type);
9190 
9191     CASE_FLT_FN (BUILT_IN_FINITE):
9192     case BUILT_IN_FINITED32:
9193     case BUILT_IN_FINITED64:
9194     case BUILT_IN_FINITED128:
9195       return fold_builtin_classify (fndecl, arglist, BUILT_IN_FINITE);
9196 
9197     CASE_FLT_FN (BUILT_IN_ISINF):
9198     case BUILT_IN_ISINFD32:
9199     case BUILT_IN_ISINFD64:
9200     case BUILT_IN_ISINFD128:
9201       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISINF);
9202 
9203     CASE_FLT_FN (BUILT_IN_ISNAN):
9204     case BUILT_IN_ISNAND32:
9205     case BUILT_IN_ISNAND64:
9206     case BUILT_IN_ISNAND128:
9207       return fold_builtin_classify (fndecl, arglist, BUILT_IN_ISNAN);
9208 
9209     case BUILT_IN_ISGREATER:
9210       return fold_builtin_unordered_cmp (fndecl, arglist, UNLE_EXPR, LE_EXPR);
9211     case BUILT_IN_ISGREATEREQUAL:
9212       return fold_builtin_unordered_cmp (fndecl, arglist, UNLT_EXPR, LT_EXPR);
9213     case BUILT_IN_ISLESS:
9214       return fold_builtin_unordered_cmp (fndecl, arglist, UNGE_EXPR, GE_EXPR);
9215     case BUILT_IN_ISLESSEQUAL:
9216       return fold_builtin_unordered_cmp (fndecl, arglist, UNGT_EXPR, GT_EXPR);
9217     case BUILT_IN_ISLESSGREATER:
9218       return fold_builtin_unordered_cmp (fndecl, arglist, UNEQ_EXPR, EQ_EXPR);
9219     case BUILT_IN_ISUNORDERED:
9220       return fold_builtin_unordered_cmp (fndecl, arglist, UNORDERED_EXPR,
9221 					 NOP_EXPR);
9222 
9223       /* We do the folding for va_start in the expander.  */
9224     case BUILT_IN_VA_START:
9225       break;
9226 
9227     case BUILT_IN_OBJECT_SIZE:
9228       return fold_builtin_object_size (arglist);
9229     case BUILT_IN_MEMCPY_CHK:
9230     case BUILT_IN_MEMPCPY_CHK:
9231     case BUILT_IN_MEMMOVE_CHK:
9232     case BUILT_IN_MEMSET_CHK:
9233       return fold_builtin_memory_chk (fndecl, arglist, NULL_TREE, ignore,
9234 				      DECL_FUNCTION_CODE (fndecl));
9235     case BUILT_IN_STRCPY_CHK:
9236     case BUILT_IN_STPCPY_CHK:
9237       return fold_builtin_stxcpy_chk (fndecl, arglist, NULL_TREE, ignore,
9238 				      DECL_FUNCTION_CODE (fndecl));
9239     case BUILT_IN_STRNCPY_CHK:
9240       return fold_builtin_strncpy_chk (arglist, NULL_TREE);
9241     case BUILT_IN_STRCAT_CHK:
9242       return fold_builtin_strcat_chk (fndecl, arglist);
9243     case BUILT_IN_STRNCAT_CHK:
9244       return fold_builtin_strncat_chk (fndecl, arglist);
9245     case BUILT_IN_SPRINTF_CHK:
9246     case BUILT_IN_VSPRINTF_CHK:
9247       return fold_builtin_sprintf_chk (arglist, DECL_FUNCTION_CODE (fndecl));
9248     case BUILT_IN_SNPRINTF_CHK:
9249     case BUILT_IN_VSNPRINTF_CHK:
9250       return fold_builtin_snprintf_chk (arglist, NULL_TREE,
9251 					DECL_FUNCTION_CODE (fndecl));
9252 
9253     case BUILT_IN_PRINTF:
9254     case BUILT_IN_PRINTF_UNLOCKED:
9255     case BUILT_IN_VPRINTF:
9256     case BUILT_IN_PRINTF_CHK:
9257     case BUILT_IN_VPRINTF_CHK:
9258       return fold_builtin_printf (fndecl, arglist, ignore,
9259 				  DECL_FUNCTION_CODE (fndecl));
9260 
9261     case BUILT_IN_FPRINTF:
9262     case BUILT_IN_FPRINTF_UNLOCKED:
9263     case BUILT_IN_VFPRINTF:
9264     case BUILT_IN_FPRINTF_CHK:
9265     case BUILT_IN_VFPRINTF_CHK:
9266       return fold_builtin_fprintf (fndecl, arglist, ignore,
9267 				   DECL_FUNCTION_CODE (fndecl));
9268 
9269     default:
9270       break;
9271     }
9272 
9273   return 0;
9274 }
9275 
9276 /* A wrapper function for builtin folding that prevents warnings for
9277    "statement without effect" and the like, caused by removing the
9278    call node earlier than the warning is generated.  */
9279 
9280 tree
fold_builtin(tree fndecl,tree arglist,bool ignore)9281 fold_builtin (tree fndecl, tree arglist, bool ignore)
9282 {
9283   tree exp = fold_builtin_1 (fndecl, arglist, ignore);
9284   if (exp)
9285     {
9286       exp = build1 (NOP_EXPR, TREE_TYPE (exp), exp);
9287       TREE_NO_WARNING (exp) = 1;
9288     }
9289 
9290   return exp;
9291 }
9292 
9293 /* Conveniently construct a function call expression.  */
9294 
9295 tree
build_function_call_expr(tree fn,tree arglist)9296 build_function_call_expr (tree fn, tree arglist)
9297 {
9298   tree call_expr;
9299 
9300   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
9301   return fold_build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
9302 		      call_expr, arglist, NULL_TREE);
9303 }
9304 
9305 /* This function validates the types of a function call argument list
9306    represented as a tree chain of parameters against a specified list
9307    of tree_codes.  If the last specifier is a 0, that represents an
9308    ellipses, otherwise the last specifier must be a VOID_TYPE.  */
9309 
9310 static int
validate_arglist(tree arglist,...)9311 validate_arglist (tree arglist, ...)
9312 {
9313   enum tree_code code;
9314   int res = 0;
9315   va_list ap;
9316 
9317   va_start (ap, arglist);
9318 
9319   do
9320     {
9321       code = va_arg (ap, enum tree_code);
9322       switch (code)
9323 	{
9324 	case 0:
9325 	  /* This signifies an ellipses, any further arguments are all ok.  */
9326 	  res = 1;
9327 	  goto end;
9328 	case VOID_TYPE:
9329 	  /* This signifies an endlink, if no arguments remain, return
9330 	     true, otherwise return false.  */
9331 	  res = arglist == 0;
9332 	  goto end;
9333 	default:
9334 	  /* If no parameters remain or the parameter's code does not
9335 	     match the specified code, return false.  Otherwise continue
9336 	     checking any remaining arguments.  */
9337 	  if (arglist == 0)
9338 	    goto end;
9339 	  if (code == POINTER_TYPE)
9340 	    {
9341 	      if (! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist))))
9342 		goto end;
9343 	    }
9344 	  else if (code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
9345 	    goto end;
9346 	  break;
9347 	}
9348       arglist = TREE_CHAIN (arglist);
9349     }
9350   while (1);
9351 
9352   /* We need gotos here since we can only have one VA_CLOSE in a
9353      function.  */
9354  end: ;
9355   va_end (ap);
9356 
9357   return res;
9358 }
9359 
9360 /* Default target-specific builtin expander that does nothing.  */
9361 
9362 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)9363 default_expand_builtin (tree exp ATTRIBUTE_UNUSED,
9364 			rtx target ATTRIBUTE_UNUSED,
9365 			rtx subtarget ATTRIBUTE_UNUSED,
9366 			enum machine_mode mode ATTRIBUTE_UNUSED,
9367 			int ignore ATTRIBUTE_UNUSED)
9368 {
9369   return NULL_RTX;
9370 }
9371 
9372 /* Returns true is EXP represents data that would potentially reside
9373    in a readonly section.  */
9374 
9375 static bool
readonly_data_expr(tree exp)9376 readonly_data_expr (tree exp)
9377 {
9378   STRIP_NOPS (exp);
9379 
9380   if (TREE_CODE (exp) != ADDR_EXPR)
9381     return false;
9382 
9383   exp = get_base_address (TREE_OPERAND (exp, 0));
9384   if (!exp)
9385     return false;
9386 
9387   /* Make sure we call decl_readonly_section only for trees it
9388      can handle (since it returns true for everything it doesn't
9389      understand).  */
9390   if (TREE_CODE (exp) == STRING_CST
9391       || TREE_CODE (exp) == CONSTRUCTOR
9392       || (TREE_CODE (exp) == VAR_DECL && TREE_STATIC (exp)))
9393     return decl_readonly_section (exp, 0);
9394   else
9395     return false;
9396 }
9397 
9398 /* Simplify a call to the strstr builtin.
9399 
9400    Return 0 if no simplification was possible, otherwise return the
9401    simplified form of the call as a tree.
9402 
9403    The simplified form may be a constant or other expression which
9404    computes the same value, but in a more efficient manner (including
9405    calls to other builtin functions).
9406 
9407    The call may contain arguments which need to be evaluated, but
9408    which are not useful to determine the result of the call.  In
9409    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9410    COMPOUND_EXPR will be an argument which must be evaluated.
9411    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9412    COMPOUND_EXPR in the chain will contain the tree for the simplified
9413    form of the builtin function call.  */
9414 
9415 static tree
fold_builtin_strstr(tree arglist,tree type)9416 fold_builtin_strstr (tree arglist, tree type)
9417 {
9418   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9419     return 0;
9420   else
9421     {
9422       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9423       tree fn;
9424       const char *p1, *p2;
9425 
9426       p2 = c_getstr (s2);
9427       if (p2 == NULL)
9428 	return 0;
9429 
9430       p1 = c_getstr (s1);
9431       if (p1 != NULL)
9432 	{
9433 	  const char *r = strstr (p1, p2);
9434 	  tree tem;
9435 
9436 	  if (r == NULL)
9437 	    return build_int_cst (TREE_TYPE (s1), 0);
9438 
9439 	  /* Return an offset into the constant string argument.  */
9440 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9441 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9442 	  return fold_convert (type, tem);
9443 	}
9444 
9445       /* The argument is const char *, and the result is char *, so we need
9446 	 a type conversion here to avoid a warning.  */
9447       if (p2[0] == '\0')
9448 	return fold_convert (type, s1);
9449 
9450       if (p2[1] != '\0')
9451 	return 0;
9452 
9453       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9454       if (!fn)
9455 	return 0;
9456 
9457       /* New argument list transforming strstr(s1, s2) to
9458 	 strchr(s1, s2[0]).  */
9459       arglist = build_tree_list (NULL_TREE,
9460 				 build_int_cst (NULL_TREE, p2[0]));
9461       arglist = tree_cons (NULL_TREE, s1, arglist);
9462       return build_function_call_expr (fn, arglist);
9463     }
9464 }
9465 
9466 /* Simplify a call to the strchr builtin.
9467 
9468    Return 0 if no simplification was possible, otherwise return the
9469    simplified form of the call as a tree.
9470 
9471    The simplified form may be a constant or other expression which
9472    computes the same value, but in a more efficient manner (including
9473    calls to other builtin functions).
9474 
9475    The call may contain arguments which need to be evaluated, but
9476    which are not useful to determine the result of the call.  In
9477    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9478    COMPOUND_EXPR will be an argument which must be evaluated.
9479    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9480    COMPOUND_EXPR in the chain will contain the tree for the simplified
9481    form of the builtin function call.  */
9482 
9483 static tree
fold_builtin_strchr(tree arglist,tree type)9484 fold_builtin_strchr (tree arglist, tree type)
9485 {
9486   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9487     return 0;
9488   else
9489     {
9490       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9491       const char *p1;
9492 
9493       if (TREE_CODE (s2) != INTEGER_CST)
9494 	return 0;
9495 
9496       p1 = c_getstr (s1);
9497       if (p1 != NULL)
9498 	{
9499 	  char c;
9500 	  const char *r;
9501 	  tree tem;
9502 
9503 	  if (target_char_cast (s2, &c))
9504 	    return 0;
9505 
9506 	  r = strchr (p1, c);
9507 
9508 	  if (r == NULL)
9509 	    return build_int_cst (TREE_TYPE (s1), 0);
9510 
9511 	  /* Return an offset into the constant string argument.  */
9512 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9513 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9514 	  return fold_convert (type, tem);
9515 	}
9516       return 0;
9517     }
9518 }
9519 
9520 /* Simplify a call to the strrchr builtin.
9521 
9522    Return 0 if no simplification was possible, otherwise return the
9523    simplified form of the call as a tree.
9524 
9525    The simplified form may be a constant or other expression which
9526    computes the same value, but in a more efficient manner (including
9527    calls to other builtin functions).
9528 
9529    The call may contain arguments which need to be evaluated, but
9530    which are not useful to determine the result of the call.  In
9531    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9532    COMPOUND_EXPR will be an argument which must be evaluated.
9533    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9534    COMPOUND_EXPR in the chain will contain the tree for the simplified
9535    form of the builtin function call.  */
9536 
9537 static tree
fold_builtin_strrchr(tree arglist,tree type)9538 fold_builtin_strrchr (tree arglist, tree type)
9539 {
9540   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9541     return 0;
9542   else
9543     {
9544       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9545       tree fn;
9546       const char *p1;
9547 
9548       if (TREE_CODE (s2) != INTEGER_CST)
9549 	return 0;
9550 
9551       p1 = c_getstr (s1);
9552       if (p1 != NULL)
9553 	{
9554 	  char c;
9555 	  const char *r;
9556 	  tree tem;
9557 
9558 	  if (target_char_cast (s2, &c))
9559 	    return 0;
9560 
9561 	  r = strrchr (p1, c);
9562 
9563 	  if (r == NULL)
9564 	    return build_int_cst (TREE_TYPE (s1), 0);
9565 
9566 	  /* Return an offset into the constant string argument.  */
9567 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9568 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9569 	  return fold_convert (type, tem);
9570 	}
9571 
9572       if (! integer_zerop (s2))
9573 	return 0;
9574 
9575       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9576       if (!fn)
9577 	return 0;
9578 
9579       /* Transform strrchr(s1, '\0') to strchr(s1, '\0').  */
9580       return build_function_call_expr (fn, arglist);
9581     }
9582 }
9583 
9584 /* Simplify a call to the strpbrk builtin.
9585 
9586    Return 0 if no simplification was possible, otherwise return the
9587    simplified form of the call as a tree.
9588 
9589    The simplified form may be a constant or other expression which
9590    computes the same value, but in a more efficient manner (including
9591    calls to other builtin functions).
9592 
9593    The call may contain arguments which need to be evaluated, but
9594    which are not useful to determine the result of the call.  In
9595    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9596    COMPOUND_EXPR will be an argument which must be evaluated.
9597    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9598    COMPOUND_EXPR in the chain will contain the tree for the simplified
9599    form of the builtin function call.  */
9600 
9601 static tree
fold_builtin_strpbrk(tree arglist,tree type)9602 fold_builtin_strpbrk (tree arglist, tree type)
9603 {
9604   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9605     return 0;
9606   else
9607     {
9608       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9609       tree fn;
9610       const char *p1, *p2;
9611 
9612       p2 = c_getstr (s2);
9613       if (p2 == NULL)
9614 	return 0;
9615 
9616       p1 = c_getstr (s1);
9617       if (p1 != NULL)
9618 	{
9619 	  const char *r = strpbrk (p1, p2);
9620 	  tree tem;
9621 
9622 	  if (r == NULL)
9623 	    return build_int_cst (TREE_TYPE (s1), 0);
9624 
9625 	  /* Return an offset into the constant string argument.  */
9626 	  tem = fold_build2 (PLUS_EXPR, TREE_TYPE (s1),
9627 			     s1, build_int_cst (TREE_TYPE (s1), r - p1));
9628 	  return fold_convert (type, tem);
9629 	}
9630 
9631       if (p2[0] == '\0')
9632 	/* strpbrk(x, "") == NULL.
9633 	   Evaluate and ignore s1 in case it had side-effects.  */
9634 	return omit_one_operand (TREE_TYPE (s1), integer_zero_node, s1);
9635 
9636       if (p2[1] != '\0')
9637 	return 0;  /* Really call strpbrk.  */
9638 
9639       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
9640       if (!fn)
9641 	return 0;
9642 
9643       /* New argument list transforming strpbrk(s1, s2) to
9644 	 strchr(s1, s2[0]).  */
9645       arglist = build_tree_list (NULL_TREE,
9646 				 build_int_cst (NULL_TREE, p2[0]));
9647       arglist = tree_cons (NULL_TREE, s1, arglist);
9648       return build_function_call_expr (fn, arglist);
9649     }
9650 }
9651 
9652 /* Simplify a call to the strcat builtin.
9653 
9654    Return 0 if no simplification was possible, otherwise return the
9655    simplified form of the call as a tree.
9656 
9657    The simplified form may be a constant or other expression which
9658    computes the same value, but in a more efficient manner (including
9659    calls to other builtin functions).
9660 
9661    The call may contain arguments which need to be evaluated, but
9662    which are not useful to determine the result of the call.  In
9663    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9664    COMPOUND_EXPR will be an argument which must be evaluated.
9665    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9666    COMPOUND_EXPR in the chain will contain the tree for the simplified
9667    form of the builtin function call.  */
9668 
9669 static tree
fold_builtin_strcat(tree arglist)9670 fold_builtin_strcat (tree arglist)
9671 {
9672   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9673     return 0;
9674   else
9675     {
9676       tree dst = TREE_VALUE (arglist),
9677 	src = TREE_VALUE (TREE_CHAIN (arglist));
9678       const char *p = c_getstr (src);
9679 
9680       /* If the string length is zero, return the dst parameter.  */
9681       if (p && *p == '\0')
9682 	return dst;
9683 
9684       return 0;
9685     }
9686 }
9687 
9688 /* Simplify a call to the strncat builtin.
9689 
9690    Return 0 if no simplification was possible, otherwise return the
9691    simplified form of the call as a tree.
9692 
9693    The simplified form may be a constant or other expression which
9694    computes the same value, but in a more efficient manner (including
9695    calls to other builtin functions).
9696 
9697    The call may contain arguments which need to be evaluated, but
9698    which are not useful to determine the result of the call.  In
9699    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9700    COMPOUND_EXPR will be an argument which must be evaluated.
9701    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9702    COMPOUND_EXPR in the chain will contain the tree for the simplified
9703    form of the builtin function call.  */
9704 
9705 static tree
fold_builtin_strncat(tree arglist)9706 fold_builtin_strncat (tree arglist)
9707 {
9708   if (!validate_arglist (arglist,
9709 			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
9710     return 0;
9711   else
9712     {
9713       tree dst = TREE_VALUE (arglist);
9714       tree src = TREE_VALUE (TREE_CHAIN (arglist));
9715       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
9716       const char *p = c_getstr (src);
9717 
9718       /* If the requested length is zero, or the src parameter string
9719 	 length is zero, return the dst parameter.  */
9720       if (integer_zerop (len) || (p && *p == '\0'))
9721 	return omit_two_operands (TREE_TYPE (dst), dst, src, len);
9722 
9723       /* If the requested len is greater than or equal to the string
9724 	 length, call strcat.  */
9725       if (TREE_CODE (len) == INTEGER_CST && p
9726 	  && compare_tree_int (len, strlen (p)) >= 0)
9727 	{
9728 	  tree newarglist
9729 	    = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
9730 	  tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
9731 
9732 	  /* If the replacement _DECL isn't initialized, don't do the
9733 	     transformation.  */
9734 	  if (!fn)
9735 	    return 0;
9736 
9737 	  return build_function_call_expr (fn, newarglist);
9738 	}
9739       return 0;
9740     }
9741 }
9742 
9743 /* Simplify a call to the strspn builtin.
9744 
9745    Return 0 if no simplification was possible, otherwise return the
9746    simplified form of the call as a tree.
9747 
9748    The simplified form may be a constant or other expression which
9749    computes the same value, but in a more efficient manner (including
9750    calls to other builtin functions).
9751 
9752    The call may contain arguments which need to be evaluated, but
9753    which are not useful to determine the result of the call.  In
9754    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9755    COMPOUND_EXPR will be an argument which must be evaluated.
9756    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9757    COMPOUND_EXPR in the chain will contain the tree for the simplified
9758    form of the builtin function call.  */
9759 
9760 static tree
fold_builtin_strspn(tree arglist)9761 fold_builtin_strspn (tree arglist)
9762 {
9763   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9764     return 0;
9765   else
9766     {
9767       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9768       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
9769 
9770       /* If both arguments are constants, evaluate at compile-time.  */
9771       if (p1 && p2)
9772 	{
9773 	  const size_t r = strspn (p1, p2);
9774 	  return size_int (r);
9775 	}
9776 
9777       /* If either argument is "", return 0.  */
9778       if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9779 	/* Evaluate and ignore both arguments in case either one has
9780 	   side-effects.  */
9781 	return omit_two_operands (integer_type_node, integer_zero_node,
9782 				  s1, s2);
9783       return 0;
9784     }
9785 }
9786 
9787 /* Simplify a call to the strcspn builtin.
9788 
9789    Return 0 if no simplification was possible, otherwise return the
9790    simplified form of the call as a tree.
9791 
9792    The simplified form may be a constant or other expression which
9793    computes the same value, but in a more efficient manner (including
9794    calls to other builtin functions).
9795 
9796    The call may contain arguments which need to be evaluated, but
9797    which are not useful to determine the result of the call.  In
9798    this case we return a chain of COMPOUND_EXPRs.  The LHS of each
9799    COMPOUND_EXPR will be an argument which must be evaluated.
9800    COMPOUND_EXPRs are chained through their RHS.  The RHS of the last
9801    COMPOUND_EXPR in the chain will contain the tree for the simplified
9802    form of the builtin function call.  */
9803 
9804 static tree
fold_builtin_strcspn(tree arglist)9805 fold_builtin_strcspn (tree arglist)
9806 {
9807   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9808     return 0;
9809   else
9810     {
9811       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
9812       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
9813 
9814       /* If both arguments are constants, evaluate at compile-time.  */
9815       if (p1 && p2)
9816 	{
9817 	  const size_t r = strcspn (p1, p2);
9818 	  return size_int (r);
9819 	}
9820 
9821       /* If the first argument is "", return 0.  */
9822       if (p1 && *p1 == '\0')
9823 	{
9824 	  /* Evaluate and ignore argument s2 in case it has
9825 	     side-effects.  */
9826 	  return omit_one_operand (integer_type_node,
9827 				   integer_zero_node, s2);
9828 	}
9829 
9830       /* If the second argument is "", return __builtin_strlen(s1).  */
9831       if (p2 && *p2 == '\0')
9832 	{
9833 	  tree newarglist = build_tree_list (NULL_TREE, s1),
9834 	    fn = implicit_built_in_decls[BUILT_IN_STRLEN];
9835 
9836 	  /* If the replacement _DECL isn't initialized, don't do the
9837 	     transformation.  */
9838 	  if (!fn)
9839 	    return 0;
9840 
9841 	  return build_function_call_expr (fn, newarglist);
9842 	}
9843       return 0;
9844     }
9845 }
9846 
9847 /* Fold a call to the fputs builtin.  IGNORE is true if the value returned
9848    by the builtin will be ignored.  UNLOCKED is true is true if this
9849    actually a call to fputs_unlocked.  If LEN in non-NULL, it represents
9850    the known length of the string.  Return NULL_TREE if no simplification
9851    was possible.  */
9852 
9853 tree
fold_builtin_fputs(tree arglist,bool ignore,bool unlocked,tree len)9854 fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
9855 {
9856   tree fn;
9857   /* If we're using an unlocked function, assume the other unlocked
9858      functions exist explicitly.  */
9859   tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
9860     : implicit_built_in_decls[BUILT_IN_FPUTC];
9861   tree const fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
9862     : implicit_built_in_decls[BUILT_IN_FWRITE];
9863 
9864   /* If the return value is used, don't do the transformation.  */
9865   if (!ignore)
9866     return 0;
9867 
9868   /* Verify the arguments in the original call.  */
9869   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
9870     return 0;
9871 
9872   if (! len)
9873     len = c_strlen (TREE_VALUE (arglist), 0);
9874 
9875   /* Get the length of the string passed to fputs.  If the length
9876      can't be determined, punt.  */
9877   if (!len
9878       || TREE_CODE (len) != INTEGER_CST)
9879     return 0;
9880 
9881   switch (compare_tree_int (len, 1))
9882     {
9883     case -1: /* length is 0, delete the call entirely .  */
9884       return omit_one_operand (integer_type_node, integer_zero_node,
9885 			       TREE_VALUE (TREE_CHAIN (arglist)));
9886 
9887     case 0: /* length is 1, call fputc.  */
9888       {
9889 	const char *p = c_getstr (TREE_VALUE (arglist));
9890 
9891 	if (p != NULL)
9892 	  {
9893 	    /* New argument list transforming fputs(string, stream) to
9894 	       fputc(string[0], stream).  */
9895 	    arglist = build_tree_list (NULL_TREE,
9896 				       TREE_VALUE (TREE_CHAIN (arglist)));
9897 	    arglist = tree_cons (NULL_TREE,
9898 				 build_int_cst (NULL_TREE, p[0]),
9899 				 arglist);
9900 	    fn = fn_fputc;
9901 	    break;
9902 	  }
9903       }
9904       /* FALLTHROUGH */
9905     case 1: /* length is greater than 1, call fwrite.  */
9906       {
9907 	tree string_arg;
9908 
9909 	/* If optimizing for size keep fputs.  */
9910 	if (optimize_size)
9911 	  return 0;
9912 	string_arg = TREE_VALUE (arglist);
9913 	/* New argument list transforming fputs(string, stream) to
9914 	   fwrite(string, 1, len, stream).  */
9915 	arglist = build_tree_list (NULL_TREE,
9916 				   TREE_VALUE (TREE_CHAIN (arglist)));
9917 	arglist = tree_cons (NULL_TREE, len, arglist);
9918 	arglist = tree_cons (NULL_TREE, size_one_node, arglist);
9919 	arglist = tree_cons (NULL_TREE, string_arg, arglist);
9920 	fn = fn_fwrite;
9921 	break;
9922       }
9923     default:
9924       gcc_unreachable ();
9925     }
9926 
9927   /* If the replacement _DECL isn't initialized, don't do the
9928      transformation.  */
9929   if (!fn)
9930     return 0;
9931 
9932   /* These optimizations are only performed when the result is ignored,
9933      hence there's no need to cast the result to integer_type_node.  */
9934   return build_function_call_expr (fn, arglist);
9935 }
9936 
9937 /* Fold the new_arg's arguments (ARGLIST). Returns true if there was an error
9938    produced.  False otherwise.  This is done so that we don't output the error
9939    or warning twice or three times.  */
9940 bool
fold_builtin_next_arg(tree arglist)9941 fold_builtin_next_arg (tree arglist)
9942 {
9943   tree fntype = TREE_TYPE (current_function_decl);
9944 
9945   if (TYPE_ARG_TYPES (fntype) == 0
9946       || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
9947 	  == void_type_node))
9948     {
9949       error ("%<va_start%> used in function with fixed args");
9950       return true;
9951     }
9952   else if (!arglist)
9953     {
9954       /* Evidently an out of date version of <stdarg.h>; can't validate
9955 	 va_start's second argument, but can still work as intended.  */
9956       warning (0, "%<__builtin_next_arg%> called without an argument");
9957       return true;
9958     }
9959   /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0)
9960      when we checked the arguments and if needed issued a warning.  */
9961   else if (!TREE_CHAIN (arglist)
9962 	   || !integer_zerop (TREE_VALUE (arglist))
9963 	   || !integer_zerop (TREE_VALUE (TREE_CHAIN (arglist)))
9964 	   || TREE_CHAIN (TREE_CHAIN (arglist)))
9965     {
9966       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
9967       tree arg = TREE_VALUE (arglist);
9968 
9969       if (TREE_CHAIN (arglist))
9970 	{
9971 	  error ("%<va_start%> used with too many arguments");
9972 	  return true;
9973 	}
9974 
9975       /* Strip off all nops for the sake of the comparison.  This
9976 	 is not quite the same as STRIP_NOPS.  It does more.
9977 	 We must also strip off INDIRECT_EXPR for C++ reference
9978 	 parameters.  */
9979       while (TREE_CODE (arg) == NOP_EXPR
9980 	     || TREE_CODE (arg) == CONVERT_EXPR
9981 	     || TREE_CODE (arg) == NON_LVALUE_EXPR
9982 	     || TREE_CODE (arg) == INDIRECT_REF)
9983 	arg = TREE_OPERAND (arg, 0);
9984       if (arg != last_parm)
9985 	{
9986 	  /* FIXME: Sometimes with the tree optimizers we can get the
9987 	     not the last argument even though the user used the last
9988 	     argument.  We just warn and set the arg to be the last
9989 	     argument so that we will get wrong-code because of
9990 	     it.  */
9991 	  warning (0, "second parameter of %<va_start%> not last named argument");
9992 	}
9993       /* We want to verify the second parameter just once before the tree
9994 	 optimizers are run and then avoid keeping it in the tree,
9995 	 as otherwise we could warn even for correct code like:
9996 	 void foo (int i, ...)
9997 	 { va_list ap; i++; va_start (ap, i); va_end (ap); }  */
9998       TREE_VALUE (arglist) = integer_zero_node;
9999       TREE_CHAIN (arglist) = build_tree_list (NULL, integer_zero_node);
10000     }
10001   return false;
10002 }
10003 
10004 
10005 /* Simplify a call to the sprintf builtin.
10006 
10007    Return 0 if no simplification was possible, otherwise return the
10008    simplified form of the call as a tree.  If IGNORED is true, it means that
10009    the caller does not use the returned value of the function.  */
10010 
10011 static tree
fold_builtin_sprintf(tree arglist,int ignored)10012 fold_builtin_sprintf (tree arglist, int ignored)
10013 {
10014   tree call, retval, dest, fmt;
10015   const char *fmt_str = NULL;
10016 
10017   /* Verify the required arguments in the original call.  We deal with two
10018      types of sprintf() calls: 'sprintf (str, fmt)' and
10019      'sprintf (dest, "%s", orig)'.  */
10020   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
10021       && !validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE,
10022 			    VOID_TYPE))
10023     return NULL_TREE;
10024 
10025   /* Get the destination string and the format specifier.  */
10026   dest = TREE_VALUE (arglist);
10027   fmt = TREE_VALUE (TREE_CHAIN (arglist));
10028   arglist = TREE_CHAIN (TREE_CHAIN (arglist));
10029 
10030   /* Check whether the format is a literal string constant.  */
10031   fmt_str = c_getstr (fmt);
10032   if (fmt_str == NULL)
10033     return NULL_TREE;
10034 
10035   call = NULL_TREE;
10036   retval = NULL_TREE;
10037 
10038   if (!init_target_chars())
10039     return 0;
10040 
10041   /* If the format doesn't contain % args or %%, use strcpy.  */
10042   if (strchr (fmt_str, target_percent) == NULL)
10043     {
10044       tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
10045 
10046       if (!fn)
10047 	return NULL_TREE;
10048 
10049       /* Don't optimize sprintf (buf, "abc", ptr++).  */
10050       if (arglist)
10051 	return NULL_TREE;
10052 
10053       /* Convert sprintf (str, fmt) into strcpy (str, fmt) when
10054 	 'format' is known to contain no % formats.  */
10055       arglist = build_tree_list (NULL_TREE, fmt);
10056       arglist = tree_cons (NULL_TREE, dest, arglist);
10057       call = build_function_call_expr (fn, arglist);
10058       if (!ignored)
10059 	retval = build_int_cst (NULL_TREE, strlen (fmt_str));
10060     }
10061 
10062   /* If the format is "%s", use strcpy if the result isn't used.  */
10063   else if (fmt_str && strcmp (fmt_str, target_percent_s) == 0)
10064     {
10065       tree fn, orig;
10066       fn = implicit_built_in_decls[BUILT_IN_STRCPY];
10067 
10068       if (!fn)
10069 	return NULL_TREE;
10070 
10071       /* Don't crash on sprintf (str1, "%s").  */
10072       if (!arglist)
10073 	return NULL_TREE;
10074 
10075       /* Convert sprintf (str1, "%s", str2) into strcpy (str1, str2).  */
10076       orig = TREE_VALUE (arglist);
10077       arglist = build_tree_list (NULL_TREE, orig);
10078       arglist = tree_cons (NULL_TREE, dest, arglist);
10079       if (!ignored)
10080 	{
10081 	  retval = c_strlen (orig, 1);
10082 	  if (!retval || TREE_CODE (retval) != INTEGER_CST)
10083 	    return NULL_TREE;
10084 	}
10085       call = build_function_call_expr (fn, arglist);
10086     }
10087 
10088   if (call && retval)
10089     {
10090       retval = fold_convert
10091 	(TREE_TYPE (TREE_TYPE (implicit_built_in_decls[BUILT_IN_SPRINTF])),
10092 	 retval);
10093       return build2 (COMPOUND_EXPR, TREE_TYPE (retval), call, retval);
10094     }
10095   else
10096     return call;
10097 }
10098 
10099 /* Expand a call to __builtin_object_size.  */
10100 
10101 rtx
expand_builtin_object_size(tree exp)10102 expand_builtin_object_size (tree exp)
10103 {
10104   tree ost;
10105   int object_size_type;
10106   tree fndecl = get_callee_fndecl (exp);
10107   tree arglist = TREE_OPERAND (exp, 1);
10108   location_t locus = EXPR_LOCATION (exp);
10109 
10110   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
10111     {
10112       error ("%Hfirst argument of %D must be a pointer, second integer constant",
10113 	     &locus, fndecl);
10114       expand_builtin_trap ();
10115       return const0_rtx;
10116     }
10117 
10118   ost = TREE_VALUE (TREE_CHAIN (arglist));
10119   STRIP_NOPS (ost);
10120 
10121   if (TREE_CODE (ost) != INTEGER_CST
10122       || tree_int_cst_sgn (ost) < 0
10123       || compare_tree_int (ost, 3) > 0)
10124     {
10125       error ("%Hlast argument of %D is not integer constant between 0 and 3",
10126 	     &locus, fndecl);
10127       expand_builtin_trap ();
10128       return const0_rtx;
10129     }
10130 
10131   object_size_type = tree_low_cst (ost, 0);
10132 
10133   return object_size_type < 2 ? constm1_rtx : const0_rtx;
10134 }
10135 
10136 /* Expand EXP, a call to the __mem{cpy,pcpy,move,set}_chk builtin.
10137    FCODE is the BUILT_IN_* to use.
10138    Return 0 if we failed; the caller should emit a normal call,
10139    otherwise try to get the result in TARGET, if convenient (and in
10140    mode MODE if that's convenient).  */
10141 
10142 static rtx
expand_builtin_memory_chk(tree exp,rtx target,enum machine_mode mode,enum built_in_function fcode)10143 expand_builtin_memory_chk (tree exp, rtx target, enum machine_mode mode,
10144 			   enum built_in_function fcode)
10145 {
10146   tree arglist = TREE_OPERAND (exp, 1);
10147   tree dest, src, len, size;
10148 
10149   if (!validate_arglist (arglist,
10150 			 POINTER_TYPE,
10151 			 fcode == BUILT_IN_MEMSET_CHK
10152 			 ? INTEGER_TYPE : POINTER_TYPE,
10153 			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
10154     return 0;
10155 
10156   dest = TREE_VALUE (arglist);
10157   src = TREE_VALUE (TREE_CHAIN (arglist));
10158   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10159   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10160 
10161   if (! host_integerp (size, 1))
10162     return 0;
10163 
10164   if (host_integerp (len, 1) || integer_all_onesp (size))
10165     {
10166       tree fn;
10167 
10168       if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
10169 	{
10170 	  location_t locus = EXPR_LOCATION (exp);
10171 	  warning (0, "%Hcall to %D will always overflow destination buffer",
10172 		   &locus, get_callee_fndecl (exp));
10173 	  return 0;
10174 	}
10175 
10176       arglist = build_tree_list (NULL_TREE, len);
10177       arglist = tree_cons (NULL_TREE, src, arglist);
10178       arglist = tree_cons (NULL_TREE, dest, arglist);
10179 
10180       fn = NULL_TREE;
10181       /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
10182 	 mem{cpy,pcpy,move,set} is available.  */
10183       switch (fcode)
10184 	{
10185 	case BUILT_IN_MEMCPY_CHK:
10186 	  fn = built_in_decls[BUILT_IN_MEMCPY];
10187 	  break;
10188 	case BUILT_IN_MEMPCPY_CHK:
10189 	  fn = built_in_decls[BUILT_IN_MEMPCPY];
10190 	  break;
10191 	case BUILT_IN_MEMMOVE_CHK:
10192 	  fn = built_in_decls[BUILT_IN_MEMMOVE];
10193 	  break;
10194 	case BUILT_IN_MEMSET_CHK:
10195 	  fn = built_in_decls[BUILT_IN_MEMSET];
10196 	  break;
10197 	default:
10198 	  break;
10199 	}
10200 
10201       if (! fn)
10202 	return 0;
10203 
10204       fn = build_function_call_expr (fn, arglist);
10205       if (TREE_CODE (fn) == CALL_EXPR)
10206 	CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10207       return expand_expr (fn, target, mode, EXPAND_NORMAL);
10208     }
10209   else if (fcode == BUILT_IN_MEMSET_CHK)
10210     return 0;
10211   else
10212     {
10213       unsigned int dest_align
10214 	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
10215 
10216       /* If DEST is not a pointer type, call the normal function.  */
10217       if (dest_align == 0)
10218 	return 0;
10219 
10220       /* If SRC and DEST are the same (and not volatile), do nothing.  */
10221       if (operand_equal_p (src, dest, 0))
10222 	{
10223 	  tree expr;
10224 
10225 	  if (fcode != BUILT_IN_MEMPCPY_CHK)
10226 	    {
10227 	      /* Evaluate and ignore LEN in case it has side-effects.  */
10228 	      expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
10229 	      return expand_expr (dest, target, mode, EXPAND_NORMAL);
10230 	    }
10231 
10232 	  len = fold_convert (TREE_TYPE (dest), len);
10233 	  expr = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len);
10234 	  return expand_expr (expr, target, mode, EXPAND_NORMAL);
10235 	}
10236 
10237       /* __memmove_chk special case.  */
10238       if (fcode == BUILT_IN_MEMMOVE_CHK)
10239 	{
10240 	  unsigned int src_align
10241 	    = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
10242 
10243 	  if (src_align == 0)
10244 	    return 0;
10245 
10246 	  /* If src is categorized for a readonly section we can use
10247 	     normal __memcpy_chk.  */
10248 	  if (readonly_data_expr (src))
10249 	    {
10250 	      tree fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10251 	      if (!fn)
10252 		return 0;
10253 	      fn = build_function_call_expr (fn, arglist);
10254 	      if (TREE_CODE (fn) == CALL_EXPR)
10255 		CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
10256 	      return expand_expr (fn, target, mode, EXPAND_NORMAL);
10257 	    }
10258 	}
10259       return 0;
10260     }
10261 }
10262 
10263 /* Emit warning if a buffer overflow is detected at compile time.  */
10264 
10265 static void
maybe_emit_chk_warning(tree exp,enum built_in_function fcode)10266 maybe_emit_chk_warning (tree exp, enum built_in_function fcode)
10267 {
10268   int arg_mask, is_strlen = 0;
10269   tree arglist = TREE_OPERAND (exp, 1), a;
10270   tree len, size;
10271   location_t locus;
10272 
10273   switch (fcode)
10274     {
10275     case BUILT_IN_STRCPY_CHK:
10276     case BUILT_IN_STPCPY_CHK:
10277     /* For __strcat_chk the warning will be emitted only if overflowing
10278        by at least strlen (dest) + 1 bytes.  */
10279     case BUILT_IN_STRCAT_CHK:
10280       arg_mask = 6;
10281       is_strlen = 1;
10282       break;
10283     case BUILT_IN_STRNCPY_CHK:
10284       arg_mask = 12;
10285       break;
10286     case BUILT_IN_SNPRINTF_CHK:
10287     case BUILT_IN_VSNPRINTF_CHK:
10288       arg_mask = 10;
10289       break;
10290     default:
10291       gcc_unreachable ();
10292     }
10293 
10294   len = NULL_TREE;
10295   size = NULL_TREE;
10296   for (a = arglist; a && arg_mask; a = TREE_CHAIN (a), arg_mask >>= 1)
10297     if (arg_mask & 1)
10298       {
10299 	if (len)
10300 	  size = a;
10301 	else
10302 	  len = a;
10303       }
10304 
10305   if (!len || !size)
10306     return;
10307 
10308   len = TREE_VALUE (len);
10309   size = TREE_VALUE (size);
10310 
10311   if (! host_integerp (size, 1) || integer_all_onesp (size))
10312     return;
10313 
10314   if (is_strlen)
10315     {
10316       len = c_strlen (len, 1);
10317       if (! len || ! host_integerp (len, 1) || tree_int_cst_lt (len, size))
10318 	return;
10319     }
10320   else if (! host_integerp (len, 1) || ! tree_int_cst_lt (size, len))
10321     return;
10322 
10323   locus = EXPR_LOCATION (exp);
10324   warning (0, "%Hcall to %D will always overflow destination buffer",
10325 	   &locus, get_callee_fndecl (exp));
10326 }
10327 
10328 /* Emit warning if a buffer overflow is detected at compile time
10329    in __sprintf_chk/__vsprintf_chk calls.  */
10330 
10331 static void
maybe_emit_sprintf_chk_warning(tree exp,enum built_in_function fcode)10332 maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode)
10333 {
10334   tree arglist = TREE_OPERAND (exp, 1);
10335   tree dest, size, len, fmt, flag;
10336   const char *fmt_str;
10337 
10338   /* Verify the required arguments in the original call.  */
10339   if (! arglist)
10340     return;
10341   dest = TREE_VALUE (arglist);
10342   arglist = TREE_CHAIN (arglist);
10343   if (! arglist)
10344     return;
10345   flag = TREE_VALUE (arglist);
10346   arglist = TREE_CHAIN (arglist);
10347   if (! arglist)
10348     return;
10349   size = TREE_VALUE (arglist);
10350   arglist = TREE_CHAIN (arglist);
10351   if (! arglist)
10352     return;
10353   fmt = TREE_VALUE (arglist);
10354   arglist = TREE_CHAIN (arglist);
10355 
10356   if (! host_integerp (size, 1) || integer_all_onesp (size))
10357     return;
10358 
10359   /* Check whether the format is a literal string constant.  */
10360   fmt_str = c_getstr (fmt);
10361   if (fmt_str == NULL)
10362     return;
10363 
10364   if (!init_target_chars())
10365     return;
10366 
10367   /* If the format doesn't contain % args or %%, we know its size.  */
10368   if (strchr (fmt_str, target_percent) == 0)
10369     len = build_int_cstu (size_type_node, strlen (fmt_str));
10370   /* If the format is "%s" and first ... argument is a string literal,
10371      we know it too.  */
10372   else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
10373     {
10374       tree arg;
10375 
10376       if (! arglist)
10377 	return;
10378       arg = TREE_VALUE (arglist);
10379       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
10380 	return;
10381 
10382       len = c_strlen (arg, 1);
10383       if (!len || ! host_integerp (len, 1))
10384 	return;
10385     }
10386   else
10387     return;
10388 
10389   if (! tree_int_cst_lt (len, size))
10390     {
10391       location_t locus = EXPR_LOCATION (exp);
10392       warning (0, "%Hcall to %D will always overflow destination buffer",
10393 	       &locus, get_callee_fndecl (exp));
10394     }
10395 }
10396 
10397 /* Fold a call to __builtin_object_size, if possible.  */
10398 
10399 tree
fold_builtin_object_size(tree arglist)10400 fold_builtin_object_size (tree arglist)
10401 {
10402   tree ptr, ost, ret = 0;
10403   int object_size_type;
10404 
10405   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
10406     return 0;
10407 
10408   ptr = TREE_VALUE (arglist);
10409   ost = TREE_VALUE (TREE_CHAIN (arglist));
10410   STRIP_NOPS (ost);
10411 
10412   if (TREE_CODE (ost) != INTEGER_CST
10413       || tree_int_cst_sgn (ost) < 0
10414       || compare_tree_int (ost, 3) > 0)
10415     return 0;
10416 
10417   object_size_type = tree_low_cst (ost, 0);
10418 
10419   /* __builtin_object_size doesn't evaluate side-effects in its arguments;
10420      if there are any side-effects, it returns (size_t) -1 for types 0 and 1
10421      and (size_t) 0 for types 2 and 3.  */
10422   if (TREE_SIDE_EFFECTS (ptr))
10423     return fold_convert (size_type_node,
10424 			 object_size_type < 2
10425 			 ? integer_minus_one_node : integer_zero_node);
10426 
10427   if (TREE_CODE (ptr) == ADDR_EXPR)
10428     ret = build_int_cstu (size_type_node,
10429 			compute_builtin_object_size (ptr, object_size_type));
10430 
10431   else if (TREE_CODE (ptr) == SSA_NAME)
10432     {
10433       unsigned HOST_WIDE_INT bytes;
10434 
10435       /* If object size is not known yet, delay folding until
10436        later.  Maybe subsequent passes will help determining
10437        it.  */
10438       bytes = compute_builtin_object_size (ptr, object_size_type);
10439       if (bytes != (unsigned HOST_WIDE_INT) (object_size_type < 2
10440 					     ? -1 : 0))
10441 	ret = build_int_cstu (size_type_node, bytes);
10442     }
10443 
10444   if (ret)
10445     {
10446       ret = force_fit_type (ret, -1, false, false);
10447       if (TREE_CONSTANT_OVERFLOW (ret))
10448 	ret = 0;
10449     }
10450 
10451   return ret;
10452 }
10453 
10454 /* Fold a call to the __mem{cpy,pcpy,move,set}_chk builtin.
10455    IGNORE is true, if return value can be ignored.  FCODE is the BUILT_IN_*
10456    code of the builtin.  If MAXLEN is not NULL, it is maximum length
10457    passed as third argument.  */
10458 
10459 tree
fold_builtin_memory_chk(tree fndecl,tree arglist,tree maxlen,bool ignore,enum built_in_function fcode)10460 fold_builtin_memory_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
10461 			 enum built_in_function fcode)
10462 {
10463   tree dest, src, len, size, fn;
10464 
10465   if (!validate_arglist (arglist,
10466 			 POINTER_TYPE,
10467 			 fcode == BUILT_IN_MEMSET_CHK
10468 			 ? INTEGER_TYPE : POINTER_TYPE,
10469 			 INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
10470     return 0;
10471 
10472   dest = TREE_VALUE (arglist);
10473   /* Actually val for __memset_chk, but it doesn't matter.  */
10474   src = TREE_VALUE (TREE_CHAIN (arglist));
10475   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10476   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10477 
10478   /* If SRC and DEST are the same (and not volatile), return DEST
10479      (resp. DEST+LEN for __mempcpy_chk).  */
10480   if (fcode != BUILT_IN_MEMSET_CHK && operand_equal_p (src, dest, 0))
10481     {
10482       if (fcode != BUILT_IN_MEMPCPY_CHK)
10483 	return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
10484       else
10485 	{
10486 	  tree temp = fold_convert (TREE_TYPE (dest), len);
10487 	  temp = fold_build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp);
10488 	  return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), temp);
10489 	}
10490     }
10491 
10492   if (! host_integerp (size, 1))
10493     return 0;
10494 
10495   if (! integer_all_onesp (size))
10496     {
10497       if (! host_integerp (len, 1))
10498 	{
10499 	  /* If LEN is not constant, try MAXLEN too.
10500 	     For MAXLEN only allow optimizing into non-_ocs function
10501 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10502 	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10503 	    {
10504 	      if (fcode == BUILT_IN_MEMPCPY_CHK && ignore)
10505 		{
10506 		  /* (void) __mempcpy_chk () can be optimized into
10507 		     (void) __memcpy_chk ().  */
10508 		  fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10509 		  if (!fn)
10510 		    return 0;
10511 
10512 		  return build_function_call_expr (fn, arglist);
10513 		}
10514 	      return 0;
10515 	    }
10516 	}
10517       else
10518 	maxlen = len;
10519 
10520       if (tree_int_cst_lt (size, maxlen))
10521 	return 0;
10522     }
10523 
10524   arglist = build_tree_list (NULL_TREE, len);
10525   arglist = tree_cons (NULL_TREE, src, arglist);
10526   arglist = tree_cons (NULL_TREE, dest, arglist);
10527 
10528   fn = NULL_TREE;
10529   /* If __builtin_mem{cpy,pcpy,move,set}_chk is used, assume
10530      mem{cpy,pcpy,move,set} is available.  */
10531   switch (fcode)
10532     {
10533     case BUILT_IN_MEMCPY_CHK:
10534       fn = built_in_decls[BUILT_IN_MEMCPY];
10535       break;
10536     case BUILT_IN_MEMPCPY_CHK:
10537       fn = built_in_decls[BUILT_IN_MEMPCPY];
10538       break;
10539     case BUILT_IN_MEMMOVE_CHK:
10540       fn = built_in_decls[BUILT_IN_MEMMOVE];
10541       break;
10542     case BUILT_IN_MEMSET_CHK:
10543       fn = built_in_decls[BUILT_IN_MEMSET];
10544       break;
10545     default:
10546       break;
10547     }
10548 
10549   if (!fn)
10550     return 0;
10551 
10552   return build_function_call_expr (fn, arglist);
10553 }
10554 
10555 /* Fold a call to the __st[rp]cpy_chk builtin.
10556    IGNORE is true, if return value can be ignored.  FCODE is the BUILT_IN_*
10557    code of the builtin.  If MAXLEN is not NULL, it is maximum length of
10558    strings passed as second argument.  */
10559 
10560 tree
fold_builtin_stxcpy_chk(tree fndecl,tree arglist,tree maxlen,bool ignore,enum built_in_function fcode)10561 fold_builtin_stxcpy_chk (tree fndecl, tree arglist, tree maxlen, bool ignore,
10562 			 enum built_in_function fcode)
10563 {
10564   tree dest, src, size, len, fn;
10565 
10566   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10567 			 VOID_TYPE))
10568     return 0;
10569 
10570   dest = TREE_VALUE (arglist);
10571   src = TREE_VALUE (TREE_CHAIN (arglist));
10572   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10573 
10574   /* If SRC and DEST are the same (and not volatile), return DEST.  */
10575   if (fcode == BUILT_IN_STRCPY_CHK && operand_equal_p (src, dest, 0))
10576     return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), dest);
10577 
10578   if (! host_integerp (size, 1))
10579     return 0;
10580 
10581   if (! integer_all_onesp (size))
10582     {
10583       len = c_strlen (src, 1);
10584       if (! len || ! host_integerp (len, 1))
10585 	{
10586 	  /* If LEN is not constant, try MAXLEN too.
10587 	     For MAXLEN only allow optimizing into non-_ocs function
10588 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10589 	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10590 	    {
10591 	      if (fcode == BUILT_IN_STPCPY_CHK)
10592 		{
10593 		  if (! ignore)
10594 		    return 0;
10595 
10596 		  /* If return value of __stpcpy_chk is ignored,
10597 		     optimize into __strcpy_chk.  */
10598 		  fn = built_in_decls[BUILT_IN_STRCPY_CHK];
10599 		  if (!fn)
10600 		    return 0;
10601 
10602 		  return build_function_call_expr (fn, arglist);
10603 		}
10604 
10605 	      if (! len || TREE_SIDE_EFFECTS (len))
10606 		return 0;
10607 
10608 	      /* If c_strlen returned something, but not a constant,
10609 		 transform __strcpy_chk into __memcpy_chk.  */
10610 	      fn = built_in_decls[BUILT_IN_MEMCPY_CHK];
10611 	      if (!fn)
10612 		return 0;
10613 
10614 	      len = size_binop (PLUS_EXPR, len, ssize_int (1));
10615 	      arglist = build_tree_list (NULL_TREE, size);
10616 	      arglist = tree_cons (NULL_TREE, len, arglist);
10617 	      arglist = tree_cons (NULL_TREE, src, arglist);
10618 	      arglist = tree_cons (NULL_TREE, dest, arglist);
10619 	      return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)),
10620 				   build_function_call_expr (fn, arglist));
10621 	    }
10622 	}
10623       else
10624 	maxlen = len;
10625 
10626       if (! tree_int_cst_lt (maxlen, size))
10627 	return 0;
10628     }
10629 
10630   arglist = build_tree_list (NULL_TREE, src);
10631   arglist = tree_cons (NULL_TREE, dest, arglist);
10632 
10633   /* If __builtin_st{r,p}cpy_chk is used, assume st{r,p}cpy is available.  */
10634   fn = built_in_decls[fcode == BUILT_IN_STPCPY_CHK
10635 		      ? BUILT_IN_STPCPY : BUILT_IN_STRCPY];
10636   if (!fn)
10637     return 0;
10638 
10639   return build_function_call_expr (fn, arglist);
10640 }
10641 
10642 /* Fold a call to the __strncpy_chk builtin.
10643    If MAXLEN is not NULL, it is maximum length passed as third argument.  */
10644 
10645 tree
fold_builtin_strncpy_chk(tree arglist,tree maxlen)10646 fold_builtin_strncpy_chk (tree arglist, tree maxlen)
10647 {
10648   tree dest, src, size, len, fn;
10649 
10650   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10651 			 INTEGER_TYPE, VOID_TYPE))
10652     return 0;
10653 
10654   dest = TREE_VALUE (arglist);
10655   src = TREE_VALUE (TREE_CHAIN (arglist));
10656   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10657   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10658 
10659   if (! host_integerp (size, 1))
10660     return 0;
10661 
10662   if (! integer_all_onesp (size))
10663     {
10664       if (! host_integerp (len, 1))
10665 	{
10666 	  /* If LEN is not constant, try MAXLEN too.
10667 	     For MAXLEN only allow optimizing into non-_ocs function
10668 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10669 	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10670 	    return 0;
10671 	}
10672       else
10673 	maxlen = len;
10674 
10675       if (tree_int_cst_lt (size, maxlen))
10676 	return 0;
10677     }
10678 
10679   arglist = build_tree_list (NULL_TREE, len);
10680   arglist = tree_cons (NULL_TREE, src, arglist);
10681   arglist = tree_cons (NULL_TREE, dest, arglist);
10682 
10683   /* If __builtin_strncpy_chk is used, assume strncpy is available.  */
10684   fn = built_in_decls[BUILT_IN_STRNCPY];
10685   if (!fn)
10686     return 0;
10687 
10688   return build_function_call_expr (fn, arglist);
10689 }
10690 
10691 /* Fold a call to the __strcat_chk builtin FNDECL with ARGLIST.  */
10692 
10693 static tree
fold_builtin_strcat_chk(tree fndecl,tree arglist)10694 fold_builtin_strcat_chk (tree fndecl, tree arglist)
10695 {
10696   tree dest, src, size, fn;
10697   const char *p;
10698 
10699   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10700 			 VOID_TYPE))
10701     return 0;
10702 
10703   dest = TREE_VALUE (arglist);
10704   src = TREE_VALUE (TREE_CHAIN (arglist));
10705   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10706 
10707   p = c_getstr (src);
10708   /* If the SRC parameter is "", return DEST.  */
10709   if (p && *p == '\0')
10710     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
10711 
10712   if (! host_integerp (size, 1) || ! integer_all_onesp (size))
10713     return 0;
10714 
10715   arglist = build_tree_list (NULL_TREE, src);
10716   arglist = tree_cons (NULL_TREE, dest, arglist);
10717 
10718   /* If __builtin_strcat_chk is used, assume strcat is available.  */
10719   fn = built_in_decls[BUILT_IN_STRCAT];
10720   if (!fn)
10721     return 0;
10722 
10723   return build_function_call_expr (fn, arglist);
10724 }
10725 
10726 /* Fold a call to the __strncat_chk builtin EXP.  */
10727 
10728 static tree
fold_builtin_strncat_chk(tree fndecl,tree arglist)10729 fold_builtin_strncat_chk (tree fndecl, tree arglist)
10730 {
10731   tree dest, src, size, len, fn;
10732   const char *p;
10733 
10734   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
10735 			 INTEGER_TYPE, VOID_TYPE))
10736     return 0;
10737 
10738   dest = TREE_VALUE (arglist);
10739   src = TREE_VALUE (TREE_CHAIN (arglist));
10740   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
10741   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
10742 
10743   p = c_getstr (src);
10744   /* If the SRC parameter is "" or if LEN is 0, return DEST.  */
10745   if (p && *p == '\0')
10746     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, len);
10747   else if (integer_zerop (len))
10748     return omit_one_operand (TREE_TYPE (TREE_TYPE (fndecl)), dest, src);
10749 
10750   if (! host_integerp (size, 1))
10751     return 0;
10752 
10753   if (! integer_all_onesp (size))
10754     {
10755       tree src_len = c_strlen (src, 1);
10756       if (src_len
10757 	  && host_integerp (src_len, 1)
10758 	  && host_integerp (len, 1)
10759 	  && ! tree_int_cst_lt (len, src_len))
10760 	{
10761 	  /* If LEN >= strlen (SRC), optimize into __strcat_chk.  */
10762 	  fn = built_in_decls[BUILT_IN_STRCAT_CHK];
10763 	  if (!fn)
10764 	    return 0;
10765 
10766 	  arglist = build_tree_list (NULL_TREE, size);
10767 	  arglist = tree_cons (NULL_TREE, src, arglist);
10768 	  arglist = tree_cons (NULL_TREE, dest, arglist);
10769 	  return build_function_call_expr (fn, arglist);
10770 	}
10771       return 0;
10772     }
10773 
10774   arglist = build_tree_list (NULL_TREE, len);
10775   arglist = tree_cons (NULL_TREE, src, arglist);
10776   arglist = tree_cons (NULL_TREE, dest, arglist);
10777 
10778   /* If __builtin_strncat_chk is used, assume strncat is available.  */
10779   fn = built_in_decls[BUILT_IN_STRNCAT];
10780   if (!fn)
10781     return 0;
10782 
10783   return build_function_call_expr (fn, arglist);
10784 }
10785 
10786 /* Fold a call to __{,v}sprintf_chk with argument list ARGLIST.  Return 0 if
10787    a normal call should be emitted rather than expanding the function
10788    inline.  FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK.  */
10789 
10790 static tree
fold_builtin_sprintf_chk(tree arglist,enum built_in_function fcode)10791 fold_builtin_sprintf_chk (tree arglist, enum built_in_function fcode)
10792 {
10793   tree dest, size, len, fn, fmt, flag;
10794   const char *fmt_str;
10795 
10796   /* Verify the required arguments in the original call.  */
10797   if (! arglist)
10798     return 0;
10799   dest = TREE_VALUE (arglist);
10800   if (! POINTER_TYPE_P (TREE_TYPE (dest)))
10801     return 0;
10802   arglist = TREE_CHAIN (arglist);
10803   if (! arglist)
10804     return 0;
10805   flag = TREE_VALUE (arglist);
10806   if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE)
10807     return 0;
10808   arglist = TREE_CHAIN (arglist);
10809   if (! arglist)
10810     return 0;
10811   size = TREE_VALUE (arglist);
10812   if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
10813     return 0;
10814   arglist = TREE_CHAIN (arglist);
10815   if (! arglist)
10816     return 0;
10817   fmt = TREE_VALUE (arglist);
10818   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10819     return 0;
10820   arglist = TREE_CHAIN (arglist);
10821 
10822   if (! host_integerp (size, 1))
10823     return 0;
10824 
10825   len = NULL_TREE;
10826 
10827   if (!init_target_chars())
10828     return 0;
10829 
10830   /* Check whether the format is a literal string constant.  */
10831   fmt_str = c_getstr (fmt);
10832   if (fmt_str != NULL)
10833     {
10834       /* If the format doesn't contain % args or %%, we know the size.  */
10835       if (strchr (fmt_str, target_percent) == 0)
10836 	{
10837 	  if (fcode != BUILT_IN_SPRINTF_CHK || arglist == NULL_TREE)
10838 	    len = build_int_cstu (size_type_node, strlen (fmt_str));
10839 	}
10840       /* If the format is "%s" and first ... argument is a string literal,
10841 	 we know the size too.  */
10842       else if (fcode == BUILT_IN_SPRINTF_CHK && strcmp (fmt_str, target_percent_s) == 0)
10843 	{
10844 	  tree arg;
10845 
10846 	  if (arglist && !TREE_CHAIN (arglist))
10847 	    {
10848 	      arg = TREE_VALUE (arglist);
10849 	      if (POINTER_TYPE_P (TREE_TYPE (arg)))
10850 		{
10851 		  len = c_strlen (arg, 1);
10852 		  if (! len || ! host_integerp (len, 1))
10853 		    len = NULL_TREE;
10854 		}
10855 	    }
10856 	}
10857     }
10858 
10859   if (! integer_all_onesp (size))
10860     {
10861       if (! len || ! tree_int_cst_lt (len, size))
10862 	return 0;
10863     }
10864 
10865   /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
10866      or if format doesn't contain % chars or is "%s".  */
10867   if (! integer_zerop (flag))
10868     {
10869       if (fmt_str == NULL)
10870 	return 0;
10871       if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
10872 	return 0;
10873     }
10874 
10875   arglist = tree_cons (NULL_TREE, fmt, arglist);
10876   arglist = tree_cons (NULL_TREE, dest, arglist);
10877 
10878   /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available.  */
10879   fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
10880 		      ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
10881   if (!fn)
10882     return 0;
10883 
10884   return build_function_call_expr (fn, arglist);
10885 }
10886 
10887 /* Fold a call to {,v}snprintf with argument list ARGLIST.  Return 0 if
10888    a normal call should be emitted rather than expanding the function
10889    inline.  FCODE is either BUILT_IN_SNPRINTF_CHK or
10890    BUILT_IN_VSNPRINTF_CHK.  If MAXLEN is not NULL, it is maximum length
10891    passed as second argument.  */
10892 
10893 tree
fold_builtin_snprintf_chk(tree arglist,tree maxlen,enum built_in_function fcode)10894 fold_builtin_snprintf_chk (tree arglist, tree maxlen,
10895 			   enum built_in_function fcode)
10896 {
10897   tree dest, size, len, fn, fmt, flag;
10898   const char *fmt_str;
10899 
10900   /* Verify the required arguments in the original call.  */
10901   if (! arglist)
10902     return 0;
10903   dest = TREE_VALUE (arglist);
10904   if (! POINTER_TYPE_P (TREE_TYPE (dest)))
10905     return 0;
10906   arglist = TREE_CHAIN (arglist);
10907   if (! arglist)
10908     return 0;
10909   len = TREE_VALUE (arglist);
10910   if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
10911     return 0;
10912   arglist = TREE_CHAIN (arglist);
10913   if (! arglist)
10914     return 0;
10915   flag = TREE_VALUE (arglist);
10916   if (TREE_CODE (TREE_TYPE (len)) != INTEGER_TYPE)
10917     return 0;
10918   arglist = TREE_CHAIN (arglist);
10919   if (! arglist)
10920     return 0;
10921   size = TREE_VALUE (arglist);
10922   if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE)
10923     return 0;
10924   arglist = TREE_CHAIN (arglist);
10925   if (! arglist)
10926     return 0;
10927   fmt = TREE_VALUE (arglist);
10928   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
10929     return 0;
10930   arglist = TREE_CHAIN (arglist);
10931 
10932   if (! host_integerp (size, 1))
10933     return 0;
10934 
10935   if (! integer_all_onesp (size))
10936     {
10937       if (! host_integerp (len, 1))
10938 	{
10939 	  /* If LEN is not constant, try MAXLEN too.
10940 	     For MAXLEN only allow optimizing into non-_ocs function
10941 	     if SIZE is >= MAXLEN, never convert to __ocs_fail ().  */
10942 	  if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
10943 	    return 0;
10944 	}
10945       else
10946 	maxlen = len;
10947 
10948       if (tree_int_cst_lt (size, maxlen))
10949 	return 0;
10950     }
10951 
10952   if (!init_target_chars())
10953     return 0;
10954 
10955   /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
10956      or if format doesn't contain % chars or is "%s".  */
10957   if (! integer_zerop (flag))
10958     {
10959       fmt_str = c_getstr (fmt);
10960       if (fmt_str == NULL)
10961 	return 0;
10962       if (strchr (fmt_str, target_percent) != NULL && strcmp (fmt_str, target_percent_s))
10963 	return 0;
10964     }
10965 
10966   arglist = tree_cons (NULL_TREE, fmt, arglist);
10967   arglist = tree_cons (NULL_TREE, len, arglist);
10968   arglist = tree_cons (NULL_TREE, dest, arglist);
10969 
10970   /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
10971      available.  */
10972   fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
10973 		      ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
10974   if (!fn)
10975     return 0;
10976 
10977   return build_function_call_expr (fn, arglist);
10978 }
10979 
10980 /* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
10981 
10982    Return 0 if no simplification was possible, otherwise return the
10983    simplified form of the call as a tree.  FCODE is the BUILT_IN_*
10984    code of the function to be simplified.  */
10985 
10986 static tree
fold_builtin_printf(tree fndecl,tree arglist,bool ignore,enum built_in_function fcode)10987 fold_builtin_printf (tree fndecl, tree arglist, bool ignore,
10988 		     enum built_in_function fcode)
10989 {
10990   tree fmt, fn = NULL_TREE, fn_putchar, fn_puts, arg, call;
10991   const char *fmt_str = NULL;
10992 
10993   /* If the return value is used, don't do the transformation.  */
10994   if (! ignore)
10995     return 0;
10996 
10997   /* Verify the required arguments in the original call.  */
10998   if (fcode == BUILT_IN_PRINTF_CHK || fcode == BUILT_IN_VPRINTF_CHK)
10999     {
11000       tree flag;
11001 
11002       if (! arglist)
11003 	return 0;
11004       flag = TREE_VALUE (arglist);
11005       if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
11006 	  || TREE_SIDE_EFFECTS (flag))
11007 	return 0;
11008       arglist = TREE_CHAIN (arglist);
11009     }
11010 
11011   if (! arglist)
11012     return 0;
11013   fmt = TREE_VALUE (arglist);
11014   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
11015     return 0;
11016   arglist = TREE_CHAIN (arglist);
11017 
11018   /* Check whether the format is a literal string constant.  */
11019   fmt_str = c_getstr (fmt);
11020   if (fmt_str == NULL)
11021     return NULL_TREE;
11022 
11023   if (fcode == BUILT_IN_PRINTF_UNLOCKED)
11024     {
11025       /* If we're using an unlocked function, assume the other
11026 	 unlocked functions exist explicitly.  */
11027       fn_putchar = built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED];
11028       fn_puts = built_in_decls[BUILT_IN_PUTS_UNLOCKED];
11029     }
11030   else
11031     {
11032       fn_putchar = implicit_built_in_decls[BUILT_IN_PUTCHAR];
11033       fn_puts = implicit_built_in_decls[BUILT_IN_PUTS];
11034     }
11035 
11036   if (!init_target_chars())
11037     return 0;
11038 
11039   if (strcmp (fmt_str, target_percent_s) == 0 || strchr (fmt_str, target_percent) == NULL)
11040     {
11041       const char *str;
11042 
11043       if (strcmp (fmt_str, target_percent_s) == 0)
11044 	{
11045 	  if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
11046 	    return 0;
11047 
11048 	  if (! arglist
11049 	      || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
11050 	      || TREE_CHAIN (arglist))
11051 	    return 0;
11052 
11053 	  str = c_getstr (TREE_VALUE (arglist));
11054 	  if (str == NULL)
11055 	    return 0;
11056 	}
11057       else
11058 	{
11059 	  /* The format specifier doesn't contain any '%' characters.  */
11060 	  if (fcode != BUILT_IN_VPRINTF && fcode != BUILT_IN_VPRINTF_CHK
11061 	      && arglist)
11062 	    return 0;
11063 	  str = fmt_str;
11064 	}
11065 
11066       /* If the string was "", printf does nothing.  */
11067       if (str[0] == '\0')
11068 	return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
11069 
11070       /* If the string has length of 1, call putchar.  */
11071       if (str[1] == '\0')
11072 	{
11073 	  /* Given printf("c"), (where c is any one character,)
11074 	     convert "c"[0] to an int and pass that to the replacement
11075 	     function.  */
11076 	  arg = build_int_cst (NULL_TREE, str[0]);
11077 	  arglist = build_tree_list (NULL_TREE, arg);
11078 	  fn = fn_putchar;
11079 	}
11080       else
11081 	{
11082 	  /* If the string was "string\n", call puts("string").  */
11083 	  size_t len = strlen (str);
11084 	  if ((unsigned char)str[len - 1] == target_newline)
11085 	    {
11086 	      /* Create a NUL-terminated string that's one char shorter
11087 		 than the original, stripping off the trailing '\n'.  */
11088 	      char *newstr = alloca (len);
11089 	      memcpy (newstr, str, len - 1);
11090 	      newstr[len - 1] = 0;
11091 
11092 	      arg = build_string_literal (len, newstr);
11093 	      arglist = build_tree_list (NULL_TREE, arg);
11094 	      fn = fn_puts;
11095 	    }
11096 	  else
11097 	    /* We'd like to arrange to call fputs(string,stdout) here,
11098 	       but we need stdout and don't have a way to get it yet.  */
11099 	    return 0;
11100 	}
11101     }
11102 
11103   /* The other optimizations can be done only on the non-va_list variants.  */
11104   else if (fcode == BUILT_IN_VPRINTF || fcode == BUILT_IN_VPRINTF_CHK)
11105     return 0;
11106 
11107   /* If the format specifier was "%s\n", call __builtin_puts(arg).  */
11108   else if (strcmp (fmt_str, target_percent_s_newline) == 0)
11109     {
11110       if (! arglist
11111 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
11112 	  || TREE_CHAIN (arglist))
11113 	return 0;
11114       fn = fn_puts;
11115     }
11116 
11117   /* If the format specifier was "%c", call __builtin_putchar(arg).  */
11118   else if (strcmp (fmt_str, target_percent_c) == 0)
11119     {
11120       if (! arglist
11121 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
11122 	  || TREE_CHAIN (arglist))
11123 	return 0;
11124       fn = fn_putchar;
11125     }
11126 
11127   if (!fn)
11128     return 0;
11129 
11130   call = build_function_call_expr (fn, arglist);
11131   return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
11132 }
11133 
11134 /* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins.
11135 
11136    Return 0 if no simplification was possible, otherwise return the
11137    simplified form of the call as a tree.  FCODE is the BUILT_IN_*
11138    code of the function to be simplified.  */
11139 
11140 static tree
fold_builtin_fprintf(tree fndecl,tree arglist,bool ignore,enum built_in_function fcode)11141 fold_builtin_fprintf (tree fndecl, tree arglist, bool ignore,
11142 		      enum built_in_function fcode)
11143 {
11144   tree fp, fmt, fn = NULL_TREE, fn_fputc, fn_fputs, arg, call;
11145   const char *fmt_str = NULL;
11146 
11147   /* If the return value is used, don't do the transformation.  */
11148   if (! ignore)
11149     return 0;
11150 
11151   /* Verify the required arguments in the original call.  */
11152   if (! arglist)
11153     return 0;
11154   fp = TREE_VALUE (arglist);
11155   if (! POINTER_TYPE_P (TREE_TYPE (fp)))
11156     return 0;
11157   arglist = TREE_CHAIN (arglist);
11158 
11159   if (fcode == BUILT_IN_FPRINTF_CHK || fcode == BUILT_IN_VFPRINTF_CHK)
11160     {
11161       tree flag;
11162 
11163       if (! arglist)
11164 	return 0;
11165       flag = TREE_VALUE (arglist);
11166       if (TREE_CODE (TREE_TYPE (flag)) != INTEGER_TYPE
11167 	  || TREE_SIDE_EFFECTS (flag))
11168 	return 0;
11169       arglist = TREE_CHAIN (arglist);
11170     }
11171 
11172   if (! arglist)
11173     return 0;
11174   fmt = TREE_VALUE (arglist);
11175   if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
11176     return 0;
11177   arglist = TREE_CHAIN (arglist);
11178 
11179   /* Check whether the format is a literal string constant.  */
11180   fmt_str = c_getstr (fmt);
11181   if (fmt_str == NULL)
11182     return NULL_TREE;
11183 
11184   if (fcode == BUILT_IN_FPRINTF_UNLOCKED)
11185     {
11186       /* If we're using an unlocked function, assume the other
11187 	 unlocked functions exist explicitly.  */
11188       fn_fputc = built_in_decls[BUILT_IN_FPUTC_UNLOCKED];
11189       fn_fputs = built_in_decls[BUILT_IN_FPUTS_UNLOCKED];
11190     }
11191   else
11192     {
11193       fn_fputc = implicit_built_in_decls[BUILT_IN_FPUTC];
11194       fn_fputs = implicit_built_in_decls[BUILT_IN_FPUTS];
11195     }
11196 
11197   if (!init_target_chars())
11198     return 0;
11199 
11200   /* If the format doesn't contain % args or %%, use strcpy.  */
11201   if (strchr (fmt_str, target_percent) == NULL)
11202     {
11203       if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK
11204 	  && arglist)
11205 	return 0;
11206 
11207       /* If the format specifier was "", fprintf does nothing.  */
11208       if (fmt_str[0] == '\0')
11209 	{
11210 	  /* If FP has side-effects, just wait until gimplification is
11211 	     done.  */
11212 	  if (TREE_SIDE_EFFECTS (fp))
11213 	    return 0;
11214 
11215 	  return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0);
11216 	}
11217 
11218       /* When "string" doesn't contain %, replace all cases of
11219 	 fprintf (fp, string) with fputs (string, fp).  The fputs
11220 	 builtin will take care of special cases like length == 1.  */
11221       arglist = build_tree_list (NULL_TREE, fp);
11222       arglist = tree_cons (NULL_TREE, fmt, arglist);
11223       fn = fn_fputs;
11224     }
11225 
11226   /* The other optimizations can be done only on the non-va_list variants.  */
11227   else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK)
11228     return 0;
11229 
11230   /* If the format specifier was "%s", call __builtin_fputs (arg, fp).  */
11231   else if (strcmp (fmt_str, target_percent_s) == 0)
11232     {
11233       if (! arglist
11234 	  || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
11235 	  || TREE_CHAIN (arglist))
11236 	return 0;
11237       arg = TREE_VALUE (arglist);
11238       arglist = build_tree_list (NULL_TREE, fp);
11239       arglist = tree_cons (NULL_TREE, arg, arglist);
11240       fn = fn_fputs;
11241     }
11242 
11243   /* If the format specifier was "%c", call __builtin_fputc (arg, fp).  */
11244   else if (strcmp (fmt_str, target_percent_c) == 0)
11245     {
11246       if (! arglist
11247 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
11248 	  || TREE_CHAIN (arglist))
11249 	return 0;
11250       arg = TREE_VALUE (arglist);
11251       arglist = build_tree_list (NULL_TREE, fp);
11252       arglist = tree_cons (NULL_TREE, arg, arglist);
11253       fn = fn_fputc;
11254     }
11255 
11256   if (!fn)
11257     return 0;
11258 
11259   call = build_function_call_expr (fn, arglist);
11260   return fold_convert (TREE_TYPE (TREE_TYPE (fndecl)), call);
11261 }
11262 
11263 /* Initialize format string characters in the target charset.  */
11264 
11265 static bool
init_target_chars(void)11266 init_target_chars (void)
11267 {
11268   static bool init;
11269   if (!init)
11270     {
11271       target_newline = lang_hooks.to_target_charset ('\n');
11272       target_percent = lang_hooks.to_target_charset ('%');
11273       target_c = lang_hooks.to_target_charset ('c');
11274       target_s = lang_hooks.to_target_charset ('s');
11275       if (target_newline == 0 || target_percent == 0 || target_c == 0
11276 	  || target_s == 0)
11277 	return false;
11278 
11279       target_percent_c[0] = target_percent;
11280       target_percent_c[1] = target_c;
11281       target_percent_c[2] = '\0';
11282 
11283       target_percent_s[0] = target_percent;
11284       target_percent_s[1] = target_s;
11285       target_percent_s[2] = '\0';
11286 
11287       target_percent_s_newline[0] = target_percent;
11288       target_percent_s_newline[1] = target_s;
11289       target_percent_s_newline[2] = target_newline;
11290       target_percent_s_newline[3] = '\0';
11291 
11292       init = true;
11293     }
11294   return true;
11295 }
11296