OSDN Git Service

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