]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
* reload.c: Revert 2003-01-31 change.
[thirdparty/gcc.git] / gcc / builtins.c
CommitLineData
53800dbe 1/* Expand builtin functions.
61f1dccc 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
53800dbe 4
f12b58b3 5This file is part of GCC.
53800dbe 6
f12b58b3 7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
53800dbe 11
f12b58b3 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
53800dbe 16
17You should have received a copy of the GNU General Public License
f12b58b3 18along with GCC; see the file COPYING. If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-1307, USA. */
53800dbe 21
22#include "config.h"
23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
53800dbe 26#include "machmode.h"
ef258422 27#include "real.h"
53800dbe 28#include "rtl.h"
29#include "tree.h"
53800dbe 30#include "flags.h"
31#include "regs.h"
32#include "hard-reg-set.h"
33#include "except.h"
34#include "function.h"
53800dbe 35#include "insn-config.h"
36#include "expr.h"
d8fc4d0b 37#include "optabs.h"
38#include "libfuncs.h"
53800dbe 39#include "recog.h"
40#include "output.h"
41#include "typeclass.h"
53800dbe 42#include "toplev.h"
689df48e 43#include "predict.h"
1dd6c958 44#include "tm_p.h"
fc2a2dcb 45#include "target.h"
63c62881 46#include "langhooks.h"
53800dbe 47
48#define CALLED_AS_BUILT_IN(NODE) \
49 (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
50
53800dbe 51/* Register mappings for target machines without register windows. */
52#ifndef INCOMING_REGNO
53#define INCOMING_REGNO(OUT) (OUT)
54#endif
55#ifndef OUTGOING_REGNO
56#define OUTGOING_REGNO(IN) (IN)
57#endif
58
726e2588 59#ifndef PAD_VARARGS_DOWN
60#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
61#endif
62
ab7943b9 63/* Define the names of the builtin function types and codes. */
8934cb0c 64const char *const built_in_class_names[4]
ab7943b9 65 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
66
0a68165a 67#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM) STRINGX(X),
8934cb0c 68const char *const built_in_names[(int) END_BUILTINS] =
4e9d90c7 69{
70#include "builtins.def"
71};
72#undef DEF_BUILTIN
ab7943b9 73
df94cd3b 74/* Setup an array of _DECL trees, make sure each element is
75 initialized to NULL_TREE. */
d2d4bdde 76tree built_in_decls[(int) END_BUILTINS];
0a68165a 77/* Declarations used when constructing the builtin implicitly in the compiler.
78 It may be NULL_TREE when this is invalid (for instance runtime is not
79 required to implement the function call in all cases. */
80tree implicit_built_in_decls[(int) END_BUILTINS];
df94cd3b 81
27d0c333 82static int get_pointer_alignment PARAMS ((tree, unsigned int));
6bcfea9e 83static tree c_strlen PARAMS ((tree));
83d79705 84static const char *c_getstr PARAMS ((tree));
6840589f 85static rtx c_readstr PARAMS ((const char *,
86 enum machine_mode));
bf8e3599 87static int target_char_cast PARAMS ((tree, char *));
6bcfea9e 88static rtx get_memory_rtx PARAMS ((tree));
89static int apply_args_size PARAMS ((void));
90static int apply_result_size PARAMS ((void));
d8c9779c 91#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
6bcfea9e 92static rtx result_vector PARAMS ((int, rtx));
d8c9779c 93#endif
6b7f6858 94static rtx expand_builtin_setjmp PARAMS ((tree, rtx));
5e3608d8 95static void expand_builtin_prefetch PARAMS ((tree));
6bcfea9e 96static rtx expand_builtin_apply_args PARAMS ((void));
97static rtx expand_builtin_apply_args_1 PARAMS ((void));
98static rtx expand_builtin_apply PARAMS ((rtx, rtx, rtx));
99static void expand_builtin_return PARAMS ((rtx));
0608064e 100static enum type_class type_to_class PARAMS ((tree));
6bcfea9e 101static rtx expand_builtin_classify_type PARAMS ((tree));
102static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx));
103static rtx expand_builtin_constant_p PARAMS ((tree));
104static rtx expand_builtin_args_info PARAMS ((tree));
105static rtx expand_builtin_next_arg PARAMS ((tree));
7ccc713a 106static rtx expand_builtin_va_start PARAMS ((tree));
6bcfea9e 107static rtx expand_builtin_va_end PARAMS ((tree));
108static rtx expand_builtin_va_copy PARAMS ((tree));
6f428e8b 109static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx,
9342ee68 110 enum machine_mode));
83d79705 111static rtx expand_builtin_strcmp PARAMS ((tree, rtx,
112 enum machine_mode));
ed09096d 113static rtx expand_builtin_strncmp PARAMS ((tree, rtx,
114 enum machine_mode));
6840589f 115static rtx builtin_memcpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
116 enum machine_mode));
49f0327b 117static rtx expand_builtin_strcat PARAMS ((tree, rtx,
118 enum machine_mode));
119static rtx expand_builtin_strncat PARAMS ((tree, rtx,
120 enum machine_mode));
121static rtx expand_builtin_strspn PARAMS ((tree, rtx,
122 enum machine_mode));
123static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
124 enum machine_mode));
6f428e8b 125static rtx expand_builtin_memcpy PARAMS ((tree, rtx,
9342ee68 126 enum machine_mode));
6f428e8b 127static rtx expand_builtin_strcpy PARAMS ((tree, rtx,
9342ee68 128 enum machine_mode));
6840589f 129static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
130 enum machine_mode));
ed09096d 131static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
132 enum machine_mode));
ecc318ff 133static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT,
134 enum machine_mode));
a7ec6974 135static rtx builtin_memset_gen_str PARAMS ((PTR, HOST_WIDE_INT,
136 enum machine_mode));
6f428e8b 137static rtx expand_builtin_memset PARAMS ((tree, rtx,
9342ee68 138 enum machine_mode));
ffc83088 139static rtx expand_builtin_bzero PARAMS ((tree));
aed0bd19 140static rtx expand_builtin_strlen PARAMS ((tree, rtx));
17f5ea87 141static rtx expand_builtin_strstr PARAMS ((tree, rtx,
142 enum machine_mode));
46f3a74a 143static rtx expand_builtin_strpbrk PARAMS ((tree, rtx,
144 enum machine_mode));
83d79705 145static rtx expand_builtin_strchr PARAMS ((tree, rtx,
146 enum machine_mode));
147static rtx expand_builtin_strrchr PARAMS ((tree, rtx,
148 enum machine_mode));
6bcfea9e 149static rtx expand_builtin_alloca PARAMS ((tree, rtx));
150static rtx expand_builtin_ffs PARAMS ((tree, rtx, rtx));
151static rtx expand_builtin_frame_address PARAMS ((tree));
c013a46e 152static rtx expand_builtin_fputs PARAMS ((tree, int, int));
6bcfea9e 153static tree stabilize_va_list PARAMS ((tree, int));
89cfe6e5 154static rtx expand_builtin_expect PARAMS ((tree, rtx));
650e4c94 155static tree fold_builtin_constant_p PARAMS ((tree));
539a3a92 156static tree fold_builtin_classify_type PARAMS ((tree));
92c43e3c 157static tree fold_builtin_inf PARAMS ((tree, int));
b0db7939 158static tree fold_builtin_nan PARAMS ((tree, tree, int));
0eb671f7 159static int validate_arglist PARAMS ((tree, ...));
6528f4f4 160static tree fold_trunc_transparent_mathfn PARAMS ((tree));
53800dbe 161
162/* Return the alignment in bits of EXP, a pointer valued expression.
163 But don't return more than MAX_ALIGN no matter what.
164 The alignment returned is, by default, the alignment of the thing that
27d0c333 165 EXP points to. If it is not a POINTER_TYPE, 0 is returned.
53800dbe 166
167 Otherwise, look at the expression to see if we can do better, i.e., if the
168 expression is actually pointing at an object whose alignment is tighter. */
169
170static int
171get_pointer_alignment (exp, max_align)
172 tree exp;
27d0c333 173 unsigned int max_align;
53800dbe 174{
27d0c333 175 unsigned int align, inner;
53800dbe 176
177 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
178 return 0;
179
180 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
181 align = MIN (align, max_align);
182
183 while (1)
184 {
185 switch (TREE_CODE (exp))
186 {
187 case NOP_EXPR:
188 case CONVERT_EXPR:
189 case NON_LVALUE_EXPR:
190 exp = TREE_OPERAND (exp, 0);
191 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
192 return align;
325d1c45 193
53800dbe 194 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
195 align = MIN (inner, max_align);
196 break;
197
198 case PLUS_EXPR:
199 /* If sum of pointer + int, restrict our maximum alignment to that
200 imposed by the integer. If not, we can't do any better than
201 ALIGN. */
325d1c45 202 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
53800dbe 203 return align;
204
0994d2ed 205 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
206 & (max_align / BITS_PER_UNIT - 1))
53800dbe 207 != 0)
208 max_align >>= 1;
209
210 exp = TREE_OPERAND (exp, 0);
211 break;
212
213 case ADDR_EXPR:
214 /* See what we are pointing at and look at its alignment. */
215 exp = TREE_OPERAND (exp, 0);
216 if (TREE_CODE (exp) == FUNCTION_DECL)
217 align = FUNCTION_BOUNDARY;
9308e976 218 else if (DECL_P (exp))
53800dbe 219 align = DECL_ALIGN (exp);
220#ifdef CONSTANT_ALIGNMENT
221 else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
222 align = CONSTANT_ALIGNMENT (exp, align);
223#endif
224 return MIN (align, max_align);
225
226 default:
227 return align;
228 }
229 }
230}
231
232/* Compute the length of a C string. TREE_STRING_LENGTH is not the right
233 way, because it could contain a zero byte in the middle.
234 TREE_STRING_LENGTH is the size of the character array, not the string.
235
902de8ed 236 The value returned is of type `ssizetype'.
237
53800dbe 238 Unfortunately, string_constant can't access the values of const char
239 arrays with initializers, so neither can we do so here. */
240
241static tree
242c_strlen (src)
243 tree src;
244{
245 tree offset_node;
27d0c333 246 HOST_WIDE_INT offset;
247 int max;
44acf429 248 const char *ptr;
53800dbe 249
250 src = string_constant (src, &offset_node);
251 if (src == 0)
252 return 0;
902de8ed 253
83d79705 254 max = TREE_STRING_LENGTH (src) - 1;
53800dbe 255 ptr = TREE_STRING_POINTER (src);
902de8ed 256
53800dbe 257 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
258 {
259 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
260 compute the offset to the following null if we don't know where to
261 start searching for it. */
262 int i;
902de8ed 263
53800dbe 264 for (i = 0; i < max; i++)
265 if (ptr[i] == 0)
266 return 0;
902de8ed 267
53800dbe 268 /* We don't know the starting offset, but we do know that the string
269 has no internal zero bytes. We can assume that the offset falls
270 within the bounds of the string; otherwise, the programmer deserves
271 what he gets. Subtract the offset from the length of the string,
902de8ed 272 and return that. This would perhaps not be valid if we were dealing
273 with named arrays in addition to literal string constants. */
274
275 return size_diffop (size_int (max), offset_node);
53800dbe 276 }
277
278 /* We have a known offset into the string. Start searching there for
27d0c333 279 a null character if we can represent it as a single HOST_WIDE_INT. */
dabc4084 280 if (offset_node == 0)
53800dbe 281 offset = 0;
dabc4084 282 else if (! host_integerp (offset_node, 0))
283 offset = -1;
53800dbe 284 else
27d0c333 285 offset = tree_low_cst (offset_node, 0);
902de8ed 286
53800dbe 287 /* If the offset is known to be out of bounds, warn, and call strlen at
288 runtime. */
289 if (offset < 0 || offset > max)
290 {
291 warning ("offset outside bounds of constant string");
292 return 0;
293 }
902de8ed 294
53800dbe 295 /* Use strlen to search for the first zero byte. Since any strings
296 constructed with build_string will have nulls appended, we win even
297 if we get handed something like (char[4])"abcd".
298
299 Since OFFSET is our starting index into the string, no further
300 calculation is needed. */
902de8ed 301 return ssize_int (strlen (ptr + offset));
53800dbe 302}
303
83d79705 304/* Return a char pointer for a C string if it is a string constant
305 or sum of string constant and integer constant. */
306
307static const char *
308c_getstr (src)
309 tree src;
310{
311 tree offset_node;
83d79705 312
313 src = string_constant (src, &offset_node);
314 if (src == 0)
315 return 0;
316
8c85fcb7 317 if (offset_node == 0)
318 return TREE_STRING_POINTER (src);
319 else if (!host_integerp (offset_node, 1)
320 || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
83d79705 321 return 0;
83d79705 322
8c85fcb7 323 return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
83d79705 324}
325
8c85fcb7 326/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
327 GET_MODE_BITSIZE (MODE) bits from string constant STR. */
ecc318ff 328
6840589f 329static rtx
330c_readstr (str, mode)
331 const char *str;
332 enum machine_mode mode;
333{
334 HOST_WIDE_INT c[2];
335 HOST_WIDE_INT ch;
336 unsigned int i, j;
337
338 if (GET_MODE_CLASS (mode) != MODE_INT)
339 abort ();
340 c[0] = 0;
341 c[1] = 0;
342 ch = 1;
343 for (i = 0; i < GET_MODE_SIZE (mode); i++)
344 {
345 j = i;
346 if (WORDS_BIG_ENDIAN)
347 j = GET_MODE_SIZE (mode) - i - 1;
348 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
349 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
350 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
351 j *= BITS_PER_UNIT;
352 if (j > 2 * HOST_BITS_PER_WIDE_INT)
353 abort ();
354 if (ch)
355 ch = (unsigned char) str[i];
356 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
357 }
358 return immed_double_const (c[0], c[1], mode);
359}
360
ecc318ff 361/* Cast a target constant CST to target CHAR and if that value fits into
362 host char type, return zero and put that value into variable pointed by
363 P. */
364
365static int
366target_char_cast (cst, p)
367 tree cst;
368 char *p;
369{
370 unsigned HOST_WIDE_INT val, hostval;
371
27d0c333 372 if (!host_integerp (cst, 1)
ecc318ff 373 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
374 return 1;
375
27d0c333 376 val = tree_low_cst (cst, 1);
ecc318ff 377 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
378 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
379
380 hostval = val;
381 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
382 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
383
384 if (val != hostval)
385 return 1;
386
387 *p = hostval;
388 return 0;
389}
390
53800dbe 391/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
392 times to get the address of either a higher stack frame, or a return
393 address located within it (depending on FNDECL_CODE). */
902de8ed 394
53800dbe 395rtx
396expand_builtin_return_addr (fndecl_code, count, tem)
397 enum built_in_function fndecl_code;
398 int count;
399 rtx tem;
400{
401 int i;
402
403 /* Some machines need special handling before we can access
404 arbitrary frames. For example, on the sparc, we must first flush
405 all register windows to the stack. */
406#ifdef SETUP_FRAME_ADDRESSES
407 if (count > 0)
408 SETUP_FRAME_ADDRESSES ();
409#endif
410
411 /* On the sparc, the return address is not in the frame, it is in a
412 register. There is no way to access it off of the current frame
413 pointer, but it can be accessed off the previous frame pointer by
414 reading the value from the register window save area. */
415#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
416 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
417 count--;
418#endif
419
420 /* Scan back COUNT frames to the specified frame. */
421 for (i = 0; i < count; i++)
422 {
423 /* Assume the dynamic chain pointer is in the word that the
424 frame address points to, unless otherwise specified. */
425#ifdef DYNAMIC_CHAIN_ADDRESS
426 tem = DYNAMIC_CHAIN_ADDRESS (tem);
427#endif
428 tem = memory_address (Pmode, tem);
83fc1478 429 tem = gen_rtx_MEM (Pmode, tem);
ab6ab77e 430 set_mem_alias_set (tem, get_frame_alias_set ());
83fc1478 431 tem = copy_to_reg (tem);
53800dbe 432 }
433
434 /* For __builtin_frame_address, return what we've got. */
435 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
436 return tem;
437
438 /* For __builtin_return_address, Get the return address from that
439 frame. */
440#ifdef RETURN_ADDR_RTX
441 tem = RETURN_ADDR_RTX (count, tem);
442#else
443 tem = memory_address (Pmode,
444 plus_constant (tem, GET_MODE_SIZE (Pmode)));
445 tem = gen_rtx_MEM (Pmode, tem);
ab6ab77e 446 set_mem_alias_set (tem, get_frame_alias_set ());
53800dbe 447#endif
448 return tem;
449}
450
f7c44134 451/* Alias set used for setjmp buffer. */
452static HOST_WIDE_INT setjmp_alias_set = -1;
453
6b7f6858 454/* Construct the leading half of a __builtin_setjmp call. Control will
455 return to RECEIVER_LABEL. This is used directly by sjlj exception
456 handling code. */
53800dbe 457
6b7f6858 458void
459expand_builtin_setjmp_setup (buf_addr, receiver_label)
53800dbe 460 rtx buf_addr;
6b7f6858 461 rtx receiver_label;
53800dbe 462{
53800dbe 463 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
53800dbe 464 rtx stack_save;
f7c44134 465 rtx mem;
53800dbe 466
f7c44134 467 if (setjmp_alias_set == -1)
468 setjmp_alias_set = new_alias_set ();
469
53800dbe 470#ifdef POINTERS_EXTEND_UNSIGNED
479e4d5e 471 if (GET_MODE (buf_addr) != Pmode)
472 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 473#endif
474
37ae8504 475 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
53800dbe 476
53800dbe 477 emit_queue ();
478
6b7f6858 479 /* We store the frame pointer and the address of receiver_label in
480 the buffer and use the rest of it for the stack save area, which
481 is machine-dependent. */
53800dbe 482
483#ifndef BUILTIN_SETJMP_FRAME_VALUE
484#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
485#endif
486
f7c44134 487 mem = gen_rtx_MEM (Pmode, buf_addr);
ab6ab77e 488 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 489 emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
490
491 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
ab6ab77e 492 set_mem_alias_set (mem, setjmp_alias_set);
f7c44134 493
494 emit_move_insn (validize_mem (mem),
6b7f6858 495 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
53800dbe 496
497 stack_save = gen_rtx_MEM (sa_mode,
498 plus_constant (buf_addr,
499 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 500 set_mem_alias_set (stack_save, setjmp_alias_set);
53800dbe 501 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
502
503 /* If there is further processing to do, do it. */
504#ifdef HAVE_builtin_setjmp_setup
505 if (HAVE_builtin_setjmp_setup)
506 emit_insn (gen_builtin_setjmp_setup (buf_addr));
507#endif
508
6b7f6858 509 /* Tell optimize_save_area_alloca that extra work is going to
510 need to go on during alloca. */
3b0fa6b6 511 current_function_calls_setjmp = 1;
80ab81b9 512
513 /* Set this so all the registers get saved in our frame; we need to be
2c0e001b 514 able to copy the saved values for any registers from frames we unwind. */
80ab81b9 515 current_function_has_nonlocal_label = 1;
6b7f6858 516}
53800dbe 517
6b7f6858 518/* Construct the trailing part of a __builtin_setjmp call.
519 This is used directly by sjlj exception handling code. */
520
521void
522expand_builtin_setjmp_receiver (receiver_label)
9342ee68 523 rtx receiver_label ATTRIBUTE_UNUSED;
6b7f6858 524{
53800dbe 525 /* Clobber the FP when we get here, so we have to make sure it's
526 marked as used by this function. */
527 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
528
529 /* Mark the static chain as clobbered here so life information
530 doesn't get messed up for it. */
531 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
532
533 /* Now put in the code to restore the frame pointer, and argument
534 pointer, if needed. The code below is from expand_end_bindings
535 in stmt.c; see detailed documentation there. */
536#ifdef HAVE_nonlocal_goto
537 if (! HAVE_nonlocal_goto)
538#endif
539 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
540
541#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
542 if (fixed_regs[ARG_POINTER_REGNUM])
543 {
544#ifdef ELIMINABLE_REGS
545 size_t i;
e99c3a1d 546 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
53800dbe 547
3098b2d3 548 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
53800dbe 549 if (elim_regs[i].from == ARG_POINTER_REGNUM
550 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
551 break;
552
3098b2d3 553 if (i == ARRAY_SIZE (elim_regs))
53800dbe 554#endif
555 {
556 /* Now restore our arg pointer from the address at which it
05927e40 557 was saved in our stack frame. */
53800dbe 558 emit_move_insn (virtual_incoming_args_rtx,
05927e40 559 copy_to_reg (get_arg_pointer_save_area (cfun)));
53800dbe 560 }
561 }
562#endif
563
564#ifdef HAVE_builtin_setjmp_receiver
565 if (HAVE_builtin_setjmp_receiver)
6b7f6858 566 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
53800dbe 567 else
568#endif
569#ifdef HAVE_nonlocal_goto_receiver
570 if (HAVE_nonlocal_goto_receiver)
571 emit_insn (gen_nonlocal_goto_receiver ());
572 else
573#endif
6b7f6858 574 { /* Nothing */ }
57f6bb94 575
576 /* @@@ This is a kludge. Not all machine descriptions define a blockage
577 insn, but we must not allow the code we just generated to be reordered
578 by scheduling. Specifically, the update of the frame pointer must
579 happen immediately, not later. So emit an ASM_INPUT to act as blockage
580 insn. */
581 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
6b7f6858 582}
53800dbe 583
6b7f6858 584/* __builtin_setjmp is passed a pointer to an array of five words (not
585 all will be used on all machines). It operates similarly to the C
586 library function of the same name, but is more efficient. Much of
587 the code below (and for longjmp) is copied from the handling of
588 non-local gotos.
589
590 NOTE: This is intended for use by GNAT and the exception handling
591 scheme in the compiler and will only work in the method used by
592 them. */
593
594static rtx
595expand_builtin_setjmp (arglist, target)
596 tree arglist;
597 rtx target;
598{
599 rtx buf_addr, next_lab, cont_lab;
600
0eb671f7 601 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
6b7f6858 602 return NULL_RTX;
603
604 if (target == 0 || GET_CODE (target) != REG
605 || REGNO (target) < FIRST_PSEUDO_REGISTER)
606 target = gen_reg_rtx (TYPE_MODE (integer_type_node));
607
608 buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
609
610 next_lab = gen_label_rtx ();
611 cont_lab = gen_label_rtx ();
612
613 expand_builtin_setjmp_setup (buf_addr, next_lab);
614
615 /* Set TARGET to zero and branch to the continue label. */
616 emit_move_insn (target, const0_rtx);
617 emit_jump_insn (gen_jump (cont_lab));
53800dbe 618 emit_barrier ();
6b7f6858 619 emit_label (next_lab);
620
621 expand_builtin_setjmp_receiver (next_lab);
622
623 /* Set TARGET to one. */
624 emit_move_insn (target, const1_rtx);
625 emit_label (cont_lab);
626
627 /* Tell flow about the strange goings on. Putting `next_lab' on
628 `nonlocal_goto_handler_labels' to indicates that function
629 calls may traverse the arc back to this label. */
630
631 current_function_has_nonlocal_label = 1;
632 nonlocal_goto_handler_labels
633 = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
53800dbe 634
635 return target;
636}
637
638/* __builtin_longjmp is passed a pointer to an array of five words (not
639 all will be used on all machines). It operates similarly to the C
640 library function of the same name, but is more efficient. Much of
641 the code below is copied from the handling of non-local gotos.
642
643 NOTE: This is intended for use by GNAT and the exception handling
644 scheme in the compiler and will only work in the method used by
645 them. */
646
647void
648expand_builtin_longjmp (buf_addr, value)
649 rtx buf_addr, value;
650{
4712c7d6 651 rtx fp, lab, stack, insn, last;
53800dbe 652 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
653
f7c44134 654 if (setjmp_alias_set == -1)
655 setjmp_alias_set = new_alias_set ();
656
53800dbe 657#ifdef POINTERS_EXTEND_UNSIGNED
479e4d5e 658 if (GET_MODE (buf_addr) != Pmode)
659 buf_addr = convert_memory_address (Pmode, buf_addr);
53800dbe 660#endif
479e4d5e 661
53800dbe 662 buf_addr = force_reg (Pmode, buf_addr);
663
664 /* We used to store value in static_chain_rtx, but that fails if pointers
665 are smaller than integers. We instead require that the user must pass
666 a second argument of 1, because that is what builtin_setjmp will
667 return. This also makes EH slightly more efficient, since we are no
668 longer copying around a value that we don't care about. */
669 if (value != const1_rtx)
670 abort ();
671
3b0fa6b6 672 current_function_calls_longjmp = 1;
673
4712c7d6 674 last = get_last_insn ();
53800dbe 675#ifdef HAVE_builtin_longjmp
676 if (HAVE_builtin_longjmp)
677 emit_insn (gen_builtin_longjmp (buf_addr));
678 else
679#endif
680 {
681 fp = gen_rtx_MEM (Pmode, buf_addr);
682 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
683 GET_MODE_SIZE (Pmode)));
684
685 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
686 2 * GET_MODE_SIZE (Pmode)));
ab6ab77e 687 set_mem_alias_set (fp, setjmp_alias_set);
688 set_mem_alias_set (lab, setjmp_alias_set);
689 set_mem_alias_set (stack, setjmp_alias_set);
53800dbe 690
691 /* Pick up FP, label, and SP from the block and jump. This code is
692 from expand_goto in stmt.c; see there for detailed comments. */
693#if HAVE_nonlocal_goto
694 if (HAVE_nonlocal_goto)
695 /* We have to pass a value to the nonlocal_goto pattern that will
696 get copied into the static_chain pointer, but it does not matter
697 what that value is, because builtin_setjmp does not use it. */
28d202a8 698 emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
53800dbe 699 else
700#endif
701 {
702 lab = copy_to_reg (lab);
703
704 emit_move_insn (hard_frame_pointer_rtx, fp);
705 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
706
707 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
708 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
709 emit_indirect_jump (lab);
710 }
711 }
615166bb 712
713 /* Search backwards and mark the jump insn as a non-local goto.
714 Note that this precludes the use of __builtin_longjmp to a
715 __builtin_setjmp target in the same function. However, we've
716 already cautioned the user that these functions are for
717 internal exception handling use only. */
449c0509 718 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
719 {
4712c7d6 720 if (insn == last)
721 abort ();
449c0509 722 if (GET_CODE (insn) == JUMP_INSN)
723 {
724 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
725 REG_NOTES (insn));
726 break;
727 }
728 else if (GET_CODE (insn) == CALL_INSN)
9342ee68 729 break;
449c0509 730 }
53800dbe 731}
732
5e3608d8 733/* Expand a call to __builtin_prefetch. For a target that does not support
734 data prefetch, evaluate the memory address argument in case it has side
735 effects. */
736
737static void
738expand_builtin_prefetch (arglist)
739 tree arglist;
740{
741 tree arg0, arg1, arg2;
742 rtx op0, op1, op2;
743
26a5cadb 744 if (!validate_arglist (arglist, POINTER_TYPE, 0))
745 return;
746
5e3608d8 747 arg0 = TREE_VALUE (arglist);
26a5cadb 748 /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
749 zero (read) and argument 2 (locality) defaults to 3 (high degree of
750 locality). */
751 if (TREE_CHAIN (arglist))
752 {
753 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
754 if (TREE_CHAIN (TREE_CHAIN (arglist)))
9342ee68 755 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
26a5cadb 756 else
757 arg2 = build_int_2 (3, 0);
758 }
759 else
760 {
761 arg1 = integer_zero_node;
762 arg2 = build_int_2 (3, 0);
763 }
5e3608d8 764
765 /* Argument 0 is an address. */
766 op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
767
768 /* Argument 1 (read/write flag) must be a compile-time constant int. */
769 if (TREE_CODE (arg1) != INTEGER_CST)
770 {
9342ee68 771 error ("second arg to `__builtin_prefetch' must be a constant");
772 arg1 = integer_zero_node;
5e3608d8 773 }
bf8e3599 774 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5e3608d8 775 /* Argument 1 must be either zero or one. */
776 if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
777 {
778 warning ("invalid second arg to __builtin_prefetch; using zero");
779 op1 = const0_rtx;
780 }
781
782 /* Argument 2 (locality) must be a compile-time constant int. */
783 if (TREE_CODE (arg2) != INTEGER_CST)
784 {
785 error ("third arg to `__builtin_prefetch' must be a constant");
786 arg2 = integer_zero_node;
787 }
bf8e3599 788 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
5e3608d8 789 /* Argument 2 must be 0, 1, 2, or 3. */
790 if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
791 {
792 warning ("invalid third arg to __builtin_prefetch; using zero");
793 op2 = const0_rtx;
794 }
795
796#ifdef HAVE_prefetch
797 if (HAVE_prefetch)
798 {
f0ce3b1f 799 if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
4cd21437 800 (op0,
f0ce3b1f 801 insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
802 || (GET_MODE(op0) != Pmode))
9342ee68 803 {
4cd21437 804#ifdef POINTERS_EXTEND_UNSIGNED
805 if (GET_MODE(op0) != Pmode)
806 op0 = convert_memory_address (Pmode, op0);
807#endif
9342ee68 808 op0 = force_reg (Pmode, op0);
809 }
5e3608d8 810 emit_insn (gen_prefetch (op0, op1, op2));
811 }
812 else
813#endif
814 op0 = protect_from_queue (op0, 0);
f0ce3b1f 815 /* Don't do anything with direct references to volatile memory, but
816 generate code to handle other side effects. */
817 if (GET_CODE (op0) != MEM && side_effects_p (op0))
818 emit_insn (op0);
5e3608d8 819}
820
f7c44134 821/* Get a MEM rtx for expression EXP which is the address of an operand
822 to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */
823
53800dbe 824static rtx
825get_memory_rtx (exp)
826 tree exp;
827{
726ec87c 828 rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_SUM);
829 rtx mem;
f7c44134 830
726ec87c 831#ifdef POINTERS_EXTEND_UNSIGNED
832 if (GET_MODE (addr) != Pmode)
833 addr = convert_memory_address (Pmode, addr);
834#endif
835
836 mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
2a631e19 837
f7c44134 838 /* Get an expression we can use to find the attributes to assign to MEM.
839 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
840 we can. First remove any nops. */
841 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
f0ce3b1f 842 || TREE_CODE (exp) == NON_LVALUE_EXPR)
f7c44134 843 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
844 exp = TREE_OPERAND (exp, 0);
845
846 if (TREE_CODE (exp) == ADDR_EXPR)
eec8e941 847 {
848 exp = TREE_OPERAND (exp, 0);
849 set_mem_attributes (mem, exp, 0);
850 }
f7c44134 851 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
eec8e941 852 {
853 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
854 /* memcpy, memset and other builtin stringops can alias with anything. */
855 set_mem_alias_set (mem, 0);
856 }
53800dbe 857
53800dbe 858 return mem;
859}
860\f
861/* Built-in functions to perform an untyped call and return. */
862
863/* For each register that may be used for calling a function, this
864 gives a mode used to copy the register's value. VOIDmode indicates
865 the register is not used for calling a function. If the machine
866 has register windows, this gives only the outbound registers.
867 INCOMING_REGNO gives the corresponding inbound register. */
868static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
869
870/* For each register that may be used for returning values, this gives
871 a mode used to copy the register's value. VOIDmode indicates the
872 register is not used for returning values. If the machine has
873 register windows, this gives only the outbound registers.
874 INCOMING_REGNO gives the corresponding inbound register. */
875static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
876
877/* For each register that may be used for calling a function, this
878 gives the offset of that register into the block returned by
879 __builtin_apply_args. 0 indicates that the register is not
880 used for calling a function. */
881static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
882
bf8e3599 883/* Return the offset of register REGNO into the block returned by
53800dbe 884 __builtin_apply_args. This is not declared static, since it is
885 needed in objc-act.c. */
886
bf8e3599 887int
53800dbe 888apply_args_register_offset (regno)
889 int regno;
890{
891 apply_args_size ();
892
893 /* Arguments are always put in outgoing registers (in the argument
894 block) if such make sense. */
895#ifdef OUTGOING_REGNO
f0ce3b1f 896 regno = OUTGOING_REGNO (regno);
53800dbe 897#endif
898 return apply_args_reg_offset[regno];
899}
900
901/* Return the size required for the block returned by __builtin_apply_args,
902 and initialize apply_args_mode. */
903
904static int
905apply_args_size ()
906{
907 static int size = -1;
58e9ce8f 908 int align;
909 unsigned int regno;
53800dbe 910 enum machine_mode mode;
911
912 /* The values computed by this function never change. */
913 if (size < 0)
914 {
915 /* The first value is the incoming arg-pointer. */
916 size = GET_MODE_SIZE (Pmode);
917
918 /* The second value is the structure value address unless this is
919 passed as an "invisible" first argument. */
920 if (struct_value_rtx)
921 size += GET_MODE_SIZE (Pmode);
922
923 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
924 if (FUNCTION_ARG_REGNO_P (regno))
925 {
926 /* Search for the proper mode for copying this register's
927 value. I'm not sure this is right, but it works so far. */
928 enum machine_mode best_mode = VOIDmode;
929
930 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
931 mode != VOIDmode;
932 mode = GET_MODE_WIDER_MODE (mode))
933 if (HARD_REGNO_MODE_OK (regno, mode)
934 && HARD_REGNO_NREGS (regno, mode) == 1)
935 best_mode = mode;
936
937 if (best_mode == VOIDmode)
938 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
939 mode != VOIDmode;
940 mode = GET_MODE_WIDER_MODE (mode))
941 if (HARD_REGNO_MODE_OK (regno, mode)
ad99e708 942 && have_insn_for (SET, mode))
53800dbe 943 best_mode = mode;
944
223097eb 945 if (best_mode == VOIDmode)
946 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
947 mode != VOIDmode;
948 mode = GET_MODE_WIDER_MODE (mode))
949 if (HARD_REGNO_MODE_OK (regno, mode)
950 && have_insn_for (SET, mode))
951 best_mode = mode;
952
953 if (best_mode == VOIDmode)
954 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
955 mode != VOIDmode;
956 mode = GET_MODE_WIDER_MODE (mode))
957 if (HARD_REGNO_MODE_OK (regno, mode)
958 && have_insn_for (SET, mode))
959 best_mode = mode;
960
53800dbe 961 mode = best_mode;
962 if (mode == VOIDmode)
963 abort ();
964
965 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
966 if (size % align != 0)
967 size = CEIL (size, align) * align;
968 apply_args_reg_offset[regno] = size;
969 size += GET_MODE_SIZE (mode);
970 apply_args_mode[regno] = mode;
971 }
972 else
973 {
974 apply_args_mode[regno] = VOIDmode;
975 apply_args_reg_offset[regno] = 0;
976 }
977 }
978 return size;
979}
980
981/* Return the size required for the block returned by __builtin_apply,
982 and initialize apply_result_mode. */
983
984static int
985apply_result_size ()
986{
987 static int size = -1;
988 int align, regno;
989 enum machine_mode mode;
990
991 /* The values computed by this function never change. */
992 if (size < 0)
993 {
994 size = 0;
995
996 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
997 if (FUNCTION_VALUE_REGNO_P (regno))
998 {
999 /* Search for the proper mode for copying this register's
1000 value. I'm not sure this is right, but it works so far. */
1001 enum machine_mode best_mode = VOIDmode;
1002
1003 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
1004 mode != TImode;
1005 mode = GET_MODE_WIDER_MODE (mode))
1006 if (HARD_REGNO_MODE_OK (regno, mode))
1007 best_mode = mode;
1008
1009 if (best_mode == VOIDmode)
1010 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
1011 mode != VOIDmode;
1012 mode = GET_MODE_WIDER_MODE (mode))
1013 if (HARD_REGNO_MODE_OK (regno, mode)
ad99e708 1014 && have_insn_for (SET, mode))
53800dbe 1015 best_mode = mode;
1016
223097eb 1017 if (best_mode == VOIDmode)
1018 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
1019 mode != VOIDmode;
1020 mode = GET_MODE_WIDER_MODE (mode))
1021 if (HARD_REGNO_MODE_OK (regno, mode)
1022 && have_insn_for (SET, mode))
f0ce3b1f 1023 best_mode = mode;
223097eb 1024
1025 if (best_mode == VOIDmode)
1026 for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
1027 mode != VOIDmode;
1028 mode = GET_MODE_WIDER_MODE (mode))
1029 if (HARD_REGNO_MODE_OK (regno, mode)
1030 && have_insn_for (SET, mode))
1031 best_mode = mode;
1032
53800dbe 1033 mode = best_mode;
1034 if (mode == VOIDmode)
1035 abort ();
1036
1037 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1038 if (size % align != 0)
1039 size = CEIL (size, align) * align;
1040 size += GET_MODE_SIZE (mode);
1041 apply_result_mode[regno] = mode;
1042 }
1043 else
1044 apply_result_mode[regno] = VOIDmode;
1045
1046 /* Allow targets that use untyped_call and untyped_return to override
1047 the size so that machine-specific information can be stored here. */
1048#ifdef APPLY_RESULT_SIZE
1049 size = APPLY_RESULT_SIZE;
1050#endif
1051 }
1052 return size;
1053}
1054
1055#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1056/* Create a vector describing the result block RESULT. If SAVEP is true,
1057 the result block is used to save the values; otherwise it is used to
1058 restore the values. */
1059
1060static rtx
1061result_vector (savep, result)
1062 int savep;
1063 rtx result;
1064{
1065 int regno, size, align, nelts;
1066 enum machine_mode mode;
1067 rtx reg, mem;
1068 rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
bf8e3599 1069
53800dbe 1070 size = nelts = 0;
1071 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1072 if ((mode = apply_result_mode[regno]) != VOIDmode)
1073 {
1074 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1075 if (size % align != 0)
1076 size = CEIL (size, align) * align;
1077 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
e513d163 1078 mem = adjust_address (result, mode, size);
53800dbe 1079 savevec[nelts++] = (savep
1080 ? gen_rtx_SET (VOIDmode, mem, reg)
1081 : gen_rtx_SET (VOIDmode, reg, mem));
1082 size += GET_MODE_SIZE (mode);
1083 }
1084 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1085}
1086#endif /* HAVE_untyped_call or HAVE_untyped_return */
1087
1088/* Save the state required to perform an untyped call with the same
1089 arguments as were passed to the current function. */
1090
1091static rtx
1092expand_builtin_apply_args_1 ()
1093{
1094 rtx registers;
1095 int size, align, regno;
1096 enum machine_mode mode;
1097
1098 /* Create a block where the arg-pointer, structure value address,
1099 and argument registers can be saved. */
1100 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1101
1102 /* Walk past the arg-pointer and structure value address. */
1103 size = GET_MODE_SIZE (Pmode);
1104 if (struct_value_rtx)
1105 size += GET_MODE_SIZE (Pmode);
1106
1107 /* Save each register used in calling a function to the block. */
1108 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1109 if ((mode = apply_args_mode[regno]) != VOIDmode)
1110 {
1111 rtx tem;
1112
1113 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1114 if (size % align != 0)
1115 size = CEIL (size, align) * align;
1116
1117 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1118
e513d163 1119 emit_move_insn (adjust_address (registers, mode, size), tem);
53800dbe 1120 size += GET_MODE_SIZE (mode);
1121 }
1122
1123 /* Save the arg pointer to the block. */
e513d163 1124 emit_move_insn (adjust_address (registers, Pmode, 0),
53800dbe 1125 copy_to_reg (virtual_incoming_args_rtx));
1126 size = GET_MODE_SIZE (Pmode);
1127
1128 /* Save the structure value address unless this is passed as an
1129 "invisible" first argument. */
1130 if (struct_value_incoming_rtx)
1131 {
e513d163 1132 emit_move_insn (adjust_address (registers, Pmode, size),
53800dbe 1133 copy_to_reg (struct_value_incoming_rtx));
1134 size += GET_MODE_SIZE (Pmode);
1135 }
1136
1137 /* Return the address of the block. */
1138 return copy_addr_to_reg (XEXP (registers, 0));
1139}
1140
1141/* __builtin_apply_args returns block of memory allocated on
1142 the stack into which is stored the arg pointer, structure
1143 value address, static chain, and all the registers that might
1144 possibly be used in performing a function call. The code is
1145 moved to the start of the function so the incoming values are
1146 saved. */
27d0c333 1147
53800dbe 1148static rtx
1149expand_builtin_apply_args ()
1150{
1151 /* Don't do __builtin_apply_args more than once in a function.
1152 Save the result of the first call and reuse it. */
1153 if (apply_args_value != 0)
1154 return apply_args_value;
1155 {
1156 /* When this function is called, it means that registers must be
1157 saved on entry to this function. So we migrate the
1158 call to the first insn of this function. */
1159 rtx temp;
1160 rtx seq;
1161
1162 start_sequence ();
1163 temp = expand_builtin_apply_args_1 ();
1164 seq = get_insns ();
1165 end_sequence ();
1166
1167 apply_args_value = temp;
1168
31d3e01c 1169 /* Put the insns after the NOTE that starts the function.
1170 If this is inside a start_sequence, make the outer-level insn
53800dbe 1171 chain current, so the code is placed at the start of the
1172 function. */
1173 push_topmost_sequence ();
31d3e01c 1174 emit_insn_before (seq, NEXT_INSN (get_insns ()));
53800dbe 1175 pop_topmost_sequence ();
1176 return temp;
1177 }
1178}
1179
1180/* Perform an untyped call and save the state required to perform an
1181 untyped return of whatever value was returned by the given function. */
1182
1183static rtx
1184expand_builtin_apply (function, arguments, argsize)
1185 rtx function, arguments, argsize;
1186{
1187 int size, align, regno;
1188 enum machine_mode mode;
2a631e19 1189 rtx incoming_args, result, reg, dest, src, call_insn;
53800dbe 1190 rtx old_stack_level = 0;
1191 rtx call_fusage = 0;
1192
726ec87c 1193#ifdef POINTERS_EXTEND_UNSIGNED
1194 if (GET_MODE (arguments) != Pmode)
1195 arguments = convert_memory_address (Pmode, arguments);
1196#endif
1197
53800dbe 1198 /* Create a block where the return registers can be saved. */
1199 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1200
53800dbe 1201 /* Fetch the arg pointer from the ARGUMENTS block. */
1202 incoming_args = gen_reg_rtx (Pmode);
726ec87c 1203 emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
53800dbe 1204#ifndef STACK_GROWS_DOWNWARD
ad99e708 1205 incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1206 incoming_args, 0, OPTAB_LIB_WIDEN);
53800dbe 1207#endif
1208
1209 /* Perform postincrements before actually calling the function. */
1210 emit_queue ();
1211
04a46d40 1212 /* Push a new argument block and copy the arguments. Do not allow
1213 the (potential) memcpy call below to interfere with our stack
1214 manipulations. */
53800dbe 1215 do_pending_stack_adjust ();
04a46d40 1216 NO_DEFER_POP;
53800dbe 1217
1218 /* Save the stack with nonlocal if available */
1219#ifdef HAVE_save_stack_nonlocal
1220 if (HAVE_save_stack_nonlocal)
1221 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1222 else
1223#endif
1224 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1225
1226 /* Push a block of memory onto the stack to store the memory arguments.
1227 Save the address in a register, and copy the memory arguments. ??? I
1228 haven't figured out how the calling convention macros effect this,
1229 but it's likely that the source and/or destination addresses in
1230 the block copy will need updating in machine specific ways. */
91b70175 1231 dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
2a631e19 1232 dest = gen_rtx_MEM (BLKmode, dest);
1233 set_mem_align (dest, PARM_BOUNDARY);
1234 src = gen_rtx_MEM (BLKmode, incoming_args);
1235 set_mem_align (src, PARM_BOUNDARY);
0378dbdc 1236 emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
53800dbe 1237
1238 /* Refer to the argument block. */
1239 apply_args_size ();
1240 arguments = gen_rtx_MEM (BLKmode, arguments);
2a631e19 1241 set_mem_align (arguments, PARM_BOUNDARY);
53800dbe 1242
1243 /* Walk past the arg-pointer and structure value address. */
1244 size = GET_MODE_SIZE (Pmode);
1245 if (struct_value_rtx)
1246 size += GET_MODE_SIZE (Pmode);
1247
1248 /* Restore each of the registers previously saved. Make USE insns
1249 for each of these registers for use in making the call. */
1250 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1251 if ((mode = apply_args_mode[regno]) != VOIDmode)
1252 {
1253 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1254 if (size % align != 0)
1255 size = CEIL (size, align) * align;
1256 reg = gen_rtx_REG (mode, regno);
e513d163 1257 emit_move_insn (reg, adjust_address (arguments, mode, size));
53800dbe 1258 use_reg (&call_fusage, reg);
1259 size += GET_MODE_SIZE (mode);
1260 }
1261
1262 /* Restore the structure value address unless this is passed as an
1263 "invisible" first argument. */
1264 size = GET_MODE_SIZE (Pmode);
1265 if (struct_value_rtx)
1266 {
1267 rtx value = gen_reg_rtx (Pmode);
e513d163 1268 emit_move_insn (value, adjust_address (arguments, Pmode, size));
53800dbe 1269 emit_move_insn (struct_value_rtx, value);
1270 if (GET_CODE (struct_value_rtx) == REG)
f0ce3b1f 1271 use_reg (&call_fusage, struct_value_rtx);
53800dbe 1272 size += GET_MODE_SIZE (Pmode);
1273 }
1274
1275 /* All arguments and registers used for the call are set up by now! */
707ff8b1 1276 function = prepare_call_address (function, NULL_TREE, &call_fusage, 0, 0);
53800dbe 1277
1278 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1279 and we don't want to load it into a register as an optimization,
1280 because prepare_call_address already did it if it should be done. */
1281 if (GET_CODE (function) != SYMBOL_REF)
1282 function = memory_address (FUNCTION_MODE, function);
1283
1284 /* Generate the actual call instruction and save the return value. */
1285#ifdef HAVE_untyped_call
1286 if (HAVE_untyped_call)
1287 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1288 result, result_vector (1, result)));
1289 else
1290#endif
1291#ifdef HAVE_call_value
1292 if (HAVE_call_value)
1293 {
1294 rtx valreg = 0;
1295
1296 /* Locate the unique return register. It is not possible to
1297 express a call that sets more than one return register using
1298 call_value; use untyped_call for that. In fact, untyped_call
1299 only needs to save the return registers in the given block. */
1300 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1301 if ((mode = apply_result_mode[regno]) != VOIDmode)
1302 {
1303 if (valreg)
1304 abort (); /* HAVE_untyped_call required. */
1305 valreg = gen_rtx_REG (mode, regno);
1306 }
1307
2ed6c343 1308 emit_call_insn (GEN_CALL_VALUE (valreg,
53800dbe 1309 gen_rtx_MEM (FUNCTION_MODE, function),
1310 const0_rtx, NULL_RTX, const0_rtx));
1311
e513d163 1312 emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
53800dbe 1313 }
1314 else
1315#endif
1316 abort ();
1317
1318 /* Find the CALL insn we just emitted. */
1319 for (call_insn = get_last_insn ();
1320 call_insn && GET_CODE (call_insn) != CALL_INSN;
1321 call_insn = PREV_INSN (call_insn))
1322 ;
1323
1324 if (! call_insn)
1325 abort ();
1326
1327 /* Put the register usage information on the CALL. If there is already
1328 some usage information, put ours at the end. */
1329 if (CALL_INSN_FUNCTION_USAGE (call_insn))
1330 {
1331 rtx link;
1332
1333 for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
1334 link = XEXP (link, 1))
1335 ;
1336
1337 XEXP (link, 1) = call_fusage;
1338 }
1339 else
1340 CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
1341
1342 /* Restore the stack. */
1343#ifdef HAVE_save_stack_nonlocal
1344 if (HAVE_save_stack_nonlocal)
1345 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1346 else
1347#endif
1348 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1349
04a46d40 1350 OK_DEFER_POP;
1351
53800dbe 1352 /* Return the address of the result block. */
1353 return copy_addr_to_reg (XEXP (result, 0));
1354}
1355
1356/* Perform an untyped return. */
1357
1358static void
1359expand_builtin_return (result)
1360 rtx result;
1361{
1362 int size, align, regno;
1363 enum machine_mode mode;
1364 rtx reg;
1365 rtx call_fusage = 0;
1366
726ec87c 1367#ifdef POINTERS_EXTEND_UNSIGNED
1368 if (GET_MODE (result) != Pmode)
1369 result = convert_memory_address (Pmode, result);
1370#endif
1371
53800dbe 1372 apply_result_size ();
1373 result = gen_rtx_MEM (BLKmode, result);
1374
1375#ifdef HAVE_untyped_return
1376 if (HAVE_untyped_return)
1377 {
1378 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1379 emit_barrier ();
1380 return;
1381 }
1382#endif
1383
1384 /* Restore the return value and note that each value is used. */
1385 size = 0;
1386 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1387 if ((mode = apply_result_mode[regno]) != VOIDmode)
1388 {
1389 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1390 if (size % align != 0)
1391 size = CEIL (size, align) * align;
1392 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
e513d163 1393 emit_move_insn (reg, adjust_address (result, mode, size));
53800dbe 1394
1395 push_to_sequence (call_fusage);
1396 emit_insn (gen_rtx_USE (VOIDmode, reg));
1397 call_fusage = get_insns ();
1398 end_sequence ();
1399 size += GET_MODE_SIZE (mode);
1400 }
1401
1402 /* Put the USE insns before the return. */
31d3e01c 1403 emit_insn (call_fusage);
53800dbe 1404
1405 /* Return whatever values was restored by jumping directly to the end
1406 of the function. */
1407 expand_null_return ();
1408}
1409
539a3a92 1410/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
27d0c333 1411
539a3a92 1412static enum type_class
1413type_to_class (type)
1414 tree type;
1415{
1416 switch (TREE_CODE (type))
1417 {
1418 case VOID_TYPE: return void_type_class;
1419 case INTEGER_TYPE: return integer_type_class;
1420 case CHAR_TYPE: return char_type_class;
1421 case ENUMERAL_TYPE: return enumeral_type_class;
1422 case BOOLEAN_TYPE: return boolean_type_class;
1423 case POINTER_TYPE: return pointer_type_class;
1424 case REFERENCE_TYPE: return reference_type_class;
1425 case OFFSET_TYPE: return offset_type_class;
1426 case REAL_TYPE: return real_type_class;
1427 case COMPLEX_TYPE: return complex_type_class;
1428 case FUNCTION_TYPE: return function_type_class;
1429 case METHOD_TYPE: return method_type_class;
1430 case RECORD_TYPE: return record_type_class;
1431 case UNION_TYPE:
1432 case QUAL_UNION_TYPE: return union_type_class;
1433 case ARRAY_TYPE: return (TYPE_STRING_FLAG (type)
1434 ? string_type_class : array_type_class);
1435 case SET_TYPE: return set_type_class;
1436 case FILE_TYPE: return file_type_class;
1437 case LANG_TYPE: return lang_type_class;
1438 default: return no_type_class;
1439 }
1440}
bf8e3599 1441
53800dbe 1442/* Expand a call to __builtin_classify_type with arguments found in
1443 ARGLIST. */
27d0c333 1444
53800dbe 1445static rtx
1446expand_builtin_classify_type (arglist)
1447 tree arglist;
1448{
1449 if (arglist != 0)
539a3a92 1450 return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
53800dbe 1451 return GEN_INT (no_type_class);
1452}
1453
1454/* Expand expression EXP, which is a call to __builtin_constant_p. */
27d0c333 1455
53800dbe 1456static rtx
1457expand_builtin_constant_p (exp)
1458 tree exp;
1459{
1460 tree arglist = TREE_OPERAND (exp, 1);
1461 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
650e4c94 1462 rtx tmp;
53800dbe 1463
1464 if (arglist == 0)
1465 return const0_rtx;
650e4c94 1466 arglist = TREE_VALUE (arglist);
53800dbe 1467
650e4c94 1468 /* We have taken care of the easy cases during constant folding. This
c7926a82 1469 case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE
1470 get a chance to see if it can deduce whether ARGLIST is constant. */
53800dbe 1471
e6f295fb 1472 current_function_calls_constant_p = 1;
1473
650e4c94 1474 tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
1475 tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
1476 return tmp;
53800dbe 1477}
1478
0a68165a 1479/* Return mathematic function equivalent to FN but operating directly on TYPE,
1480 if available. */
1481tree
1482mathfn_built_in (type, fn)
1483 tree type;
1484 enum built_in_function fn;
1485{
1486 enum built_in_function fcode = NOT_BUILT_IN;
1487 if (TYPE_MODE (type) == TYPE_MODE (double_type_node))
1488 switch (fn)
1489 {
1490 case BUILT_IN_SQRT:
1491 case BUILT_IN_SQRTF:
1492 case BUILT_IN_SQRTL:
1493 fcode = BUILT_IN_SQRT;
1494 break;
1495 case BUILT_IN_SIN:
1496 case BUILT_IN_SINF:
1497 case BUILT_IN_SINL:
1498 fcode = BUILT_IN_SIN;
1499 break;
1500 case BUILT_IN_COS:
1501 case BUILT_IN_COSF:
1502 case BUILT_IN_COSL:
1503 fcode = BUILT_IN_COS;
1504 break;
1505 case BUILT_IN_EXP:
1506 case BUILT_IN_EXPF:
1507 case BUILT_IN_EXPL:
1508 fcode = BUILT_IN_EXP;
1509 break;
1510 case BUILT_IN_FLOOR:
1511 case BUILT_IN_FLOORF:
1512 case BUILT_IN_FLOORL:
1513 fcode = BUILT_IN_FLOOR;
1514 break;
1515 case BUILT_IN_CEIL:
1516 case BUILT_IN_CEILF:
1517 case BUILT_IN_CEILL:
1518 fcode = BUILT_IN_CEIL;
1519 break;
1520 case BUILT_IN_TRUNC:
1521 case BUILT_IN_TRUNCF:
1522 case BUILT_IN_TRUNCL:
1523 fcode = BUILT_IN_TRUNC;
1524 break;
1525 case BUILT_IN_ROUND:
1526 case BUILT_IN_ROUNDF:
1527 case BUILT_IN_ROUNDL:
1528 fcode = BUILT_IN_ROUND;
1529 break;
1530 case BUILT_IN_NEARBYINT:
1531 case BUILT_IN_NEARBYINTF:
1532 case BUILT_IN_NEARBYINTL:
1533 fcode = BUILT_IN_NEARBYINT;
1534 break;
1535 default:
1536 abort ();
1537 }
1538 else if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
1539 switch (fn)
1540 {
1541 case BUILT_IN_SQRT:
1542 case BUILT_IN_SQRTF:
1543 case BUILT_IN_SQRTL:
1544 fcode = BUILT_IN_SQRTF;
1545 break;
1546 case BUILT_IN_SIN:
1547 case BUILT_IN_SINF:
1548 case BUILT_IN_SINL:
1549 fcode = BUILT_IN_SINF;
1550 break;
1551 case BUILT_IN_COS:
1552 case BUILT_IN_COSF:
1553 case BUILT_IN_COSL:
1554 fcode = BUILT_IN_COSF;
1555 break;
1556 case BUILT_IN_EXP:
1557 case BUILT_IN_EXPF:
1558 case BUILT_IN_EXPL:
1559 fcode = BUILT_IN_EXPF;
1560 break;
1561 case BUILT_IN_FLOOR:
1562 case BUILT_IN_FLOORF:
1563 case BUILT_IN_FLOORL:
1564 fcode = BUILT_IN_FLOORF;
1565 break;
1566 case BUILT_IN_CEIL:
1567 case BUILT_IN_CEILF:
1568 case BUILT_IN_CEILL:
1569 fcode = BUILT_IN_CEILF;
1570 break;
1571 case BUILT_IN_TRUNC:
1572 case BUILT_IN_TRUNCF:
1573 case BUILT_IN_TRUNCL:
1574 fcode = BUILT_IN_TRUNCF;
1575 break;
1576 case BUILT_IN_ROUND:
1577 case BUILT_IN_ROUNDF:
1578 case BUILT_IN_ROUNDL:
1579 fcode = BUILT_IN_ROUNDF;
1580 break;
1581 case BUILT_IN_NEARBYINT:
1582 case BUILT_IN_NEARBYINTF:
1583 case BUILT_IN_NEARBYINTL:
1584 fcode = BUILT_IN_NEARBYINTF;
1585 break;
1586 default:
1587 abort ();
1588 }
1589 else if (TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
1590 switch (fn)
1591 {
1592 case BUILT_IN_SQRT:
1593 case BUILT_IN_SQRTF:
1594 case BUILT_IN_SQRTL:
1595 fcode = BUILT_IN_SQRTL;
1596 break;
1597 case BUILT_IN_SIN:
1598 case BUILT_IN_SINF:
1599 case BUILT_IN_SINL:
1600 fcode = BUILT_IN_SINL;
1601 break;
1602 case BUILT_IN_COS:
1603 case BUILT_IN_COSF:
1604 case BUILT_IN_COSL:
1605 fcode = BUILT_IN_COSL;
1606 break;
1607 case BUILT_IN_EXP:
1608 case BUILT_IN_EXPF:
1609 case BUILT_IN_EXPL:
1610 fcode = BUILT_IN_EXPL;
1611 break;
1612 case BUILT_IN_FLOOR:
1613 case BUILT_IN_FLOORF:
1614 case BUILT_IN_FLOORL:
1615 fcode = BUILT_IN_FLOORL;
1616 break;
1617 case BUILT_IN_CEIL:
1618 case BUILT_IN_CEILF:
1619 case BUILT_IN_CEILL:
1620 fcode = BUILT_IN_CEILL;
1621 break;
1622 case BUILT_IN_TRUNC:
1623 case BUILT_IN_TRUNCF:
1624 case BUILT_IN_TRUNCL:
1625 fcode = BUILT_IN_TRUNCL;
1626 break;
1627 case BUILT_IN_ROUND:
1628 case BUILT_IN_ROUNDF:
1629 case BUILT_IN_ROUNDL:
1630 fcode = BUILT_IN_ROUNDL;
1631 break;
1632 case BUILT_IN_NEARBYINT:
1633 case BUILT_IN_NEARBYINTF:
1634 case BUILT_IN_NEARBYINTL:
1635 fcode = BUILT_IN_NEARBYINTL;
1636 break;
1637 default:
1638 abort ();
1639 }
1640 return implicit_built_in_decls[fcode];
1641}
1642
53800dbe 1643/* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1644 Return 0 if a normal call should be emitted rather than expanding the
1645 function in-line. EXP is the expression that is a call to the builtin
1646 function; if convenient, the result should be placed in TARGET.
1647 SUBTARGET may be used as the target for computing one of EXP's operands. */
27d0c333 1648
53800dbe 1649static rtx
1650expand_builtin_mathfn (exp, target, subtarget)
1651 tree exp;
1652 rtx target, subtarget;
1653{
bf8e3599 1654 optab builtin_optab;
53800dbe 1655 rtx op0, insns;
1656 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1657 tree arglist = TREE_OPERAND (exp, 1);
920d0fb5 1658 enum machine_mode argmode;
805e22b2 1659 bool errno_set = true;
53800dbe 1660
0eb671f7 1661 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
53800dbe 1662 return 0;
1663
1664 /* Stabilize and compute the argument. */
1665 if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
1666 && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
1667 {
1668 exp = copy_node (exp);
53800dbe 1669 TREE_OPERAND (exp, 1) = arglist;
f6326164 1670 /* Wrap the computation of the argument in a SAVE_EXPR. That
1671 way, if we need to expand the argument again (as in the
1672 flag_errno_math case below where we cannot directly set
1673 errno), we will not perform side-effects more than once.
1674 Note that here we're mutating the original EXP as well as the
1675 copy; that's the right thing to do in case the original EXP
1676 is expanded later. */
53800dbe 1677 TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
f6326164 1678 arglist = copy_node (arglist);
53800dbe 1679 }
1680 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
1681
1682 /* Make a suitable register to place result in. */
1683 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
1684
1685 emit_queue ();
1686 start_sequence ();
1687
1688 switch (DECL_FUNCTION_CODE (fndecl))
1689 {
d2d4bdde 1690 case BUILT_IN_SIN:
1691 case BUILT_IN_SINF:
1692 case BUILT_IN_SINL:
53800dbe 1693 builtin_optab = sin_optab; break;
d2d4bdde 1694 case BUILT_IN_COS:
1695 case BUILT_IN_COSF:
1696 case BUILT_IN_COSL:
53800dbe 1697 builtin_optab = cos_optab; break;
75357f66 1698 case BUILT_IN_SQRT:
d2d4bdde 1699 case BUILT_IN_SQRTF:
1700 case BUILT_IN_SQRTL:
53800dbe 1701 builtin_optab = sqrt_optab; break;
42721db0 1702 case BUILT_IN_EXP:
1703 case BUILT_IN_EXPF:
1704 case BUILT_IN_EXPL:
1705 builtin_optab = exp_optab; break;
1706 case BUILT_IN_LOG:
1707 case BUILT_IN_LOGF:
1708 case BUILT_IN_LOGL:
1709 builtin_optab = log_optab; break;
805e22b2 1710 case BUILT_IN_FLOOR:
1711 case BUILT_IN_FLOORF:
1712 case BUILT_IN_FLOORL:
1713 errno_set = false ; builtin_optab = floor_optab; break;
1714 case BUILT_IN_CEIL:
1715 case BUILT_IN_CEILF:
1716 case BUILT_IN_CEILL:
1717 errno_set = false ; builtin_optab = ceil_optab; break;
1718 case BUILT_IN_TRUNC:
1719 case BUILT_IN_TRUNCF:
1720 case BUILT_IN_TRUNCL:
1721 errno_set = false ; builtin_optab = trunc_optab; break;
1722 case BUILT_IN_ROUND:
1723 case BUILT_IN_ROUNDF:
1724 case BUILT_IN_ROUNDL:
1725 errno_set = false ; builtin_optab = round_optab; break;
1726 case BUILT_IN_NEARBYINT:
1727 case BUILT_IN_NEARBYINTF:
1728 case BUILT_IN_NEARBYINTL:
1729 errno_set = false ; builtin_optab = nearbyint_optab; break;
42721db0 1730 default:
53800dbe 1731 abort ();
1732 }
1733
1734 /* Compute into TARGET.
1735 Set TARGET to wherever the result comes back. */
920d0fb5 1736 argmode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
1737 target = expand_unop (argmode, builtin_optab, op0, target, 0);
53800dbe 1738
1739 /* If we were unable to expand via the builtin, stop the
1740 sequence (without outputting the insns) and return 0, causing
1741 a call to the library function. */
1742 if (target == 0)
1743 {
1744 end_sequence ();
1745 return 0;
1746 }
1747
920d0fb5 1748 /* If errno must be maintained, we must set it to EDOM for NaN results. */
53800dbe 1749
805e22b2 1750 if (flag_errno_math && errno_set && HONOR_NANS (argmode))
53800dbe 1751 {
1752 rtx lab1;
1753
53800dbe 1754 lab1 = gen_label_rtx ();
1755
1756 /* Test the result; if it is NaN, set errno=EDOM because
1757 the argument was not in the domain. */
1758 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
7e69f45b 1759 0, lab1);
53800dbe 1760
1761#ifdef TARGET_EDOM
9342ee68 1762 {
53800dbe 1763#ifdef GEN_ERRNO_RTX
9342ee68 1764 rtx errno_rtx = GEN_ERRNO_RTX;
53800dbe 1765#else
9342ee68 1766 rtx errno_rtx
1767 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
53800dbe 1768#endif
1769
9342ee68 1770 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1771 }
53800dbe 1772#else
1773 /* We can't set errno=EDOM directly; let the library call do it.
1774 Pop the arguments right away in case the call gets deleted. */
1775 NO_DEFER_POP;
1776 expand_call (exp, target, 0);
1777 OK_DEFER_POP;
1778#endif
1779
1780 emit_label (lab1);
1781 }
1782
1783 /* Output the entire sequence. */
1784 insns = get_insns ();
1785 end_sequence ();
31d3e01c 1786 emit_insn (insns);
bf8e3599 1787
53800dbe 1788 return target;
1789}
1790
1791/* Expand expression EXP which is a call to the strlen builtin. Return 0
1792 if we failed the caller should emit a normal call, otherwise
aed0bd19 1793 try to get the result in TARGET, if convenient. */
f7c44134 1794
53800dbe 1795static rtx
aed0bd19 1796expand_builtin_strlen (exp, target)
53800dbe 1797 tree exp;
1798 rtx target;
53800dbe 1799{
1800 tree arglist = TREE_OPERAND (exp, 1);
1801 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1802
0eb671f7 1803 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
53800dbe 1804 return 0;
1805 else
1806 {
911c0150 1807 rtx pat;
53800dbe 1808 tree src = TREE_VALUE (arglist);
53800dbe 1809
1810 int align
1811 = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1812
911c0150 1813 rtx result, src_reg, char_rtx, before_strlen;
53800dbe 1814 enum machine_mode insn_mode = value_mode, char_mode;
ef2c4a29 1815 enum insn_code icode = CODE_FOR_nothing;
53800dbe 1816
53800dbe 1817 /* If SRC is not a pointer type, don't do this operation inline. */
1818 if (align == 0)
1819 return 0;
1820
911c0150 1821 /* Bail out if we can't compute strlen in the right mode. */
53800dbe 1822 while (insn_mode != VOIDmode)
1823 {
1824 icode = strlen_optab->handlers[(int) insn_mode].insn_code;
1825 if (icode != CODE_FOR_nothing)
c28ae87f 1826 break;
53800dbe 1827
1828 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
1829 }
1830 if (insn_mode == VOIDmode)
1831 return 0;
1832
1833 /* Make a place to write the result of the instruction. */
1834 result = target;
1835 if (! (result != 0
1836 && GET_CODE (result) == REG
1837 && GET_MODE (result) == insn_mode
1838 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1839 result = gen_reg_rtx (insn_mode);
1840
911c0150 1841 /* Make a place to hold the source address. We will not expand
1842 the actual source until we are sure that the expansion will
1843 not fail -- there are trees that cannot be expanded twice. */
1844 src_reg = gen_reg_rtx (Pmode);
53800dbe 1845
911c0150 1846 /* Mark the beginning of the strlen sequence so we can emit the
1847 source operand later. */
f0ce3b1f 1848 before_strlen = get_last_insn ();
53800dbe 1849
53800dbe 1850 char_rtx = const0_rtx;
f7c44134 1851 char_mode = insn_data[(int) icode].operand[2].mode;
1852 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
1853 char_mode))
53800dbe 1854 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
1855
911c0150 1856 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
1857 char_rtx, GEN_INT (align));
1858 if (! pat)
1859 return 0;
1860 emit_insn (pat);
1861
1862 /* Now that we are assured of success, expand the source. */
1863 start_sequence ();
bf8e3599 1864 pat = memory_address (BLKmode,
f7c44134 1865 expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
911c0150 1866 if (pat != src_reg)
1867 emit_move_insn (src_reg, pat);
31d3e01c 1868 pat = get_insns ();
911c0150 1869 end_sequence ();
bceb0d1f 1870
1871 if (before_strlen)
1872 emit_insn_after (pat, before_strlen);
1873 else
1874 emit_insn_before (pat, get_insns ());
53800dbe 1875
1876 /* Return the value in the proper mode for this function. */
1877 if (GET_MODE (result) == value_mode)
911c0150 1878 target = result;
53800dbe 1879 else if (target != 0)
911c0150 1880 convert_move (target, result, 0);
53800dbe 1881 else
911c0150 1882 target = convert_to_mode (value_mode, result, 0);
1883
1884 return target;
53800dbe 1885 }
1886}
1887
17f5ea87 1888/* Expand a call to the strstr builtin. Return 0 if we failed the
1889 caller should emit a normal call, otherwise try to get the result
1890 in TARGET, if convenient (and in mode MODE if that's convenient). */
1891
1892static rtx
1893expand_builtin_strstr (arglist, target, mode)
1894 tree arglist;
1895 rtx target;
1896 enum machine_mode mode;
1897{
8a06f2d4 1898 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
17f5ea87 1899 return 0;
1900 else
1901 {
1902 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
7e15618b 1903 tree fn;
83d79705 1904 const char *p1, *p2;
17f5ea87 1905
83d79705 1906 p2 = c_getstr (s2);
1907 if (p2 == NULL)
17f5ea87 1908 return 0;
1909
83d79705 1910 p1 = c_getstr (s1);
1911 if (p1 != NULL)
1912 {
1913 const char *r = strstr (p1, p2);
17f5ea87 1914
83d79705 1915 if (r == NULL)
1916 return const0_rtx;
17f5ea87 1917
83d79705 1918 /* Return an offset into the constant string argument. */
1919 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1920 s1, ssize_int (r - p1))),
1921 target, mode, EXPAND_NORMAL);
17f5ea87 1922 }
83d79705 1923
1924 if (p2[0] == '\0')
1925 return expand_expr (s1, target, mode, EXPAND_NORMAL);
1926
1927 if (p2[1] != '\0')
1928 return 0;
1929
0a68165a 1930 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
83d79705 1931 if (!fn)
1932 return 0;
1933
1934 /* New argument list transforming strstr(s1, s2) to
1935 strchr(s1, s2[0]). */
1936 arglist =
1937 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
1938 arglist = tree_cons (NULL_TREE, s1, arglist);
7e15618b 1939 return expand_expr (build_function_call_expr (fn, arglist),
1940 target, mode, EXPAND_NORMAL);
17f5ea87 1941 }
1942}
1943
83d79705 1944/* Expand a call to the strchr builtin. Return 0 if we failed the
46f3a74a 1945 caller should emit a normal call, otherwise try to get the result
1946 in TARGET, if convenient (and in mode MODE if that's convenient). */
1947
1948static rtx
83d79705 1949expand_builtin_strchr (arglist, target, mode)
46f3a74a 1950 tree arglist;
1951 rtx target;
1952 enum machine_mode mode;
1953{
8a06f2d4 1954 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
46f3a74a 1955 return 0;
1956 else
1957 {
1958 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
83d79705 1959 const char *p1;
46f3a74a 1960
83d79705 1961 if (TREE_CODE (s2) != INTEGER_CST)
1962 return 0;
1963
1964 p1 = c_getstr (s1);
1965 if (p1 != NULL)
1966 {
ecc318ff 1967 char c;
1968 const char *r;
1969
1970 if (target_char_cast (s2, &c))
1971 return 0;
1972
1973 r = strchr (p1, c);
83d79705 1974
1975 if (r == NULL)
46f3a74a 1976 return const0_rtx;
83d79705 1977
1978 /* Return an offset into the constant string argument. */
1979 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1980 s1, ssize_int (r - p1))),
1981 target, mode, EXPAND_NORMAL);
46f3a74a 1982 }
1983
83d79705 1984 /* FIXME: Should use here strchrM optab so that ports can optimize
1985 this. */
1986 return 0;
1987 }
1988}
1989
1990/* Expand a call to the strrchr builtin. Return 0 if we failed the
1991 caller should emit a normal call, otherwise try to get the result
1992 in TARGET, if convenient (and in mode MODE if that's convenient). */
1993
1994static rtx
1995expand_builtin_strrchr (arglist, target, mode)
1996 tree arglist;
1997 rtx target;
1998 enum machine_mode mode;
1999{
8a06f2d4 2000 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
83d79705 2001 return 0;
2002 else
2003 {
2004 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
7e15618b 2005 tree fn;
83d79705 2006 const char *p1;
2007
2008 if (TREE_CODE (s2) != INTEGER_CST)
46f3a74a 2009 return 0;
2010
83d79705 2011 p1 = c_getstr (s1);
2012 if (p1 != NULL)
2013 {
ecc318ff 2014 char c;
2015 const char *r;
2016
2017 if (target_char_cast (s2, &c))
2018 return 0;
2019
2020 r = strrchr (p1, c);
83d79705 2021
2022 if (r == NULL)
46f3a74a 2023 return const0_rtx;
46f3a74a 2024
83d79705 2025 /* Return an offset into the constant string argument. */
2026 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2027 s1, ssize_int (r - p1))),
2028 target, mode, EXPAND_NORMAL);
2029 }
46f3a74a 2030
83d79705 2031 if (! integer_zerop (s2))
2032 return 0;
2033
0a68165a 2034 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
83d79705 2035 if (!fn)
2036 return 0;
2037
2038 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
7e15618b 2039 return expand_expr (build_function_call_expr (fn, arglist),
2040 target, mode, EXPAND_NORMAL);
83d79705 2041 }
2042}
2043
2044/* Expand a call to the strpbrk builtin. Return 0 if we failed the
2045 caller should emit a normal call, otherwise try to get the result
2046 in TARGET, if convenient (and in mode MODE if that's convenient). */
2047
2048static rtx
2049expand_builtin_strpbrk (arglist, target, mode)
2050 tree arglist;
2051 rtx target;
2052 enum machine_mode mode;
2053{
8a06f2d4 2054 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
83d79705 2055 return 0;
2056 else
2057 {
2058 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
7e15618b 2059 tree fn;
83d79705 2060 const char *p1, *p2;
2061
2062 p2 = c_getstr (s2);
2063 if (p2 == NULL)
2064 return 0;
2065
2066 p1 = c_getstr (s1);
2067 if (p1 != NULL)
2068 {
2069 const char *r = strpbrk (p1, p2);
2070
2071 if (r == NULL)
2072 return const0_rtx;
2073
2074 /* Return an offset into the constant string argument. */
2075 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2076 s1, ssize_int (r - p1))),
2077 target, mode, EXPAND_NORMAL);
46f3a74a 2078 }
83d79705 2079
2080 if (p2[0] == '\0')
2081 {
2082 /* strpbrk(x, "") == NULL.
2083 Evaluate and ignore the arguments in case they had
2084 side-effects. */
2085 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2086 return const0_rtx;
2087 }
2088
2089 if (p2[1] != '\0')
2090 return 0; /* Really call strpbrk. */
2091
0a68165a 2092 fn = implicit_built_in_decls[BUILT_IN_STRCHR];
83d79705 2093 if (!fn)
2094 return 0;
2095
2096 /* New argument list transforming strpbrk(s1, s2) to
2097 strchr(s1, s2[0]). */
2098 arglist =
2099 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
2100 arglist = tree_cons (NULL_TREE, s1, arglist);
7e15618b 2101 return expand_expr (build_function_call_expr (fn, arglist),
2102 target, mode, EXPAND_NORMAL);
46f3a74a 2103 }
2104}
2105
6840589f 2106/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2107 bytes from constant string DATA + OFFSET and return it as target
2108 constant. */
2109
2110static rtx
2111builtin_memcpy_read_str (data, offset, mode)
2112 PTR data;
2113 HOST_WIDE_INT offset;
2114 enum machine_mode mode;
2115{
2116 const char *str = (const char *) data;
2117
27d0c333 2118 if (offset < 0
2119 || ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
2120 > strlen (str) + 1))
6840589f 2121 abort (); /* Attempt to read past the end of constant string. */
2122
2123 return c_readstr (str + offset, mode);
2124}
2125
6f428e8b 2126/* Expand a call to the memcpy builtin, with arguments in ARGLIST.
2127 Return 0 if we failed, the caller should emit a normal call, otherwise
2128 try to get the result in TARGET, if convenient (and in mode MODE if
2129 that's convenient). */
27d0c333 2130
53800dbe 2131static rtx
6f428e8b 2132expand_builtin_memcpy (arglist, target, mode)
53800dbe 2133 tree arglist;
6f428e8b 2134 rtx target;
2135 enum machine_mode mode;
53800dbe 2136{
0eb671f7 2137 if (!validate_arglist (arglist,
2138 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 2139 return 0;
2140 else
2141 {
2142 tree dest = TREE_VALUE (arglist);
2143 tree src = TREE_VALUE (TREE_CHAIN (arglist));
2144 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6840589f 2145 const char *src_str;
53800dbe 2146
27d0c333 2147 unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2148 unsigned int dest_align
2149 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 2150 rtx dest_mem, src_mem, dest_addr, len_rtx;
2151
6f428e8b 2152 /* If DEST is not a pointer type, call the normal function. */
2153 if (dest_align == 0)
9342ee68 2154 return 0;
6f428e8b 2155
2156 /* If the LEN parameter is zero, return DEST. */
2157 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
9342ee68 2158 {
2159 /* Evaluate and ignore SRC in case it has side-effects. */
2160 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2161 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2162 }
6f428e8b 2163
2164 /* If either SRC is not a pointer type, don't do this
2165 operation in-line. */
2166 if (src_align == 0)
9342ee68 2167 return 0;
53800dbe 2168
2169 dest_mem = get_memory_rtx (dest);
2a631e19 2170 set_mem_align (dest_mem, dest_align);
53800dbe 2171 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
6840589f 2172 src_str = c_getstr (src);
2173
2174 /* If SRC is a string constant and block move would be done
2175 by pieces, we can avoid loading the string from memory
2176 and only stored the computed constants. */
2177 if (src_str
6840589f 2178 && GET_CODE (len_rtx) == CONST_INT
2179 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2180 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2181 (PTR) src_str, dest_align))
2182 {
2183 store_by_pieces (dest_mem, INTVAL (len_rtx),
2184 builtin_memcpy_read_str,
2185 (PTR) src_str, dest_align);
e5716f7e 2186 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2187#ifdef POINTERS_EXTEND_UNSIGNED
2188 if (GET_MODE (dest_mem) != ptr_mode)
2189 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2190#endif
2191 return dest_mem;
6840589f 2192 }
2193
2194 src_mem = get_memory_rtx (src);
2a631e19 2195 set_mem_align (src_mem, src_align);
53800dbe 2196
53800dbe 2197 /* Copy word part most expediently. */
0378dbdc 2198 dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
2199 BLOCK_OP_NORMAL);
53800dbe 2200
2201 if (dest_addr == 0)
e5716f7e 2202 {
2203 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2204#ifdef POINTERS_EXTEND_UNSIGNED
2205 if (GET_MODE (dest_addr) != ptr_mode)
2206 dest_addr = convert_memory_address (ptr_mode, dest_addr);
2207#endif
2208 }
53800dbe 2209
2210 return dest_addr;
2211 }
2212}
2213
2214/* Expand expression EXP, which is a call to the strcpy builtin. Return 0
6f428e8b 2215 if we failed the caller should emit a normal call, otherwise try to get
2216 the result in TARGET, if convenient (and in mode MODE if that's
2217 convenient). */
902de8ed 2218
53800dbe 2219static rtx
6f428e8b 2220expand_builtin_strcpy (exp, target, mode)
53800dbe 2221 tree exp;
6f428e8b 2222 rtx target;
2223 enum machine_mode mode;
53800dbe 2224{
2225 tree arglist = TREE_OPERAND (exp, 1);
6f428e8b 2226 tree fn, len;
53800dbe 2227
0eb671f7 2228 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
53800dbe 2229 return 0;
53800dbe 2230
0a68165a 2231 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
6f428e8b 2232 if (!fn)
2233 return 0;
902de8ed 2234
6f428e8b 2235 len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
2236 if (len == 0)
2237 return 0;
902de8ed 2238
6f428e8b 2239 len = size_binop (PLUS_EXPR, len, ssize_int (1));
2240 chainon (arglist, build_tree_list (NULL_TREE, len));
2241 return expand_expr (build_function_call_expr (fn, arglist),
9342ee68 2242 target, mode, EXPAND_NORMAL);
53800dbe 2243}
2244
6840589f 2245/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2246 bytes from constant string DATA + OFFSET and return it as target
2247 constant. */
2248
2249static rtx
2250builtin_strncpy_read_str (data, offset, mode)
2251 PTR data;
2252 HOST_WIDE_INT offset;
2253 enum machine_mode mode;
2254{
2255 const char *str = (const char *) data;
2256
2257 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
2258 return const0_rtx;
2259
2260 return c_readstr (str + offset, mode);
2261}
2262
ed09096d 2263/* Expand expression EXP, which is a call to the strncpy builtin. Return 0
2264 if we failed the caller should emit a normal call. */
2265
2266static rtx
2267expand_builtin_strncpy (arglist, target, mode)
2268 tree arglist;
2269 rtx target;
2270 enum machine_mode mode;
2271{
0eb671f7 2272 if (!validate_arglist (arglist,
2273 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 2274 return 0;
2275 else
2276 {
2277 tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
2278 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
6f428e8b 2279 tree fn;
ed09096d 2280
2281 /* We must be passed a constant len parameter. */
2282 if (TREE_CODE (len) != INTEGER_CST)
2283 return 0;
2284
2285 /* If the len parameter is zero, return the dst parameter. */
df5c389e 2286 if (integer_zerop (len))
9342ee68 2287 {
2288 /* Evaluate and ignore the src argument in case it has
2289 side-effects. */
ed09096d 2290 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
2291 VOIDmode, EXPAND_NORMAL);
bf8e3599 2292 /* Return the dst parameter. */
ed09096d 2293 return expand_expr (TREE_VALUE (arglist), target, mode,
2294 EXPAND_NORMAL);
2295 }
6840589f 2296
ed09096d 2297 /* Now, we must be passed a constant src ptr parameter. */
6840589f 2298 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
ed09096d 2299 return 0;
2300
2301 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
2302
2303 /* We're required to pad with trailing zeros if the requested
6840589f 2304 len is greater than strlen(s2)+1. In that case try to
2305 use store_by_pieces, if it fails, punt. */
ed09096d 2306 if (tree_int_cst_lt (slen, len))
6840589f 2307 {
2308 tree dest = TREE_VALUE (arglist);
27d0c333 2309 unsigned int dest_align
2310 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
6840589f 2311 const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
2312 rtx dest_mem;
2313
27d0c333 2314 if (!p || dest_align == 0 || !host_integerp (len, 1)
2315 || !can_store_by_pieces (tree_low_cst (len, 1),
6840589f 2316 builtin_strncpy_read_str,
2317 (PTR) p, dest_align))
2318 return 0;
2319
2320 dest_mem = get_memory_rtx (dest);
27d0c333 2321 store_by_pieces (dest_mem, tree_low_cst (len, 1),
6840589f 2322 builtin_strncpy_read_str,
2323 (PTR) p, dest_align);
e5716f7e 2324 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2325#ifdef POINTERS_EXTEND_UNSIGNED
2326 if (GET_MODE (dest_mem) != ptr_mode)
2327 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2328#endif
2329 return dest_mem;
6840589f 2330 }
bf8e3599 2331
ed09096d 2332 /* OK transform into builtin memcpy. */
0a68165a 2333 fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
6f428e8b 2334 if (!fn)
9342ee68 2335 return 0;
6f428e8b 2336 return expand_expr (build_function_call_expr (fn, arglist),
9342ee68 2337 target, mode, EXPAND_NORMAL);
ed09096d 2338 }
2339}
2340
ecc318ff 2341/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2342 bytes from constant string DATA + OFFSET and return it as target
2343 constant. */
2344
2345static rtx
2346builtin_memset_read_str (data, offset, mode)
2347 PTR data;
2348 HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
2349 enum machine_mode mode;
2350{
2351 const char *c = (const char *) data;
2352 char *p = alloca (GET_MODE_SIZE (mode));
2353
2354 memset (p, *c, GET_MODE_SIZE (mode));
2355
2356 return c_readstr (p, mode);
2357}
2358
a7ec6974 2359/* Callback routine for store_by_pieces. Return the RTL of a register
2360 containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
2361 char value given in the RTL register data. For example, if mode is
2362 4 bytes wide, return the RTL for 0x01010101*data. */
2363
2364static rtx
2365builtin_memset_gen_str (data, offset, mode)
2366 PTR data;
2367 HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
2368 enum machine_mode mode;
2369{
2370 rtx target, coeff;
2371 size_t size;
2372 char *p;
2373
2374 size = GET_MODE_SIZE (mode);
f0ce3b1f 2375 if (size == 1)
2376 return (rtx) data;
a7ec6974 2377
2378 p = alloca (size);
2379 memset (p, 1, size);
2380 coeff = c_readstr (p, mode);
2381
f0ce3b1f 2382 target = convert_to_mode (mode, (rtx) data, 1);
a7ec6974 2383 target = expand_mult (mode, target, coeff, NULL_RTX, 1);
2384 return force_reg (mode, target);
2385}
2386
53800dbe 2387/* Expand expression EXP, which is a call to the memset builtin. Return 0
6f428e8b 2388 if we failed the caller should emit a normal call, otherwise try to get
2389 the result in TARGET, if convenient (and in mode MODE if that's
2390 convenient). */
902de8ed 2391
53800dbe 2392static rtx
6f428e8b 2393expand_builtin_memset (exp, target, mode)
53800dbe 2394 tree exp;
6f428e8b 2395 rtx target;
2396 enum machine_mode mode;
53800dbe 2397{
2398 tree arglist = TREE_OPERAND (exp, 1);
2399
0eb671f7 2400 if (!validate_arglist (arglist,
2401 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 2402 return 0;
2403 else
2404 {
2405 tree dest = TREE_VALUE (arglist);
2406 tree val = TREE_VALUE (TREE_CHAIN (arglist));
2407 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
ecc318ff 2408 char c;
53800dbe 2409
27d0c333 2410 unsigned int dest_align
2411 = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
53800dbe 2412 rtx dest_mem, dest_addr, len_rtx;
2413
bf8e3599 2414 /* If DEST is not a pointer type, don't do this
53800dbe 2415 operation in-line. */
2416 if (dest_align == 0)
2417 return 0;
2418
6f428e8b 2419 /* If the LEN parameter is zero, return DEST. */
2420 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
9342ee68 2421 {
2422 /* Evaluate and ignore VAL in case it has side-effects. */
2423 expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
2424 return expand_expr (dest, target, mode, EXPAND_NORMAL);
2425 }
6f428e8b 2426
ecc318ff 2427 if (TREE_CODE (val) != INTEGER_CST)
9342ee68 2428 {
2429 rtx val_rtx;
a7ec6974 2430
9342ee68 2431 if (!host_integerp (len, 1))
2432 return 0;
a7ec6974 2433
9342ee68 2434 if (optimize_size && tree_low_cst (len, 1) > 1)
2435 return 0;
a7ec6974 2436
9342ee68 2437 /* Assume that we can memset by pieces if we can store the
2438 * the coefficients by pieces (in the required modes).
2439 * We can't pass builtin_memset_gen_str as that emits RTL. */
2440 c = 1;
a7ec6974 2441 if (!can_store_by_pieces (tree_low_cst (len, 1),
2442 builtin_memset_read_str,
9342ee68 2443 (PTR) &c, dest_align))
a7ec6974 2444 return 0;
2445
9342ee68 2446 val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val));
2447 val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
2448 val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
2449 val_rtx);
a7ec6974 2450 dest_mem = get_memory_rtx (dest);
2451 store_by_pieces (dest_mem, tree_low_cst (len, 1),
2452 builtin_memset_gen_str,
f0ce3b1f 2453 (PTR) val_rtx, dest_align);
e5716f7e 2454 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2455#ifdef POINTERS_EXTEND_UNSIGNED
2456 if (GET_MODE (dest_mem) != ptr_mode)
2457 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2458#endif
2459 return dest_mem;
9342ee68 2460 }
53800dbe 2461
ecc318ff 2462 if (target_char_cast (val, &c))
53800dbe 2463 return 0;
2464
ecc318ff 2465 if (c)
2466 {
27d0c333 2467 if (!host_integerp (len, 1))
ecc318ff 2468 return 0;
8a06f2d4 2469 if (!can_store_by_pieces (tree_low_cst (len, 1),
2470 builtin_memset_read_str, (PTR) &c,
2471 dest_align))
ecc318ff 2472 return 0;
2473
2474 dest_mem = get_memory_rtx (dest);
27d0c333 2475 store_by_pieces (dest_mem, tree_low_cst (len, 1),
ecc318ff 2476 builtin_memset_read_str,
2477 (PTR) &c, dest_align);
e5716f7e 2478 dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2479#ifdef POINTERS_EXTEND_UNSIGNED
2480 if (GET_MODE (dest_mem) != ptr_mode)
2481 dest_mem = convert_memory_address (ptr_mode, dest_mem);
2482#endif
2483 return dest_mem;
ecc318ff 2484 }
2485
53800dbe 2486 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
53800dbe 2487
2488 dest_mem = get_memory_rtx (dest);
2a631e19 2489 set_mem_align (dest_mem, dest_align);
2a631e19 2490 dest_addr = clear_storage (dest_mem, len_rtx);
53800dbe 2491
2492 if (dest_addr == 0)
e5716f7e 2493 {
2494 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2495#ifdef POINTERS_EXTEND_UNSIGNED
2496 if (GET_MODE (dest_addr) != ptr_mode)
2497 dest_addr = convert_memory_address (ptr_mode, dest_addr);
2498#endif
2499 }
53800dbe 2500
2501 return dest_addr;
2502 }
2503}
2504
ffc83088 2505/* Expand expression EXP, which is a call to the bzero builtin. Return 0
2506 if we failed the caller should emit a normal call. */
27d0c333 2507
ffc83088 2508static rtx
2509expand_builtin_bzero (exp)
2510 tree exp;
2511{
2512 tree arglist = TREE_OPERAND (exp, 1);
7369e7ba 2513 tree dest, size, newarglist;
2514 rtx result;
ffc83088 2515
0eb671f7 2516 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
7369e7ba 2517 return NULL_RTX;
ffc83088 2518
0eb671f7 2519 dest = TREE_VALUE (arglist);
2520 size = TREE_VALUE (TREE_CHAIN (arglist));
bf8e3599 2521
7369e7ba 2522 /* New argument list transforming bzero(ptr x, int y) to
6f428e8b 2523 memset(ptr x, int 0, size_t y). This is done this way
2524 so that if it isn't expanded inline, we fallback to
2525 calling bzero instead of memset. */
bf8e3599 2526
7369e7ba 2527 newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
2528 newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
2529 newarglist = tree_cons (NULL_TREE, dest, newarglist);
ffc83088 2530
7369e7ba 2531 TREE_OPERAND (exp, 1) = newarglist;
6f428e8b 2532 result = expand_builtin_memset (exp, const0_rtx, VOIDmode);
bf8e3599 2533
7369e7ba 2534 /* Always restore the original arguments. */
2535 TREE_OPERAND (exp, 1) = arglist;
ffc83088 2536
7369e7ba 2537 return result;
ffc83088 2538}
2539
53800dbe 2540/* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
2541 ARGLIST is the argument list for this call. Return 0 if we failed and the
2542 caller should emit a normal call, otherwise try to get the result in
6f428e8b 2543 TARGET, if convenient (and in mode MODE, if that's convenient). */
27d0c333 2544
53800dbe 2545static rtx
6f428e8b 2546expand_builtin_memcmp (exp, arglist, target, mode)
7cc1628d 2547 tree exp ATTRIBUTE_UNUSED;
53800dbe 2548 tree arglist;
2549 rtx target;
6f428e8b 2550 enum machine_mode mode;
53800dbe 2551{
6f428e8b 2552 tree arg1, arg2, len;
d470d782 2553 const char *p1, *p2;
6f428e8b 2554
0eb671f7 2555 if (!validate_arglist (arglist,
9342ee68 2556 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 2557 return 0;
53800dbe 2558
6f428e8b 2559 arg1 = TREE_VALUE (arglist);
2560 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2561 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2562
2563 /* If the len parameter is zero, return zero. */
2564 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
2565 {
2566 /* Evaluate and ignore arg1 and arg2 in case they have
2567 side-effects. */
2568 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2569 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2570 return const0_rtx;
2571 }
2572
d470d782 2573 p1 = c_getstr (arg1);
2574 p2 = c_getstr (arg2);
2575
2576 /* If all arguments are constant, and the value of len is not greater
2577 than the lengths of arg1 and arg2, evaluate at compile-time. */
2578 if (host_integerp (len, 1) && p1 && p2
df5c389e 2579 && compare_tree_int (len, strlen (p1) + 1) <= 0
2580 && compare_tree_int (len, strlen (p2) + 1) <= 0)
d470d782 2581 {
2582 const int r = memcmp (p1, p2, tree_low_cst (len, 1));
df5c389e 2583
d470d782 2584 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2585 }
2586
6f428e8b 2587 /* If len parameter is one, return an expression corresponding to
2588 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
2589 if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
2590 {
2591 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2592 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2593 tree ind1 =
2594 fold (build1 (CONVERT_EXPR, integer_type_node,
9342ee68 2595 build1 (INDIRECT_REF, cst_uchar_node,
2596 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
6f428e8b 2597 tree ind2 =
2598 fold (build1 (CONVERT_EXPR, integer_type_node,
9342ee68 2599 build1 (INDIRECT_REF, cst_uchar_node,
2600 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
6f428e8b 2601 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2602 return expand_expr (result, target, mode, EXPAND_NORMAL);
2603 }
2604
2605#ifdef HAVE_cmpstrsi
53800dbe 2606 {
0cd832f0 2607 rtx arg1_rtx, arg2_rtx, arg3_rtx;
53800dbe 2608 rtx result;
0cd832f0 2609 rtx insn;
53800dbe 2610
2611 int arg1_align
2612 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2613 int arg2_align
2614 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2615 enum machine_mode insn_mode
6357eaae 2616 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
53800dbe 2617
2618 /* If we don't have POINTER_TYPE, call the function. */
2619 if (arg1_align == 0 || arg2_align == 0)
2620 return 0;
2621
2622 /* Make a place to write the result of the instruction. */
2623 result = target;
2624 if (! (result != 0
2625 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
2626 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2627 result = gen_reg_rtx (insn_mode);
2628
0cd832f0 2629 arg1_rtx = get_memory_rtx (arg1);
2630 arg2_rtx = get_memory_rtx (arg2);
2631 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2632 if (!HAVE_cmpstrsi)
2633 insn = NULL_RTX;
2634 else
2635 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
2636 GEN_INT (MIN (arg1_align, arg2_align)));
2637
2638 if (insn)
2639 emit_insn (insn);
2640 else
2c5d421b 2641 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
0cd832f0 2642 TYPE_MODE (integer_type_node), 3,
2643 XEXP (arg1_rtx, 0), Pmode,
2644 XEXP (arg2_rtx, 0), Pmode,
2645 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
2646 TREE_UNSIGNED (sizetype)),
2647 TYPE_MODE (sizetype));
53800dbe 2648
2649 /* Return the value in the proper mode for this function. */
2650 mode = TYPE_MODE (TREE_TYPE (exp));
2651 if (GET_MODE (result) == mode)
2652 return result;
2653 else if (target != 0)
2654 {
2655 convert_move (target, result, 0);
2656 return target;
2657 }
2658 else
2659 return convert_to_mode (mode, result, 0);
2660 }
83d79705 2661#endif
53800dbe 2662
6f428e8b 2663 return 0;
2664}
2665
53800dbe 2666/* Expand expression EXP, which is a call to the strcmp builtin. Return 0
2667 if we failed the caller should emit a normal call, otherwise try to get
2668 the result in TARGET, if convenient. */
902de8ed 2669
53800dbe 2670static rtx
83d79705 2671expand_builtin_strcmp (exp, target, mode)
53800dbe 2672 tree exp;
2673 rtx target;
83d79705 2674 enum machine_mode mode;
53800dbe 2675{
2676 tree arglist = TREE_OPERAND (exp, 1);
6f428e8b 2677 tree arg1, arg2, len, len2, fn;
83d79705 2678 const char *p1, *p2;
53800dbe 2679
0eb671f7 2680 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
53800dbe 2681 return 0;
902de8ed 2682
83d79705 2683 arg1 = TREE_VALUE (arglist);
2684 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2685
2686 p1 = c_getstr (arg1);
2687 p2 = c_getstr (arg2);
2688
2689 if (p1 && p2)
2690 {
ef6c187e 2691 const int i = strcmp (p1, p2);
2692 return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
83d79705 2693 }
2694
ef6c187e 2695 /* If either arg is "", return an expression corresponding to
2696 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
2697 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2698 {
2699 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2700 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2701 tree ind1 =
2702 fold (build1 (CONVERT_EXPR, integer_type_node,
2703 build1 (INDIRECT_REF, cst_uchar_node,
2704 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2705 tree ind2 =
2706 fold (build1 (CONVERT_EXPR, integer_type_node,
2707 build1 (INDIRECT_REF, cst_uchar_node,
2708 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2709 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2710 return expand_expr (result, target, mode, EXPAND_NORMAL);
2711 }
bf8e3599 2712
6f428e8b 2713 len = c_strlen (arg1);
2714 len2 = c_strlen (arg2);
902de8ed 2715
6f428e8b 2716 if (len)
2717 len = size_binop (PLUS_EXPR, ssize_int (1), len);
902de8ed 2718
6f428e8b 2719 if (len2)
2720 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
53800dbe 2721
6f428e8b 2722 /* If we don't have a constant length for the first, use the length
2723 of the second, if we know it. We don't require a constant for
2724 this case; some cost analysis could be done if both are available
2725 but neither is constant. For now, assume they're equally cheap
2726 unless one has side effects.
53800dbe 2727
6f428e8b 2728 If both strings have constant lengths, use the smaller. This
2729 could arise if optimization results in strcpy being called with
2730 two fixed strings, or if the code was machine-generated. We should
2731 add some code to the `memcmp' handler below to deal with such
2732 situations, someday. */
902de8ed 2733
6f428e8b 2734 if (!len || TREE_CODE (len) != INTEGER_CST)
2735 {
2736 if (len2 && !TREE_SIDE_EFFECTS (len2))
9342ee68 2737 len = len2;
6f428e8b 2738 else if (len == 0)
9342ee68 2739 return 0;
6f428e8b 2740 }
2741 else if (len2 && TREE_CODE (len2) == INTEGER_CST
9342ee68 2742 && tree_int_cst_lt (len2, len))
6f428e8b 2743 len = len2;
53800dbe 2744
6f428e8b 2745 /* If both arguments have side effects, we cannot optimize. */
2746 if (TREE_SIDE_EFFECTS (len))
2747 return 0;
6840589f 2748
0a68165a 2749 fn = implicit_built_in_decls[BUILT_IN_MEMCMP];
6f428e8b 2750 if (!fn)
2751 return 0;
902de8ed 2752
6f428e8b 2753 chainon (arglist, build_tree_list (NULL_TREE, len));
2754 return expand_expr (build_function_call_expr (fn, arglist),
9342ee68 2755 target, mode, EXPAND_NORMAL);
83d79705 2756}
53800dbe 2757
ed09096d 2758/* Expand expression EXP, which is a call to the strncmp builtin. Return 0
2759 if we failed the caller should emit a normal call, otherwise try to get
2760 the result in TARGET, if convenient. */
27d0c333 2761
ed09096d 2762static rtx
2763expand_builtin_strncmp (exp, target, mode)
2764 tree exp;
2765 rtx target;
2766 enum machine_mode mode;
2767{
2768 tree arglist = TREE_OPERAND (exp, 1);
6f428e8b 2769 tree fn, newarglist, len = 0;
ed09096d 2770 tree arg1, arg2, arg3;
2771 const char *p1, *p2;
2772
0eb671f7 2773 if (!validate_arglist (arglist,
2774 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
ed09096d 2775 return 0;
2776
2777 arg1 = TREE_VALUE (arglist);
2778 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2779 arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2780
ed09096d 2781 /* If the len parameter is zero, return zero. */
6e34e617 2782 if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0)
9342ee68 2783 {
2784 /* Evaluate and ignore arg1 and arg2 in case they have
2785 side-effects. */
2786 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2787 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2788 return const0_rtx;
2789 }
ed09096d 2790
2791 p1 = c_getstr (arg1);
2792 p2 = c_getstr (arg2);
2793
2794 /* If all arguments are constant, evaluate at compile-time. */
6e34e617 2795 if (host_integerp (arg3, 1) && p1 && p2)
9342ee68 2796 {
2797 const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
2798 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2799 }
ed09096d 2800
ef6c187e 2801 /* If len == 1 or (either string parameter is "" and (len >= 1)),
6e34e617 2802 return (*(const u_char*)arg1 - *(const u_char*)arg2). */
2803 if (host_integerp (arg3, 1)
2804 && (tree_low_cst (arg3, 1) == 1
2805 || (tree_low_cst (arg3, 1) > 1
2806 && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
ef6c187e 2807 {
2808 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2809 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2810 tree ind1 =
2811 fold (build1 (CONVERT_EXPR, integer_type_node,
2812 build1 (INDIRECT_REF, cst_uchar_node,
2813 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2814 tree ind2 =
2815 fold (build1 (CONVERT_EXPR, integer_type_node,
2816 build1 (INDIRECT_REF, cst_uchar_node,
2817 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2818 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2819 return expand_expr (result, target, mode, EXPAND_NORMAL);
2820 }
ed09096d 2821
6e34e617 2822 /* If c_strlen can determine an expression for one of the string
2823 lengths, and it doesn't have side effects, then call
2824 expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3). */
bf8e3599 2825
6f428e8b 2826 /* Perhaps one of the strings is really constant, if so prefer
2827 that constant length over the other string's length. */
2828 if (p1)
2829 len = c_strlen (arg1);
2830 else if (p2)
2831 len = c_strlen (arg2);
2832
2833 /* If we still don't have a len, try either string arg as long
2834 as they don't have side effects. */
2835 if (!len && !TREE_SIDE_EFFECTS (arg1))
2836 len = c_strlen (arg1);
2837 if (!len && !TREE_SIDE_EFFECTS (arg2))
2838 len = c_strlen (arg2);
2839 /* If we still don't have a length, punt. */
2840 if (!len)
2841 return 0;
2842
0a68165a 2843 fn = implicit_built_in_decls[BUILT_IN_MEMCMP];
6f428e8b 2844 if (!fn)
2845 return 0;
bf8e3599 2846
6f428e8b 2847 /* Add one to the string length. */
2848 len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
6e34e617 2849
6f428e8b 2850 /* The actual new length parameter is MIN(len,arg3). */
2851 len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
bf8e3599 2852
6f428e8b 2853 newarglist = build_tree_list (NULL_TREE, len);
2854 newarglist = tree_cons (NULL_TREE, arg2, newarglist);
2855 newarglist = tree_cons (NULL_TREE, arg1, newarglist);
2856 return expand_expr (build_function_call_expr (fn, newarglist),
9342ee68 2857 target, mode, EXPAND_NORMAL);
ed09096d 2858}
2859
49f0327b 2860/* Expand expression EXP, which is a call to the strcat builtin.
2861 Return 0 if we failed the caller should emit a normal call,
2862 otherwise try to get the result in TARGET, if convenient. */
27d0c333 2863
49f0327b 2864static rtx
2865expand_builtin_strcat (arglist, target, mode)
2866 tree arglist;
2867 rtx target;
2868 enum machine_mode mode;
2869{
0eb671f7 2870 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 2871 return 0;
2872 else
2873 {
2874 tree dst = TREE_VALUE (arglist),
2875 src = TREE_VALUE (TREE_CHAIN (arglist));
2876 const char *p = c_getstr (src);
2877
2878 /* If the string length is zero, return the dst parameter. */
2879 if (p && *p == '\0')
2880 return expand_expr (dst, target, mode, EXPAND_NORMAL);
2881
2882 return 0;
2883 }
2884}
2885
2886/* Expand expression EXP, which is a call to the strncat builtin.
2887 Return 0 if we failed the caller should emit a normal call,
2888 otherwise try to get the result in TARGET, if convenient. */
27d0c333 2889
49f0327b 2890static rtx
2891expand_builtin_strncat (arglist, target, mode)
2892 tree arglist;
2893 rtx target;
2894 enum machine_mode mode;
2895{
0eb671f7 2896 if (!validate_arglist (arglist,
2897 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
49f0327b 2898 return 0;
2899 else
2900 {
2901 tree dst = TREE_VALUE (arglist),
2902 src = TREE_VALUE (TREE_CHAIN (arglist)),
2903 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2904 const char *p = c_getstr (src);
2905
2906 /* If the requested length is zero, or the src parameter string
2907 length is zero, return the dst parameter. */
b527e67e 2908 if (integer_zerop (len) || (p && *p == '\0'))
9342ee68 2909 {
49f0327b 2910 /* Evaluate and ignore the src and len parameters in case
2911 they have side-effects. */
2912 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2913 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2914 return expand_expr (dst, target, mode, EXPAND_NORMAL);
2915 }
2916
2917 /* If the requested len is greater than or equal to the string
2918 length, call strcat. */
2919 if (TREE_CODE (len) == INTEGER_CST && p
2920 && compare_tree_int (len, strlen (p)) >= 0)
9342ee68 2921 {
df5c389e 2922 tree newarglist
2923 = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
0a68165a 2924 tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
bf8e3599 2925
49f0327b 2926 /* If the replacement _DECL isn't initialized, don't do the
2c0e001b 2927 transformation. */
49f0327b 2928 if (!fn)
2929 return 0;
2930
7e15618b 2931 return expand_expr (build_function_call_expr (fn, newarglist),
2932 target, mode, EXPAND_NORMAL);
49f0327b 2933 }
2934 return 0;
2935 }
2936}
2937
2938/* Expand expression EXP, which is a call to the strspn builtin.
2939 Return 0 if we failed the caller should emit a normal call,
2940 otherwise try to get the result in TARGET, if convenient. */
27d0c333 2941
49f0327b 2942static rtx
2943expand_builtin_strspn (arglist, target, mode)
2944 tree arglist;
2945 rtx target;
2946 enum machine_mode mode;
2947{
0eb671f7 2948 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 2949 return 0;
2950 else
2951 {
2952 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2953 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
bf8e3599 2954
49f0327b 2955 /* If both arguments are constants, evaluate at compile-time. */
2956 if (p1 && p2)
9342ee68 2957 {
49f0327b 2958 const size_t r = strspn (p1, p2);
2959 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2960 }
bf8e3599 2961
fb1f44c5 2962 /* If either argument is "", return 0. */
2963 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
9342ee68 2964 {
fb1f44c5 2965 /* Evaluate and ignore both arguments in case either one has
49f0327b 2966 side-effects. */
2967 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
fb1f44c5 2968 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
49f0327b 2969 return const0_rtx;
2970 }
2971 return 0;
2972 }
2973}
2974
2975/* Expand expression EXP, which is a call to the strcspn builtin.
2976 Return 0 if we failed the caller should emit a normal call,
2977 otherwise try to get the result in TARGET, if convenient. */
27d0c333 2978
49f0327b 2979static rtx
2980expand_builtin_strcspn (arglist, target, mode)
2981 tree arglist;
2982 rtx target;
2983 enum machine_mode mode;
2984{
0eb671f7 2985 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
49f0327b 2986 return 0;
2987 else
2988 {
2989 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2990 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
bf8e3599 2991
49f0327b 2992 /* If both arguments are constants, evaluate at compile-time. */
2993 if (p1 && p2)
9342ee68 2994 {
49f0327b 2995 const size_t r = strcspn (p1, p2);
2996 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2997 }
bf8e3599 2998
fb1f44c5 2999 /* If the first argument is "", return 0. */
3000 if (p1 && *p1 == '\0')
9342ee68 3001 {
fb1f44c5 3002 /* Evaluate and ignore argument s2 in case it has
3003 side-effects. */
3004 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3005 return const0_rtx;
3006 }
3007
49f0327b 3008 /* If the second argument is "", return __builtin_strlen(s1). */
3009 if (p2 && *p2 == '\0')
9342ee68 3010 {
7e15618b 3011 tree newarglist = build_tree_list (NULL_TREE, s1),
0a68165a 3012 fn = implicit_built_in_decls[BUILT_IN_STRLEN];
bf8e3599 3013
49f0327b 3014 /* If the replacement _DECL isn't initialized, don't do the
2c0e001b 3015 transformation. */
49f0327b 3016 if (!fn)
3017 return 0;
3018
7e15618b 3019 return expand_expr (build_function_call_expr (fn, newarglist),
3020 target, mode, EXPAND_NORMAL);
49f0327b 3021 }
3022 return 0;
3023 }
3024}
3025
a66c9326 3026/* Expand a call to __builtin_saveregs, generating the result in TARGET,
3027 if that's convenient. */
902de8ed 3028
a66c9326 3029rtx
3030expand_builtin_saveregs ()
53800dbe 3031{
a66c9326 3032 rtx val, seq;
53800dbe 3033
3034 /* Don't do __builtin_saveregs more than once in a function.
3035 Save the result of the first call and reuse it. */
3036 if (saveregs_value != 0)
3037 return saveregs_value;
53800dbe 3038
a66c9326 3039 /* When this function is called, it means that registers must be
3040 saved on entry to this function. So we migrate the call to the
3041 first insn of this function. */
3042
3043 start_sequence ();
53800dbe 3044
3045#ifdef EXPAND_BUILTIN_SAVEREGS
a66c9326 3046 /* Do whatever the machine needs done in this case. */
3047 val = EXPAND_BUILTIN_SAVEREGS ();
53800dbe 3048#else
a66c9326 3049 /* ??? We used to try and build up a call to the out of line function,
3050 guessing about what registers needed saving etc. This became much
3051 harder with __builtin_va_start, since we don't have a tree for a
3052 call to __builtin_saveregs to fall back on. There was exactly one
3053 port (i860) that used this code, and I'm unconvinced it could actually
3054 handle the general case. So we no longer try to handle anything
3055 weird and make the backend absorb the evil. */
3056
3057 error ("__builtin_saveregs not supported by this target");
3058 val = const0_rtx;
53800dbe 3059#endif
3060
a66c9326 3061 seq = get_insns ();
3062 end_sequence ();
53800dbe 3063
a66c9326 3064 saveregs_value = val;
53800dbe 3065
31d3e01c 3066 /* Put the insns after the NOTE that starts the function. If this
3067 is inside a start_sequence, make the outer-level insn chain current, so
a66c9326 3068 the code is placed at the start of the function. */
3069 push_topmost_sequence ();
31d3e01c 3070 emit_insn_after (seq, get_insns ());
a66c9326 3071 pop_topmost_sequence ();
3072
3073 return val;
53800dbe 3074}
3075
3076/* __builtin_args_info (N) returns word N of the arg space info
3077 for the current function. The number and meanings of words
3078 is controlled by the definition of CUMULATIVE_ARGS. */
f7c44134 3079
53800dbe 3080static rtx
3081expand_builtin_args_info (exp)
3082 tree exp;
3083{
3084 tree arglist = TREE_OPERAND (exp, 1);
3085 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
3086 int *word_ptr = (int *) &current_function_args_info;
bf8e3599 3087#if 0
53800dbe 3088 /* These are used by the code below that is if 0'ed away */
3089 int i;
3090 tree type, elts, result;
3091#endif
3092
3093 if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
dda90815 3094 abort ();
53800dbe 3095
3096 if (arglist != 0)
3097 {
27d0c333 3098 if (!host_integerp (TREE_VALUE (arglist), 0))
53800dbe 3099 error ("argument of `__builtin_args_info' must be constant");
3100 else
3101 {
27d0c333 3102 HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
53800dbe 3103
27d0c333 3104 if (wordnum < 0 || wordnum >= nwords)
53800dbe 3105 error ("argument of `__builtin_args_info' out of range");
3106 else
3107 return GEN_INT (word_ptr[wordnum]);
3108 }
3109 }
3110 else
3111 error ("missing argument in `__builtin_args_info'");
3112
3113 return const0_rtx;
3114
3115#if 0
3116 for (i = 0; i < nwords; i++)
3117 elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
3118
3119 type = build_array_type (integer_type_node,
3120 build_index_type (build_int_2 (nwords, 0)));
3121 result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
3122 TREE_CONSTANT (result) = 1;
3123 TREE_STATIC (result) = 1;
a66c9326 3124 result = build1 (INDIRECT_REF, build_pointer_type (type), result);
53800dbe 3125 TREE_CONSTANT (result) = 1;
8a06f2d4 3126 return expand_expr (result, NULL_RTX, VOIDmode, 0);
53800dbe 3127#endif
3128}
3129
a66c9326 3130/* Expand ARGLIST, from a call to __builtin_next_arg. */
27d0c333 3131
53800dbe 3132static rtx
a66c9326 3133expand_builtin_next_arg (arglist)
3134 tree arglist;
53800dbe 3135{
53800dbe 3136 tree fntype = TREE_TYPE (current_function_decl);
3137
7ccc713a 3138 if (TYPE_ARG_TYPES (fntype) == 0
3139 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
3140 == void_type_node))
53800dbe 3141 {
3142 error ("`va_start' used in function with fixed args");
3143 return const0_rtx;
3144 }
3145
3146 if (arglist)
3147 {
3148 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
3149 tree arg = TREE_VALUE (arglist);
3150
3151 /* Strip off all nops for the sake of the comparison. This
bf8e3599 3152 is not quite the same as STRIP_NOPS. It does more.
53800dbe 3153 We must also strip off INDIRECT_EXPR for C++ reference
3154 parameters. */
3155 while (TREE_CODE (arg) == NOP_EXPR
3156 || TREE_CODE (arg) == CONVERT_EXPR
3157 || TREE_CODE (arg) == NON_LVALUE_EXPR
3158 || TREE_CODE (arg) == INDIRECT_REF)
3159 arg = TREE_OPERAND (arg, 0);
3160 if (arg != last_parm)
3161 warning ("second parameter of `va_start' not last named argument");
3162 }
7ccc713a 3163 else
53800dbe 3164 /* Evidently an out of date version of <stdarg.h>; can't validate
3165 va_start's second argument, but can still work as intended. */
3166 warning ("`__builtin_next_arg' called without an argument");
3167
3168 return expand_binop (Pmode, add_optab,
3169 current_function_internal_arg_pointer,
3170 current_function_arg_offset_rtx,
3171 NULL_RTX, 0, OPTAB_LIB_WIDEN);
3172}
3173
a66c9326 3174/* Make it easier for the backends by protecting the valist argument
3175 from multiple evaluations. */
3176
3177static tree
2d47cc32 3178stabilize_va_list (valist, needs_lvalue)
a66c9326 3179 tree valist;
2d47cc32 3180 int needs_lvalue;
a66c9326 3181{
11a61dea 3182 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
a66c9326 3183 {
2d47cc32 3184 if (TREE_SIDE_EFFECTS (valist))
3185 valist = save_expr (valist);
11a61dea 3186
2d47cc32 3187 /* For this case, the backends will be expecting a pointer to
3188 TREE_TYPE (va_list_type_node), but it's possible we've
3189 actually been given an array (an actual va_list_type_node).
3190 So fix it. */
3191 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
8a15c04a 3192 {
bf8e3599 3193 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
3194 tree p2 = build_pointer_type (va_list_type_node);
325d1c45 3195
bf8e3599 3196 valist = build1 (ADDR_EXPR, p2, valist);
2d47cc32 3197 valist = fold (build1 (NOP_EXPR, p1, valist));
8a15c04a 3198 }
a66c9326 3199 }
11a61dea 3200 else
a66c9326 3201 {
2d47cc32 3202 tree pt;
11a61dea 3203
2d47cc32 3204 if (! needs_lvalue)
3205 {
11a61dea 3206 if (! TREE_SIDE_EFFECTS (valist))
3207 return valist;
bf8e3599 3208
11a61dea 3209 pt = build_pointer_type (va_list_type_node);
2d47cc32 3210 valist = fold (build1 (ADDR_EXPR, pt, valist));
a66c9326 3211 TREE_SIDE_EFFECTS (valist) = 1;
a66c9326 3212 }
2d47cc32 3213
11a61dea 3214 if (TREE_SIDE_EFFECTS (valist))
2d47cc32 3215 valist = save_expr (valist);
11a61dea 3216 valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
3217 valist));
a66c9326 3218 }
3219
3220 return valist;
3221}
3222
3223/* The "standard" implementation of va_start: just assign `nextarg' to
3224 the variable. */
27d0c333 3225
a66c9326 3226void
7df226a2 3227std_expand_builtin_va_start (valist, nextarg)
a66c9326 3228 tree valist;
3229 rtx nextarg;
3230{
3231 tree t;
3232
3233 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
3234 make_tree (ptr_type_node, nextarg));
3235 TREE_SIDE_EFFECTS (t) = 1;
3236
3237 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3238}
3239
7ccc713a 3240/* Expand ARGLIST, from a call to __builtin_va_start. */
27d0c333 3241
a66c9326 3242static rtx
7ccc713a 3243expand_builtin_va_start (arglist)
a66c9326 3244 tree arglist;
3245{
3246 rtx nextarg;
7ccc713a 3247 tree chain, valist;
a66c9326 3248
7ccc713a 3249 chain = TREE_CHAIN (arglist);
a66c9326 3250
3251 if (TREE_CHAIN (chain))
3252 error ("too many arguments to function `va_start'");
3253
7ccc713a 3254 nextarg = expand_builtin_next_arg (chain);
a66c9326 3255 valist = stabilize_va_list (TREE_VALUE (arglist), 1);
3256
3257#ifdef EXPAND_BUILTIN_VA_START
7df226a2 3258 EXPAND_BUILTIN_VA_START (valist, nextarg);
a66c9326 3259#else
7df226a2 3260 std_expand_builtin_va_start (valist, nextarg);
a66c9326 3261#endif
3262
3263 return const0_rtx;
3264}
3265
a66c9326 3266/* The "standard" implementation of va_arg: read the value from the
3267 current (padded) address and increment by the (padded) size. */
f7c44134 3268
a66c9326 3269rtx
3270std_expand_builtin_va_arg (valist, type)
3271 tree valist, type;
3272{
91f95e00 3273 tree addr_tree, t, type_size = NULL;
3274 tree align, alignm1;
3275 tree rounded_size;
a66c9326 3276 rtx addr;
3277
3278 /* Compute the rounded size of the type. */
91f95e00 3279 align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
3280 alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
3281 if (type == error_mark_node
3282 || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
3283 || TREE_OVERFLOW (type_size))
3284 rounded_size = size_zero_node;
3285 else
3286 rounded_size = fold (build (MULT_EXPR, sizetype,
3287 fold (build (TRUNC_DIV_EXPR, sizetype,
3288 fold (build (PLUS_EXPR, sizetype,
3289 type_size, alignm1)),
3290 align)),
3291 align));
a66c9326 3292
3293 /* Get AP. */
3294 addr_tree = valist;
91f95e00 3295 if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size))
a66c9326 3296 {
3297 /* Small args are padded downward. */
91f95e00 3298 addr_tree = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
3299 fold (build (COND_EXPR, sizetype,
3300 fold (build (GT_EXPR, sizetype,
3301 rounded_size,
3302 align)),
3303 size_zero_node,
3304 fold (build (MINUS_EXPR, sizetype,
3305 rounded_size,
3306 type_size))))));
a66c9326 3307 }
3308
3309 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
3310 addr = copy_to_reg (addr);
3311
3312 /* Compute new value for AP. */
91f95e00 3313 if (! integer_zerop (rounded_size))
3314 {
3315 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
3316 build (PLUS_EXPR, TREE_TYPE (valist), valist,
3317 rounded_size));
3318 TREE_SIDE_EFFECTS (t) = 1;
3319 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3320 }
a66c9326 3321
3322 return addr;
3323}
3324
3325/* Expand __builtin_va_arg, which is not really a builtin function, but
3326 a very special sort of operator. */
f7c44134 3327
a66c9326 3328rtx
3329expand_builtin_va_arg (valist, type)
3330 tree valist, type;
3331{
3332 rtx addr, result;
6cd005c9 3333 tree promoted_type, want_va_type, have_va_type;
a66c9326 3334
6cd005c9 3335 /* Verify that valist is of the proper type. */
3336
3337 want_va_type = va_list_type_node;
3338 have_va_type = TREE_TYPE (valist);
3339 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
3340 {
bf8e3599 3341 /* If va_list is an array type, the argument may have decayed
6cd005c9 3342 to a pointer type, e.g. by being passed to another function.
3343 In that case, unwrap both types so that we can compare the
3344 underlying records. */
3345 if (TREE_CODE (have_va_type) == ARRAY_TYPE
3346 || TREE_CODE (have_va_type) == POINTER_TYPE)
3347 {
3348 want_va_type = TREE_TYPE (want_va_type);
3349 have_va_type = TREE_TYPE (have_va_type);
3350 }
3351 }
3352 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
a66c9326 3353 {
e94026da 3354 error ("first argument to `va_arg' not of type `va_list'");
3355 addr = const0_rtx;
3356 }
6cd005c9 3357
3358 /* Generate a diagnostic for requesting data of a type that cannot
3359 be passed through `...' due to type promotion at the call site. */
63c62881 3360 else if ((promoted_type = (*lang_hooks.types.type_promotes_to) (type))
3361 != type)
e94026da 3362 {
01ce7a1b 3363 const char *name = "<anonymous type>", *pname = 0;
a0ef1725 3364 static bool gave_help;
e94026da 3365
3366 if (TYPE_NAME (type))
3367 {
3368 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
3369 name = IDENTIFIER_POINTER (TYPE_NAME (type));
3370 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
3371 && DECL_NAME (TYPE_NAME (type)))
3372 name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
3373 }
3374 if (TYPE_NAME (promoted_type))
3375 {
3376 if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
3377 pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
3378 else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
3379 && DECL_NAME (TYPE_NAME (promoted_type)))
3380 pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
3381 }
3382
a0ef1725 3383 /* Unfortunately, this is merely undefined, rather than a constraint
3384 violation, so we cannot make this an error. If this call is never
3385 executed, the program is still strictly conforming. */
3386 warning ("`%s' is promoted to `%s' when passed through `...'",
3387 name, pname);
e94026da 3388 if (! gave_help)
3389 {
a0ef1725 3390 gave_help = true;
3391 warning ("(so you should pass `%s' not `%s' to `va_arg')",
3392 pname, name);
e94026da 3393 }
3394
a0ef1725 3395 /* We can, however, treat "undefined" any way we please.
3396 Call abort to encourage the user to fix the program. */
3397 expand_builtin_trap ();
3398
3399 /* This is dead code, but go ahead and finish so that the
3400 mode of the result comes out right. */
a66c9326 3401 addr = const0_rtx;
3402 }
3403 else
3404 {
3405 /* Make it easier for the backends by protecting the valist argument
3406 from multiple evaluations. */
3407 valist = stabilize_va_list (valist, 0);
3408
3409#ifdef EXPAND_BUILTIN_VA_ARG
3410 addr = EXPAND_BUILTIN_VA_ARG (valist, type);
3411#else
3412 addr = std_expand_builtin_va_arg (valist, type);
3413#endif
3414 }
3415
726ec87c 3416#ifdef POINTERS_EXTEND_UNSIGNED
3417 if (GET_MODE (addr) != Pmode)
3418 addr = convert_memory_address (Pmode, addr);
3419#endif
3420
a66c9326 3421 result = gen_rtx_MEM (TYPE_MODE (type), addr);
ab6ab77e 3422 set_mem_alias_set (result, get_varargs_alias_set ());
a66c9326 3423
3424 return result;
3425}
3426
3427/* Expand ARGLIST, from a call to __builtin_va_end. */
f7c44134 3428
a66c9326 3429static rtx
3430expand_builtin_va_end (arglist)
8a15c04a 3431 tree arglist;
a66c9326 3432{
8a15c04a 3433 tree valist = TREE_VALUE (arglist);
3434
a66c9326 3435#ifdef EXPAND_BUILTIN_VA_END
a66c9326 3436 valist = stabilize_va_list (valist, 0);
f0ce3b1f 3437 EXPAND_BUILTIN_VA_END (arglist);
8a15c04a 3438#else
3439 /* Evaluate for side effects, if needed. I hate macros that don't
3440 do that. */
3441 if (TREE_SIDE_EFFECTS (valist))
3442 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
a66c9326 3443#endif
3444
3445 return const0_rtx;
3446}
3447
bf8e3599 3448/* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a
a66c9326 3449 builtin rather than just as an assignment in stdarg.h because of the
3450 nastiness of array-type va_list types. */
f7c44134 3451
a66c9326 3452static rtx
3453expand_builtin_va_copy (arglist)
3454 tree arglist;
3455{
3456 tree dst, src, t;
3457
3458 dst = TREE_VALUE (arglist);
3459 src = TREE_VALUE (TREE_CHAIN (arglist));
3460
3461 dst = stabilize_va_list (dst, 1);
3462 src = stabilize_va_list (src, 0);
3463
3464 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
3465 {
3466 t = build (MODIFY_EXPR, va_list_type_node, dst, src);
3467 TREE_SIDE_EFFECTS (t) = 1;
3468 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3469 }
3470 else
3471 {
11a61dea 3472 rtx dstb, srcb, size;
3473
3474 /* Evaluate to pointers. */
3475 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
3476 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
3477 size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
3478 VOIDmode, EXPAND_NORMAL);
3479
726ec87c 3480#ifdef POINTERS_EXTEND_UNSIGNED
3481 if (GET_MODE (dstb) != Pmode)
3482 dstb = convert_memory_address (Pmode, dstb);
3483
3484 if (GET_MODE (srcb) != Pmode)
3485 srcb = convert_memory_address (Pmode, srcb);
3486#endif
3487
11a61dea 3488 /* "Dereference" to BLKmode memories. */
3489 dstb = gen_rtx_MEM (BLKmode, dstb);
ab6ab77e 3490 set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
2a631e19 3491 set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
11a61dea 3492 srcb = gen_rtx_MEM (BLKmode, srcb);
ab6ab77e 3493 set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
2a631e19 3494 set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
11a61dea 3495
3496 /* Copy. */
0378dbdc 3497 emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
a66c9326 3498 }
3499
3500 return const0_rtx;
3501}
3502
53800dbe 3503/* Expand a call to one of the builtin functions __builtin_frame_address or
3504 __builtin_return_address. */
27d0c333 3505
53800dbe 3506static rtx
3507expand_builtin_frame_address (exp)
3508 tree exp;
3509{
3510 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3511 tree arglist = TREE_OPERAND (exp, 1);
3512
3513 /* The argument must be a nonnegative integer constant.
3514 It counts the number of frames to scan up the stack.
3515 The value is the return address saved in that frame. */
3516 if (arglist == 0)
3517 /* Warning about missing arg was already issued. */
3518 return const0_rtx;
27d0c333 3519 else if (! host_integerp (TREE_VALUE (arglist), 1))
53800dbe 3520 {
3521 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3522 error ("invalid arg to `__builtin_frame_address'");
3523 else
3524 error ("invalid arg to `__builtin_return_address'");
3525 return const0_rtx;
3526 }
3527 else
3528 {
27d0c333 3529 rtx tem
3530 = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
3531 tree_low_cst (TREE_VALUE (arglist), 1),
3532 hard_frame_pointer_rtx);
53800dbe 3533
3534 /* Some ports cannot access arbitrary stack frames. */
3535 if (tem == NULL)
3536 {
3537 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3538 warning ("unsupported arg to `__builtin_frame_address'");
3539 else
3540 warning ("unsupported arg to `__builtin_return_address'");
3541 return const0_rtx;
3542 }
3543
3544 /* For __builtin_frame_address, return what we've got. */
3545 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3546 return tem;
3547
3548 if (GET_CODE (tem) != REG
3549 && ! CONSTANT_P (tem))
3550 tem = copy_to_mode_reg (Pmode, tem);
3551 return tem;
3552 }
3553}
3554
3555/* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if
3556 we failed and the caller should emit a normal call, otherwise try to get
3557 the result in TARGET, if convenient. */
15c6cf6b 3558
53800dbe 3559static rtx
3560expand_builtin_alloca (arglist, target)
3561 tree arglist;
3562 rtx target;
3563{
3564 rtx op0;
15c6cf6b 3565 rtx result;
53800dbe 3566
0eb671f7 3567 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
53800dbe 3568 return 0;
3569
3570 /* Compute the argument. */
3571 op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
3572
3573 /* Allocate the desired space. */
15c6cf6b 3574 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
3575
3576#ifdef POINTERS_EXTEND_UNSIGNED
479e4d5e 3577 if (GET_MODE (result) != ptr_mode)
3578 result = convert_memory_address (ptr_mode, result);
15c6cf6b 3579#endif
3580
3581 return result;
53800dbe 3582}
3583
3584/* Expand a call to the ffs builtin. The arguments are in ARGLIST.
3585 Return 0 if a normal call should be emitted rather than expanding the
3586 function in-line. If convenient, the result should be placed in TARGET.
3587 SUBTARGET may be used as the target for computing one of EXP's operands. */
15c6cf6b 3588
53800dbe 3589static rtx
3590expand_builtin_ffs (arglist, target, subtarget)
3591 tree arglist;
3592 rtx target, subtarget;
3593{
3594 rtx op0;
0eb671f7 3595 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
53800dbe 3596 return 0;
3597
3598 /* Compute the argument. */
3599 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
3600 /* Compute ffs, into TARGET if possible.
3601 Set TARGET to wherever the result comes back. */
3602 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
3603 ffs_optab, op0, target, 1);
3604 if (target == 0)
3605 abort ();
3606 return target;
3607}
89cfe6e5 3608
df94cd3b 3609/* If the string passed to fputs is a constant and is one character
2c0e001b 3610 long, we attempt to transform this call into __builtin_fputc(). */
15c6cf6b 3611
df94cd3b 3612static rtx
c013a46e 3613expand_builtin_fputs (arglist, ignore, unlocked)
df94cd3b 3614 tree arglist;
3615 int ignore;
c013a46e 3616 int unlocked;
df94cd3b 3617{
c013a46e 3618 tree len, fn;
0a68165a 3619 tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
3620 : implicit_built_in_decls[BUILT_IN_FPUTC];
3621 tree fn_fwrite = unlocked ? implicit_built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
3622 : implicit_built_in_decls[BUILT_IN_FWRITE];
df94cd3b 3623
3624 /* If the return value is used, or the replacement _DECL isn't
2c0e001b 3625 initialized, don't do the transformation. */
ce1b14f4 3626 if (!ignore || !fn_fputc || !fn_fwrite)
df94cd3b 3627 return 0;
3628
2c0e001b 3629 /* Verify the arguments in the original call. */
8a06f2d4 3630 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
df94cd3b 3631 return 0;
3632
ce1b14f4 3633 /* Get the length of the string passed to fputs. If the length
3634 can't be determined, punt. */
6840589f 3635 if (!(len = c_strlen (TREE_VALUE (arglist)))
3636 || TREE_CODE (len) != INTEGER_CST)
df94cd3b 3637 return 0;
3638
ce1b14f4 3639 switch (compare_tree_int (len, 1))
3640 {
3641 case -1: /* length is 0, delete the call entirely . */
6d42b7e4 3642 {
3643 /* Evaluate and ignore the argument in case it has
3644 side-effects. */
3645 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
3646 VOIDmode, EXPAND_NORMAL);
3647 return const0_rtx;
3648 }
ce1b14f4 3649 case 0: /* length is 1, call fputc. */
3650 {
83d79705 3651 const char *p = c_getstr (TREE_VALUE (arglist));
df94cd3b 3652
83d79705 3653 if (p != NULL)
bf8e3599 3654 {
83d79705 3655 /* New argument list transforming fputs(string, stream) to
3656 fputc(string[0], stream). */
3657 arglist =
3658 build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3659 arglist =
3660 tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
3661 fn = fn_fputc;
3662 break;
3663 }
ce1b14f4 3664 }
83d79705 3665 /* FALLTHROUGH */
ce1b14f4 3666 case 1: /* length is greater than 1, call fwrite. */
3667 {
3668 tree string_arg = TREE_VALUE (arglist);
bf8e3599 3669
ce1b14f4 3670 /* New argument list transforming fputs(string, stream) to
3671 fwrite(string, 1, len, stream). */
3672 arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3673 arglist = tree_cons (NULL_TREE, len, arglist);
38d76e41 3674 arglist = tree_cons (NULL_TREE, size_one_node, arglist);
ce1b14f4 3675 arglist = tree_cons (NULL_TREE, string_arg, arglist);
3676 fn = fn_fwrite;
3677 break;
3678 }
3679 default:
e17f5b23 3680 abort ();
ce1b14f4 3681 }
bf8e3599 3682
7e15618b 3683 return expand_expr (build_function_call_expr (fn, arglist),
3684 (ignore ? const0_rtx : NULL_RTX),
3311f67b 3685 VOIDmode, EXPAND_NORMAL);
3686}
3687
689df48e 3688/* Expand a call to __builtin_expect. We return our argument and emit a
3689 NOTE_INSN_EXPECTED_VALUE note. This is the expansion of __builtin_expect in
3690 a non-jump context. */
89cfe6e5 3691
3692static rtx
3693expand_builtin_expect (arglist, target)
3694 tree arglist;
3695 rtx target;
3696{
3697 tree exp, c;
3698 rtx note, rtx_c;
3699
3700 if (arglist == NULL_TREE
3701 || TREE_CHAIN (arglist) == NULL_TREE)
3702 return const0_rtx;
3703 exp = TREE_VALUE (arglist);
3704 c = TREE_VALUE (TREE_CHAIN (arglist));
3705
3706 if (TREE_CODE (c) != INTEGER_CST)
3707 {
3708 error ("second arg to `__builtin_expect' must be a constant");
3709 c = integer_zero_node;
3710 }
3711
3712 target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
3713
3714 /* Don't bother with expected value notes for integral constants. */
3715 if (GET_CODE (target) != CONST_INT)
3716 {
3717 /* We do need to force this into a register so that we can be
3718 moderately sure to be able to correctly interpret the branch
3719 condition later. */
3720 target = force_reg (GET_MODE (target), target);
bf8e3599 3721
89cfe6e5 3722 rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
3723
3724 note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
3725 NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
3726 }
3727
3728 return target;
3729}
689df48e 3730
3731/* Like expand_builtin_expect, except do this in a jump context. This is
3732 called from do_jump if the conditional is a __builtin_expect. Return either
31d3e01c 3733 a list of insns to emit the jump or NULL if we cannot optimize
689df48e 3734 __builtin_expect. We need to optimize this at jump time so that machines
3735 like the PowerPC don't turn the test into a SCC operation, and then jump
3736 based on the test being 0/1. */
3737
3738rtx
3739expand_builtin_expect_jump (exp, if_false_label, if_true_label)
3740 tree exp;
3741 rtx if_false_label;
3742 rtx if_true_label;
3743{
3744 tree arglist = TREE_OPERAND (exp, 1);
3745 tree arg0 = TREE_VALUE (arglist);
3746 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
3747 rtx ret = NULL_RTX;
3748
3749 /* Only handle __builtin_expect (test, 0) and
3750 __builtin_expect (test, 1). */
3751 if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
27d0c333 3752 && (integer_zerop (arg1) || integer_onep (arg1)))
689df48e 3753 {
689df48e 3754 int num_jumps = 0;
31d3e01c 3755 rtx insn;
689df48e 3756
1dc55962 3757 /* If we fail to locate an appropriate conditional jump, we'll
3758 fall back to normal evaluation. Ensure that the expression
3759 can be re-evaluated. */
3760 switch (unsafe_for_reeval (arg0))
3761 {
3762 case 0: /* Safe. */
3763 break;
3764
3765 case 1: /* Mildly unsafe. */
3766 arg0 = unsave_expr (arg0);
3767 break;
3768
3769 case 2: /* Wildly unsafe. */
3770 return NULL_RTX;
3771 }
3772
689df48e 3773 /* Expand the jump insns. */
3774 start_sequence ();
3775 do_jump (arg0, if_false_label, if_true_label);
31d3e01c 3776 ret = get_insns ();
689df48e 3777 end_sequence ();
3778
3779 /* Now that the __builtin_expect has been validated, go through and add
3780 the expect's to each of the conditional jumps. If we run into an
3781 error, just give up and generate the 'safe' code of doing a SCC
3782 operation and then doing a branch on that. */
31d3e01c 3783 insn = ret;
3784 while (insn != NULL_RTX)
689df48e 3785 {
31d3e01c 3786 rtx next = NEXT_INSN (insn);
689df48e 3787 rtx pattern;
3788
3789 if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn)
3790 && (pattern = pc_set (insn)) != NULL_RTX)
3791 {
3792 rtx ifelse = SET_SRC (pattern);
3793 rtx label;
3794 int taken;
3795
3796 if (GET_CODE (ifelse) != IF_THEN_ELSE)
31d3e01c 3797 goto do_next_insn;
689df48e 3798
3799 if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF)
3800 {
3801 taken = 1;
3802 label = XEXP (XEXP (ifelse, 1), 0);
3803 }
3804 /* An inverted jump reverses the probabilities. */
3805 else if (GET_CODE (XEXP (ifelse, 2)) == LABEL_REF)
3806 {
3807 taken = 0;
3808 label = XEXP (XEXP (ifelse, 2), 0);
3809 }
3810 /* We shouldn't have to worry about conditional returns during
3811 the expansion stage, but handle it gracefully anyway. */
3812 else if (GET_CODE (XEXP (ifelse, 1)) == RETURN)
3813 {
3814 taken = 1;
3815 label = NULL_RTX;
3816 }
3817 /* An inverted return reverses the probabilities. */
3818 else if (GET_CODE (XEXP (ifelse, 2)) == RETURN)
3819 {
3820 taken = 0;
3821 label = NULL_RTX;
3822 }
3823 else
31d3e01c 3824 goto do_next_insn;
689df48e 3825
3826 /* If the test is expected to fail, reverse the
3827 probabilities. */
27d0c333 3828 if (integer_zerop (arg1))
689df48e 3829 taken = 1 - taken;
3830
3831 /* If we are jumping to the false label, reverse the
3832 probabilities. */
3833 if (label == NULL_RTX)
3834 ; /* conditional return */
3835 else if (label == if_false_label)
3836 taken = 1 - taken;
3837 else if (label != if_true_label)
31d3e01c 3838 goto do_next_insn;
689df48e 3839
3840 num_jumps++;
3841 predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
3842 }
31d3e01c 3843
3844 do_next_insn:
3845 insn = next;
689df48e 3846 }
3847
3848 /* If no jumps were modified, fail and do __builtin_expect the normal
3849 way. */
3850 if (num_jumps == 0)
3851 ret = NULL_RTX;
3852 }
3853
3854 return ret;
3855}
a0ef1725 3856
3857void
3858expand_builtin_trap ()
3859{
3860#ifdef HAVE_trap
3861 if (HAVE_trap)
3862 emit_insn (gen_trap ());
3863 else
3864#endif
3865 emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
3866 emit_barrier ();
3867}
53800dbe 3868\f
3869/* Expand an expression EXP that calls a built-in function,
3870 with result going to TARGET if that's convenient
3871 (and in mode MODE if that's convenient).
3872 SUBTARGET may be used as the target for computing one of EXP's operands.
3873 IGNORE is nonzero if the value is to be ignored. */
3874
3875rtx
3876expand_builtin (exp, target, subtarget, mode, ignore)
3877 tree exp;
3878 rtx target;
3879 rtx subtarget;
3880 enum machine_mode mode;
3881 int ignore;
3882{
3883 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3884 tree arglist = TREE_OPERAND (exp, 1);
3885 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
3886
8305149e 3887 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
fc2a2dcb 3888 return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore);
bf8e3599 3889
53800dbe 3890 /* When not optimizing, generate calls to library functions for a certain
3891 set of builtins. */
bf8e3599 3892 if (!optimize && !CALLED_AS_BUILT_IN (fndecl))
3893 switch (fcode)
3894 {
75357f66 3895 case BUILT_IN_SQRT:
bf8e3599 3896 case BUILT_IN_SQRTF:
3897 case BUILT_IN_SQRTL:
42721db0 3898 case BUILT_IN_SIN:
3899 case BUILT_IN_SINF:
3900 case BUILT_IN_SINL:
3901 case BUILT_IN_COS:
3902 case BUILT_IN_COSF:
3903 case BUILT_IN_COSL:
3904 case BUILT_IN_EXP:
3905 case BUILT_IN_EXPF:
3906 case BUILT_IN_EXPL:
bf8e3599 3907 case BUILT_IN_MEMSET:
3908 case BUILT_IN_MEMCPY:
3909 case BUILT_IN_MEMCMP:
3910 case BUILT_IN_BCMP:
3911 case BUILT_IN_BZERO:
3912 case BUILT_IN_INDEX:
3913 case BUILT_IN_RINDEX:
3914 case BUILT_IN_STRCHR:
3915 case BUILT_IN_STRRCHR:
3916 case BUILT_IN_STRLEN:
3917 case BUILT_IN_STRCPY:
3918 case BUILT_IN_STRNCPY:
3919 case BUILT_IN_STRNCMP:
3920 case BUILT_IN_STRSTR:
3921 case BUILT_IN_STRPBRK:
3922 case BUILT_IN_STRCAT:
3923 case BUILT_IN_STRNCAT:
3924 case BUILT_IN_STRSPN:
3925 case BUILT_IN_STRCSPN:
3926 case BUILT_IN_STRCMP:
3927 case BUILT_IN_FFS:
3928 case BUILT_IN_PUTCHAR:
3929 case BUILT_IN_PUTS:
3930 case BUILT_IN_PRINTF:
3931 case BUILT_IN_FPUTC:
3932 case BUILT_IN_FPUTS:
3933 case BUILT_IN_FWRITE:
c013a46e 3934 case BUILT_IN_PUTCHAR_UNLOCKED:
3935 case BUILT_IN_PUTS_UNLOCKED:
3936 case BUILT_IN_PRINTF_UNLOCKED:
3937 case BUILT_IN_FPUTC_UNLOCKED:
3938 case BUILT_IN_FPUTS_UNLOCKED:
3939 case BUILT_IN_FWRITE_UNLOCKED:
805e22b2 3940 case BUILT_IN_FLOOR:
3941 case BUILT_IN_FLOORF:
3942 case BUILT_IN_FLOORL:
3943 case BUILT_IN_CEIL:
3944 case BUILT_IN_CEILF:
3945 case BUILT_IN_CEILL:
3946 case BUILT_IN_TRUNC:
3947 case BUILT_IN_TRUNCF:
3948 case BUILT_IN_TRUNCL:
3949 case BUILT_IN_ROUND:
3950 case BUILT_IN_ROUNDF:
3951 case BUILT_IN_ROUNDL:
3952 case BUILT_IN_NEARBYINT:
3953 case BUILT_IN_NEARBYINTF:
3954 case BUILT_IN_NEARBYINTL:
9342ee68 3955 return expand_call (exp, target, ignore);
bf8e3599 3956
3957 default:
9342ee68 3958 break;
3959 }
53800dbe 3960
3961 switch (fcode)
3962 {
3963 case BUILT_IN_ABS:
d2d4bdde 3964 case BUILT_IN_LABS:
3965 case BUILT_IN_LLABS:
3966 case BUILT_IN_IMAXABS:
53800dbe 3967 case BUILT_IN_FABS:
d2d4bdde 3968 case BUILT_IN_FABSF:
3969 case BUILT_IN_FABSL:
53800dbe 3970 /* build_function_call changes these into ABS_EXPR. */
3971 abort ();
3972
d30e4d04 3973 case BUILT_IN_CONJ:
d2d4bdde 3974 case BUILT_IN_CONJF:
3975 case BUILT_IN_CONJL:
d30e4d04 3976 case BUILT_IN_CREAL:
d2d4bdde 3977 case BUILT_IN_CREALF:
3978 case BUILT_IN_CREALL:
d30e4d04 3979 case BUILT_IN_CIMAG:
d2d4bdde 3980 case BUILT_IN_CIMAGF:
3981 case BUILT_IN_CIMAGL:
d30e4d04 3982 /* expand_tree_builtin changes these into CONJ_EXPR, REALPART_EXPR
3983 and IMAGPART_EXPR. */
3984 abort ();
3985
53800dbe 3986 case BUILT_IN_SIN:
d2d4bdde 3987 case BUILT_IN_SINF:
3988 case BUILT_IN_SINL:
53800dbe 3989 case BUILT_IN_COS:
d2d4bdde 3990 case BUILT_IN_COSF:
3991 case BUILT_IN_COSL:
42721db0 3992 case BUILT_IN_EXP:
3993 case BUILT_IN_EXPF:
3994 case BUILT_IN_EXPL:
3995 case BUILT_IN_LOG:
3996 case BUILT_IN_LOGF:
3997 case BUILT_IN_LOGL:
7f3be425 3998 /* Treat these like sqrt only if unsafe math optimizations are allowed,
3999 because of possible accuracy problems. */
4000 if (! flag_unsafe_math_optimizations)
53800dbe 4001 break;
75357f66 4002 case BUILT_IN_SQRT:
d2d4bdde 4003 case BUILT_IN_SQRTF:
4004 case BUILT_IN_SQRTL:
805e22b2 4005 case BUILT_IN_FLOOR:
4006 case BUILT_IN_FLOORF:
4007 case BUILT_IN_FLOORL:
4008 case BUILT_IN_CEIL:
4009 case BUILT_IN_CEILF:
4010 case BUILT_IN_CEILL:
4011 case BUILT_IN_TRUNC:
4012 case BUILT_IN_TRUNCF:
4013 case BUILT_IN_TRUNCL:
4014 case BUILT_IN_ROUND:
4015 case BUILT_IN_ROUNDF:
4016 case BUILT_IN_ROUNDL:
4017 case BUILT_IN_NEARBYINT:
4018 case BUILT_IN_NEARBYINTF:
4019 case BUILT_IN_NEARBYINTL:
53800dbe 4020 target = expand_builtin_mathfn (exp, target, subtarget);
4021 if (target)
4022 return target;
4023 break;
4024
53800dbe 4025 case BUILT_IN_APPLY_ARGS:
4026 return expand_builtin_apply_args ();
4027
4028 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
4029 FUNCTION with a copy of the parameters described by
4030 ARGUMENTS, and ARGSIZE. It returns a block of memory
4031 allocated on the stack into which is stored all the registers
4032 that might possibly be used for returning the result of a
4033 function. ARGUMENTS is the value returned by
4034 __builtin_apply_args. ARGSIZE is the number of bytes of
4035 arguments that must be copied. ??? How should this value be
4036 computed? We'll also need a safe worst case value for varargs
4037 functions. */
4038 case BUILT_IN_APPLY:
0eb671f7 4039 if (!validate_arglist (arglist, POINTER_TYPE,
4040 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
4041 && !validate_arglist (arglist, REFERENCE_TYPE,
4042 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 4043 return const0_rtx;
4044 else
4045 {
4046 int i;
4047 tree t;
4048 rtx ops[3];
4049
4050 for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
4051 ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
4052
4053 return expand_builtin_apply (ops[0], ops[1], ops[2]);
4054 }
4055
4056 /* __builtin_return (RESULT) causes the function to return the
4057 value described by RESULT. RESULT is address of the block of
4058 memory returned by __builtin_apply. */
4059 case BUILT_IN_RETURN:
0eb671f7 4060 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
53800dbe 4061 expand_builtin_return (expand_expr (TREE_VALUE (arglist),
4062 NULL_RTX, VOIDmode, 0));
4063 return const0_rtx;
4064
4065 case BUILT_IN_SAVEREGS:
a66c9326 4066 return expand_builtin_saveregs ();
53800dbe 4067
4068 case BUILT_IN_ARGS_INFO:
4069 return expand_builtin_args_info (exp);
4070
4071 /* Return the address of the first anonymous stack arg. */
4072 case BUILT_IN_NEXT_ARG:
a66c9326 4073 return expand_builtin_next_arg (arglist);
53800dbe 4074
4075 case BUILT_IN_CLASSIFY_TYPE:
4076 return expand_builtin_classify_type (arglist);
4077
4078 case BUILT_IN_CONSTANT_P:
4079 return expand_builtin_constant_p (exp);
4080
4081 case BUILT_IN_FRAME_ADDRESS:
4082 case BUILT_IN_RETURN_ADDRESS:
4083 return expand_builtin_frame_address (exp);
4084
4085 /* Returns the address of the area where the structure is returned.
4086 0 otherwise. */
4087 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
4088 if (arglist != 0
9342ee68 4089 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
4090 || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
4091 return const0_rtx;
53800dbe 4092 else
9342ee68 4093 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
53800dbe 4094
4095 case BUILT_IN_ALLOCA:
4096 target = expand_builtin_alloca (arglist, target);
4097 if (target)
4098 return target;
4099 break;
4100
4101 case BUILT_IN_FFS:
bdc5170d 4102 target = expand_builtin_ffs (arglist, target, subtarget);
53800dbe 4103 if (target)
4104 return target;
4105 break;
4106
4107 case BUILT_IN_STRLEN:
aed0bd19 4108 target = expand_builtin_strlen (exp, target);
53800dbe 4109 if (target)
4110 return target;
4111 break;
4112
4113 case BUILT_IN_STRCPY:
6f428e8b 4114 target = expand_builtin_strcpy (exp, target, mode);
53800dbe 4115 if (target)
4116 return target;
4117 break;
bf8e3599 4118
ed09096d 4119 case BUILT_IN_STRNCPY:
4120 target = expand_builtin_strncpy (arglist, target, mode);
4121 if (target)
4122 return target;
4123 break;
bf8e3599 4124
49f0327b 4125 case BUILT_IN_STRCAT:
4126 target = expand_builtin_strcat (arglist, target, mode);
4127 if (target)
4128 return target;
4129 break;
bf8e3599 4130
49f0327b 4131 case BUILT_IN_STRNCAT:
4132 target = expand_builtin_strncat (arglist, target, mode);
4133 if (target)
4134 return target;
4135 break;
bf8e3599 4136
49f0327b 4137 case BUILT_IN_STRSPN:
4138 target = expand_builtin_strspn (arglist, target, mode);
4139 if (target)
4140 return target;
4141 break;
bf8e3599 4142
49f0327b 4143 case BUILT_IN_STRCSPN:
4144 target = expand_builtin_strcspn (arglist, target, mode);
4145 if (target)
4146 return target;
4147 break;
bf8e3599 4148
17f5ea87 4149 case BUILT_IN_STRSTR:
4150 target = expand_builtin_strstr (arglist, target, mode);
4151 if (target)
4152 return target;
4153 break;
bf8e3599 4154
46f3a74a 4155 case BUILT_IN_STRPBRK:
4156 target = expand_builtin_strpbrk (arglist, target, mode);
4157 if (target)
4158 return target;
4159 break;
bf8e3599 4160
398aae36 4161 case BUILT_IN_INDEX:
83d79705 4162 case BUILT_IN_STRCHR:
4163 target = expand_builtin_strchr (arglist, target, mode);
4164 if (target)
4165 return target;
4166 break;
4167
398aae36 4168 case BUILT_IN_RINDEX:
83d79705 4169 case BUILT_IN_STRRCHR:
4170 target = expand_builtin_strrchr (arglist, target, mode);
4171 if (target)
4172 return target;
4173 break;
4174
53800dbe 4175 case BUILT_IN_MEMCPY:
6f428e8b 4176 target = expand_builtin_memcpy (arglist, target, mode);
53800dbe 4177 if (target)
4178 return target;
4179 break;
4180
4181 case BUILT_IN_MEMSET:
6f428e8b 4182 target = expand_builtin_memset (exp, target, mode);
53800dbe 4183 if (target)
4184 return target;
4185 break;
4186
ffc83088 4187 case BUILT_IN_BZERO:
4188 target = expand_builtin_bzero (exp);
4189 if (target)
4190 return target;
4191 break;
4192
53800dbe 4193 case BUILT_IN_STRCMP:
83d79705 4194 target = expand_builtin_strcmp (exp, target, mode);
53800dbe 4195 if (target)
4196 return target;
4197 break;
4198
ed09096d 4199 case BUILT_IN_STRNCMP:
4200 target = expand_builtin_strncmp (exp, target, mode);
4201 if (target)
4202 return target;
4203 break;
4204
071f1696 4205 case BUILT_IN_BCMP:
53800dbe 4206 case BUILT_IN_MEMCMP:
6f428e8b 4207 target = expand_builtin_memcmp (exp, arglist, target, mode);
53800dbe 4208 if (target)
4209 return target;
4210 break;
53800dbe 4211
4212 case BUILT_IN_SETJMP:
6b7f6858 4213 target = expand_builtin_setjmp (arglist, target);
4214 if (target)
4215 return target;
4216 break;
53800dbe 4217
4218 /* __builtin_longjmp is passed a pointer to an array of five words.
4219 It's similar to the C library longjmp function but works with
4220 __builtin_setjmp above. */
4221 case BUILT_IN_LONGJMP:
0eb671f7 4222 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
53800dbe 4223 break;
4224 else
4225 {
4226 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
4227 VOIDmode, 0);
4228 rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
4229 NULL_RTX, VOIDmode, 0);
4230
4231 if (value != const1_rtx)
4232 {
4233 error ("__builtin_longjmp second argument must be 1");
4234 return const0_rtx;
4235 }
4236
4237 expand_builtin_longjmp (buf_addr, value);
4238 return const0_rtx;
4239 }
4240
4241 case BUILT_IN_TRAP:
a0ef1725 4242 expand_builtin_trap ();
53800dbe 4243 return const0_rtx;
4244
df94cd3b 4245 case BUILT_IN_FPUTS:
c013a46e 4246 target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 0);
4247 if (target)
4248 return target;
4249 break;
4250 case BUILT_IN_FPUTS_UNLOCKED:
4251 target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 1);
df94cd3b 4252 if (target)
4253 return target;
4254 break;
bf8e3599 4255
53800dbe 4256 /* Various hooks for the DWARF 2 __throw routine. */
4257 case BUILT_IN_UNWIND_INIT:
4258 expand_builtin_unwind_init ();
4259 return const0_rtx;
4260 case BUILT_IN_DWARF_CFA:
4261 return virtual_cfa_rtx;
4262#ifdef DWARF2_UNWIND_INFO
4263 case BUILT_IN_DWARF_FP_REGNUM:
4264 return expand_builtin_dwarf_fp_regnum ();
695e919b 4265 case BUILT_IN_INIT_DWARF_REG_SIZES:
4266 expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
4267 return const0_rtx;
53800dbe 4268#endif
4269 case BUILT_IN_FROB_RETURN_ADDR:
4270 return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
4271 case BUILT_IN_EXTRACT_RETURN_ADDR:
4272 return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
4273 case BUILT_IN_EH_RETURN:
4274 expand_builtin_eh_return (TREE_VALUE (arglist),
df4b504c 4275 TREE_VALUE (TREE_CHAIN (arglist)));
53800dbe 4276 return const0_rtx;
df4b504c 4277#ifdef EH_RETURN_DATA_REGNO
4278 case BUILT_IN_EH_RETURN_DATA_REGNO:
4279 return expand_builtin_eh_return_data_regno (arglist);
4280#endif
7ccc713a 4281 case BUILT_IN_VA_START:
a66c9326 4282 case BUILT_IN_STDARG_START:
7ccc713a 4283 return expand_builtin_va_start (arglist);
a66c9326 4284 case BUILT_IN_VA_END:
4285 return expand_builtin_va_end (arglist);
4286 case BUILT_IN_VA_COPY:
4287 return expand_builtin_va_copy (arglist);
89cfe6e5 4288 case BUILT_IN_EXPECT:
4289 return expand_builtin_expect (arglist, target);
5e3608d8 4290 case BUILT_IN_PREFETCH:
4291 expand_builtin_prefetch (arglist);
4292 return const0_rtx;
4293
53800dbe 4294
92482ee0 4295 default: /* just do library call, if unknown builtin */
4296 if (!DECL_ASSEMBLER_NAME_SET_P (fndecl))
4297 error ("built-in function `%s' not currently supported",
4298 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
53800dbe 4299 }
4300
4301 /* The switch statement above can drop through to cause the function
4302 to be called normally. */
4303 return expand_call (exp, target, ignore);
4304}
650e4c94 4305
805e22b2 4306/* Determine whether a tree node represents a call to a built-in
4307 math function. If the tree T is a call to a built-in function
4308 taking a single real argument, then the return value is the
4309 DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT. Otherwise
4310 the return value is END_BUILTINS. */
4311
4312enum built_in_function
4313builtin_mathfn_code (t)
4314 tree t;
4315{
4316 tree fndecl, arglist;
4317
4318 if (TREE_CODE (t) != CALL_EXPR
4319 || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
4320 return END_BUILTINS;
4321
4322 fndecl = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
4323 if (TREE_CODE (fndecl) != FUNCTION_DECL
4324 || ! DECL_BUILT_IN (fndecl)
4325 || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
4326 return END_BUILTINS;
4327
4328 arglist = TREE_OPERAND (t, 1);
4329 if (! arglist
4330 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE
4331 || TREE_CHAIN (arglist))
4332 return END_BUILTINS;
4333
4334 return DECL_FUNCTION_CODE (fndecl);
4335}
4336
650e4c94 4337/* Fold a call to __builtin_constant_p, if we know it will evaluate to a
4338 constant. ARGLIST is the argument list of the call. */
4339
4340static tree
4341fold_builtin_constant_p (arglist)
4342 tree arglist;
4343{
4344 if (arglist == 0)
4345 return 0;
4346
4347 arglist = TREE_VALUE (arglist);
4348
4349 /* We return 1 for a numeric type that's known to be a constant
4350 value at compile-time or for an aggregate type that's a
4351 literal constant. */
4352 STRIP_NOPS (arglist);
4353
4354 /* If we know this is a constant, emit the constant of one. */
4355 if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
4356 || (TREE_CODE (arglist) == CONSTRUCTOR
4357 && TREE_CONSTANT (arglist))
4358 || (TREE_CODE (arglist) == ADDR_EXPR
4359 && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
4360 return integer_one_node;
4361
4362 /* If we aren't going to be running CSE or this expression
4363 has side effects, show we don't know it to be a constant.
4364 Likewise if it's a pointer or aggregate type since in those
4365 case we only want literals, since those are only optimized
f97c71a1 4366 when generating RTL, not later.
4367 And finally, if we are compiling an initializer, not code, we
4368 need to return a definite result now; there's not going to be any
4369 more optimization done. */
650e4c94 4370 if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected
4371 || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
f97c71a1 4372 || POINTER_TYPE_P (TREE_TYPE (arglist))
4373 || cfun == 0)
650e4c94 4374 return integer_zero_node;
4375
4376 return 0;
4377}
4378
539a3a92 4379/* Fold a call to __builtin_classify_type. */
27d0c333 4380
539a3a92 4381static tree
4382fold_builtin_classify_type (arglist)
4383 tree arglist;
4384{
4385 if (arglist == 0)
4386 return build_int_2 (no_type_class, 0);
4387
4388 return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
4389}
4390
92c43e3c 4391/* Fold a call to __builtin_inf or __builtin_huge_val. */
4392
4393static tree
4394fold_builtin_inf (type, warn)
4395 tree type;
4396 int warn;
4397{
aa870c1b 4398 REAL_VALUE_TYPE real;
4399
92c43e3c 4400 if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
4401 warning ("target format does not support infinity");
4402
aa870c1b 4403 real_inf (&real);
4404 return build_real (type, real);
92c43e3c 4405}
4406
b0db7939 4407/* Fold a call to __builtin_nan or __builtin_nans. */
4408
4409static tree
4410fold_builtin_nan (arglist, type, quiet)
4411 tree arglist, type;
4412 int quiet;
4413{
4414 REAL_VALUE_TYPE real;
4415 const char *str;
4416
4417 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
4418 return 0;
4419 str = c_getstr (TREE_VALUE (arglist));
4420 if (!str)
4421 return 0;
4422
4423 if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
4424 return 0;
4425
4426 return build_real (type, real);
4427}
4428
6528f4f4 4429/* EXP is assumed to me builtin call where truncation can be propagated
4430 across (for instance floor((double)f) == (double)floorf (f).
4431 Do the transformation. */
4432static tree
4433fold_trunc_transparent_mathfn (exp)
4434 tree exp;
4435{
4436 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4437 tree arglist = TREE_OPERAND (exp, 1);
4438 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
4439
4440 if (optimize && validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
4441 {
4442 tree arg0 = strip_float_extensions (TREE_VALUE (arglist));
4443 tree ftype = TREE_TYPE (exp);
4444 tree newtype = TREE_TYPE (arg0);
4445 tree decl;
4446
4447 if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
4448 && (decl = mathfn_built_in (newtype, fcode)))
4449 {
4450 arglist =
4451 build_tree_list (NULL_TREE, fold (convert (newtype, arg0)));
4452 return convert (ftype,
4453 build_function_call_expr (decl, arglist));
4454 }
4455 }
4456 return 0;
4457}
4458
650e4c94 4459/* Used by constant folding to eliminate some builtin calls early. EXP is
4460 the CALL_EXPR of a call to a builtin function. */
4461
4462tree
4463fold_builtin (exp)
4464 tree exp;
4465{
4466 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4467 tree arglist = TREE_OPERAND (exp, 1);
4468 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
4469
4470 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
4471 return 0;
4472
4473 switch (fcode)
4474 {
4475 case BUILT_IN_CONSTANT_P:
4476 return fold_builtin_constant_p (arglist);
4477
539a3a92 4478 case BUILT_IN_CLASSIFY_TYPE:
4479 return fold_builtin_classify_type (arglist);
4480
650e4c94 4481 case BUILT_IN_STRLEN:
0eb671f7 4482 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
650e4c94 4483 {
4484 tree len = c_strlen (TREE_VALUE (arglist));
654ef926 4485 if (len)
4486 {
4487 /* Convert from the internal "sizetype" type to "size_t". */
4488 if (size_type_node)
4489 len = convert (size_type_node, len);
4490 return len;
4491 }
650e4c94 4492 }
4493 break;
4494
805e22b2 4495 case BUILT_IN_SQRT:
4496 case BUILT_IN_SQRTF:
4497 case BUILT_IN_SQRTL:
4498 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
4499 {
4500 enum built_in_function fcode;
4501 tree arg = TREE_VALUE (arglist);
4502
4503 /* Optimize sqrt of constant value. */
4504 if (TREE_CODE (arg) == REAL_CST
4505 && ! TREE_CONSTANT_OVERFLOW (arg))
4506 {
4507 enum machine_mode mode;
4508 REAL_VALUE_TYPE r, x;
4509
4510 x = TREE_REAL_CST (arg);
4511 mode = TYPE_MODE (TREE_TYPE (arg));
61f1dccc 4512 if (real_sqrt (&r, mode, &x)
4513 || (!flag_trapping_math && !flag_errno_math))
805e22b2 4514 return build_real (TREE_TYPE (arg), r);
805e22b2 4515 }
4516
4517 /* Optimize sqrt(exp(x)) = exp(x/2.0). */
4518 fcode = builtin_mathfn_code (arg);
4519 if (flag_unsafe_math_optimizations
4520 && (fcode == BUILT_IN_EXP
4521 || fcode == BUILT_IN_EXPF
4522 || fcode == BUILT_IN_EXPL))
4523 {
4524 tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
4525 arg = build (RDIV_EXPR, TREE_TYPE (arg),
4526 TREE_VALUE (TREE_OPERAND (arg, 1)),
4527 build_real (TREE_TYPE (arg), dconst2));
4528 arglist = build_tree_list (NULL_TREE, arg);
4529 return build_function_call_expr (expfn, arglist);
4530 }
4531 }
4532 break;
4533
4534 case BUILT_IN_EXP:
4535 case BUILT_IN_EXPF:
4536 case BUILT_IN_EXPL:
4537 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
4538 {
4539 enum built_in_function fcode;
4540 tree arg = TREE_VALUE (arglist);
4541
4542 /* Optimize exp(0.0) = 1.0. */
4543 if (real_zerop (arg))
4544 return build_real (TREE_TYPE (arg), dconst1);
4545
4546 /* Optimize exp(log(x)) = x. */
4547 fcode = builtin_mathfn_code (arg);
4548 if (flag_unsafe_math_optimizations
4549 && (fcode == BUILT_IN_LOG
4550 || fcode == BUILT_IN_LOGF
4551 || fcode == BUILT_IN_LOGL))
4552 return TREE_VALUE (TREE_OPERAND (arg, 1));
4553 }
4554 break;
4555
4556 case BUILT_IN_LOG:
4557 case BUILT_IN_LOGF:
4558 case BUILT_IN_LOGL:
4559 if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
4560 {
4561 enum built_in_function fcode;
4562 tree arg = TREE_VALUE (arglist);
4563
4564 /* Optimize log(1.0) = 0.0. */
4565 if (real_onep (arg))
4566 return build_real (TREE_TYPE (arg), dconst0);
4567
4568 /* Optimize log(exp(x)) = x. */
4569 fcode = builtin_mathfn_code (arg);
4570 if (flag_unsafe_math_optimizations
4571 && (fcode == BUILT_IN_EXP
4572 || fcode == BUILT_IN_EXPF
4573 || fcode == BUILT_IN_EXPL))
4574 return TREE_VALUE (TREE_OPERAND (arg, 1));
4575
4576 /* Optimize log(sqrt(x)) = log(x)/2.0. */
4577 if (flag_unsafe_math_optimizations
4578 && (fcode == BUILT_IN_SQRT
4579 || fcode == BUILT_IN_SQRTF
4580 || fcode == BUILT_IN_SQRTL))
4581 {
4582 tree logfn = build_function_call_expr (fndecl,
4583 TREE_OPERAND (arg, 1));
4584 return fold (build (RDIV_EXPR, TREE_TYPE (arg), logfn,
4585 build_real (TREE_TYPE (arg), dconst2)));
4586 }
4587 }
4588 break;
4589
92c43e3c 4590 case BUILT_IN_INF:
4591 case BUILT_IN_INFF:
4592 case BUILT_IN_INFL:
4593 return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), true);
4594
4595 case BUILT_IN_HUGE_VAL:
4596 case BUILT_IN_HUGE_VALF:
4597 case BUILT_IN_HUGE_VALL:
4598 return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), false);
4599
b0db7939 4600 case BUILT_IN_NAN:
4601 case BUILT_IN_NANF:
4602 case BUILT_IN_NANL:
4603 return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), true);
4604
4605 case BUILT_IN_NANS:
4606 case BUILT_IN_NANSF:
4607 case BUILT_IN_NANSL:
4608 return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), false);
4609
6528f4f4 4610 case BUILT_IN_FLOOR:
4611 case BUILT_IN_FLOORF:
4612 case BUILT_IN_FLOORL:
4613 case BUILT_IN_CEIL:
4614 case BUILT_IN_CEILF:
4615 case BUILT_IN_CEILL:
4616 case BUILT_IN_TRUNC:
4617 case BUILT_IN_TRUNCF:
4618 case BUILT_IN_TRUNCL:
4619 case BUILT_IN_ROUND:
4620 case BUILT_IN_ROUNDF:
4621 case BUILT_IN_ROUNDL:
4622 case BUILT_IN_NEARBYINT:
4623 case BUILT_IN_NEARBYINTF:
4624 case BUILT_IN_NEARBYINTL:
4625 return fold_trunc_transparent_mathfn (exp);
4626
650e4c94 4627 default:
4628 break;
4629 }
4630
4631 return 0;
4632}
7e15618b 4633
805e22b2 4634/* Conveniently construct a function call expression. */
4635
4636tree
7e15618b 4637build_function_call_expr (fn, arglist)
4638 tree fn, arglist;
4639{
4640 tree call_expr;
4641
4642 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
4643 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
4644 call_expr, arglist);
4645 TREE_SIDE_EFFECTS (call_expr) = 1;
4646 return fold (call_expr);
4647}
0eb671f7 4648
4649/* This function validates the types of a function call argument list
4650 represented as a tree chain of parameters against a specified list
4651 of tree_codes. If the last specifier is a 0, that represents an
4652 ellipses, otherwise the last specifier must be a VOID_TYPE. */
27d0c333 4653
0eb671f7 4654static int
4655validate_arglist VPARAMS ((tree arglist, ...))
4656{
0eb671f7 4657 enum tree_code code;
0903457a 4658 int res = 0;
0eb671f7 4659
0903457a 4660 VA_OPEN (ap, arglist);
4661 VA_FIXEDARG (ap, tree, arglist);
0eb671f7 4662
f0ce3b1f 4663 do
0eb671f7 4664 {
f0ce3b1f 4665 code = va_arg (ap, enum tree_code);
4666 switch (code)
4667 {
4668 case 0:
4669 /* This signifies an ellipses, any further arguments are all ok. */
4670 res = 1;
4671 goto end;
4672 case VOID_TYPE:
4673 /* This signifies an endlink, if no arguments remain, return
4674 true, otherwise return false. */
4675 res = arglist == 0;
4676 goto end;
4677 default:
4678 /* If no parameters remain or the parameter's code does not
4679 match the specified code, return false. Otherwise continue
4680 checking any remaining arguments. */
4681 if (arglist == 0
4682 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
4683 goto end;
4684 break;
4685 }
4686 arglist = TREE_CHAIN (arglist);
0eb671f7 4687 }
f0ce3b1f 4688 while (1);
0903457a 4689
4690 /* We need gotos here since we can only have one VA_CLOSE in a
4691 function. */
4692 end: ;
4693 VA_CLOSE (ap);
4694
4695 return res;
0eb671f7 4696}
fc2a2dcb 4697
4698/* Default version of target-specific builtin setup that does nothing. */
4699
4700void
4701default_init_builtins ()
4702{
4703}
4704
4705/* Default target-specific builtin expander that does nothing. */
4706
4707rtx
4708default_expand_builtin (exp, target, subtarget, mode, ignore)
4709 tree exp ATTRIBUTE_UNUSED;
4710 rtx target ATTRIBUTE_UNUSED;
4711 rtx subtarget ATTRIBUTE_UNUSED;
4712 enum machine_mode mode ATTRIBUTE_UNUSED;
4713 int ignore ATTRIBUTE_UNUSED;
4714{
4715 return NULL_RTX;
4716}
c7926a82 4717
4718/* Instantiate all remaining CONSTANT_P_RTX nodes. */
4719
4720void
4721purge_builtin_constant_p ()
4722{
ea06a334 4723 rtx insn, set, arg, new, note;
c7926a82 4724
ea06a334 4725 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4726 if (INSN_P (insn)
4727 && (set = single_set (insn)) != NULL_RTX
4728 && GET_CODE (SET_SRC (set)) == CONSTANT_P_RTX)
4729 {
4730 arg = XEXP (SET_SRC (set), 0);
4731 new = CONSTANT_P (arg) ? const1_rtx : const0_rtx;
4732 validate_change (insn, &SET_SRC (set), new, 0);
c7926a82 4733
ea06a334 4734 /* Remove the REG_EQUAL note from the insn. */
4735 if ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0)
4736 remove_note (insn, note);
4737 }
c7926a82 4738}
4739