OSDN Git Service

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