OSDN Git Service

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