OSDN Git Service

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