OSDN Git Service

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