]> gcc.gnu.org Git - gcc.git/blame - gcc/builtins.c
configure.in (noconfigdirs): Disable target-newlib and target-libgloss.
[gcc.git] / gcc / builtins.c
Content-type: text/html ]> gcc.gnu.org Git - gcc.git/blame - gcc/builtins.c


500 - Internal Server Error

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