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