OSDN Git Service

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