]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c
* doc/md.texi (Processor pipeline description): Improve wording.
[thirdparty/gcc.git] / gcc / builtins.c
Content-type: text/html ]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/builtins.c


500 - Internal Server Error

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