OSDN Git Service

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