OSDN Git Service

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