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