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