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