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