OSDN Git Service

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