OSDN Git Service

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