source: trunk/src/gcc/gcc/builtins.c@ 1392

Last change on this file since 1392 was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

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