OSDN Git Service

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