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