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