OSDN Git Service

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