OSDN Git Service

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