OSDN Git Service

* builtins.c (expand_builtin_strncmp): Use host_integerp and
[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   /* If the len parameter is zero, return zero.  */
2334   if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0)
2335   {
2336     /* Evaluate and ignore arg1 and arg2 in case they have
2337        side-effects.  */
2338     expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2339     expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2340     return const0_rtx;
2341   }
2342
2343   p1 = c_getstr (arg1);
2344   p2 = c_getstr (arg2);
2345
2346   /* If all arguments are constant, evaluate at compile-time.  */
2347   if (host_integerp (arg3, 1) && p1 && p2)
2348   {
2349     const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
2350     return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2351   }
2352
2353   /* If len == 1 or (either string parameter is "" and (len >= 1)),
2354       return (*(const u_char*)arg1 - *(const u_char*)arg2).  */
2355   if (host_integerp (arg3, 1)
2356       && (tree_low_cst (arg3, 1) == 1
2357           || (tree_low_cst (arg3, 1) > 1
2358               && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
2359     {
2360       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2361       tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2362       tree ind1 =
2363         fold (build1 (CONVERT_EXPR, integer_type_node,
2364                       build1 (INDIRECT_REF, cst_uchar_node,
2365                               build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2366       tree ind2 =
2367         fold (build1 (CONVERT_EXPR, integer_type_node,
2368                       build1 (INDIRECT_REF, cst_uchar_node,
2369                               build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2370       tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2371       return expand_expr (result, target, mode, EXPAND_NORMAL);
2372     }
2373
2374 #ifdef HAVE_cmpstrsi
2375   /* If c_strlen can determine an expression for one of the string
2376      lengths, and it doesn't have side effects, then call
2377      expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3).  */
2378   if (HAVE_cmpstrsi)
2379     { 
2380       tree newarglist, len = 0;
2381
2382       /* Perhaps one of the strings is really constant, if so prefer
2383          that constant length over the other string's length.  */
2384       if (p1)
2385         len = c_strlen (arg1);
2386       else if (p2)
2387         len = c_strlen (arg2);
2388
2389       /* If we still don't have a len, try either string arg as long
2390          as they don't have side effects.  */
2391       if (!len && !TREE_SIDE_EFFECTS (arg1))
2392         len = c_strlen (arg1);
2393       if (!len && !TREE_SIDE_EFFECTS (arg2))
2394         len = c_strlen (arg2);
2395       /* If we still don't have a length, punt.  */
2396       if (!len)
2397         return 0;
2398         
2399       /* Add one to the string length.  */
2400       len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
2401         
2402       /* The actual new length parameter is MIN(len,arg3).  */
2403       len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
2404
2405       newarglist = build_tree_list (NULL_TREE, len);
2406       newarglist = tree_cons (NULL_TREE, arg2, newarglist);
2407       newarglist = tree_cons (NULL_TREE, arg1, newarglist);
2408       return expand_builtin_memcmp (exp, newarglist, target);
2409     }
2410 #endif
2411   
2412   return 0;
2413 }
2414
2415 /* Expand expression EXP, which is a call to the strcat builtin.
2416    Return 0 if we failed the caller should emit a normal call,
2417    otherwise try to get the result in TARGET, if convenient.  */
2418 static rtx
2419 expand_builtin_strcat (arglist, target, mode)
2420      tree arglist;
2421      rtx target;
2422      enum machine_mode mode;
2423 {
2424   /* If we need to check memory accesses, call the library function.  */
2425   if (current_function_check_memory_usage)
2426     return 0;
2427
2428   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2429     return 0;
2430   else
2431     {
2432       tree dst = TREE_VALUE (arglist),
2433         src = TREE_VALUE (TREE_CHAIN (arglist));
2434       const char *p = c_getstr (src);
2435
2436       /* If the string length is zero, return the dst parameter.  */
2437       if (p && *p == '\0')
2438         return expand_expr (dst, target, mode, EXPAND_NORMAL);
2439
2440       return 0;
2441     }
2442 }
2443
2444 /* Expand expression EXP, which is a call to the strncat builtin.
2445    Return 0 if we failed the caller should emit a normal call,
2446    otherwise try to get the result in TARGET, if convenient.  */
2447 static rtx
2448 expand_builtin_strncat (arglist, target, mode)
2449      tree arglist;
2450      rtx target;
2451      enum machine_mode mode;
2452 {
2453   /* If we need to check memory accesses, call the library function.  */
2454   if (current_function_check_memory_usage)
2455     return 0;
2456
2457   if (!validate_arglist (arglist,
2458                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2459     return 0;
2460   else
2461     {
2462       tree dst = TREE_VALUE (arglist),
2463         src = TREE_VALUE (TREE_CHAIN (arglist)),
2464         len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2465       const char *p = c_getstr (src);
2466
2467       /* If the requested length is zero, or the src parameter string
2468           length is zero, return the dst parameter.  */
2469       if ((TREE_CODE (len) == INTEGER_CST && compare_tree_int (len, 0) == 0)
2470           || (p && *p == '\0'))
2471         {
2472           /* Evaluate and ignore the src and len parameters in case
2473              they have side-effects.  */
2474           expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2475           expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2476           return expand_expr (dst, target, mode, EXPAND_NORMAL);
2477         }
2478
2479       /* If the requested len is greater than or equal to the string
2480          length, call strcat.  */
2481       if (TREE_CODE (len) == INTEGER_CST && p
2482           && compare_tree_int (len, strlen (p)) >= 0)
2483         {
2484           tree newarglist =
2485             tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src)),
2486             fn = built_in_decls[BUILT_IN_STRCAT];
2487           
2488           /* If the replacement _DECL isn't initialized, don't do the
2489              transformation. */
2490           if (!fn)
2491             return 0;
2492
2493           return expand_expr (build_function_call_expr (fn, newarglist),
2494                               target, mode, EXPAND_NORMAL);
2495         }
2496       return 0;
2497     }
2498 }
2499
2500 /* Expand expression EXP, which is a call to the strspn builtin.
2501    Return 0 if we failed the caller should emit a normal call,
2502    otherwise try to get the result in TARGET, if convenient.  */
2503 static rtx
2504 expand_builtin_strspn (arglist, target, mode)
2505      tree arglist;
2506      rtx target;
2507      enum machine_mode mode;
2508 {
2509   /* If we need to check memory accesses, call the library function.  */
2510   if (current_function_check_memory_usage)
2511     return 0;
2512
2513   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2514     return 0;
2515   else
2516     {
2517       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2518       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2519       
2520       /* If both arguments are constants, evaluate at compile-time.  */
2521       if (p1 && p2)
2522         {
2523           const size_t r = strspn (p1, p2);
2524           return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2525         }
2526       
2527       /* If either argument is "", return 0.  */
2528       if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2529         {
2530           /* Evaluate and ignore both arguments in case either one has
2531              side-effects.  */
2532           expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2533           expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2534           return const0_rtx;
2535         }
2536       return 0;
2537     }
2538 }
2539
2540 /* Expand expression EXP, which is a call to the strcspn builtin.
2541    Return 0 if we failed the caller should emit a normal call,
2542    otherwise try to get the result in TARGET, if convenient.  */
2543 static rtx
2544 expand_builtin_strcspn (arglist, target, mode)
2545      tree arglist;
2546      rtx target;
2547      enum machine_mode mode;
2548 {
2549   /* If we need to check memory accesses, call the library function.  */
2550   if (current_function_check_memory_usage)
2551     return 0;
2552
2553   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2554     return 0;
2555   else
2556     {
2557       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2558       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2559       
2560       /* If both arguments are constants, evaluate at compile-time.  */
2561       if (p1 && p2)
2562         {
2563           const size_t r = strcspn (p1, p2);
2564           return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2565         }
2566       
2567       /* If the first argument is "", return 0.  */
2568       if (p1 && *p1 == '\0')
2569         {
2570           /* Evaluate and ignore argument s2 in case it has
2571              side-effects.  */
2572           expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2573           return const0_rtx;
2574         }
2575
2576       /* If the second argument is "", return __builtin_strlen(s1).  */
2577       if (p2 && *p2 == '\0')
2578         {
2579           tree newarglist = build_tree_list (NULL_TREE, s1),
2580             fn = built_in_decls[BUILT_IN_STRLEN];
2581           
2582           /* If the replacement _DECL isn't initialized, don't do the
2583              transformation. */
2584           if (!fn)
2585             return 0;
2586
2587           return expand_expr (build_function_call_expr (fn, newarglist),
2588                               target, mode, EXPAND_NORMAL);
2589         }
2590       return 0;
2591     }
2592 }
2593
2594 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
2595    if that's convenient.  */
2596
2597 rtx
2598 expand_builtin_saveregs ()
2599 {
2600   rtx val, seq;
2601
2602   /* Don't do __builtin_saveregs more than once in a function.
2603      Save the result of the first call and reuse it.  */
2604   if (saveregs_value != 0)
2605     return saveregs_value;
2606
2607   /* When this function is called, it means that registers must be
2608      saved on entry to this function.  So we migrate the call to the
2609      first insn of this function.  */
2610
2611   start_sequence ();
2612
2613 #ifdef EXPAND_BUILTIN_SAVEREGS
2614   /* Do whatever the machine needs done in this case.  */
2615   val = EXPAND_BUILTIN_SAVEREGS ();
2616 #else
2617   /* ??? We used to try and build up a call to the out of line function,
2618      guessing about what registers needed saving etc.  This became much
2619      harder with __builtin_va_start, since we don't have a tree for a
2620      call to __builtin_saveregs to fall back on.  There was exactly one
2621      port (i860) that used this code, and I'm unconvinced it could actually
2622      handle the general case.  So we no longer try to handle anything
2623      weird and make the backend absorb the evil.  */
2624
2625   error ("__builtin_saveregs not supported by this target");
2626   val = const0_rtx;
2627 #endif
2628
2629   seq = get_insns ();
2630   end_sequence ();
2631
2632   saveregs_value = val;
2633
2634   /* Put the sequence after the NOTE that starts the function.  If this
2635      is inside a SEQUENCE, make the outer-level insn chain current, so
2636      the code is placed at the start of the function.  */
2637   push_topmost_sequence ();
2638   emit_insns_after (seq, get_insns ());
2639   pop_topmost_sequence ();
2640
2641   return val;
2642 }
2643
2644 /* __builtin_args_info (N) returns word N of the arg space info
2645    for the current function.  The number and meanings of words
2646    is controlled by the definition of CUMULATIVE_ARGS.  */
2647
2648 static rtx
2649 expand_builtin_args_info (exp)
2650      tree exp;
2651 {
2652   tree arglist = TREE_OPERAND (exp, 1);
2653   int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
2654   int *word_ptr = (int *) &current_function_args_info;
2655 #if 0   
2656   /* These are used by the code below that is if 0'ed away */
2657   int i;
2658   tree type, elts, result;
2659 #endif
2660
2661   if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
2662     abort ();
2663
2664   if (arglist != 0)
2665     {
2666       tree arg = TREE_VALUE (arglist);
2667       if (TREE_CODE (arg) != INTEGER_CST)
2668         error ("argument of `__builtin_args_info' must be constant");
2669       else
2670         {
2671           int wordnum = TREE_INT_CST_LOW (arg);
2672
2673           if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg))
2674             error ("argument of `__builtin_args_info' out of range");
2675           else
2676             return GEN_INT (word_ptr[wordnum]);
2677         }
2678     }
2679   else
2680     error ("missing argument in `__builtin_args_info'");
2681
2682   return const0_rtx;
2683
2684 #if 0
2685   for (i = 0; i < nwords; i++)
2686     elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
2687
2688   type = build_array_type (integer_type_node,
2689                            build_index_type (build_int_2 (nwords, 0)));
2690   result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
2691   TREE_CONSTANT (result) = 1;
2692   TREE_STATIC (result) = 1;
2693   result = build1 (INDIRECT_REF, build_pointer_type (type), result);
2694   TREE_CONSTANT (result) = 1;
2695   return expand_expr (result, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD);
2696 #endif
2697 }
2698
2699 /* Expand ARGLIST, from a call to __builtin_next_arg.  */
2700 static rtx
2701 expand_builtin_next_arg (arglist)
2702      tree arglist;
2703 {
2704   tree fntype = TREE_TYPE (current_function_decl);
2705
2706   if ((TYPE_ARG_TYPES (fntype) == 0
2707        || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2708            == void_type_node))
2709       && ! current_function_varargs)
2710     {
2711       error ("`va_start' used in function with fixed args");
2712       return const0_rtx;
2713     }
2714
2715   if (arglist)
2716     {
2717       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
2718       tree arg = TREE_VALUE (arglist);
2719
2720       /* Strip off all nops for the sake of the comparison.  This
2721          is not quite the same as STRIP_NOPS.  It does more.  
2722          We must also strip off INDIRECT_EXPR for C++ reference
2723          parameters.  */
2724       while (TREE_CODE (arg) == NOP_EXPR
2725              || TREE_CODE (arg) == CONVERT_EXPR
2726              || TREE_CODE (arg) == NON_LVALUE_EXPR
2727              || TREE_CODE (arg) == INDIRECT_REF)
2728         arg = TREE_OPERAND (arg, 0);
2729       if (arg != last_parm)
2730         warning ("second parameter of `va_start' not last named argument");
2731     }
2732   else if (! current_function_varargs)
2733     /* Evidently an out of date version of <stdarg.h>; can't validate
2734        va_start's second argument, but can still work as intended.  */
2735     warning ("`__builtin_next_arg' called without an argument");
2736
2737   return expand_binop (Pmode, add_optab,
2738                        current_function_internal_arg_pointer,
2739                        current_function_arg_offset_rtx,
2740                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
2741 }
2742
2743 /* Make it easier for the backends by protecting the valist argument
2744    from multiple evaluations.  */
2745
2746 static tree
2747 stabilize_va_list (valist, needs_lvalue)
2748      tree valist;
2749      int needs_lvalue;
2750 {
2751   if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
2752     {
2753       if (TREE_SIDE_EFFECTS (valist))
2754         valist = save_expr (valist);
2755
2756       /* For this case, the backends will be expecting a pointer to
2757          TREE_TYPE (va_list_type_node), but it's possible we've
2758          actually been given an array (an actual va_list_type_node).
2759          So fix it.  */
2760       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
2761         {
2762           tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
2763           tree p2 = build_pointer_type (va_list_type_node);
2764
2765           valist = build1 (ADDR_EXPR, p2, valist);
2766           valist = fold (build1 (NOP_EXPR, p1, valist));
2767         }
2768     }
2769   else
2770     {
2771       tree pt;
2772
2773       if (! needs_lvalue)
2774         {
2775           if (! TREE_SIDE_EFFECTS (valist))
2776             return valist;
2777           
2778           pt = build_pointer_type (va_list_type_node);
2779           valist = fold (build1 (ADDR_EXPR, pt, valist));
2780           TREE_SIDE_EFFECTS (valist) = 1;
2781         }
2782
2783       if (TREE_SIDE_EFFECTS (valist))
2784         valist = save_expr (valist);
2785       valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
2786                              valist));
2787     }
2788
2789   return valist;
2790 }
2791
2792 /* The "standard" implementation of va_start: just assign `nextarg' to
2793    the variable.  */
2794 void
2795 std_expand_builtin_va_start (stdarg_p, valist, nextarg)
2796      int stdarg_p;
2797      tree valist;
2798      rtx nextarg;
2799 {
2800   tree t;
2801
2802   if (! stdarg_p)
2803     {
2804       int align = PARM_BOUNDARY / BITS_PER_UNIT;
2805       int offset = (((UNITS_PER_WORD + align - 1) / align) * align);
2806       nextarg = plus_constant (nextarg, -offset);
2807     }
2808
2809   t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2810              make_tree (ptr_type_node, nextarg));
2811   TREE_SIDE_EFFECTS (t) = 1;
2812
2813   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2814 }
2815
2816 /* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
2817    __builtin_varargs_va_start, depending on STDARG_P.  */
2818 static rtx
2819 expand_builtin_va_start (stdarg_p, arglist)
2820      int stdarg_p;
2821      tree arglist;
2822 {
2823   rtx nextarg;
2824   tree chain = arglist, valist;
2825
2826   if (stdarg_p)
2827     nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
2828   else
2829     nextarg = expand_builtin_next_arg (NULL_TREE);
2830
2831   if (TREE_CHAIN (chain))
2832     error ("too many arguments to function `va_start'");
2833
2834   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
2835
2836 #ifdef EXPAND_BUILTIN_VA_START
2837   EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
2838 #else
2839   std_expand_builtin_va_start (stdarg_p, valist, nextarg);
2840 #endif
2841
2842   return const0_rtx;
2843 }
2844
2845 /* The "standard" implementation of va_arg: read the value from the
2846    current (padded) address and increment by the (padded) size.  */
2847
2848 rtx
2849 std_expand_builtin_va_arg (valist, type)
2850      tree valist, type;
2851 {
2852   tree addr_tree, t;
2853   HOST_WIDE_INT align;
2854   HOST_WIDE_INT rounded_size;
2855   rtx addr;
2856
2857   /* Compute the rounded size of the type.  */
2858   align = PARM_BOUNDARY / BITS_PER_UNIT;
2859   rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
2860
2861   /* Get AP.  */
2862   addr_tree = valist;
2863   if (PAD_VARARGS_DOWN)
2864     {
2865       /* Small args are padded downward.  */
2866
2867       HOST_WIDE_INT adj;
2868       adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT;
2869       if (rounded_size > align)
2870         adj = rounded_size;
2871
2872       addr_tree = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
2873                          build_int_2 (rounded_size - adj, 0));
2874     }
2875
2876   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2877   addr = copy_to_reg (addr);
2878
2879   /* Compute new value for AP.  */
2880   t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2881              build (PLUS_EXPR, TREE_TYPE (valist), valist,
2882                     build_int_2 (rounded_size, 0)));
2883   TREE_SIDE_EFFECTS (t) = 1;
2884   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2885
2886   return addr;
2887 }
2888
2889 /* Expand __builtin_va_arg, which is not really a builtin function, but
2890    a very special sort of operator.  */
2891
2892 rtx
2893 expand_builtin_va_arg (valist, type)
2894      tree valist, type;
2895 {
2896   rtx addr, result;
2897   tree promoted_type, want_va_type, have_va_type;
2898
2899   /* Verify that valist is of the proper type.  */
2900
2901   want_va_type = va_list_type_node;
2902   have_va_type = TREE_TYPE (valist);
2903   if (TREE_CODE (want_va_type) == ARRAY_TYPE)
2904     {
2905       /* If va_list is an array type, the argument may have decayed 
2906          to a pointer type, e.g. by being passed to another function.
2907          In that case, unwrap both types so that we can compare the
2908          underlying records.  */
2909       if (TREE_CODE (have_va_type) == ARRAY_TYPE
2910           || TREE_CODE (have_va_type) == POINTER_TYPE)
2911         {
2912           want_va_type = TREE_TYPE (want_va_type);
2913           have_va_type = TREE_TYPE (have_va_type);
2914         }
2915     }
2916   if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
2917     {
2918       error ("first argument to `va_arg' not of type `va_list'");
2919       addr = const0_rtx;
2920     }
2921
2922   /* Generate a diagnostic for requesting data of a type that cannot
2923      be passed through `...' due to type promotion at the call site.  */
2924   else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
2925     {
2926       const char *name = "<anonymous type>", *pname = 0;
2927       static int gave_help;
2928
2929       if (TYPE_NAME (type))
2930         {
2931           if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
2932             name = IDENTIFIER_POINTER (TYPE_NAME (type));
2933           else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
2934                    && DECL_NAME (TYPE_NAME (type)))
2935             name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
2936         }
2937       if (TYPE_NAME (promoted_type))
2938         {
2939           if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
2940             pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
2941           else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
2942                    && DECL_NAME (TYPE_NAME (promoted_type)))
2943             pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
2944         }
2945
2946       error ("`%s' is promoted to `%s' when passed through `...'", name, pname);
2947       if (! gave_help)
2948         {
2949           gave_help = 1;
2950           error ("(so you should pass `%s' not `%s' to `va_arg')", pname, name);
2951         }
2952
2953       addr = const0_rtx;
2954     }
2955   else
2956     {
2957       /* Make it easier for the backends by protecting the valist argument
2958          from multiple evaluations.  */
2959       valist = stabilize_va_list (valist, 0);
2960
2961 #ifdef EXPAND_BUILTIN_VA_ARG
2962       addr = EXPAND_BUILTIN_VA_ARG (valist, type);
2963 #else
2964       addr = std_expand_builtin_va_arg (valist, type);
2965 #endif
2966     }
2967
2968   result = gen_rtx_MEM (TYPE_MODE (type), addr);
2969   MEM_ALIAS_SET (result) = get_varargs_alias_set ();
2970
2971   return result;
2972 }
2973
2974 /* Expand ARGLIST, from a call to __builtin_va_end.  */
2975
2976 static rtx
2977 expand_builtin_va_end (arglist)
2978      tree arglist;
2979 {
2980   tree valist = TREE_VALUE (arglist);
2981
2982 #ifdef EXPAND_BUILTIN_VA_END
2983   valist = stabilize_va_list (valist, 0);
2984   EXPAND_BUILTIN_VA_END(arglist);
2985 #else
2986   /* Evaluate for side effects, if needed.  I hate macros that don't
2987      do that.  */
2988   if (TREE_SIDE_EFFECTS (valist))
2989     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
2990 #endif
2991
2992   return const0_rtx;
2993 }
2994
2995 /* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a 
2996    builtin rather than just as an assignment in stdarg.h because of the
2997    nastiness of array-type va_list types.  */
2998
2999 static rtx
3000 expand_builtin_va_copy (arglist)
3001      tree arglist;
3002 {
3003   tree dst, src, t;
3004
3005   dst = TREE_VALUE (arglist);
3006   src = TREE_VALUE (TREE_CHAIN (arglist));
3007
3008   dst = stabilize_va_list (dst, 1);
3009   src = stabilize_va_list (src, 0);
3010
3011   if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
3012     {
3013       t = build (MODIFY_EXPR, va_list_type_node, dst, src);
3014       TREE_SIDE_EFFECTS (t) = 1;
3015       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3016     }
3017   else
3018     {
3019       rtx dstb, srcb, size;
3020
3021       /* Evaluate to pointers.  */
3022       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
3023       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
3024       size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
3025                           VOIDmode, EXPAND_NORMAL);
3026
3027       /* "Dereference" to BLKmode memories.  */
3028       dstb = gen_rtx_MEM (BLKmode, dstb);
3029       MEM_ALIAS_SET (dstb) = get_alias_set (TREE_TYPE (TREE_TYPE (dst)));
3030       srcb = gen_rtx_MEM (BLKmode, srcb);
3031       MEM_ALIAS_SET (srcb) = get_alias_set (TREE_TYPE (TREE_TYPE (src)));
3032
3033       /* Copy.  */
3034       emit_block_move (dstb, srcb, size, TYPE_ALIGN (va_list_type_node));
3035     }
3036
3037   return const0_rtx;
3038 }
3039
3040 /* Expand a call to one of the builtin functions __builtin_frame_address or
3041    __builtin_return_address.  */
3042 static rtx
3043 expand_builtin_frame_address (exp)
3044      tree exp;
3045 {
3046   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3047   tree arglist = TREE_OPERAND (exp, 1);
3048
3049   /* The argument must be a nonnegative integer constant.
3050      It counts the number of frames to scan up the stack.
3051      The value is the return address saved in that frame.  */
3052   if (arglist == 0)
3053     /* Warning about missing arg was already issued.  */
3054     return const0_rtx;
3055   else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST
3056            || tree_int_cst_sgn (TREE_VALUE (arglist)) < 0)
3057     {
3058       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3059         error ("invalid arg to `__builtin_frame_address'");
3060       else
3061         error ("invalid arg to `__builtin_return_address'");
3062       return const0_rtx;
3063     }
3064   else
3065     {
3066       rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
3067                                             TREE_INT_CST_LOW (TREE_VALUE (arglist)),
3068                                             hard_frame_pointer_rtx);
3069
3070       /* Some ports cannot access arbitrary stack frames.  */
3071       if (tem == NULL)
3072         {
3073           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3074             warning ("unsupported arg to `__builtin_frame_address'");
3075           else
3076             warning ("unsupported arg to `__builtin_return_address'");
3077           return const0_rtx;
3078         }
3079
3080       /* For __builtin_frame_address, return what we've got.  */
3081       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3082         return tem;
3083
3084       if (GET_CODE (tem) != REG
3085           && ! CONSTANT_P (tem))
3086         tem = copy_to_mode_reg (Pmode, tem);
3087       return tem;
3088     }
3089 }
3090
3091 /* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
3092    we failed and the caller should emit a normal call, otherwise try to get
3093    the result in TARGET, if convenient.  */
3094 static rtx
3095 expand_builtin_alloca (arglist, target)
3096      tree arglist;
3097      rtx target;
3098 {
3099   rtx op0;
3100
3101   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3102     return 0;
3103
3104   /* Compute the argument.  */
3105   op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
3106
3107   /* Allocate the desired space.  */
3108   return allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
3109 }
3110
3111 /* Expand a call to the ffs builtin.  The arguments are in ARGLIST.
3112    Return 0 if a normal call should be emitted rather than expanding the
3113    function in-line.  If convenient, the result should be placed in TARGET.
3114    SUBTARGET may be used as the target for computing one of EXP's operands.  */
3115 static rtx
3116 expand_builtin_ffs (arglist, target, subtarget)
3117      tree arglist;
3118      rtx target, subtarget;
3119 {
3120   rtx op0;
3121   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3122     return 0;
3123
3124   /* Compute the argument.  */
3125   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
3126   /* Compute ffs, into TARGET if possible.
3127      Set TARGET to wherever the result comes back.  */
3128   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
3129                         ffs_optab, op0, target, 1);
3130   if (target == 0)
3131     abort ();
3132   return target;
3133 }
3134
3135 /* If the string passed to fputs is a constant and is one character
3136    long, we attempt to transform this call into __builtin_fputc(). */
3137 static rtx
3138 expand_builtin_fputs (arglist, ignore)
3139      tree arglist;
3140      int ignore;
3141 {
3142   tree len, fn, fn_fputc = built_in_decls[BUILT_IN_FPUTC],
3143     fn_fwrite = built_in_decls[BUILT_IN_FWRITE];
3144
3145   /* If the return value is used, or the replacement _DECL isn't
3146      initialized, don't do the transformation. */
3147   if (!ignore || !fn_fputc || !fn_fwrite)
3148     return 0;
3149
3150   /* Verify the arguments in the original call. */
3151   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
3152       || current_function_check_memory_usage)
3153     return 0;
3154
3155   /* Get the length of the string passed to fputs.  If the length
3156      can't be determined, punt.  */
3157   if (!(len = c_strlen (TREE_VALUE (arglist)))
3158       || TREE_CODE (len) != INTEGER_CST)
3159     return 0;
3160
3161   switch (compare_tree_int (len, 1))
3162     {
3163     case -1: /* length is 0, delete the call entirely .  */
3164       {
3165         /* Evaluate and ignore the argument in case it has
3166            side-effects.  */
3167         expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
3168                      VOIDmode, EXPAND_NORMAL);
3169         return const0_rtx;
3170       }
3171     case 0: /* length is 1, call fputc.  */
3172       {
3173         const char *p = c_getstr (TREE_VALUE (arglist));
3174
3175         if (p != NULL)
3176           {      
3177             /* New argument list transforming fputs(string, stream) to
3178                fputc(string[0], stream).  */
3179             arglist =
3180               build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3181             arglist =
3182               tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
3183             fn = fn_fputc;
3184             break;
3185           }
3186       }
3187       /* FALLTHROUGH */
3188     case 1: /* length is greater than 1, call fwrite.  */
3189       {
3190         tree string_arg = TREE_VALUE (arglist);
3191       
3192         /* New argument list transforming fputs(string, stream) to
3193            fwrite(string, 1, len, stream).  */
3194         arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3195         arglist = tree_cons (NULL_TREE, len, arglist);
3196         arglist = tree_cons (NULL_TREE, integer_one_node, arglist);
3197         arglist = tree_cons (NULL_TREE, string_arg, arglist);
3198         fn = fn_fwrite;
3199         break;
3200       }
3201     default:
3202       abort();
3203     }
3204   
3205   return expand_expr (build_function_call_expr (fn, arglist),
3206                       (ignore ? const0_rtx : NULL_RTX),
3207                       VOIDmode, EXPAND_NORMAL);
3208 }
3209
3210 /* Expand a call to __builtin_expect.  We return our argument and
3211    emit a NOTE_INSN_EXPECTED_VALUE note.  */
3212
3213 static rtx
3214 expand_builtin_expect (arglist, target)
3215      tree arglist;
3216      rtx target;
3217 {
3218   tree exp, c;
3219   rtx note, rtx_c;
3220
3221   if (arglist == NULL_TREE
3222       || TREE_CHAIN (arglist) == NULL_TREE)
3223     return const0_rtx;
3224   exp = TREE_VALUE (arglist);
3225   c = TREE_VALUE (TREE_CHAIN (arglist));
3226
3227   if (TREE_CODE (c) != INTEGER_CST)
3228     {
3229       error ("second arg to `__builtin_expect' must be a constant");
3230       c = integer_zero_node;
3231     }
3232
3233   target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
3234
3235   /* Don't bother with expected value notes for integral constants.  */
3236   if (GET_CODE (target) != CONST_INT)
3237     {
3238       /* We do need to force this into a register so that we can be
3239          moderately sure to be able to correctly interpret the branch
3240          condition later.  */
3241       target = force_reg (GET_MODE (target), target);
3242   
3243       rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
3244
3245       note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
3246       NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
3247     }
3248
3249   return target;
3250 }
3251 \f
3252 /* Expand an expression EXP that calls a built-in function,
3253    with result going to TARGET if that's convenient
3254    (and in mode MODE if that's convenient).
3255    SUBTARGET may be used as the target for computing one of EXP's operands.
3256    IGNORE is nonzero if the value is to be ignored.  */
3257
3258 rtx
3259 expand_builtin (exp, target, subtarget, mode, ignore)
3260      tree exp;
3261      rtx target;
3262      rtx subtarget;
3263      enum machine_mode mode;
3264      int ignore;
3265 {
3266   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3267   tree arglist = TREE_OPERAND (exp, 1);
3268   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
3269
3270 #ifdef MD_EXPAND_BUILTIN
3271   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
3272     return MD_EXPAND_BUILTIN (exp, target, subtarget, mode, ignore);
3273 #endif
3274   
3275   /* When not optimizing, generate calls to library functions for a certain
3276      set of builtins.  */
3277   if (! optimize && ! CALLED_AS_BUILT_IN (fndecl)
3278       && (fcode == BUILT_IN_SIN || fcode == BUILT_IN_COS
3279           || fcode == BUILT_IN_FSQRT || fcode == BUILT_IN_MEMSET
3280           || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
3281           || fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO
3282           || fcode == BUILT_IN_INDEX || fcode == BUILT_IN_RINDEX
3283           || fcode == BUILT_IN_STRCHR || fcode == BUILT_IN_STRRCHR
3284           || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
3285           || fcode == BUILT_IN_STRNCPY || fcode == BUILT_IN_STRNCMP
3286           || fcode == BUILT_IN_STRSTR || fcode == BUILT_IN_STRPBRK
3287           || fcode == BUILT_IN_STRCAT || fcode == BUILT_IN_STRNCAT
3288           || fcode == BUILT_IN_STRSPN || fcode == BUILT_IN_STRCSPN
3289           || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS
3290           || fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS
3291           || fcode == BUILT_IN_PRINTF || fcode == BUILT_IN_FPUTC
3292           || fcode == BUILT_IN_FPUTS || fcode == BUILT_IN_FWRITE))
3293     return expand_call (exp, target, ignore);
3294
3295   switch (fcode)
3296     {
3297     case BUILT_IN_ABS:
3298     case BUILT_IN_FABS:
3299       /* build_function_call changes these into ABS_EXPR.  */
3300       abort ();
3301
3302     case BUILT_IN_SIN:
3303     case BUILT_IN_COS:
3304       /* Treat these like sqrt, but only if the user asks for them.  */
3305       if (! flag_fast_math)
3306         break;
3307     case BUILT_IN_FSQRT:
3308       target = expand_builtin_mathfn (exp, target, subtarget);
3309       if (target)
3310         return target;
3311       break;
3312
3313     case BUILT_IN_FMOD:
3314       break;
3315
3316     case BUILT_IN_APPLY_ARGS:
3317       return expand_builtin_apply_args ();
3318
3319       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
3320          FUNCTION with a copy of the parameters described by
3321          ARGUMENTS, and ARGSIZE.  It returns a block of memory
3322          allocated on the stack into which is stored all the registers
3323          that might possibly be used for returning the result of a
3324          function.  ARGUMENTS is the value returned by
3325          __builtin_apply_args.  ARGSIZE is the number of bytes of
3326          arguments that must be copied.  ??? How should this value be
3327          computed?  We'll also need a safe worst case value for varargs
3328          functions.  */
3329     case BUILT_IN_APPLY:
3330       if (!validate_arglist (arglist, POINTER_TYPE,
3331                              POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
3332           && !validate_arglist (arglist, REFERENCE_TYPE,
3333                                 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3334         return const0_rtx;
3335       else
3336         {
3337           int i;
3338           tree t;
3339           rtx ops[3];
3340
3341           for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
3342             ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
3343
3344           return expand_builtin_apply (ops[0], ops[1], ops[2]);
3345         }
3346
3347       /* __builtin_return (RESULT) causes the function to return the
3348          value described by RESULT.  RESULT is address of the block of
3349          memory returned by __builtin_apply.  */
3350     case BUILT_IN_RETURN:
3351       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
3352         expand_builtin_return (expand_expr (TREE_VALUE (arglist),
3353                                             NULL_RTX, VOIDmode, 0));
3354       return const0_rtx;
3355
3356     case BUILT_IN_SAVEREGS:
3357       return expand_builtin_saveregs ();
3358
3359     case BUILT_IN_ARGS_INFO:
3360       return expand_builtin_args_info (exp);
3361
3362       /* Return the address of the first anonymous stack arg.  */
3363     case BUILT_IN_NEXT_ARG:
3364       return expand_builtin_next_arg (arglist);
3365
3366     case BUILT_IN_CLASSIFY_TYPE:
3367       return expand_builtin_classify_type (arglist);
3368
3369     case BUILT_IN_CONSTANT_P:
3370       return expand_builtin_constant_p (exp);
3371
3372     case BUILT_IN_FRAME_ADDRESS:
3373     case BUILT_IN_RETURN_ADDRESS:
3374       return expand_builtin_frame_address (exp);
3375
3376     /* Returns the address of the area where the structure is returned.
3377        0 otherwise.  */
3378     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
3379       if (arglist != 0
3380           || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
3381           || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
3382         return const0_rtx;
3383       else
3384         return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
3385
3386     case BUILT_IN_ALLOCA:
3387       target = expand_builtin_alloca (arglist, target);
3388       if (target)
3389         return target;
3390       break;
3391
3392     case BUILT_IN_FFS:
3393       target = expand_builtin_ffs (arglist, target, subtarget);
3394       if (target)
3395         return target;
3396       break;
3397
3398     case BUILT_IN_STRLEN:
3399       target = expand_builtin_strlen (exp, target);
3400       if (target)
3401         return target;
3402       break;
3403
3404     case BUILT_IN_STRCPY:
3405       target = expand_builtin_strcpy (exp);
3406       if (target)
3407         return target;
3408       break;
3409       
3410     case BUILT_IN_STRNCPY:
3411       target = expand_builtin_strncpy (arglist, target, mode);
3412       if (target)
3413         return target;
3414       break;
3415       
3416     case BUILT_IN_STRCAT:
3417       target = expand_builtin_strcat (arglist, target, mode);
3418       if (target)
3419         return target;
3420       break;
3421       
3422     case BUILT_IN_STRNCAT:
3423       target = expand_builtin_strncat (arglist, target, mode);
3424       if (target)
3425         return target;
3426       break;
3427       
3428     case BUILT_IN_STRSPN:
3429       target = expand_builtin_strspn (arglist, target, mode);
3430       if (target)
3431         return target;
3432       break;
3433       
3434     case BUILT_IN_STRCSPN:
3435       target = expand_builtin_strcspn (arglist, target, mode);
3436       if (target)
3437         return target;
3438       break;
3439       
3440     case BUILT_IN_STRSTR:
3441       target = expand_builtin_strstr (arglist, target, mode);
3442       if (target)
3443         return target;
3444       break;
3445       
3446     case BUILT_IN_STRPBRK:
3447       target = expand_builtin_strpbrk (arglist, target, mode);
3448       if (target)
3449         return target;
3450       break;
3451       
3452     case BUILT_IN_INDEX:
3453     case BUILT_IN_STRCHR:
3454       target = expand_builtin_strchr (arglist, target, mode);
3455       if (target)
3456         return target;
3457       break;
3458
3459     case BUILT_IN_RINDEX:
3460     case BUILT_IN_STRRCHR:
3461       target = expand_builtin_strrchr (arglist, target, mode);
3462       if (target)
3463         return target;
3464       break;
3465
3466     case BUILT_IN_MEMCPY:
3467       target = expand_builtin_memcpy (arglist);
3468       if (target)
3469         return target;
3470       break;
3471
3472     case BUILT_IN_MEMSET:
3473       target = expand_builtin_memset (exp);
3474       if (target)
3475         return target;
3476       break;
3477
3478     case BUILT_IN_BZERO:
3479       target = expand_builtin_bzero (exp);
3480       if (target)
3481         return target;
3482       break;
3483
3484     case BUILT_IN_STRCMP:
3485       target = expand_builtin_strcmp (exp, target, mode);
3486       if (target)
3487         return target;
3488       break;
3489
3490     case BUILT_IN_STRNCMP:
3491       target = expand_builtin_strncmp (exp, target, mode);
3492       if (target)
3493         return target;
3494       break;
3495
3496 /* These comparison functions need an instruction that returns an actual
3497    index.  An ordinary compare that just sets the condition codes
3498    is not enough.  */
3499 #ifdef HAVE_cmpstrsi
3500     case BUILT_IN_BCMP:
3501     case BUILT_IN_MEMCMP:
3502       target = expand_builtin_memcmp (exp, arglist, target);
3503       if (target)
3504         return target;
3505       break;
3506 #else
3507     case BUILT_IN_BCMP:
3508     case BUILT_IN_MEMCMP:
3509       break;
3510 #endif
3511
3512     case BUILT_IN_SETJMP:
3513       target = expand_builtin_setjmp (arglist, target);
3514       if (target)
3515         return target;
3516       break;
3517
3518       /* __builtin_longjmp is passed a pointer to an array of five words.
3519          It's similar to the C library longjmp function but works with
3520          __builtin_setjmp above.  */
3521     case BUILT_IN_LONGJMP:
3522       if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3523         break;
3524       else
3525         {
3526           rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
3527                                       VOIDmode, 0);
3528           rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
3529                                    NULL_RTX, VOIDmode, 0);
3530
3531           if (value != const1_rtx)
3532             {
3533               error ("__builtin_longjmp second argument must be 1");
3534               return const0_rtx;
3535             }
3536
3537           expand_builtin_longjmp (buf_addr, value);
3538           return const0_rtx;
3539         }
3540
3541     case BUILT_IN_TRAP:
3542 #ifdef HAVE_trap
3543       if (HAVE_trap)
3544         emit_insn (gen_trap ());
3545       else
3546 #endif
3547         error ("__builtin_trap not supported by this target");
3548       emit_barrier ();
3549       return const0_rtx;
3550
3551     case BUILT_IN_PUTCHAR:
3552     case BUILT_IN_PUTS:
3553     case BUILT_IN_FPUTC:
3554     case BUILT_IN_FWRITE:
3555       break;
3556     case BUILT_IN_FPUTS:
3557       target = expand_builtin_fputs (arglist, ignore);
3558       if (target)
3559         return target;
3560       break;
3561       
3562       /* Various hooks for the DWARF 2 __throw routine.  */
3563     case BUILT_IN_UNWIND_INIT:
3564       expand_builtin_unwind_init ();
3565       return const0_rtx;
3566     case BUILT_IN_DWARF_CFA:
3567       return virtual_cfa_rtx;
3568 #ifdef DWARF2_UNWIND_INFO
3569     case BUILT_IN_DWARF_FP_REGNUM:
3570       return expand_builtin_dwarf_fp_regnum ();
3571     case BUILT_IN_INIT_DWARF_REG_SIZES:
3572       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
3573       return const0_rtx;
3574 #endif
3575     case BUILT_IN_FROB_RETURN_ADDR:
3576       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
3577     case BUILT_IN_EXTRACT_RETURN_ADDR:
3578       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
3579     case BUILT_IN_EH_RETURN:
3580       expand_builtin_eh_return (TREE_VALUE (arglist),
3581                                 TREE_VALUE (TREE_CHAIN (arglist)),
3582                                 TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
3583       return const0_rtx;
3584     case BUILT_IN_VARARGS_START:
3585       return expand_builtin_va_start (0, arglist);
3586     case BUILT_IN_STDARG_START:
3587       return expand_builtin_va_start (1, arglist);
3588     case BUILT_IN_VA_END:
3589       return expand_builtin_va_end (arglist);
3590     case BUILT_IN_VA_COPY:
3591       return expand_builtin_va_copy (arglist);
3592     case BUILT_IN_EXPECT:
3593       return expand_builtin_expect (arglist, target);
3594
3595     default:                    /* just do library call, if unknown builtin */
3596       error ("built-in function `%s' not currently supported",
3597              IDENTIFIER_POINTER (DECL_NAME (fndecl)));
3598     }
3599
3600   /* The switch statement above can drop through to cause the function
3601      to be called normally.  */
3602   return expand_call (exp, target, ignore);
3603 }
3604
3605 /* Fold a call to __builtin_constant_p, if we know it will evaluate to a
3606    constant.  ARGLIST is the argument list of the call.  */
3607
3608 static tree
3609 fold_builtin_constant_p (arglist)
3610      tree arglist;
3611 {
3612   if (arglist == 0)
3613     return 0;
3614
3615   arglist = TREE_VALUE (arglist);
3616
3617   /* We return 1 for a numeric type that's known to be a constant
3618      value at compile-time or for an aggregate type that's a
3619      literal constant.  */
3620   STRIP_NOPS (arglist);
3621
3622   /* If we know this is a constant, emit the constant of one.  */
3623   if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
3624       || (TREE_CODE (arglist) == CONSTRUCTOR
3625           && TREE_CONSTANT (arglist))
3626       || (TREE_CODE (arglist) == ADDR_EXPR
3627           && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
3628     return integer_one_node;
3629
3630   /* If we aren't going to be running CSE or this expression
3631      has side effects, show we don't know it to be a constant.
3632      Likewise if it's a pointer or aggregate type since in those
3633      case we only want literals, since those are only optimized
3634      when generating RTL, not later.  */
3635   if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected
3636       || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
3637       || POINTER_TYPE_P (TREE_TYPE (arglist)))
3638     return integer_zero_node;
3639
3640   return 0;
3641 }
3642
3643 /* Used by constant folding to eliminate some builtin calls early.  EXP is
3644    the CALL_EXPR of a call to a builtin function.  */
3645
3646 tree
3647 fold_builtin (exp)
3648      tree exp;
3649 {
3650   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3651   tree arglist = TREE_OPERAND (exp, 1);
3652   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
3653
3654   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
3655     return 0;
3656
3657   switch (fcode)
3658     {
3659     case BUILT_IN_CONSTANT_P:
3660       return fold_builtin_constant_p (arglist);
3661
3662     case BUILT_IN_STRLEN:
3663       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
3664         {
3665           tree len = c_strlen (TREE_VALUE (arglist));
3666           if (len != 0)
3667             return len;
3668         }
3669       break;
3670
3671     default:
3672       break;
3673     }
3674
3675   return 0;
3676 }
3677
3678 static tree
3679 build_function_call_expr (fn, arglist)
3680      tree fn, arglist;
3681 {
3682   tree call_expr;
3683
3684   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
3685   call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
3686                      call_expr, arglist);
3687   TREE_SIDE_EFFECTS (call_expr) = 1;
3688   return fold (call_expr);
3689 }
3690
3691 /* This function validates the types of a function call argument list
3692    represented as a tree chain of parameters against a specified list
3693    of tree_codes.  If the last specifier is a 0, that represents an
3694    ellipses, otherwise the last specifier must be a VOID_TYPE.  */
3695 static int
3696 validate_arglist VPARAMS ((tree arglist, ...))
3697 {
3698 #ifndef ANSI_PROTOTYPES
3699   tree arglist;
3700 #endif
3701   enum tree_code code;
3702   va_list ap;
3703
3704   VA_START (ap, arglist);
3705
3706 #ifndef ANSI_PROTOTYPES
3707   arglist = va_arg (ap, tree);
3708 #endif
3709
3710   do {
3711     code = va_arg (ap, enum tree_code);
3712     switch (code)
3713     {
3714     case 0:
3715       /* This signifies an ellipses, any further arguments are all ok.  */
3716       va_end (ap);
3717       return 1;
3718     case VOID_TYPE:
3719       /* This signifies an endlink, if no arguments remain, return
3720          true, otherwise return false.  */
3721       va_end (ap);
3722       return arglist == 0;
3723     default:
3724       /* If no parameters remain or the parameter's code does not
3725          match the specified code, return false.  Otherwise continue
3726          checking any remaining arguments.  */
3727       if (arglist == 0 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
3728         {
3729           va_end (ap);
3730           return 0;
3731         }
3732       break;
3733     }
3734     arglist = TREE_CHAIN (arglist);
3735   } while (1);
3736 }