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