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