OSDN Git Service

* builtins.c (expand_builtin_mempcpy): New function.
[pf3gnuchains/gcc-fork.git] / gcc / builtins.c
1 /* Expand builtin functions.
2    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3    2000, 2001, 2002, 2003 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 "coretypes.h"
25 #include "tm.h"
26 #include "machmode.h"
27 #include "real.h"
28 #include "rtl.h"
29 #include "tree.h"
30 #include "flags.h"
31 #include "regs.h"
32 #include "hard-reg-set.h"
33 #include "except.h"
34 #include "function.h"
35 #include "insn-config.h"
36 #include "expr.h"
37 #include "optabs.h"
38 #include "libfuncs.h"
39 #include "recog.h"
40 #include "output.h"
41 #include "typeclass.h"
42 #include "toplev.h"
43 #include "predict.h"
44 #include "tm_p.h"
45 #include "target.h"
46 #include "langhooks.h"
47
48 #define CALLED_AS_BUILT_IN(NODE) \
49    (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
50
51 /* Register mappings for target machines without register windows.  */
52 #ifndef INCOMING_REGNO
53 #define INCOMING_REGNO(OUT) (OUT)
54 #endif
55 #ifndef OUTGOING_REGNO
56 #define OUTGOING_REGNO(IN) (IN)
57 #endif
58
59 #ifndef PAD_VARARGS_DOWN
60 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
61 #endif
62
63 /* Define the names of the builtin function types and codes.  */
64 const char *const built_in_class_names[4]
65   = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
66
67 #define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT, IM) STRINGX(X),
68 const char *const built_in_names[(int) END_BUILTINS] =
69 {
70 #include "builtins.def"
71 };
72 #undef DEF_BUILTIN
73
74 /* Setup an array of _DECL trees, make sure each element is
75    initialized to NULL_TREE.  */
76 tree built_in_decls[(int) END_BUILTINS];
77 /* Declarations used when constructing the builtin implicitly in the compiler.
78    It may be NULL_TREE when this is invalid (for instance runtime is not
79    required to implement the function call in all cases.  */
80 tree implicit_built_in_decls[(int) END_BUILTINS];
81
82 static int get_pointer_alignment        PARAMS ((tree, unsigned int));
83 static tree c_strlen                    PARAMS ((tree));
84 static const char *c_getstr             PARAMS ((tree));
85 static rtx c_readstr                    PARAMS ((const char *,
86                                                  enum machine_mode));
87 static int target_char_cast             PARAMS ((tree, char *));
88 static rtx get_memory_rtx               PARAMS ((tree));
89 static int apply_args_size              PARAMS ((void));
90 static int apply_result_size            PARAMS ((void));
91 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
92 static rtx result_vector                PARAMS ((int, rtx));
93 #endif
94 static rtx expand_builtin_setjmp        PARAMS ((tree, rtx));
95 static void expand_builtin_prefetch     PARAMS ((tree));
96 static rtx expand_builtin_apply_args    PARAMS ((void));
97 static rtx expand_builtin_apply_args_1  PARAMS ((void));
98 static rtx expand_builtin_apply         PARAMS ((rtx, rtx, rtx));
99 static void expand_builtin_return       PARAMS ((rtx));
100 static enum type_class type_to_class    PARAMS ((tree));
101 static rtx expand_builtin_classify_type PARAMS ((tree));
102 static void expand_errno_check          PARAMS ((tree, rtx));
103 static rtx expand_builtin_mathfn        PARAMS ((tree, rtx, rtx));
104 static rtx expand_builtin_mathfn_2      PARAMS ((tree, rtx, rtx));
105 static rtx expand_builtin_constant_p    PARAMS ((tree, enum machine_mode));
106 static rtx expand_builtin_args_info     PARAMS ((tree));
107 static rtx expand_builtin_next_arg      PARAMS ((tree));
108 static rtx expand_builtin_va_start      PARAMS ((tree));
109 static rtx expand_builtin_va_end        PARAMS ((tree));
110 static rtx expand_builtin_va_copy       PARAMS ((tree));
111 static rtx expand_builtin_memcmp        PARAMS ((tree, tree, rtx,
112                                                  enum machine_mode));
113 static rtx expand_builtin_strcmp        PARAMS ((tree, rtx,
114                                                  enum machine_mode));
115 static rtx expand_builtin_strncmp       PARAMS ((tree, rtx,
116                                                  enum machine_mode));
117 static rtx builtin_memcpy_read_str      PARAMS ((PTR, HOST_WIDE_INT,
118                                                  enum machine_mode));
119 static rtx expand_builtin_strcat        PARAMS ((tree, rtx,
120                                                  enum machine_mode));
121 static rtx expand_builtin_strncat       PARAMS ((tree, rtx,
122                                                  enum machine_mode));
123 static rtx expand_builtin_strspn        PARAMS ((tree, rtx,
124                                                  enum machine_mode));
125 static rtx expand_builtin_strcspn       PARAMS ((tree, rtx,
126                                                  enum machine_mode));
127 static rtx expand_builtin_memcpy        PARAMS ((tree, rtx,
128                                                  enum machine_mode, int));
129 static rtx expand_builtin_mempcpy       PARAMS ((tree, rtx,
130                                                  enum machine_mode));
131 static rtx expand_builtin_memmove       PARAMS ((tree, rtx,
132                                                  enum machine_mode));
133 static rtx expand_builtin_bcopy         PARAMS ((tree));
134 static rtx expand_builtin_strcpy        PARAMS ((tree, rtx,
135                                                  enum machine_mode));
136 static rtx expand_builtin_stpcpy        PARAMS ((tree, rtx,
137                                                  enum machine_mode));
138 static rtx builtin_strncpy_read_str     PARAMS ((PTR, HOST_WIDE_INT,
139                                                  enum machine_mode));
140 static rtx expand_builtin_strncpy       PARAMS ((tree, rtx,
141                                                  enum machine_mode));
142 static rtx builtin_memset_read_str      PARAMS ((PTR, HOST_WIDE_INT,
143                                                  enum machine_mode));
144 static rtx builtin_memset_gen_str       PARAMS ((PTR, HOST_WIDE_INT,
145                                                  enum machine_mode));
146 static rtx expand_builtin_memset        PARAMS ((tree, rtx,
147                                                  enum machine_mode));
148 static rtx expand_builtin_bzero         PARAMS ((tree));
149 static rtx expand_builtin_strlen        PARAMS ((tree, rtx, enum machine_mode));
150 static rtx expand_builtin_strstr        PARAMS ((tree, rtx,
151                                                  enum machine_mode));
152 static rtx expand_builtin_strpbrk       PARAMS ((tree, rtx,
153                                                  enum machine_mode));
154 static rtx expand_builtin_strchr        PARAMS ((tree, rtx,
155                                                  enum machine_mode));
156 static rtx expand_builtin_strrchr       PARAMS ((tree, rtx,
157                                                  enum machine_mode));
158 static rtx expand_builtin_alloca        PARAMS ((tree, rtx));
159 static rtx expand_builtin_unop          PARAMS ((enum machine_mode,
160                                                  tree, rtx, rtx, optab));
161 static rtx expand_builtin_frame_address PARAMS ((tree, tree));
162 static rtx expand_builtin_fputs         PARAMS ((tree, int, int));
163 static tree stabilize_va_list           PARAMS ((tree, int));
164 static rtx expand_builtin_expect        PARAMS ((tree, rtx));
165 static tree fold_builtin_constant_p     PARAMS ((tree));
166 static tree fold_builtin_classify_type  PARAMS ((tree));
167 static tree fold_builtin_inf            PARAMS ((tree, int));
168 static tree fold_builtin_nan            PARAMS ((tree, tree, int));
169 static int validate_arglist             PARAMS ((tree, ...));
170 static tree fold_trunc_transparent_mathfn PARAMS ((tree));
171
172 /* Return the alignment in bits of EXP, a pointer valued expression.
173    But don't return more than MAX_ALIGN no matter what.
174    The alignment returned is, by default, the alignment of the thing that
175    EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
176
177    Otherwise, look at the expression to see if we can do better, i.e., if the
178    expression is actually pointing at an object whose alignment is tighter.  */
179
180 static int
181 get_pointer_alignment (exp, max_align)
182      tree exp;
183      unsigned int max_align;
184 {
185   unsigned int align, inner;
186
187   if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
188     return 0;
189
190   align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
191   align = MIN (align, max_align);
192
193   while (1)
194     {
195       switch (TREE_CODE (exp))
196         {
197         case NOP_EXPR:
198         case CONVERT_EXPR:
199         case NON_LVALUE_EXPR:
200           exp = TREE_OPERAND (exp, 0);
201           if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
202             return align;
203
204           inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
205           align = MIN (inner, max_align);
206           break;
207
208         case PLUS_EXPR:
209           /* If sum of pointer + int, restrict our maximum alignment to that
210              imposed by the integer.  If not, we can't do any better than
211              ALIGN.  */
212           if (! host_integerp (TREE_OPERAND (exp, 1), 1))
213             return align;
214
215           while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
216                   & (max_align / BITS_PER_UNIT - 1))
217                  != 0)
218             max_align >>= 1;
219
220           exp = TREE_OPERAND (exp, 0);
221           break;
222
223         case ADDR_EXPR:
224           /* See what we are pointing at and look at its alignment.  */
225           exp = TREE_OPERAND (exp, 0);
226           if (TREE_CODE (exp) == FUNCTION_DECL)
227             align = FUNCTION_BOUNDARY;
228           else if (DECL_P (exp))
229             align = DECL_ALIGN (exp);
230 #ifdef CONSTANT_ALIGNMENT
231           else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
232             align = CONSTANT_ALIGNMENT (exp, align);
233 #endif
234           return MIN (align, max_align);
235
236         default:
237           return align;
238         }
239     }
240 }
241
242 /* Compute the length of a C string.  TREE_STRING_LENGTH is not the right
243    way, because it could contain a zero byte in the middle.
244    TREE_STRING_LENGTH is the size of the character array, not the string.
245
246    The value returned is of type `ssizetype'.
247
248    Unfortunately, string_constant can't access the values of const char
249    arrays with initializers, so neither can we do so here.  */
250
251 static tree
252 c_strlen (src)
253      tree src;
254 {
255   tree offset_node;
256   HOST_WIDE_INT offset;
257   int max;
258   const char *ptr;
259
260   src = string_constant (src, &offset_node);
261   if (src == 0)
262     return 0;
263
264   max = TREE_STRING_LENGTH (src) - 1;
265   ptr = TREE_STRING_POINTER (src);
266
267   if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
268     {
269       /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
270          compute the offset to the following null if we don't know where to
271          start searching for it.  */
272       int i;
273
274       for (i = 0; i < max; i++)
275         if (ptr[i] == 0)
276           return 0;
277
278       /* We don't know the starting offset, but we do know that the string
279          has no internal zero bytes.  We can assume that the offset falls
280          within the bounds of the string; otherwise, the programmer deserves
281          what he gets.  Subtract the offset from the length of the string,
282          and return that.  This would perhaps not be valid if we were dealing
283          with named arrays in addition to literal string constants.  */
284
285       return size_diffop (size_int (max), offset_node);
286     }
287
288   /* We have a known offset into the string.  Start searching there for
289      a null character if we can represent it as a single HOST_WIDE_INT.  */
290   if (offset_node == 0)
291     offset = 0;
292   else if (! host_integerp (offset_node, 0))
293     offset = -1;
294   else
295     offset = tree_low_cst (offset_node, 0);
296
297   /* If the offset is known to be out of bounds, warn, and call strlen at
298      runtime.  */
299   if (offset < 0 || offset > max)
300     {
301       warning ("offset outside bounds of constant string");
302       return 0;
303     }
304
305   /* Use strlen to search for the first zero byte.  Since any strings
306      constructed with build_string will have nulls appended, we win even
307      if we get handed something like (char[4])"abcd".
308
309      Since OFFSET is our starting index into the string, no further
310      calculation is needed.  */
311   return ssize_int (strlen (ptr + offset));
312 }
313
314 /* Return a char pointer for a C string if it is a string constant
315    or sum of string constant and integer constant.  */
316
317 static const char *
318 c_getstr (src)
319      tree src;
320 {
321   tree offset_node;
322
323   src = string_constant (src, &offset_node);
324   if (src == 0)
325     return 0;
326
327   if (offset_node == 0)
328     return TREE_STRING_POINTER (src);
329   else if (!host_integerp (offset_node, 1)
330            || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
331     return 0;
332
333   return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
334 }
335
336 /* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
337    GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
338
339 static rtx
340 c_readstr (str, mode)
341      const char *str;
342      enum machine_mode mode;
343 {
344   HOST_WIDE_INT c[2];
345   HOST_WIDE_INT ch;
346   unsigned int i, j;
347
348   if (GET_MODE_CLASS (mode) != MODE_INT)
349     abort ();
350   c[0] = 0;
351   c[1] = 0;
352   ch = 1;
353   for (i = 0; i < GET_MODE_SIZE (mode); i++)
354     {
355       j = i;
356       if (WORDS_BIG_ENDIAN)
357         j = GET_MODE_SIZE (mode) - i - 1;
358       if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
359           && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
360         j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
361       j *= BITS_PER_UNIT;
362       if (j > 2 * HOST_BITS_PER_WIDE_INT)
363         abort ();
364       if (ch)
365         ch = (unsigned char) str[i];
366       c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
367     }
368   return immed_double_const (c[0], c[1], mode);
369 }
370
371 /* Cast a target constant CST to target CHAR and if that value fits into
372    host char type, return zero and put that value into variable pointed by
373    P.  */
374
375 static int
376 target_char_cast (cst, p)
377      tree cst;
378      char *p;
379 {
380   unsigned HOST_WIDE_INT val, hostval;
381
382   if (!host_integerp (cst, 1)
383       || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
384     return 1;
385
386   val = tree_low_cst (cst, 1);
387   if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
388     val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
389
390   hostval = val;
391   if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
392     hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
393
394   if (val != hostval)
395     return 1;
396
397   *p = hostval;
398   return 0;
399 }
400
401 /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
402    times to get the address of either a higher stack frame, or a return
403    address located within it (depending on FNDECL_CODE).  */
404
405 rtx
406 expand_builtin_return_addr (fndecl_code, count, tem)
407      enum built_in_function fndecl_code;
408      int count;
409      rtx tem;
410 {
411   int i;
412
413   /* Some machines need special handling before we can access
414      arbitrary frames.  For example, on the sparc, we must first flush
415      all register windows to the stack.  */
416 #ifdef SETUP_FRAME_ADDRESSES
417   if (count > 0)
418     SETUP_FRAME_ADDRESSES ();
419 #endif
420
421   /* On the sparc, the return address is not in the frame, it is in a
422      register.  There is no way to access it off of the current frame
423      pointer, but it can be accessed off the previous frame pointer by
424      reading the value from the register window save area.  */
425 #ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
426   if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
427     count--;
428 #endif
429
430   /* Scan back COUNT frames to the specified frame.  */
431   for (i = 0; i < count; i++)
432     {
433       /* Assume the dynamic chain pointer is in the word that the
434          frame address points to, unless otherwise specified.  */
435 #ifdef DYNAMIC_CHAIN_ADDRESS
436       tem = DYNAMIC_CHAIN_ADDRESS (tem);
437 #endif
438       tem = memory_address (Pmode, tem);
439       tem = gen_rtx_MEM (Pmode, tem);
440       set_mem_alias_set (tem, get_frame_alias_set ());
441       tem = copy_to_reg (tem);
442     }
443
444   /* For __builtin_frame_address, return what we've got.  */
445   if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
446     return tem;
447
448   /* For __builtin_return_address, Get the return address from that
449      frame.  */
450 #ifdef RETURN_ADDR_RTX
451   tem = RETURN_ADDR_RTX (count, tem);
452 #else
453   tem = memory_address (Pmode,
454                         plus_constant (tem, GET_MODE_SIZE (Pmode)));
455   tem = gen_rtx_MEM (Pmode, tem);
456   set_mem_alias_set (tem, get_frame_alias_set ());
457 #endif
458   return tem;
459 }
460
461 /* Alias set used for setjmp buffer.  */
462 static HOST_WIDE_INT setjmp_alias_set = -1;
463
464 /* Construct the leading half of a __builtin_setjmp call.  Control will
465    return to RECEIVER_LABEL.  This is used directly by sjlj exception
466    handling code.  */
467
468 void
469 expand_builtin_setjmp_setup (buf_addr, receiver_label)
470      rtx buf_addr;
471      rtx receiver_label;
472 {
473   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
474   rtx stack_save;
475   rtx mem;
476
477   if (setjmp_alias_set == -1)
478     setjmp_alias_set = new_alias_set ();
479
480 #ifdef POINTERS_EXTEND_UNSIGNED
481   if (GET_MODE (buf_addr) != Pmode)
482     buf_addr = convert_memory_address (Pmode, buf_addr);
483 #endif
484
485   buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
486
487   emit_queue ();
488
489   /* We store the frame pointer and the address of receiver_label in
490      the buffer and use the rest of it for the stack save area, which
491      is machine-dependent.  */
492
493 #ifndef BUILTIN_SETJMP_FRAME_VALUE
494 #define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
495 #endif
496
497   mem = gen_rtx_MEM (Pmode, buf_addr);
498   set_mem_alias_set (mem, setjmp_alias_set);
499   emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
500
501   mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
502   set_mem_alias_set (mem, setjmp_alias_set);
503
504   emit_move_insn (validize_mem (mem),
505                   force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
506
507   stack_save = gen_rtx_MEM (sa_mode,
508                             plus_constant (buf_addr,
509                                            2 * GET_MODE_SIZE (Pmode)));
510   set_mem_alias_set (stack_save, setjmp_alias_set);
511   emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
512
513   /* If there is further processing to do, do it.  */
514 #ifdef HAVE_builtin_setjmp_setup
515   if (HAVE_builtin_setjmp_setup)
516     emit_insn (gen_builtin_setjmp_setup (buf_addr));
517 #endif
518
519   /* Tell optimize_save_area_alloca that extra work is going to
520      need to go on during alloca.  */
521   current_function_calls_setjmp = 1;
522
523   /* Set this so all the registers get saved in our frame; we need to be
524      able to copy the saved values for any registers from frames we unwind.  */
525   current_function_has_nonlocal_label = 1;
526 }
527
528 /* Construct the trailing part of a __builtin_setjmp call.
529    This is used directly by sjlj exception handling code.  */
530
531 void
532 expand_builtin_setjmp_receiver (receiver_label)
533      rtx receiver_label ATTRIBUTE_UNUSED;
534 {
535   /* Clobber the FP when we get here, so we have to make sure it's
536      marked as used by this function.  */
537   emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
538
539   /* Mark the static chain as clobbered here so life information
540      doesn't get messed up for it.  */
541   emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
542
543   /* Now put in the code to restore the frame pointer, and argument
544      pointer, if needed.  The code below is from expand_end_bindings
545      in stmt.c; see detailed documentation there.  */
546 #ifdef HAVE_nonlocal_goto
547   if (! HAVE_nonlocal_goto)
548 #endif
549     emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
550
551 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
552   if (fixed_regs[ARG_POINTER_REGNUM])
553     {
554 #ifdef ELIMINABLE_REGS
555       size_t i;
556       static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
557
558       for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
559         if (elim_regs[i].from == ARG_POINTER_REGNUM
560             && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
561           break;
562
563       if (i == ARRAY_SIZE (elim_regs))
564 #endif
565         {
566           /* Now restore our arg pointer from the address at which it
567              was saved in our stack frame.  */
568           emit_move_insn (virtual_incoming_args_rtx,
569                           copy_to_reg (get_arg_pointer_save_area (cfun)));
570         }
571     }
572 #endif
573
574 #ifdef HAVE_builtin_setjmp_receiver
575   if (HAVE_builtin_setjmp_receiver)
576     emit_insn (gen_builtin_setjmp_receiver (receiver_label));
577   else
578 #endif
579 #ifdef HAVE_nonlocal_goto_receiver
580     if (HAVE_nonlocal_goto_receiver)
581       emit_insn (gen_nonlocal_goto_receiver ());
582     else
583 #endif
584       { /* Nothing */ }
585
586   /* @@@ This is a kludge.  Not all machine descriptions define a blockage
587      insn, but we must not allow the code we just generated to be reordered
588      by scheduling.  Specifically, the update of the frame pointer must
589      happen immediately, not later.  So emit an ASM_INPUT to act as blockage
590      insn.  */
591   emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
592 }
593
594 /* __builtin_setjmp is passed a pointer to an array of five words (not
595    all will be used on all machines).  It operates similarly to the C
596    library function of the same name, but is more efficient.  Much of
597    the code below (and for longjmp) is copied from the handling of
598    non-local gotos.
599
600    NOTE: This is intended for use by GNAT and the exception handling
601    scheme in the compiler and will only work in the method used by
602    them.  */
603
604 static rtx
605 expand_builtin_setjmp (arglist, target)
606      tree arglist;
607      rtx target;
608 {
609   rtx buf_addr, next_lab, cont_lab;
610
611   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
612     return NULL_RTX;
613
614   if (target == 0 || GET_CODE (target) != REG
615       || REGNO (target) < FIRST_PSEUDO_REGISTER)
616     target = gen_reg_rtx (TYPE_MODE (integer_type_node));
617
618   buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
619
620   next_lab = gen_label_rtx ();
621   cont_lab = gen_label_rtx ();
622
623   expand_builtin_setjmp_setup (buf_addr, next_lab);
624
625   /* Set TARGET to zero and branch to the continue label.  */
626   emit_move_insn (target, const0_rtx);
627   emit_jump_insn (gen_jump (cont_lab));
628   emit_barrier ();
629   emit_label (next_lab);
630
631   expand_builtin_setjmp_receiver (next_lab);
632
633   /* Set TARGET to one.  */
634   emit_move_insn (target, const1_rtx);
635   emit_label (cont_lab);
636
637   /* Tell flow about the strange goings on.  Putting `next_lab' on
638      `nonlocal_goto_handler_labels' to indicates that function
639      calls may traverse the arc back to this label.  */
640
641   current_function_has_nonlocal_label = 1;
642   nonlocal_goto_handler_labels
643     = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
644
645   return target;
646 }
647
648 /* __builtin_longjmp is passed a pointer to an array of five words (not
649    all will be used on all machines).  It operates similarly to the C
650    library function of the same name, but is more efficient.  Much of
651    the code below is copied from the handling of non-local gotos.
652
653    NOTE: This is intended for use by GNAT and the exception handling
654    scheme in the compiler and will only work in the method used by
655    them.  */
656
657 void
658 expand_builtin_longjmp (buf_addr, value)
659      rtx buf_addr, value;
660 {
661   rtx fp, lab, stack, insn, last;
662   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
663
664   if (setjmp_alias_set == -1)
665     setjmp_alias_set = new_alias_set ();
666
667 #ifdef POINTERS_EXTEND_UNSIGNED
668   if (GET_MODE (buf_addr) != Pmode)
669     buf_addr = convert_memory_address (Pmode, buf_addr);
670 #endif
671
672   buf_addr = force_reg (Pmode, buf_addr);
673
674   /* We used to store value in static_chain_rtx, but that fails if pointers
675      are smaller than integers.  We instead require that the user must pass
676      a second argument of 1, because that is what builtin_setjmp will
677      return.  This also makes EH slightly more efficient, since we are no
678      longer copying around a value that we don't care about.  */
679   if (value != const1_rtx)
680     abort ();
681
682   current_function_calls_longjmp = 1;
683
684   last = get_last_insn ();
685 #ifdef HAVE_builtin_longjmp
686   if (HAVE_builtin_longjmp)
687     emit_insn (gen_builtin_longjmp (buf_addr));
688   else
689 #endif
690     {
691       fp = gen_rtx_MEM (Pmode, buf_addr);
692       lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
693                                                GET_MODE_SIZE (Pmode)));
694
695       stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
696                                                    2 * GET_MODE_SIZE (Pmode)));
697       set_mem_alias_set (fp, setjmp_alias_set);
698       set_mem_alias_set (lab, setjmp_alias_set);
699       set_mem_alias_set (stack, setjmp_alias_set);
700
701       /* Pick up FP, label, and SP from the block and jump.  This code is
702          from expand_goto in stmt.c; see there for detailed comments.  */
703 #if HAVE_nonlocal_goto
704       if (HAVE_nonlocal_goto)
705         /* We have to pass a value to the nonlocal_goto pattern that will
706            get copied into the static_chain pointer, but it does not matter
707            what that value is, because builtin_setjmp does not use it.  */
708         emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
709       else
710 #endif
711         {
712           lab = copy_to_reg (lab);
713
714           emit_move_insn (hard_frame_pointer_rtx, fp);
715           emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
716
717           emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
718           emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
719           emit_indirect_jump (lab);
720         }
721     }
722
723   /* Search backwards and mark the jump insn as a non-local goto.
724      Note that this precludes the use of __builtin_longjmp to a
725      __builtin_setjmp target in the same function.  However, we've
726      already cautioned the user that these functions are for
727      internal exception handling use only.  */
728   for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
729     {
730       if (insn == last)
731         abort ();
732       if (GET_CODE (insn) == JUMP_INSN)
733         {
734           REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
735                                               REG_NOTES (insn));
736           break;
737         }
738       else if (GET_CODE (insn) == CALL_INSN)
739         break;
740     }
741 }
742
743 /* Expand a call to __builtin_prefetch.  For a target that does not support
744    data prefetch, evaluate the memory address argument in case it has side
745    effects.  */
746
747 static void
748 expand_builtin_prefetch (arglist)
749      tree arglist;
750 {
751   tree arg0, arg1, arg2;
752   rtx op0, op1, op2;
753
754   if (!validate_arglist (arglist, POINTER_TYPE, 0))
755     return;
756
757   arg0 = TREE_VALUE (arglist);
758   /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
759      zero (read) and argument 2 (locality) defaults to 3 (high degree of
760      locality).  */
761   if (TREE_CHAIN (arglist))
762     {
763       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
764       if (TREE_CHAIN (TREE_CHAIN (arglist)))
765         arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
766       else
767         arg2 = build_int_2 (3, 0);
768     }
769   else
770     {
771       arg1 = integer_zero_node;
772       arg2 = build_int_2 (3, 0);
773     }
774
775   /* Argument 0 is an address.  */
776   op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
777
778   /* Argument 1 (read/write flag) must be a compile-time constant int.  */
779   if (TREE_CODE (arg1) != INTEGER_CST)
780     {
781       error ("second arg to `__builtin_prefetch' must be a constant");
782       arg1 = integer_zero_node;
783     }
784   op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
785   /* Argument 1 must be either zero or one.  */
786   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
787     {
788       warning ("invalid second arg to __builtin_prefetch; using zero");
789       op1 = const0_rtx;
790     }
791
792   /* Argument 2 (locality) must be a compile-time constant int.  */
793   if (TREE_CODE (arg2) != INTEGER_CST)
794     {
795       error ("third arg to `__builtin_prefetch' must be a constant");
796       arg2 = integer_zero_node;
797     }
798   op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
799   /* Argument 2 must be 0, 1, 2, or 3.  */
800   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
801     {
802       warning ("invalid third arg to __builtin_prefetch; using zero");
803       op2 = const0_rtx;
804     }
805
806 #ifdef HAVE_prefetch
807   if (HAVE_prefetch)
808     {
809       if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
810              (op0,
811               insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
812           || (GET_MODE(op0) != Pmode))
813         {
814 #ifdef POINTERS_EXTEND_UNSIGNED
815           if (GET_MODE(op0) != Pmode)
816             op0 = convert_memory_address (Pmode, op0);
817 #endif
818           op0 = force_reg (Pmode, op0);
819         }
820       emit_insn (gen_prefetch (op0, op1, op2));
821     }
822   else
823 #endif
824     op0 = protect_from_queue (op0, 0);
825   /* Don't do anything with direct references to volatile memory, but
826      generate code to handle other side effects.  */
827   if (GET_CODE (op0) != MEM && side_effects_p (op0))
828     emit_insn (op0);
829 }
830
831 /* Get a MEM rtx for expression EXP which is the address of an operand
832    to be used to be used in a string instruction (cmpstrsi, movstrsi, ..).  */
833
834 static rtx
835 get_memory_rtx (exp)
836      tree exp;
837 {
838   rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_SUM);
839   rtx mem;
840
841 #ifdef POINTERS_EXTEND_UNSIGNED
842   if (GET_MODE (addr) != Pmode)
843     addr = convert_memory_address (Pmode, addr);
844 #endif
845
846   mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
847
848   /* Get an expression we can use to find the attributes to assign to MEM.
849      If it is an ADDR_EXPR, use the operand.  Otherwise, dereference it if
850      we can.  First remove any nops.  */
851   while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
852           || TREE_CODE (exp) == NON_LVALUE_EXPR)
853          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
854     exp = TREE_OPERAND (exp, 0);
855
856   if (TREE_CODE (exp) == ADDR_EXPR)
857     {
858       exp = TREE_OPERAND (exp, 0);
859       set_mem_attributes (mem, exp, 0);
860     }
861   else if (POINTER_TYPE_P (TREE_TYPE (exp)))
862     {
863       exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
864       /* memcpy, memset and other builtin stringops can alias with anything.  */
865       set_mem_alias_set (mem, 0);
866     }
867
868   return mem;
869 }
870 \f
871 /* Built-in functions to perform an untyped call and return.  */
872
873 /* For each register that may be used for calling a function, this
874    gives a mode used to copy the register's value.  VOIDmode indicates
875    the register is not used for calling a function.  If the machine
876    has register windows, this gives only the outbound registers.
877    INCOMING_REGNO gives the corresponding inbound register.  */
878 static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
879
880 /* For each register that may be used for returning values, this gives
881    a mode used to copy the register's value.  VOIDmode indicates the
882    register is not used for returning values.  If the machine has
883    register windows, this gives only the outbound registers.
884    INCOMING_REGNO gives the corresponding inbound register.  */
885 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
886
887 /* For each register that may be used for calling a function, this
888    gives the offset of that register into the block returned by
889    __builtin_apply_args.  0 indicates that the register is not
890    used for calling a function.  */
891 static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
892
893 /* Return the offset of register REGNO into the block returned by
894    __builtin_apply_args.  This is not declared static, since it is
895    needed in objc-act.c.  */
896
897 int
898 apply_args_register_offset (regno)
899      int regno;
900 {
901   apply_args_size ();
902
903   /* Arguments are always put in outgoing registers (in the argument
904      block) if such make sense.  */
905 #ifdef OUTGOING_REGNO
906   regno = OUTGOING_REGNO (regno);
907 #endif
908   return apply_args_reg_offset[regno];
909 }
910
911 /* Return the size required for the block returned by __builtin_apply_args,
912    and initialize apply_args_mode.  */
913
914 static int
915 apply_args_size ()
916 {
917   static int size = -1;
918   int align;
919   unsigned int regno;
920   enum machine_mode mode;
921
922   /* The values computed by this function never change.  */
923   if (size < 0)
924     {
925       /* The first value is the incoming arg-pointer.  */
926       size = GET_MODE_SIZE (Pmode);
927
928       /* The second value is the structure value address unless this is
929          passed as an "invisible" first argument.  */
930       if (struct_value_rtx)
931         size += GET_MODE_SIZE (Pmode);
932
933       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
934         if (FUNCTION_ARG_REGNO_P (regno))
935           {
936             /* Search for the proper mode for copying this register's
937                value.  I'm not sure this is right, but it works so far.  */
938             enum machine_mode best_mode = VOIDmode;
939
940             for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
941                  mode != VOIDmode;
942                  mode = GET_MODE_WIDER_MODE (mode))
943               if (HARD_REGNO_MODE_OK (regno, mode)
944                   && HARD_REGNO_NREGS (regno, mode) == 1)
945                 best_mode = mode;
946
947             if (best_mode == VOIDmode)
948               for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
949                    mode != VOIDmode;
950                    mode = GET_MODE_WIDER_MODE (mode))
951                 if (HARD_REGNO_MODE_OK (regno, mode)
952                     && have_insn_for (SET, mode))
953                   best_mode = mode;
954
955             if (best_mode == VOIDmode)
956               for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
957                    mode != VOIDmode;
958                    mode = GET_MODE_WIDER_MODE (mode))
959                 if (HARD_REGNO_MODE_OK (regno, mode)
960                     && have_insn_for (SET, mode))
961                   best_mode = mode;
962
963             if (best_mode == VOIDmode)
964               for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
965                    mode != VOIDmode;
966                    mode = GET_MODE_WIDER_MODE (mode))
967                 if (HARD_REGNO_MODE_OK (regno, mode)
968                     && have_insn_for (SET, mode))
969                   best_mode = mode;
970
971             mode = best_mode;
972             if (mode == VOIDmode)
973               abort ();
974
975             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
976             if (size % align != 0)
977               size = CEIL (size, align) * align;
978             apply_args_reg_offset[regno] = size;
979             size += GET_MODE_SIZE (mode);
980             apply_args_mode[regno] = mode;
981           }
982         else
983           {
984             apply_args_mode[regno] = VOIDmode;
985             apply_args_reg_offset[regno] = 0;
986           }
987     }
988   return size;
989 }
990
991 /* Return the size required for the block returned by __builtin_apply,
992    and initialize apply_result_mode.  */
993
994 static int
995 apply_result_size ()
996 {
997   static int size = -1;
998   int align, regno;
999   enum machine_mode mode;
1000
1001   /* The values computed by this function never change.  */
1002   if (size < 0)
1003     {
1004       size = 0;
1005
1006       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1007         if (FUNCTION_VALUE_REGNO_P (regno))
1008           {
1009             /* Search for the proper mode for copying this register's
1010                value.  I'm not sure this is right, but it works so far.  */
1011             enum machine_mode best_mode = VOIDmode;
1012
1013             for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
1014                  mode != TImode;
1015                  mode = GET_MODE_WIDER_MODE (mode))
1016               if (HARD_REGNO_MODE_OK (regno, mode))
1017                 best_mode = mode;
1018
1019             if (best_mode == VOIDmode)
1020               for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
1021                    mode != VOIDmode;
1022                    mode = GET_MODE_WIDER_MODE (mode))
1023                 if (HARD_REGNO_MODE_OK (regno, mode)
1024                     && have_insn_for (SET, mode))
1025                   best_mode = mode;
1026
1027             if (best_mode == VOIDmode)
1028               for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
1029                    mode != VOIDmode;
1030                    mode = GET_MODE_WIDER_MODE (mode))
1031                 if (HARD_REGNO_MODE_OK (regno, mode)
1032                     && have_insn_for (SET, mode))
1033                   best_mode = mode;
1034
1035             if (best_mode == VOIDmode)
1036               for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
1037                    mode != VOIDmode;
1038                    mode = GET_MODE_WIDER_MODE (mode))
1039                 if (HARD_REGNO_MODE_OK (regno, mode)
1040                     && have_insn_for (SET, mode))
1041                   best_mode = mode;
1042
1043             mode = best_mode;
1044             if (mode == VOIDmode)
1045               abort ();
1046
1047             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1048             if (size % align != 0)
1049               size = CEIL (size, align) * align;
1050             size += GET_MODE_SIZE (mode);
1051             apply_result_mode[regno] = mode;
1052           }
1053         else
1054           apply_result_mode[regno] = VOIDmode;
1055
1056       /* Allow targets that use untyped_call and untyped_return to override
1057          the size so that machine-specific information can be stored here.  */
1058 #ifdef APPLY_RESULT_SIZE
1059       size = APPLY_RESULT_SIZE;
1060 #endif
1061     }
1062   return size;
1063 }
1064
1065 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1066 /* Create a vector describing the result block RESULT.  If SAVEP is true,
1067    the result block is used to save the values; otherwise it is used to
1068    restore the values.  */
1069
1070 static rtx
1071 result_vector (savep, result)
1072      int savep;
1073      rtx result;
1074 {
1075   int regno, size, align, nelts;
1076   enum machine_mode mode;
1077   rtx reg, mem;
1078   rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
1079
1080   size = nelts = 0;
1081   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1082     if ((mode = apply_result_mode[regno]) != VOIDmode)
1083       {
1084         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1085         if (size % align != 0)
1086           size = CEIL (size, align) * align;
1087         reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
1088         mem = adjust_address (result, mode, size);
1089         savevec[nelts++] = (savep
1090                             ? gen_rtx_SET (VOIDmode, mem, reg)
1091                             : gen_rtx_SET (VOIDmode, reg, mem));
1092         size += GET_MODE_SIZE (mode);
1093       }
1094   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1095 }
1096 #endif /* HAVE_untyped_call or HAVE_untyped_return */
1097
1098 /* Save the state required to perform an untyped call with the same
1099    arguments as were passed to the current function.  */
1100
1101 static rtx
1102 expand_builtin_apply_args_1 ()
1103 {
1104   rtx registers;
1105   int size, align, regno;
1106   enum machine_mode mode;
1107
1108   /* Create a block where the arg-pointer, structure value address,
1109      and argument registers can be saved.  */
1110   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1111
1112   /* Walk past the arg-pointer and structure value address.  */
1113   size = GET_MODE_SIZE (Pmode);
1114   if (struct_value_rtx)
1115     size += GET_MODE_SIZE (Pmode);
1116
1117   /* Save each register used in calling a function to the block.  */
1118   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1119     if ((mode = apply_args_mode[regno]) != VOIDmode)
1120       {
1121         rtx tem;
1122
1123         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1124         if (size % align != 0)
1125           size = CEIL (size, align) * align;
1126
1127         tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1128
1129         emit_move_insn (adjust_address (registers, mode, size), tem);
1130         size += GET_MODE_SIZE (mode);
1131       }
1132
1133   /* Save the arg pointer to the block.  */
1134   emit_move_insn (adjust_address (registers, Pmode, 0),
1135                   copy_to_reg (virtual_incoming_args_rtx));
1136   size = GET_MODE_SIZE (Pmode);
1137
1138   /* Save the structure value address unless this is passed as an
1139      "invisible" first argument.  */
1140   if (struct_value_incoming_rtx)
1141     {
1142       emit_move_insn (adjust_address (registers, Pmode, size),
1143                       copy_to_reg (struct_value_incoming_rtx));
1144       size += GET_MODE_SIZE (Pmode);
1145     }
1146
1147   /* Return the address of the block.  */
1148   return copy_addr_to_reg (XEXP (registers, 0));
1149 }
1150
1151 /* __builtin_apply_args returns block of memory allocated on
1152    the stack into which is stored the arg pointer, structure
1153    value address, static chain, and all the registers that might
1154    possibly be used in performing a function call.  The code is
1155    moved to the start of the function so the incoming values are
1156    saved.  */
1157
1158 static rtx
1159 expand_builtin_apply_args ()
1160 {
1161   /* Don't do __builtin_apply_args more than once in a function.
1162      Save the result of the first call and reuse it.  */
1163   if (apply_args_value != 0)
1164     return apply_args_value;
1165   {
1166     /* When this function is called, it means that registers must be
1167        saved on entry to this function.  So we migrate the
1168        call to the first insn of this function.  */
1169     rtx temp;
1170     rtx seq;
1171
1172     start_sequence ();
1173     temp = expand_builtin_apply_args_1 ();
1174     seq = get_insns ();
1175     end_sequence ();
1176
1177     apply_args_value = temp;
1178
1179     /* Put the insns after the NOTE that starts the function.
1180        If this is inside a start_sequence, make the outer-level insn
1181        chain current, so the code is placed at the start of the
1182        function.  */
1183     push_topmost_sequence ();
1184     emit_insn_before (seq, NEXT_INSN (get_insns ()));
1185     pop_topmost_sequence ();
1186     return temp;
1187   }
1188 }
1189
1190 /* Perform an untyped call and save the state required to perform an
1191    untyped return of whatever value was returned by the given function.  */
1192
1193 static rtx
1194 expand_builtin_apply (function, arguments, argsize)
1195      rtx function, arguments, argsize;
1196 {
1197   int size, align, regno;
1198   enum machine_mode mode;
1199   rtx incoming_args, result, reg, dest, src, call_insn;
1200   rtx old_stack_level = 0;
1201   rtx call_fusage = 0;
1202
1203 #ifdef POINTERS_EXTEND_UNSIGNED
1204   if (GET_MODE (arguments) != Pmode)
1205     arguments = convert_memory_address (Pmode, arguments);
1206 #endif
1207
1208   /* Create a block where the return registers can be saved.  */
1209   result = assign_stack_local (BLKmode, apply_result_size (), -1);
1210
1211   /* Fetch the arg pointer from the ARGUMENTS block.  */
1212   incoming_args = gen_reg_rtx (Pmode);
1213   emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1214 #ifndef STACK_GROWS_DOWNWARD
1215   incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1216                                        incoming_args, 0, OPTAB_LIB_WIDEN);
1217 #endif
1218
1219   /* Perform postincrements before actually calling the function.  */
1220   emit_queue ();
1221
1222   /* Push a new argument block and copy the arguments.  Do not allow
1223      the (potential) memcpy call below to interfere with our stack
1224      manipulations.  */
1225   do_pending_stack_adjust ();
1226   NO_DEFER_POP;
1227
1228   /* Save the stack with nonlocal if available */
1229 #ifdef HAVE_save_stack_nonlocal
1230   if (HAVE_save_stack_nonlocal)
1231     emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1232   else
1233 #endif
1234     emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1235
1236   /* Push a block of memory onto the stack to store the memory arguments.
1237      Save the address in a register, and copy the memory arguments.  ??? I
1238      haven't figured out how the calling convention macros effect this,
1239      but it's likely that the source and/or destination addresses in
1240      the block copy will need updating in machine specific ways.  */
1241   dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1242   dest = gen_rtx_MEM (BLKmode, dest);
1243   set_mem_align (dest, PARM_BOUNDARY);
1244   src = gen_rtx_MEM (BLKmode, incoming_args);
1245   set_mem_align (src, PARM_BOUNDARY);
1246   emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
1247
1248   /* Refer to the argument block.  */
1249   apply_args_size ();
1250   arguments = gen_rtx_MEM (BLKmode, arguments);
1251   set_mem_align (arguments, PARM_BOUNDARY);
1252
1253   /* Walk past the arg-pointer and structure value address.  */
1254   size = GET_MODE_SIZE (Pmode);
1255   if (struct_value_rtx)
1256     size += GET_MODE_SIZE (Pmode);
1257
1258   /* Restore each of the registers previously saved.  Make USE insns
1259      for each of these registers for use in making the call.  */
1260   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1261     if ((mode = apply_args_mode[regno]) != VOIDmode)
1262       {
1263         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1264         if (size % align != 0)
1265           size = CEIL (size, align) * align;
1266         reg = gen_rtx_REG (mode, regno);
1267         emit_move_insn (reg, adjust_address (arguments, mode, size));
1268         use_reg (&call_fusage, reg);
1269         size += GET_MODE_SIZE (mode);
1270       }
1271
1272   /* Restore the structure value address unless this is passed as an
1273      "invisible" first argument.  */
1274   size = GET_MODE_SIZE (Pmode);
1275   if (struct_value_rtx)
1276     {
1277       rtx value = gen_reg_rtx (Pmode);
1278       emit_move_insn (value, adjust_address (arguments, Pmode, size));
1279       emit_move_insn (struct_value_rtx, value);
1280       if (GET_CODE (struct_value_rtx) == REG)
1281         use_reg (&call_fusage, struct_value_rtx);
1282       size += GET_MODE_SIZE (Pmode);
1283     }
1284
1285   /* All arguments and registers used for the call are set up by now!  */
1286   function = prepare_call_address (function, NULL_TREE, &call_fusage, 0, 0);
1287
1288   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
1289      and we don't want to load it into a register as an optimization,
1290      because prepare_call_address already did it if it should be done.  */
1291   if (GET_CODE (function) != SYMBOL_REF)
1292     function = memory_address (FUNCTION_MODE, function);
1293
1294   /* Generate the actual call instruction and save the return value.  */
1295 #ifdef HAVE_untyped_call
1296   if (HAVE_untyped_call)
1297     emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1298                                       result, result_vector (1, result)));
1299   else
1300 #endif
1301 #ifdef HAVE_call_value
1302   if (HAVE_call_value)
1303     {
1304       rtx valreg = 0;
1305
1306       /* Locate the unique return register.  It is not possible to
1307          express a call that sets more than one return register using
1308          call_value; use untyped_call for that.  In fact, untyped_call
1309          only needs to save the return registers in the given block.  */
1310       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1311         if ((mode = apply_result_mode[regno]) != VOIDmode)
1312           {
1313             if (valreg)
1314               abort (); /* HAVE_untyped_call required.  */
1315             valreg = gen_rtx_REG (mode, regno);
1316           }
1317
1318       emit_call_insn (GEN_CALL_VALUE (valreg,
1319                                       gen_rtx_MEM (FUNCTION_MODE, function),
1320                                       const0_rtx, NULL_RTX, const0_rtx));
1321
1322       emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1323     }
1324   else
1325 #endif
1326     abort ();
1327
1328   /* Find the CALL insn we just emitted, and attach the register usage
1329      information.  */
1330   call_insn = last_call_insn ();
1331   add_function_usage_to (call_insn, call_fusage);
1332
1333   /* Restore the stack.  */
1334 #ifdef HAVE_save_stack_nonlocal
1335   if (HAVE_save_stack_nonlocal)
1336     emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1337   else
1338 #endif
1339     emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1340
1341   OK_DEFER_POP;
1342
1343   /* Return the address of the result block.  */
1344   return copy_addr_to_reg (XEXP (result, 0));
1345 }
1346
1347 /* Perform an untyped return.  */
1348
1349 static void
1350 expand_builtin_return (result)
1351      rtx result;
1352 {
1353   int size, align, regno;
1354   enum machine_mode mode;
1355   rtx reg;
1356   rtx call_fusage = 0;
1357
1358 #ifdef POINTERS_EXTEND_UNSIGNED
1359   if (GET_MODE (result) != Pmode)
1360     result = convert_memory_address (Pmode, result);
1361 #endif
1362
1363   apply_result_size ();
1364   result = gen_rtx_MEM (BLKmode, result);
1365
1366 #ifdef HAVE_untyped_return
1367   if (HAVE_untyped_return)
1368     {
1369       emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1370       emit_barrier ();
1371       return;
1372     }
1373 #endif
1374
1375   /* Restore the return value and note that each value is used.  */
1376   size = 0;
1377   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1378     if ((mode = apply_result_mode[regno]) != VOIDmode)
1379       {
1380         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1381         if (size % align != 0)
1382           size = CEIL (size, align) * align;
1383         reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1384         emit_move_insn (reg, adjust_address (result, mode, size));
1385
1386         push_to_sequence (call_fusage);
1387         emit_insn (gen_rtx_USE (VOIDmode, reg));
1388         call_fusage = get_insns ();
1389         end_sequence ();
1390         size += GET_MODE_SIZE (mode);
1391       }
1392
1393   /* Put the USE insns before the return.  */
1394   emit_insn (call_fusage);
1395
1396   /* Return whatever values was restored by jumping directly to the end
1397      of the function.  */
1398   expand_null_return ();
1399 }
1400
1401 /* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
1402
1403 static enum type_class
1404 type_to_class (type)
1405      tree type;
1406 {
1407   switch (TREE_CODE (type))
1408     {
1409     case VOID_TYPE:        return void_type_class;
1410     case INTEGER_TYPE:     return integer_type_class;
1411     case CHAR_TYPE:        return char_type_class;
1412     case ENUMERAL_TYPE:    return enumeral_type_class;
1413     case BOOLEAN_TYPE:     return boolean_type_class;
1414     case POINTER_TYPE:     return pointer_type_class;
1415     case REFERENCE_TYPE:   return reference_type_class;
1416     case OFFSET_TYPE:      return offset_type_class;
1417     case REAL_TYPE:        return real_type_class;
1418     case COMPLEX_TYPE:     return complex_type_class;
1419     case FUNCTION_TYPE:    return function_type_class;
1420     case METHOD_TYPE:      return method_type_class;
1421     case RECORD_TYPE:      return record_type_class;
1422     case UNION_TYPE:
1423     case QUAL_UNION_TYPE:  return union_type_class;
1424     case ARRAY_TYPE:       return (TYPE_STRING_FLAG (type)
1425                                    ? string_type_class : array_type_class);
1426     case SET_TYPE:         return set_type_class;
1427     case FILE_TYPE:        return file_type_class;
1428     case LANG_TYPE:        return lang_type_class;
1429     default:               return no_type_class;
1430     }
1431 }
1432
1433 /* Expand a call to __builtin_classify_type with arguments found in
1434    ARGLIST.  */
1435
1436 static rtx
1437 expand_builtin_classify_type (arglist)
1438      tree arglist;
1439 {
1440   if (arglist != 0)
1441     return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
1442   return GEN_INT (no_type_class);
1443 }
1444
1445 /* Expand expression EXP, which is a call to __builtin_constant_p.  */
1446
1447 static rtx
1448 expand_builtin_constant_p (arglist, target_mode)
1449      tree arglist;
1450      enum machine_mode target_mode;
1451 {
1452   rtx tmp;
1453
1454   if (arglist == 0)
1455     return const0_rtx;
1456   arglist = TREE_VALUE (arglist);
1457
1458   /* We have taken care of the easy cases during constant folding.  This
1459      case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE
1460      get a chance to see if it can deduce whether ARGLIST is constant.  */
1461
1462   current_function_calls_constant_p = 1;
1463
1464   tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
1465   tmp = gen_rtx_CONSTANT_P_RTX (target_mode, tmp);
1466   return tmp;
1467 }
1468
1469 /* Return mathematic function equivalent to FN but operating directly on TYPE,
1470    if available.  */
1471 tree
1472 mathfn_built_in (type, fn)
1473      tree type;
1474      enum built_in_function fn;
1475 {
1476   enum built_in_function fcode = NOT_BUILT_IN;
1477   if (TYPE_MODE (type) == TYPE_MODE (double_type_node))
1478     switch (fn)
1479       {
1480       case BUILT_IN_SQRT:
1481       case BUILT_IN_SQRTF:
1482       case BUILT_IN_SQRTL:
1483         fcode = BUILT_IN_SQRT;
1484         break;
1485       case BUILT_IN_SIN:
1486       case BUILT_IN_SINF:
1487       case BUILT_IN_SINL:
1488         fcode = BUILT_IN_SIN;
1489         break;
1490       case BUILT_IN_COS:
1491       case BUILT_IN_COSF:
1492       case BUILT_IN_COSL:
1493         fcode = BUILT_IN_COS;
1494         break;
1495       case BUILT_IN_EXP:
1496       case BUILT_IN_EXPF:
1497       case BUILT_IN_EXPL:
1498         fcode = BUILT_IN_EXP;
1499         break;
1500       case BUILT_IN_LOG:
1501       case BUILT_IN_LOGF:
1502       case BUILT_IN_LOGL:
1503         fcode = BUILT_IN_LOG;
1504         break;
1505       case BUILT_IN_FLOOR:
1506       case BUILT_IN_FLOORF:
1507       case BUILT_IN_FLOORL:
1508         fcode = BUILT_IN_FLOOR;
1509         break;
1510       case BUILT_IN_CEIL:
1511       case BUILT_IN_CEILF:
1512       case BUILT_IN_CEILL:
1513         fcode = BUILT_IN_CEIL;
1514         break;
1515       case BUILT_IN_TRUNC:
1516       case BUILT_IN_TRUNCF:
1517       case BUILT_IN_TRUNCL:
1518         fcode = BUILT_IN_TRUNC;
1519         break;
1520       case BUILT_IN_ROUND:
1521       case BUILT_IN_ROUNDF:
1522       case BUILT_IN_ROUNDL:
1523         fcode = BUILT_IN_ROUND;
1524         break;
1525       case BUILT_IN_NEARBYINT:
1526       case BUILT_IN_NEARBYINTF:
1527       case BUILT_IN_NEARBYINTL:
1528         fcode = BUILT_IN_NEARBYINT;
1529         break;
1530       default:
1531         abort ();
1532       }
1533   else if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
1534     switch (fn)
1535       {
1536       case BUILT_IN_SQRT:
1537       case BUILT_IN_SQRTF:
1538       case BUILT_IN_SQRTL:
1539         fcode = BUILT_IN_SQRTF;
1540         break;
1541       case BUILT_IN_SIN:
1542       case BUILT_IN_SINF:
1543       case BUILT_IN_SINL:
1544         fcode = BUILT_IN_SINF;
1545         break;
1546       case BUILT_IN_COS:
1547       case BUILT_IN_COSF:
1548       case BUILT_IN_COSL:
1549         fcode = BUILT_IN_COSF;
1550         break;
1551       case BUILT_IN_EXP:
1552       case BUILT_IN_EXPF:
1553       case BUILT_IN_EXPL:
1554         fcode = BUILT_IN_EXPF;
1555         break;
1556       case BUILT_IN_LOG:
1557       case BUILT_IN_LOGF:
1558       case BUILT_IN_LOGL:
1559         fcode = BUILT_IN_LOGF;
1560         break;
1561       case BUILT_IN_FLOOR:
1562       case BUILT_IN_FLOORF:
1563       case BUILT_IN_FLOORL:
1564         fcode = BUILT_IN_FLOORF;
1565         break;
1566       case BUILT_IN_CEIL:
1567       case BUILT_IN_CEILF:
1568       case BUILT_IN_CEILL:
1569         fcode = BUILT_IN_CEILF;
1570         break;
1571       case BUILT_IN_TRUNC:
1572       case BUILT_IN_TRUNCF:
1573       case BUILT_IN_TRUNCL:
1574         fcode = BUILT_IN_TRUNCF;
1575         break;
1576       case BUILT_IN_ROUND:
1577       case BUILT_IN_ROUNDF:
1578       case BUILT_IN_ROUNDL:
1579         fcode = BUILT_IN_ROUNDF;
1580         break;
1581       case BUILT_IN_NEARBYINT:
1582       case BUILT_IN_NEARBYINTF:
1583       case BUILT_IN_NEARBYINTL:
1584         fcode = BUILT_IN_NEARBYINTF;
1585         break;
1586       default:
1587         abort ();
1588       }
1589   else if (TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
1590     switch (fn)
1591       {
1592       case BUILT_IN_SQRT:
1593       case BUILT_IN_SQRTF:
1594       case BUILT_IN_SQRTL:
1595         fcode = BUILT_IN_SQRTL;
1596         break;
1597       case BUILT_IN_SIN:
1598       case BUILT_IN_SINF:
1599       case BUILT_IN_SINL:
1600         fcode = BUILT_IN_SINL;
1601         break;
1602       case BUILT_IN_COS:
1603       case BUILT_IN_COSF:
1604       case BUILT_IN_COSL:
1605         fcode = BUILT_IN_COSL;
1606         break;
1607       case BUILT_IN_EXP:
1608       case BUILT_IN_EXPF:
1609       case BUILT_IN_EXPL:
1610         fcode = BUILT_IN_EXPL;
1611         break;
1612       case BUILT_IN_LOG:
1613       case BUILT_IN_LOGF:
1614       case BUILT_IN_LOGL:
1615         fcode = BUILT_IN_LOGL;
1616         break;
1617       case BUILT_IN_FLOOR:
1618       case BUILT_IN_FLOORF:
1619       case BUILT_IN_FLOORL:
1620         fcode = BUILT_IN_FLOORL;
1621         break;
1622       case BUILT_IN_CEIL:
1623       case BUILT_IN_CEILF:
1624       case BUILT_IN_CEILL:
1625         fcode = BUILT_IN_CEILL;
1626         break;
1627       case BUILT_IN_TRUNC:
1628       case BUILT_IN_TRUNCF:
1629       case BUILT_IN_TRUNCL:
1630         fcode = BUILT_IN_TRUNCL;
1631         break;
1632       case BUILT_IN_ROUND:
1633       case BUILT_IN_ROUNDF:
1634       case BUILT_IN_ROUNDL:
1635         fcode = BUILT_IN_ROUNDL;
1636         break;
1637       case BUILT_IN_NEARBYINT:
1638       case BUILT_IN_NEARBYINTF:
1639       case BUILT_IN_NEARBYINTL:
1640         fcode = BUILT_IN_NEARBYINTL;
1641         break;
1642       default:
1643         abort ();
1644       }
1645   return implicit_built_in_decls[fcode];
1646 }
1647
1648 /* If errno must be maintained, expand the RTL to check if the result,
1649    TARGET, of a built-in function call, EXP, is NaN, and if so set
1650    errno to EDOM.  */
1651
1652 static void
1653 expand_errno_check (exp, target)
1654      tree exp;
1655      rtx target;
1656 {
1657   rtx lab;
1658
1659   if (flag_errno_math && HONOR_NANS (GET_MODE (target)))
1660     {
1661       lab = gen_label_rtx ();
1662
1663       /* Test the result; if it is NaN, set errno=EDOM because
1664          the argument was not in the domain.  */
1665       emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1666                                0, lab);
1667
1668 #ifdef TARGET_EDOM
1669       {
1670 #ifdef GEN_ERRNO_RTX
1671         rtx errno_rtx = GEN_ERRNO_RTX;
1672 #else
1673         rtx errno_rtx
1674           = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1675 #endif
1676
1677         emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1678       }
1679 #else
1680       /* We can't set errno=EDOM directly; let the library call do it.
1681          Pop the arguments right away in case the call gets deleted.  */
1682       NO_DEFER_POP;
1683       expand_call (exp, target, 0);
1684       OK_DEFER_POP;
1685 #endif
1686
1687       emit_label (lab);
1688     }
1689 }
1690
1691
1692 /* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1693    Return 0 if a normal call should be emitted rather than expanding the
1694    function in-line.  EXP is the expression that is a call to the builtin
1695    function; if convenient, the result should be placed in TARGET.
1696    SUBTARGET may be used as the target for computing one of EXP's operands.  */
1697
1698 static rtx
1699 expand_builtin_mathfn (exp, target, subtarget)
1700      tree exp;
1701      rtx target, subtarget;
1702 {
1703   optab builtin_optab;
1704   rtx op0, insns;
1705   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1706   tree arglist = TREE_OPERAND (exp, 1);
1707   enum machine_mode argmode;
1708   bool errno_set = true;
1709
1710   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
1711     return 0;
1712
1713   /* Stabilize and compute the argument.  */
1714   if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
1715       && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
1716     {
1717       exp = copy_node (exp);
1718       TREE_OPERAND (exp, 1) = arglist;
1719       /* Wrap the computation of the argument in a SAVE_EXPR.  That
1720          way, if we need to expand the argument again (as in the
1721          flag_errno_math case below where we cannot directly set
1722          errno), we will not perform side-effects more than once.
1723          Note that here we're mutating the original EXP as well as the
1724          copy; that's the right thing to do in case the original EXP
1725          is expanded later.  */
1726       TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
1727       arglist = copy_node (arglist);
1728     }
1729   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
1730
1731   /* Make a suitable register to place result in.  */
1732   target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
1733
1734   emit_queue ();
1735   start_sequence ();
1736
1737   switch (DECL_FUNCTION_CODE (fndecl))
1738     {
1739     case BUILT_IN_SIN:
1740     case BUILT_IN_SINF:
1741     case BUILT_IN_SINL:
1742       builtin_optab = sin_optab; break;
1743     case BUILT_IN_COS:
1744     case BUILT_IN_COSF:
1745     case BUILT_IN_COSL:
1746       builtin_optab = cos_optab; break;
1747     case BUILT_IN_SQRT:
1748     case BUILT_IN_SQRTF:
1749     case BUILT_IN_SQRTL:
1750       builtin_optab = sqrt_optab; break;
1751     case BUILT_IN_EXP:
1752     case BUILT_IN_EXPF:
1753     case BUILT_IN_EXPL:
1754       builtin_optab = exp_optab; break;
1755     case BUILT_IN_LOG:
1756     case BUILT_IN_LOGF:
1757     case BUILT_IN_LOGL:
1758       builtin_optab = log_optab; break;
1759     case BUILT_IN_FLOOR:
1760     case BUILT_IN_FLOORF:
1761     case BUILT_IN_FLOORL:
1762       errno_set = false ; builtin_optab = floor_optab; break;
1763     case BUILT_IN_CEIL:
1764     case BUILT_IN_CEILF:
1765     case BUILT_IN_CEILL:
1766       errno_set = false ; builtin_optab = ceil_optab; break;
1767     case BUILT_IN_TRUNC:
1768     case BUILT_IN_TRUNCF:
1769     case BUILT_IN_TRUNCL:
1770       errno_set = false ; builtin_optab = trunc_optab; break;
1771     case BUILT_IN_ROUND:
1772     case BUILT_IN_ROUNDF:
1773     case BUILT_IN_ROUNDL:
1774       errno_set = false ; builtin_optab = round_optab; break;
1775     case BUILT_IN_NEARBYINT:
1776     case BUILT_IN_NEARBYINTF:
1777     case BUILT_IN_NEARBYINTL:
1778       errno_set = false ; builtin_optab = nearbyint_optab; break;
1779     default:
1780       abort ();
1781     }
1782
1783   /* Compute into TARGET.
1784      Set TARGET to wherever the result comes back.  */
1785   argmode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
1786   target = expand_unop (argmode, builtin_optab, op0, target, 0);
1787
1788   /* If we were unable to expand via the builtin, stop the
1789      sequence (without outputting the insns) and return 0, causing
1790      a call to the library function.  */
1791   if (target == 0)
1792     {
1793       end_sequence ();
1794       return 0;
1795     }
1796
1797   if (errno_set)
1798     expand_errno_check (exp, target);
1799
1800   /* Output the entire sequence.  */
1801   insns = get_insns ();
1802   end_sequence ();
1803   emit_insn (insns);
1804
1805   return target;
1806 }
1807
1808 /* Expand a call to the builtin binary math functions (pow and atan2).
1809    Return 0 if a normal call should be emitted rather than expanding the
1810    function in-line.  EXP is the expression that is a call to the builtin
1811    function; if convenient, the result should be placed in TARGET.
1812    SUBTARGET may be used as the target for computing one of EXP's
1813    operands.  */
1814
1815 static rtx
1816 expand_builtin_mathfn_2 (exp, target, subtarget)
1817      tree exp;
1818      rtx target, subtarget;
1819 {
1820   optab builtin_optab;
1821   rtx op0, op1, insns;
1822   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1823   tree arglist = TREE_OPERAND (exp, 1);
1824   tree arg0, arg1;
1825   enum machine_mode argmode;
1826   bool errno_set = true;
1827   bool stable = true;
1828
1829   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
1830     return 0;
1831
1832   arg0 = TREE_VALUE (arglist);
1833   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
1834
1835   /* Stabilize the arguments.  */
1836   if (TREE_CODE (arg0) != VAR_DECL && TREE_CODE (arg0) != PARM_DECL)
1837     {
1838       arg0 = save_expr (arg0);
1839       TREE_VALUE (arglist) = arg0;
1840       stable = false;
1841     }
1842   if (TREE_CODE (arg1) != VAR_DECL && TREE_CODE (arg1) != PARM_DECL)
1843     {
1844       arg1 = save_expr (arg1);
1845       TREE_VALUE (TREE_CHAIN (arglist)) = arg1;
1846       stable = false;
1847     }
1848
1849   if (! stable)
1850     {
1851       exp = copy_node (exp);
1852       arglist = tree_cons (NULL_TREE, arg0,
1853                            build_tree_list (NULL_TREE, arg1));
1854       TREE_OPERAND (exp, 1) = arglist;
1855     }
1856
1857   op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
1858   op1 = expand_expr (arg1, 0, VOIDmode, 0);
1859
1860   /* Make a suitable register to place result in.  */
1861   target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
1862
1863   emit_queue ();
1864   start_sequence ();
1865
1866   switch (DECL_FUNCTION_CODE (fndecl))
1867     {
1868     case BUILT_IN_POW:
1869     case BUILT_IN_POWF:
1870     case BUILT_IN_POWL:
1871       builtin_optab = pow_optab; break;
1872     case BUILT_IN_ATAN2:
1873     case BUILT_IN_ATAN2F:
1874     case BUILT_IN_ATAN2L:
1875       builtin_optab = atan2_optab; break;
1876     default:
1877       abort ();
1878     }
1879
1880   /* Compute into TARGET.
1881      Set TARGET to wherever the result comes back.  */
1882   argmode = TYPE_MODE (TREE_TYPE (arg0));
1883   target = expand_binop (argmode, builtin_optab, op0, op1,
1884                          target, 0, OPTAB_DIRECT);
1885
1886   /* If we were unable to expand via the builtin, stop the
1887      sequence (without outputting the insns) and return 0, causing
1888      a call to the library function.  */
1889   if (target == 0)
1890     {
1891       end_sequence ();
1892       return 0;
1893     }
1894
1895   if (errno_set)
1896     expand_errno_check (exp, target);
1897
1898   /* Output the entire sequence.  */
1899   insns = get_insns ();
1900   end_sequence ();
1901   emit_insn (insns);
1902
1903   return target;
1904 }
1905
1906 /* Expand expression EXP which is a call to the strlen builtin.  Return 0
1907    if we failed the caller should emit a normal call, otherwise
1908    try to get the result in TARGET, if convenient.  */
1909
1910 static rtx
1911 expand_builtin_strlen (arglist, target, target_mode)
1912      tree arglist;
1913      rtx target;
1914      enum machine_mode target_mode;
1915 {
1916   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
1917     return 0;
1918   else
1919     {
1920       rtx pat;
1921       tree len, src = TREE_VALUE (arglist);
1922       rtx result, src_reg, char_rtx, before_strlen;
1923       enum machine_mode insn_mode = target_mode, char_mode;
1924       enum insn_code icode = CODE_FOR_nothing;
1925       int align;
1926
1927       /* If the length can be computed at compile-time, return it.  */
1928       len = c_strlen (src);
1929       if (len)
1930         return expand_expr (len, target, target_mode, EXPAND_NORMAL);
1931
1932       align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1933
1934       /* If SRC is not a pointer type, don't do this operation inline.  */
1935       if (align == 0)
1936         return 0;
1937
1938       /* Bail out if we can't compute strlen in the right mode.  */
1939       while (insn_mode != VOIDmode)
1940         {
1941           icode = strlen_optab->handlers[(int) insn_mode].insn_code;
1942           if (icode != CODE_FOR_nothing)
1943             break;
1944
1945           insn_mode = GET_MODE_WIDER_MODE (insn_mode);
1946         }
1947       if (insn_mode == VOIDmode)
1948         return 0;
1949
1950       /* Make a place to write the result of the instruction.  */
1951       result = target;
1952       if (! (result != 0
1953              && GET_CODE (result) == REG
1954              && GET_MODE (result) == insn_mode
1955              && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1956         result = gen_reg_rtx (insn_mode);
1957
1958       /* Make a place to hold the source address.  We will not expand
1959          the actual source until we are sure that the expansion will
1960          not fail -- there are trees that cannot be expanded twice.  */
1961       src_reg = gen_reg_rtx (Pmode);
1962
1963       /* Mark the beginning of the strlen sequence so we can emit the
1964          source operand later.  */
1965       before_strlen = get_last_insn ();
1966
1967       char_rtx = const0_rtx;
1968       char_mode = insn_data[(int) icode].operand[2].mode;
1969       if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
1970                                                             char_mode))
1971         char_rtx = copy_to_mode_reg (char_mode, char_rtx);
1972
1973       pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
1974                              char_rtx, GEN_INT (align));
1975       if (! pat)
1976         return 0;
1977       emit_insn (pat);
1978
1979       /* Now that we are assured of success, expand the source.  */
1980       start_sequence ();
1981       pat = memory_address (BLKmode,
1982                             expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
1983       if (pat != src_reg)
1984         emit_move_insn (src_reg, pat);
1985       pat = get_insns ();
1986       end_sequence ();
1987
1988       if (before_strlen)
1989         emit_insn_after (pat, before_strlen);
1990       else
1991         emit_insn_before (pat, get_insns ());
1992
1993       /* Return the value in the proper mode for this function.  */
1994       if (GET_MODE (result) == target_mode)
1995         target = result;
1996       else if (target != 0)
1997         convert_move (target, result, 0);
1998       else
1999         target = convert_to_mode (target_mode, result, 0);
2000
2001       return target;
2002     }
2003 }
2004
2005 /* Expand a call to the strstr builtin.  Return 0 if we failed the
2006    caller should emit a normal call, otherwise try to get the result
2007    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2008
2009 static rtx
2010 expand_builtin_strstr (arglist, target, mode)
2011      tree arglist;
2012      rtx target;
2013      enum machine_mode mode;
2014 {
2015   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2016     return 0;
2017   else
2018     {
2019       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2020       tree fn;
2021       const char *p1, *p2;
2022
2023       p2 = c_getstr (s2);
2024       if (p2 == NULL)
2025         return 0;
2026
2027       p1 = c_getstr (s1);
2028       if (p1 != NULL)
2029         {
2030           const char *r = strstr (p1, p2);
2031
2032           if (r == NULL)
2033             return const0_rtx;
2034
2035           /* Return an offset into the constant string argument.  */
2036           return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2037                                            s1, ssize_int (r - p1))),
2038                               target, mode, EXPAND_NORMAL);
2039         }
2040
2041       if (p2[0] == '\0')
2042         return expand_expr (s1, target, mode, EXPAND_NORMAL);
2043
2044       if (p2[1] != '\0')
2045         return 0;
2046
2047       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
2048       if (!fn)
2049         return 0;
2050
2051       /* New argument list transforming strstr(s1, s2) to
2052          strchr(s1, s2[0]).  */
2053       arglist =
2054         build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
2055       arglist = tree_cons (NULL_TREE, s1, arglist);
2056       return expand_expr (build_function_call_expr (fn, arglist),
2057                           target, mode, EXPAND_NORMAL);
2058     }
2059 }
2060
2061 /* Expand a call to the strchr builtin.  Return 0 if we failed the
2062    caller should emit a normal call, otherwise try to get the result
2063    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2064
2065 static rtx
2066 expand_builtin_strchr (arglist, target, mode)
2067      tree arglist;
2068      rtx target;
2069      enum machine_mode mode;
2070 {
2071   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2072     return 0;
2073   else
2074     {
2075       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2076       const char *p1;
2077
2078       if (TREE_CODE (s2) != INTEGER_CST)
2079         return 0;
2080
2081       p1 = c_getstr (s1);
2082       if (p1 != NULL)
2083         {
2084           char c;
2085           const char *r;
2086
2087           if (target_char_cast (s2, &c))
2088             return 0;
2089
2090           r = strchr (p1, c);
2091
2092           if (r == NULL)
2093             return const0_rtx;
2094
2095           /* Return an offset into the constant string argument.  */
2096           return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2097                                            s1, ssize_int (r - p1))),
2098                               target, mode, EXPAND_NORMAL);
2099         }
2100
2101       /* FIXME: Should use here strchrM optab so that ports can optimize
2102          this.  */
2103       return 0;
2104     }
2105 }
2106
2107 /* Expand a call to the strrchr builtin.  Return 0 if we failed the
2108    caller should emit a normal call, otherwise try to get the result
2109    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2110
2111 static rtx
2112 expand_builtin_strrchr (arglist, target, mode)
2113      tree arglist;
2114      rtx target;
2115      enum machine_mode mode;
2116 {
2117   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2118     return 0;
2119   else
2120     {
2121       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2122       tree fn;
2123       const char *p1;
2124
2125       if (TREE_CODE (s2) != INTEGER_CST)
2126         return 0;
2127
2128       p1 = c_getstr (s1);
2129       if (p1 != NULL)
2130         {
2131           char c;
2132           const char *r;
2133
2134           if (target_char_cast (s2, &c))
2135             return 0;
2136
2137           r = strrchr (p1, c);
2138
2139           if (r == NULL)
2140             return const0_rtx;
2141
2142           /* Return an offset into the constant string argument.  */
2143           return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2144                                            s1, ssize_int (r - p1))),
2145                               target, mode, EXPAND_NORMAL);
2146         }
2147
2148       if (! integer_zerop (s2))
2149         return 0;
2150
2151       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
2152       if (!fn)
2153         return 0;
2154
2155       /* Transform strrchr(s1, '\0') to strchr(s1, '\0').  */
2156       return expand_expr (build_function_call_expr (fn, arglist),
2157                           target, mode, EXPAND_NORMAL);
2158     }
2159 }
2160
2161 /* Expand a call to the strpbrk builtin.  Return 0 if we failed the
2162    caller should emit a normal call, otherwise try to get the result
2163    in TARGET, if convenient (and in mode MODE if that's convenient).  */
2164
2165 static rtx
2166 expand_builtin_strpbrk (arglist, target, mode)
2167      tree arglist;
2168      rtx target;
2169      enum machine_mode mode;
2170 {
2171   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2172     return 0;
2173   else
2174     {
2175       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2176       tree fn;
2177       const char *p1, *p2;
2178
2179       p2 = c_getstr (s2);
2180       if (p2 == NULL)
2181         return 0;
2182
2183       p1 = c_getstr (s1);
2184       if (p1 != NULL)
2185         {
2186           const char *r = strpbrk (p1, p2);
2187
2188           if (r == NULL)
2189             return const0_rtx;
2190
2191           /* Return an offset into the constant string argument.  */
2192           return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
2193                                            s1, ssize_int (r - p1))),
2194                               target, mode, EXPAND_NORMAL);
2195         }
2196
2197       if (p2[0] == '\0')
2198         {
2199           /* strpbrk(x, "") == NULL.
2200              Evaluate and ignore the arguments in case they had
2201              side-effects.  */
2202           expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2203           return const0_rtx;
2204         }
2205
2206       if (p2[1] != '\0')
2207         return 0;  /* Really call strpbrk.  */
2208
2209       fn = implicit_built_in_decls[BUILT_IN_STRCHR];
2210       if (!fn)
2211         return 0;
2212
2213       /* New argument list transforming strpbrk(s1, s2) to
2214          strchr(s1, s2[0]).  */
2215       arglist =
2216         build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
2217       arglist = tree_cons (NULL_TREE, s1, arglist);
2218       return expand_expr (build_function_call_expr (fn, arglist),
2219                           target, mode, EXPAND_NORMAL);
2220     }
2221 }
2222
2223 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
2224    bytes from constant string DATA + OFFSET and return it as target
2225    constant.  */
2226
2227 static rtx
2228 builtin_memcpy_read_str (data, offset, mode)
2229      PTR data;
2230      HOST_WIDE_INT offset;
2231      enum machine_mode mode;
2232 {
2233   const char *str = (const char *) data;
2234
2235   if (offset < 0
2236       || ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
2237           > strlen (str) + 1))
2238     abort ();  /* Attempt to read past the end of constant string.  */
2239
2240   return c_readstr (str + offset, mode);
2241 }
2242
2243 /* Expand a call to the memcpy builtin, with arguments in ARGLIST.
2244    Return 0 if we failed, the caller should emit a normal call,
2245    otherwise try to get the result in TARGET, if convenient (and in
2246    mode MODE if that's convenient).  If ENDP is 0 return the
2247    destination pointer, if ENDP is 1 return the end pointer ala
2248    mempcpy, and if ENDP is 2 return the end pointer minus one ala
2249    stpcpy.  */
2250 static rtx
2251 expand_builtin_memcpy (arglist, target, mode, endp)
2252      tree arglist;
2253      rtx target;
2254      enum machine_mode mode;
2255      int endp;
2256 {
2257   if (!validate_arglist (arglist,
2258                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2259     return 0;
2260   else
2261     {
2262       tree dest = TREE_VALUE (arglist);
2263       tree src = TREE_VALUE (TREE_CHAIN (arglist));
2264       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2265       const char *src_str;
2266
2267       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2268       unsigned int dest_align
2269         = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2270       rtx dest_mem, src_mem, dest_addr, len_rtx;
2271
2272       /* If DEST is not a pointer type, call the normal function.  */
2273       if (dest_align == 0)
2274         return 0;
2275
2276       /* If the LEN parameter is zero, return DEST.  */
2277       if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
2278         {
2279           /* Evaluate and ignore SRC in case it has side-effects.  */
2280           expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2281           return expand_expr (dest, target, mode, EXPAND_NORMAL);
2282         }
2283
2284       /* If either SRC is not a pointer type, don't do this
2285          operation in-line.  */
2286       if (src_align == 0)
2287         return 0;
2288
2289       dest_mem = get_memory_rtx (dest);
2290       set_mem_align (dest_mem, dest_align);
2291       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2292       src_str = c_getstr (src);
2293
2294       /* If SRC is a string constant and block move would be done
2295          by pieces, we can avoid loading the string from memory
2296          and only stored the computed constants.  */
2297       if (src_str
2298           && GET_CODE (len_rtx) == CONST_INT
2299           && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
2300           && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
2301                                   (PTR) src_str, dest_align))
2302         {
2303           store_by_pieces (dest_mem, INTVAL (len_rtx),
2304                            builtin_memcpy_read_str,
2305                            (PTR) src_str, dest_align);
2306           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2307 #ifdef POINTERS_EXTEND_UNSIGNED
2308           if (GET_MODE (dest_mem) != ptr_mode)
2309             dest_mem = convert_memory_address (ptr_mode, dest_mem);
2310 #endif
2311           if (endp)
2312             {
2313               rtx result = gen_rtx_PLUS (GET_MODE (dest_mem), dest_mem, len_rtx);
2314               if (endp == 2)
2315                 result = simplify_gen_binary (MINUS, GET_MODE (result), result, const1_rtx);
2316               return result;
2317             }
2318           else
2319             return dest_mem;
2320         }
2321
2322       src_mem = get_memory_rtx (src);
2323       set_mem_align (src_mem, src_align);
2324
2325       /* Copy word part most expediently.  */
2326       dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
2327                                    BLOCK_OP_NORMAL);
2328
2329       if (dest_addr == 0)
2330         {
2331           dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2332 #ifdef POINTERS_EXTEND_UNSIGNED
2333           if (GET_MODE (dest_addr) != ptr_mode)
2334             dest_addr = convert_memory_address (ptr_mode, dest_addr);
2335 #endif
2336         }
2337
2338       if (endp)
2339         {
2340           rtx result = gen_rtx_PLUS (GET_MODE (dest_addr), dest_addr, len_rtx);
2341           if (endp == 2)
2342             result = simplify_gen_binary (MINUS, GET_MODE (result), result, const1_rtx);
2343           return result;
2344         }
2345       else
2346         return dest_addr;
2347     }
2348 }
2349
2350 /* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
2351    Return 0 if we failed the caller should emit a normal call,
2352    otherwise try to get the result in TARGET, if convenient (and in
2353    mode MODE if that's convenient).  */
2354
2355 static rtx
2356 expand_builtin_mempcpy (arglist, target, mode)
2357      tree arglist;
2358      rtx target;
2359      enum machine_mode mode;
2360 {
2361   if (!validate_arglist (arglist,
2362                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2363     return 0;
2364   else
2365     {
2366       /* If return value is ignored, transform mempcpy into memcpy.  */
2367       if (target == const0_rtx)
2368         {
2369           tree fn;
2370           rtx ret = expand_builtin_memcpy (arglist, target, mode, /*endp=*/0);
2371
2372           if (ret)
2373             return ret;
2374
2375           fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2376           if (!fn)
2377             return 0;
2378
2379           return expand_expr (build_function_call_expr (fn, arglist),
2380                               target, mode, EXPAND_NORMAL);
2381         }
2382
2383       return expand_builtin_memcpy (arglist, target, mode, /*endp=*/1);
2384     }
2385 }
2386
2387 /* Expand expression EXP, which is a call to the memmove builtin.  Return 0
2388    if we failed the caller should emit a normal call.  */
2389
2390 static rtx
2391 expand_builtin_memmove (arglist, target, mode)
2392      tree arglist;
2393      rtx target;
2394      enum machine_mode mode;
2395 {
2396   if (!validate_arglist (arglist,
2397                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2398     return 0;
2399   else
2400     {
2401       tree dest = TREE_VALUE (arglist);
2402       tree src = TREE_VALUE (TREE_CHAIN (arglist));
2403       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2404
2405       unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
2406       unsigned int dest_align
2407         = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2408
2409       /* If DEST is not a pointer type, call the normal function.  */
2410       if (dest_align == 0)
2411         return 0;
2412
2413       /* If the LEN parameter is zero, return DEST.  */
2414       if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
2415         {
2416           /* Evaluate and ignore SRC in case it has side-effects.  */
2417           expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2418           return expand_expr (dest, target, mode, EXPAND_NORMAL);
2419         }
2420
2421       /* If either SRC is not a pointer type, don't do this
2422          operation in-line.  */
2423       if (src_align == 0)
2424         return 0;
2425
2426       /* If src is a string constant and strings are not writable,
2427          we can use normal memcpy.  */
2428       if (!flag_writable_strings && c_getstr (src))
2429         return expand_builtin_memcpy (arglist, target, mode, 0);
2430
2431       /* Otherwise, call the normal function.  */
2432       return 0;
2433    }
2434 }
2435
2436 /* Expand expression EXP, which is a call to the bcopy builtin.  Return 0
2437    if we failed the caller should emit a normal call.  */
2438
2439 static rtx
2440 expand_builtin_bcopy (arglist)
2441      tree arglist;
2442 {
2443   tree src, dest, size, newarglist;
2444
2445   if (!validate_arglist (arglist,
2446                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2447     return NULL_RTX;
2448
2449   src = TREE_VALUE (arglist);
2450   dest = TREE_VALUE (TREE_CHAIN (arglist));
2451   size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2452
2453   /* New argument list transforming bcopy(ptr x, ptr y, int z) to
2454      memmove(ptr y, ptr x, size_t z).   This is done this way
2455      so that if it isn't expanded inline, we fallback to
2456      calling bcopy instead of memmove.  */
2457
2458   newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
2459   newarglist = tree_cons (NULL_TREE, src, newarglist);
2460   newarglist = tree_cons (NULL_TREE, dest, newarglist);
2461
2462   return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode);
2463 }
2464
2465 /* Expand expression EXP, which is a call to the strcpy builtin.  Return 0
2466    if we failed the caller should emit a normal call, otherwise try to get
2467    the result in TARGET, if convenient (and in mode MODE if that's
2468    convenient).  */
2469
2470 static rtx
2471 expand_builtin_strcpy (arglist, target, mode)
2472      tree arglist;
2473      rtx target;
2474      enum machine_mode mode;
2475 {
2476   tree fn, len;
2477
2478   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2479     return 0;
2480
2481   fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2482   if (!fn)
2483     return 0;
2484
2485   len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
2486   if (len == 0)
2487     return 0;
2488
2489   len = size_binop (PLUS_EXPR, len, ssize_int (1));
2490   chainon (arglist, build_tree_list (NULL_TREE, len));
2491   return expand_expr (build_function_call_expr (fn, arglist),
2492                       target, mode, EXPAND_NORMAL);
2493 }
2494
2495 /* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
2496    Return 0 if we failed the caller should emit a normal call,
2497    otherwise try to get the result in TARGET, if convenient (and in
2498    mode MODE if that's convenient).  */
2499
2500 static rtx
2501 expand_builtin_stpcpy (arglist, target, mode)
2502      tree arglist;
2503      rtx target;
2504      enum machine_mode mode;
2505 {
2506   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2507     return 0;
2508   else
2509     {
2510       tree newarglist;
2511       tree len;
2512
2513       /* If return value is ignored, transform stpcpy into strcpy.  */
2514       if (target == const0_rtx)
2515         {
2516           tree fn;
2517           rtx ret = expand_builtin_strcpy (arglist, target, mode);
2518
2519           if (ret)
2520             return ret;
2521
2522           fn = implicit_built_in_decls[BUILT_IN_STRCPY];
2523           if (!fn)
2524             return 0;
2525
2526           return expand_expr (build_function_call_expr (fn, arglist),
2527                               target, mode, EXPAND_NORMAL);
2528         }
2529
2530       len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
2531       if (len == 0)
2532         return 0;
2533
2534       len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
2535       newarglist = copy_list (arglist);
2536       chainon (newarglist, build_tree_list (NULL_TREE, len));
2537       return expand_builtin_memcpy (newarglist, target, mode, /*endp=*/2);
2538     }
2539 }
2540
2541 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
2542    bytes from constant string DATA + OFFSET and return it as target
2543    constant.  */
2544
2545 static rtx
2546 builtin_strncpy_read_str (data, offset, mode)
2547      PTR data;
2548      HOST_WIDE_INT offset;
2549      enum machine_mode mode;
2550 {
2551   const char *str = (const char *) data;
2552
2553   if ((unsigned HOST_WIDE_INT) offset > strlen (str))
2554     return const0_rtx;
2555
2556   return c_readstr (str + offset, mode);
2557 }
2558
2559 /* Expand expression EXP, which is a call to the strncpy builtin.  Return 0
2560    if we failed the caller should emit a normal call.  */
2561
2562 static rtx
2563 expand_builtin_strncpy (arglist, target, mode)
2564      tree arglist;
2565      rtx target;
2566      enum machine_mode mode;
2567 {
2568   if (!validate_arglist (arglist,
2569                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2570     return 0;
2571   else
2572     {
2573       tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
2574       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2575       tree fn;
2576
2577       /* We must be passed a constant len parameter.  */
2578       if (TREE_CODE (len) != INTEGER_CST)
2579         return 0;
2580
2581       /* If the len parameter is zero, return the dst parameter.  */
2582       if (integer_zerop (len))
2583         {
2584           /* Evaluate and ignore the src argument in case it has
2585              side-effects.  */
2586           expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
2587                        VOIDmode, EXPAND_NORMAL);
2588           /* Return the dst parameter.  */
2589           return expand_expr (TREE_VALUE (arglist), target, mode,
2590                               EXPAND_NORMAL);
2591         }
2592
2593       /* Now, we must be passed a constant src ptr parameter.  */
2594       if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
2595         return 0;
2596
2597       slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
2598
2599       /* We're required to pad with trailing zeros if the requested
2600          len is greater than strlen(s2)+1.  In that case try to
2601          use store_by_pieces, if it fails, punt.  */
2602       if (tree_int_cst_lt (slen, len))
2603         {
2604           tree dest = TREE_VALUE (arglist);
2605           unsigned int dest_align
2606             = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2607           const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
2608           rtx dest_mem;
2609
2610           if (!p || dest_align == 0 || !host_integerp (len, 1)
2611               || !can_store_by_pieces (tree_low_cst (len, 1),
2612                                        builtin_strncpy_read_str,
2613                                        (PTR) p, dest_align))
2614             return 0;
2615
2616           dest_mem = get_memory_rtx (dest);
2617           store_by_pieces (dest_mem, tree_low_cst (len, 1),
2618                            builtin_strncpy_read_str,
2619                            (PTR) p, dest_align);
2620           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2621 #ifdef POINTERS_EXTEND_UNSIGNED
2622           if (GET_MODE (dest_mem) != ptr_mode)
2623             dest_mem = convert_memory_address (ptr_mode, dest_mem);
2624 #endif
2625           return dest_mem;
2626         }
2627
2628       /* OK transform into builtin memcpy.  */
2629       fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
2630       if (!fn)
2631         return 0;
2632       return expand_expr (build_function_call_expr (fn, arglist),
2633                           target, mode, EXPAND_NORMAL);
2634     }
2635 }
2636
2637 /* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
2638    bytes from constant string DATA + OFFSET and return it as target
2639    constant.  */
2640
2641 static rtx
2642 builtin_memset_read_str (data, offset, mode)
2643      PTR data;
2644      HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
2645      enum machine_mode mode;
2646 {
2647   const char *c = (const char *) data;
2648   char *p = alloca (GET_MODE_SIZE (mode));
2649
2650   memset (p, *c, GET_MODE_SIZE (mode));
2651
2652   return c_readstr (p, mode);
2653 }
2654
2655 /* Callback routine for store_by_pieces.  Return the RTL of a register
2656    containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
2657    char value given in the RTL register data.  For example, if mode is
2658    4 bytes wide, return the RTL for 0x01010101*data.  */
2659
2660 static rtx
2661 builtin_memset_gen_str (data, offset, mode)
2662      PTR data;
2663      HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
2664      enum machine_mode mode;
2665 {
2666   rtx target, coeff;
2667   size_t size;
2668   char *p;
2669
2670   size = GET_MODE_SIZE (mode);
2671   if (size == 1)
2672     return (rtx) data;
2673
2674   p = alloca (size);
2675   memset (p, 1, size);
2676   coeff = c_readstr (p, mode);
2677
2678   target = convert_to_mode (mode, (rtx) data, 1);
2679   target = expand_mult (mode, target, coeff, NULL_RTX, 1);
2680   return force_reg (mode, target);
2681 }
2682
2683 /* Expand expression EXP, which is a call to the memset builtin.  Return 0
2684    if we failed the caller should emit a normal call, otherwise try to get
2685    the result in TARGET, if convenient (and in mode MODE if that's
2686    convenient).  */
2687
2688 static rtx
2689 expand_builtin_memset (arglist, target, mode)
2690      tree arglist;
2691      rtx target;
2692      enum machine_mode mode;
2693 {
2694   if (!validate_arglist (arglist,
2695                          POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
2696     return 0;
2697   else
2698     {
2699       tree dest = TREE_VALUE (arglist);
2700       tree val = TREE_VALUE (TREE_CHAIN (arglist));
2701       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2702       char c;
2703
2704       unsigned int dest_align
2705         = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2706       rtx dest_mem, dest_addr, len_rtx;
2707
2708       /* If DEST is not a pointer type, don't do this
2709          operation in-line.  */
2710       if (dest_align == 0)
2711         return 0;
2712
2713       /* If the LEN parameter is zero, return DEST.  */
2714       if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
2715         {
2716           /* Evaluate and ignore VAL in case it has side-effects.  */
2717           expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
2718           return expand_expr (dest, target, mode, EXPAND_NORMAL);
2719         }
2720
2721       if (TREE_CODE (val) != INTEGER_CST)
2722         {
2723           rtx val_rtx;
2724
2725           if (!host_integerp (len, 1))
2726             return 0;
2727
2728           if (optimize_size && tree_low_cst (len, 1) > 1)
2729             return 0;
2730
2731           /* Assume that we can memset by pieces if we can store the
2732            * the coefficients by pieces (in the required modes).
2733            * We can't pass builtin_memset_gen_str as that emits RTL.  */
2734           c = 1;
2735           if (!can_store_by_pieces (tree_low_cst (len, 1),
2736                                     builtin_memset_read_str,
2737                                     (PTR) &c, dest_align))
2738             return 0;
2739
2740           val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val));
2741           val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
2742           val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
2743                                val_rtx);
2744           dest_mem = get_memory_rtx (dest);
2745           store_by_pieces (dest_mem, tree_low_cst (len, 1),
2746                            builtin_memset_gen_str,
2747                            (PTR) val_rtx, dest_align);
2748           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2749 #ifdef POINTERS_EXTEND_UNSIGNED
2750           if (GET_MODE (dest_mem) != ptr_mode)
2751             dest_mem = convert_memory_address (ptr_mode, dest_mem);
2752 #endif
2753           return dest_mem;
2754         }
2755
2756       if (target_char_cast (val, &c))
2757         return 0;
2758
2759       if (c)
2760         {
2761           if (!host_integerp (len, 1))
2762             return 0;
2763           if (!can_store_by_pieces (tree_low_cst (len, 1),
2764                                     builtin_memset_read_str, (PTR) &c,
2765                                     dest_align))
2766             return 0;
2767
2768           dest_mem = get_memory_rtx (dest);
2769           store_by_pieces (dest_mem, tree_low_cst (len, 1),
2770                            builtin_memset_read_str,
2771                            (PTR) &c, dest_align);
2772           dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2773 #ifdef POINTERS_EXTEND_UNSIGNED
2774           if (GET_MODE (dest_mem) != ptr_mode)
2775             dest_mem = convert_memory_address (ptr_mode, dest_mem);
2776 #endif
2777           return dest_mem;
2778         }
2779
2780       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2781
2782       dest_mem = get_memory_rtx (dest);
2783       set_mem_align (dest_mem, dest_align);
2784       dest_addr = clear_storage (dest_mem, len_rtx);
2785
2786       if (dest_addr == 0)
2787         {
2788           dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2789 #ifdef POINTERS_EXTEND_UNSIGNED
2790           if (GET_MODE (dest_addr) != ptr_mode)
2791             dest_addr = convert_memory_address (ptr_mode, dest_addr);
2792 #endif
2793         }
2794
2795       return dest_addr;
2796     }
2797 }
2798
2799 /* Expand expression EXP, which is a call to the bzero builtin.  Return 0
2800    if we failed the caller should emit a normal call.  */
2801
2802 static rtx
2803 expand_builtin_bzero (arglist)
2804      tree arglist;
2805 {
2806   tree dest, size, newarglist;
2807
2808   if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2809     return NULL_RTX;
2810
2811   dest = TREE_VALUE (arglist);
2812   size = TREE_VALUE (TREE_CHAIN (arglist));
2813
2814   /* New argument list transforming bzero(ptr x, int y) to
2815      memset(ptr x, int 0, size_t y).   This is done this way
2816      so that if it isn't expanded inline, we fallback to
2817      calling bzero instead of memset.  */
2818
2819   newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
2820   newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
2821   newarglist = tree_cons (NULL_TREE, dest, newarglist);
2822
2823   return expand_builtin_memset (newarglist, const0_rtx, VOIDmode);
2824 }
2825
2826 /* Expand expression EXP, which is a call to the memcmp built-in function.
2827    ARGLIST is the argument list for this call.  Return 0 if we failed and the
2828    caller should emit a normal call, otherwise try to get the result in
2829    TARGET, if convenient (and in mode MODE, if that's convenient).  */
2830
2831 static rtx
2832 expand_builtin_memcmp (exp, arglist, target, mode)
2833      tree exp ATTRIBUTE_UNUSED;
2834      tree arglist;
2835      rtx target;
2836      enum machine_mode mode;
2837 {
2838   tree arg1, arg2, len;
2839   const char *p1, *p2;
2840
2841   if (!validate_arglist (arglist,
2842                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2843     return 0;
2844
2845   arg1 = TREE_VALUE (arglist);
2846   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2847   len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2848
2849   /* If the len parameter is zero, return zero.  */
2850   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
2851     {
2852       /* Evaluate and ignore arg1 and arg2 in case they have
2853          side-effects.  */
2854       expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2855       expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2856       return const0_rtx;
2857     }
2858
2859   p1 = c_getstr (arg1);
2860   p2 = c_getstr (arg2);
2861
2862   /* If all arguments are constant, and the value of len is not greater
2863      than the lengths of arg1 and arg2, evaluate at compile-time.  */
2864   if (host_integerp (len, 1) && p1 && p2
2865       && compare_tree_int (len, strlen (p1) + 1) <= 0
2866       && compare_tree_int (len, strlen (p2) + 1) <= 0)
2867     {
2868       const int r = memcmp (p1, p2, tree_low_cst (len, 1));
2869
2870       return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2871     }
2872
2873   /* If len parameter is one, return an expression corresponding to
2874      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
2875   if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
2876     {
2877       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2878       tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2879       tree ind1 =
2880       fold (build1 (CONVERT_EXPR, integer_type_node,
2881                     build1 (INDIRECT_REF, cst_uchar_node,
2882                             build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2883       tree ind2 =
2884       fold (build1 (CONVERT_EXPR, integer_type_node,
2885                     build1 (INDIRECT_REF, cst_uchar_node,
2886                             build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2887       tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2888       return expand_expr (result, target, mode, EXPAND_NORMAL);
2889     }
2890
2891 #ifdef HAVE_cmpstrsi
2892   {
2893     rtx arg1_rtx, arg2_rtx, arg3_rtx;
2894     rtx result;
2895     rtx insn;
2896
2897     int arg1_align
2898       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2899     int arg2_align
2900       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2901     enum machine_mode insn_mode
2902       = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
2903
2904     /* If we don't have POINTER_TYPE, call the function.  */
2905     if (arg1_align == 0 || arg2_align == 0)
2906       return 0;
2907
2908     /* Make a place to write the result of the instruction.  */
2909     result = target;
2910     if (! (result != 0
2911            && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
2912            && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2913       result = gen_reg_rtx (insn_mode);
2914
2915     arg1_rtx = get_memory_rtx (arg1);
2916     arg2_rtx = get_memory_rtx (arg2);
2917     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2918     if (!HAVE_cmpstrsi)
2919       insn = NULL_RTX;
2920     else
2921       insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
2922                            GEN_INT (MIN (arg1_align, arg2_align)));
2923
2924     if (insn)
2925       emit_insn (insn);
2926     else
2927       emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
2928                                TYPE_MODE (integer_type_node), 3,
2929                                XEXP (arg1_rtx, 0), Pmode,
2930                                XEXP (arg2_rtx, 0), Pmode,
2931                                convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
2932                                                 TREE_UNSIGNED (sizetype)),
2933                                TYPE_MODE (sizetype));
2934
2935     /* Return the value in the proper mode for this function.  */
2936     mode = TYPE_MODE (TREE_TYPE (exp));
2937     if (GET_MODE (result) == mode)
2938       return result;
2939     else if (target != 0)
2940       {
2941         convert_move (target, result, 0);
2942         return target;
2943       }
2944     else
2945       return convert_to_mode (mode, result, 0);
2946   }
2947 #endif
2948
2949   return 0;
2950 }
2951
2952 /* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
2953    if we failed the caller should emit a normal call, otherwise try to get
2954    the result in TARGET, if convenient.  */
2955
2956 static rtx
2957 expand_builtin_strcmp (exp, target, mode)
2958      tree exp;
2959      rtx target;
2960      enum machine_mode mode;
2961 {
2962   tree arglist = TREE_OPERAND (exp, 1);
2963   tree arg1, arg2;
2964   const char *p1, *p2;
2965
2966   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2967     return 0;
2968
2969   arg1 = TREE_VALUE (arglist);
2970   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2971
2972   p1 = c_getstr (arg1);
2973   p2 = c_getstr (arg2);
2974
2975   if (p1 && p2)
2976     {
2977       const int i = strcmp (p1, p2);
2978       return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
2979     }
2980
2981   /* If either arg is "", return an expression corresponding to
2982      (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
2983   if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2984     {
2985       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2986       tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2987       tree ind1 =
2988         fold (build1 (CONVERT_EXPR, integer_type_node,
2989                       build1 (INDIRECT_REF, cst_uchar_node,
2990                               build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2991       tree ind2 =
2992         fold (build1 (CONVERT_EXPR, integer_type_node,
2993                       build1 (INDIRECT_REF, cst_uchar_node,
2994                               build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2995       tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2996       return expand_expr (result, target, mode, EXPAND_NORMAL);
2997     }
2998
2999 #ifdef HAVE_cmpstrsi
3000   if (HAVE_cmpstrsi)
3001   {
3002     tree len, len1, len2;
3003     rtx arg1_rtx, arg2_rtx, arg3_rtx;
3004     rtx result, insn;
3005
3006     int arg1_align
3007       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3008     int arg2_align
3009       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3010     enum machine_mode insn_mode
3011       = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3012
3013     len1 = c_strlen (arg1);
3014     len2 = c_strlen (arg2);
3015
3016     if (len1)
3017       len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3018     if (len2)
3019       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3020
3021     /* If we don't have a constant length for the first, use the length
3022        of the second, if we know it.  We don't require a constant for
3023        this case; some cost analysis could be done if both are available
3024        but neither is constant.  For now, assume they're equally cheap,
3025        unless one has side effects.  If both strings have constant lengths,
3026        use the smaller.  */
3027
3028     if (!len1)
3029       len = len2;
3030     else if (!len2)
3031       len = len1;
3032     else if (TREE_SIDE_EFFECTS (len1))
3033       len = len2;
3034     else if (TREE_SIDE_EFFECTS (len2))
3035       len = len1;
3036     else if (TREE_CODE (len1) != INTEGER_CST)
3037       len = len2;
3038     else if (TREE_CODE (len2) != INTEGER_CST)
3039       len = len1;
3040     else if (tree_int_cst_lt (len1, len2))
3041       len = len1;
3042     else
3043       len = len2;
3044
3045     /* If both arguments have side effects, we cannot optimize.  */
3046     if (!len || TREE_SIDE_EFFECTS (len))
3047       return 0;
3048
3049     /* If we don't have POINTER_TYPE, call the function.  */
3050     if (arg1_align == 0 || arg2_align == 0)
3051       return 0;
3052
3053     /* Make a place to write the result of the instruction.  */
3054     result = target;
3055     if (! (result != 0
3056            && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
3057            && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3058       result = gen_reg_rtx (insn_mode);
3059
3060     arg1_rtx = get_memory_rtx (arg1);
3061     arg2_rtx = get_memory_rtx (arg2);
3062     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3063     insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3064                          GEN_INT (MIN (arg1_align, arg2_align)));
3065     if (!insn)
3066       return 0;
3067
3068     emit_insn (insn);
3069
3070     /* Return the value in the proper mode for this function.  */
3071     mode = TYPE_MODE (TREE_TYPE (exp));
3072     if (GET_MODE (result) == mode)
3073       return result;
3074     if (target == 0)
3075       return convert_to_mode (mode, result, 0);
3076     convert_move (target, result, 0);
3077     return target;
3078   }
3079 #endif
3080   return 0;
3081 }
3082
3083 /* Expand expression EXP, which is a call to the strncmp builtin.  Return 0
3084    if we failed the caller should emit a normal call, otherwise try to get
3085    the result in TARGET, if convenient.  */
3086
3087 static rtx
3088 expand_builtin_strncmp (exp, target, mode)
3089      tree exp;
3090      rtx target;
3091      enum machine_mode mode;
3092 {
3093   tree arglist = TREE_OPERAND (exp, 1);
3094   tree arg1, arg2, arg3;
3095   const char *p1, *p2;
3096
3097   if (!validate_arglist (arglist,
3098                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3099     return 0;
3100
3101   arg1 = TREE_VALUE (arglist);
3102   arg2 = TREE_VALUE (TREE_CHAIN (arglist));
3103   arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3104
3105   /* If the len parameter is zero, return zero.  */
3106   if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0)
3107     {
3108       /* Evaluate and ignore arg1 and arg2 in case they have
3109          side-effects.  */
3110       expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
3111       expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3112       return const0_rtx;
3113     }
3114
3115   p1 = c_getstr (arg1);
3116   p2 = c_getstr (arg2);
3117
3118   /* If all arguments are constant, evaluate at compile-time.  */
3119   if (host_integerp (arg3, 1) && p1 && p2)
3120     {
3121       const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
3122       return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
3123     }
3124
3125   /* If len == 1 or (either string parameter is "" and (len >= 1)),
3126       return (*(const u_char*)arg1 - *(const u_char*)arg2).  */
3127   if (host_integerp (arg3, 1)
3128       && (tree_low_cst (arg3, 1) == 1
3129           || (tree_low_cst (arg3, 1) > 1
3130               && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
3131     {
3132       tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
3133       tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
3134       tree ind1 =
3135         fold (build1 (CONVERT_EXPR, integer_type_node,
3136                       build1 (INDIRECT_REF, cst_uchar_node,
3137                               build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
3138       tree ind2 =
3139         fold (build1 (CONVERT_EXPR, integer_type_node,
3140                       build1 (INDIRECT_REF, cst_uchar_node,
3141                               build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
3142       tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
3143       return expand_expr (result, target, mode, EXPAND_NORMAL);
3144     }
3145
3146   /* If c_strlen can determine an expression for one of the string
3147      lengths, and it doesn't have side effects, then emit cmpstrsi
3148      using length MIN(strlen(string)+1, arg3).  */
3149 #ifdef HAVE_cmpstrsi
3150   if (HAVE_cmpstrsi)
3151   {
3152     tree len, len1, len2;
3153     rtx arg1_rtx, arg2_rtx, arg3_rtx;
3154     rtx result, insn;
3155
3156     int arg1_align
3157       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3158     int arg2_align
3159       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
3160     enum machine_mode insn_mode
3161       = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
3162
3163     len1 = c_strlen (arg1);
3164     len2 = c_strlen (arg2);
3165
3166     if (len1)
3167       len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
3168     if (len2)
3169       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
3170
3171     /* If we don't have a constant length for the first, use the length
3172        of the second, if we know it.  We don't require a constant for
3173        this case; some cost analysis could be done if both are available
3174        but neither is constant.  For now, assume they're equally cheap,
3175        unless one has side effects.  If both strings have constant lengths,
3176        use the smaller.  */
3177
3178     if (!len1)
3179       len = len2;
3180     else if (!len2)
3181       len = len1;
3182     else if (TREE_SIDE_EFFECTS (len1))
3183       len = len2;
3184     else if (TREE_SIDE_EFFECTS (len2))
3185       len = len1;
3186     else if (TREE_CODE (len1) != INTEGER_CST)
3187       len = len2;
3188     else if (TREE_CODE (len2) != INTEGER_CST)
3189       len = len1;
3190     else if (tree_int_cst_lt (len1, len2))
3191       len = len1;
3192     else
3193       len = len2;
3194
3195     /* If both arguments have side effects, we cannot optimize.  */
3196     if (!len || TREE_SIDE_EFFECTS (len))
3197       return 0;
3198
3199     /* The actual new length parameter is MIN(len,arg3).  */
3200     len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
3201
3202     /* If we don't have POINTER_TYPE, call the function.  */
3203     if (arg1_align == 0 || arg2_align == 0)
3204       return 0;
3205
3206     /* Make a place to write the result of the instruction.  */
3207     result = target;
3208     if (! (result != 0
3209            && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
3210            && REGNO (result) >= FIRST_PSEUDO_REGISTER))
3211       result = gen_reg_rtx (insn_mode);
3212
3213     arg1_rtx = get_memory_rtx (arg1);
3214     arg2_rtx = get_memory_rtx (arg2);
3215     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
3216     insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
3217                          GEN_INT (MIN (arg1_align, arg2_align)));
3218     if (!insn)
3219       return 0;
3220
3221     emit_insn (insn);
3222
3223     /* Return the value in the proper mode for this function.  */
3224     mode = TYPE_MODE (TREE_TYPE (exp));
3225     if (GET_MODE (result) == mode)
3226       return result;
3227     if (target == 0)
3228       return convert_to_mode (mode, result, 0);
3229     convert_move (target, result, 0);
3230     return target;
3231   }
3232 #endif
3233   return 0;
3234 }
3235
3236 /* Expand expression EXP, which is a call to the strcat builtin.
3237    Return 0 if we failed the caller should emit a normal call,
3238    otherwise try to get the result in TARGET, if convenient.  */
3239
3240 static rtx
3241 expand_builtin_strcat (arglist, target, mode)
3242      tree arglist;
3243      rtx target;
3244      enum machine_mode mode;
3245 {
3246   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3247     return 0;
3248   else
3249     {
3250       tree dst = TREE_VALUE (arglist),
3251         src = TREE_VALUE (TREE_CHAIN (arglist));
3252       const char *p = c_getstr (src);
3253
3254       /* If the string length is zero, return the dst parameter.  */
3255       if (p && *p == '\0')
3256         return expand_expr (dst, target, mode, EXPAND_NORMAL);
3257
3258       return 0;
3259     }
3260 }
3261
3262 /* Expand expression EXP, which is a call to the strncat builtin.
3263    Return 0 if we failed the caller should emit a normal call,
3264    otherwise try to get the result in TARGET, if convenient.  */
3265
3266 static rtx
3267 expand_builtin_strncat (arglist, target, mode)
3268      tree arglist;
3269      rtx target;
3270      enum machine_mode mode;
3271 {
3272   if (!validate_arglist (arglist,
3273                          POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3274     return 0;
3275   else
3276     {
3277       tree dst = TREE_VALUE (arglist),
3278         src = TREE_VALUE (TREE_CHAIN (arglist)),
3279         len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
3280       const char *p = c_getstr (src);
3281
3282       /* If the requested length is zero, or the src parameter string
3283           length is zero, return the dst parameter.  */
3284       if (integer_zerop (len) || (p && *p == '\0'))
3285         {
3286           /* Evaluate and ignore the src and len parameters in case
3287              they have side-effects.  */
3288           expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
3289           expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
3290           return expand_expr (dst, target, mode, EXPAND_NORMAL);
3291         }
3292
3293       /* If the requested len is greater than or equal to the string
3294          length, call strcat.  */
3295       if (TREE_CODE (len) == INTEGER_CST && p
3296           && compare_tree_int (len, strlen (p)) >= 0)
3297         {
3298           tree newarglist
3299             = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
3300           tree fn = implicit_built_in_decls[BUILT_IN_STRCAT];
3301
3302           /* If the replacement _DECL isn't initialized, don't do the
3303              transformation.  */
3304           if (!fn)
3305             return 0;
3306
3307           return expand_expr (build_function_call_expr (fn, newarglist),
3308                               target, mode, EXPAND_NORMAL);
3309         }
3310       return 0;
3311     }
3312 }
3313
3314 /* Expand expression EXP, which is a call to the strspn builtin.
3315    Return 0 if we failed the caller should emit a normal call,
3316    otherwise try to get the result in TARGET, if convenient.  */
3317
3318 static rtx
3319 expand_builtin_strspn (arglist, target, mode)
3320      tree arglist;
3321      rtx target;
3322      enum machine_mode mode;
3323 {
3324   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3325     return 0;
3326   else
3327     {
3328       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
3329       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
3330
3331       /* If both arguments are constants, evaluate at compile-time.  */
3332       if (p1 && p2)
3333         {
3334           const size_t r = strspn (p1, p2);
3335           return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
3336         }
3337
3338       /* If either argument is "", return 0.  */
3339       if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
3340         {
3341           /* Evaluate and ignore both arguments in case either one has
3342              side-effects.  */
3343           expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
3344           expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3345           return const0_rtx;
3346         }
3347       return 0;
3348     }
3349 }
3350
3351 /* Expand expression EXP, which is a call to the strcspn builtin.
3352    Return 0 if we failed the caller should emit a normal call,
3353    otherwise try to get the result in TARGET, if convenient.  */
3354
3355 static rtx
3356 expand_builtin_strcspn (arglist, target, mode)
3357      tree arglist;
3358      rtx target;
3359      enum machine_mode mode;
3360 {
3361   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3362     return 0;
3363   else
3364     {
3365       tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
3366       const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
3367
3368       /* If both arguments are constants, evaluate at compile-time.  */
3369       if (p1 && p2)
3370         {
3371           const size_t r = strcspn (p1, p2);
3372           return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
3373         }
3374
3375       /* If the first argument is "", return 0.  */
3376       if (p1 && *p1 == '\0')
3377         {
3378           /* Evaluate and ignore argument s2 in case it has
3379              side-effects.  */
3380           expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
3381           return const0_rtx;
3382         }
3383
3384       /* If the second argument is "", return __builtin_strlen(s1).  */
3385       if (p2 && *p2 == '\0')
3386         {
3387           tree newarglist = build_tree_list (NULL_TREE, s1),
3388             fn = implicit_built_in_decls[BUILT_IN_STRLEN];
3389
3390           /* If the replacement _DECL isn't initialized, don't do the
3391              transformation.  */
3392           if (!fn)
3393             return 0;
3394
3395           return expand_expr (build_function_call_expr (fn, newarglist),
3396                               target, mode, EXPAND_NORMAL);
3397         }
3398       return 0;
3399     }
3400 }
3401
3402 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
3403    if that's convenient.  */
3404
3405 rtx
3406 expand_builtin_saveregs ()
3407 {
3408   rtx val, seq;
3409
3410   /* Don't do __builtin_saveregs more than once in a function.
3411      Save the result of the first call and reuse it.  */
3412   if (saveregs_value != 0)
3413     return saveregs_value;
3414
3415   /* When this function is called, it means that registers must be
3416      saved on entry to this function.  So we migrate the call to the
3417      first insn of this function.  */
3418
3419   start_sequence ();
3420
3421 #ifdef EXPAND_BUILTIN_SAVEREGS
3422   /* Do whatever the machine needs done in this case.  */
3423   val = EXPAND_BUILTIN_SAVEREGS ();
3424 #else
3425   /* ??? We used to try and build up a call to the out of line function,
3426      guessing about what registers needed saving etc.  This became much
3427      harder with __builtin_va_start, since we don't have a tree for a
3428      call to __builtin_saveregs to fall back on.  There was exactly one
3429      port (i860) that used this code, and I'm unconvinced it could actually
3430      handle the general case.  So we no longer try to handle anything
3431      weird and make the backend absorb the evil.  */
3432
3433   error ("__builtin_saveregs not supported by this target");
3434   val = const0_rtx;
3435 #endif
3436
3437   seq = get_insns ();
3438   end_sequence ();
3439
3440   saveregs_value = val;
3441
3442   /* Put the insns after the NOTE that starts the function.  If this
3443      is inside a start_sequence, make the outer-level insn chain current, so
3444      the code is placed at the start of the function.  */
3445   push_topmost_sequence ();
3446   emit_insn_after (seq, get_insns ());
3447   pop_topmost_sequence ();
3448
3449   return val;
3450 }
3451
3452 /* __builtin_args_info (N) returns word N of the arg space info
3453    for the current function.  The number and meanings of words
3454    is controlled by the definition of CUMULATIVE_ARGS.  */
3455
3456 static rtx
3457 expand_builtin_args_info (arglist)
3458      tree arglist;
3459 {
3460   int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
3461   int *word_ptr = (int *) &current_function_args_info;
3462
3463   if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
3464     abort ();
3465
3466   if (arglist != 0)
3467     {
3468       if (!host_integerp (TREE_VALUE (arglist), 0))
3469         error ("argument of `__builtin_args_info' must be constant");
3470       else
3471         {
3472           HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
3473
3474           if (wordnum < 0 || wordnum >= nwords)
3475             error ("argument of `__builtin_args_info' out of range");
3476           else
3477             return GEN_INT (word_ptr[wordnum]);
3478         }
3479     }
3480   else
3481     error ("missing argument in `__builtin_args_info'");
3482
3483   return const0_rtx;
3484 }
3485
3486 /* Expand ARGLIST, from a call to __builtin_next_arg.  */
3487
3488 static rtx
3489 expand_builtin_next_arg (arglist)
3490      tree arglist;
3491 {
3492   tree fntype = TREE_TYPE (current_function_decl);
3493
3494   if (TYPE_ARG_TYPES (fntype) == 0
3495       || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
3496           == void_type_node))
3497     {
3498       error ("`va_start' used in function with fixed args");
3499       return const0_rtx;
3500     }
3501
3502   if (arglist)
3503     {
3504       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
3505       tree arg = TREE_VALUE (arglist);
3506
3507       /* Strip off all nops for the sake of the comparison.  This
3508          is not quite the same as STRIP_NOPS.  It does more.
3509          We must also strip off INDIRECT_EXPR for C++ reference
3510          parameters.  */
3511       while (TREE_CODE (arg) == NOP_EXPR
3512              || TREE_CODE (arg) == CONVERT_EXPR
3513              || TREE_CODE (arg) == NON_LVALUE_EXPR
3514              || TREE_CODE (arg) == INDIRECT_REF)
3515         arg = TREE_OPERAND (arg, 0);
3516       if (arg != last_parm)
3517         warning ("second parameter of `va_start' not last named argument");
3518     }
3519   else
3520     /* Evidently an out of date version of <stdarg.h>; can't validate
3521        va_start's second argument, but can still work as intended.  */
3522     warning ("`__builtin_next_arg' called without an argument");
3523
3524   return expand_binop (Pmode, add_optab,
3525                        current_function_internal_arg_pointer,
3526                        current_function_arg_offset_rtx,
3527                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
3528 }
3529
3530 /* Make it easier for the backends by protecting the valist argument
3531    from multiple evaluations.  */
3532
3533 static tree
3534 stabilize_va_list (valist, needs_lvalue)
3535      tree valist;
3536      int needs_lvalue;
3537 {
3538   if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
3539     {
3540       if (TREE_SIDE_EFFECTS (valist))
3541         valist = save_expr (valist);
3542
3543       /* For this case, the backends will be expecting a pointer to
3544          TREE_TYPE (va_list_type_node), but it's possible we've
3545          actually been given an array (an actual va_list_type_node).
3546          So fix it.  */
3547       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
3548         {
3549           tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
3550           tree p2 = build_pointer_type (va_list_type_node);
3551
3552           valist = build1 (ADDR_EXPR, p2, valist);
3553           valist = fold (build1 (NOP_EXPR, p1, valist));
3554         }
3555     }
3556   else
3557     {
3558       tree pt;
3559
3560       if (! needs_lvalue)
3561         {
3562           if (! TREE_SIDE_EFFECTS (valist))
3563             return valist;
3564
3565           pt = build_pointer_type (va_list_type_node);
3566           valist = fold (build1 (ADDR_EXPR, pt, valist));
3567           TREE_SIDE_EFFECTS (valist) = 1;
3568         }
3569
3570       if (TREE_SIDE_EFFECTS (valist))
3571         valist = save_expr (valist);
3572       valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
3573                              valist));
3574     }
3575
3576   return valist;
3577 }
3578
3579 /* The "standard" implementation of va_start: just assign `nextarg' to
3580    the variable.  */
3581
3582 void
3583 std_expand_builtin_va_start (valist, nextarg)
3584      tree valist;
3585      rtx nextarg;
3586 {
3587   tree t;
3588
3589   t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
3590              make_tree (ptr_type_node, nextarg));
3591   TREE_SIDE_EFFECTS (t) = 1;
3592
3593   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3594 }
3595
3596 /* Expand ARGLIST, from a call to __builtin_va_start.  */
3597
3598 static rtx
3599 expand_builtin_va_start (arglist)
3600      tree arglist;
3601 {
3602   rtx nextarg;
3603   tree chain, valist;
3604
3605   chain = TREE_CHAIN (arglist);
3606
3607   if (TREE_CHAIN (chain))
3608     error ("too many arguments to function `va_start'");
3609
3610   nextarg = expand_builtin_next_arg (chain);
3611   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
3612
3613 #ifdef EXPAND_BUILTIN_VA_START
3614   EXPAND_BUILTIN_VA_START (valist, nextarg);
3615 #else
3616   std_expand_builtin_va_start (valist, nextarg);
3617 #endif
3618
3619   return const0_rtx;
3620 }
3621
3622 /* The "standard" implementation of va_arg: read the value from the
3623    current (padded) address and increment by the (padded) size.  */
3624
3625 rtx
3626 std_expand_builtin_va_arg (valist, type)
3627      tree valist, type;
3628 {
3629   tree addr_tree, t, type_size = NULL;
3630   tree align, alignm1;
3631   tree rounded_size;
3632   rtx addr;
3633
3634   /* Compute the rounded size of the type.  */
3635   align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
3636   alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
3637   if (type == error_mark_node
3638       || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
3639       || TREE_OVERFLOW (type_size))
3640     rounded_size = size_zero_node;
3641   else
3642     rounded_size = fold (build (MULT_EXPR, sizetype,
3643                                 fold (build (TRUNC_DIV_EXPR, sizetype,
3644                                              fold (build (PLUS_EXPR, sizetype,
3645                                                           type_size, alignm1)),
3646                                              align)),
3647                                 align));
3648
3649   /* Get AP.  */
3650   addr_tree = valist;
3651   if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size))
3652     {
3653       /* Small args are padded downward.  */
3654       addr_tree = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
3655                                fold (build (COND_EXPR, sizetype,
3656                                             fold (build (GT_EXPR, sizetype,
3657                                                          rounded_size,
3658                                                          align)),
3659                                             size_zero_node,
3660                                             fold (build (MINUS_EXPR, sizetype,
3661                                                          rounded_size,
3662                                                          type_size))))));
3663     }
3664
3665   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
3666   addr = copy_to_reg (addr);
3667
3668   /* Compute new value for AP.  */
3669   if (! integer_zerop (rounded_size))
3670     {
3671       t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
3672                  build (PLUS_EXPR, TREE_TYPE (valist), valist,
3673                         rounded_size));
3674       TREE_SIDE_EFFECTS (t) = 1;
3675       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3676     }
3677
3678   return addr;
3679 }
3680
3681 /* Expand __builtin_va_arg, which is not really a builtin function, but
3682    a very special sort of operator.  */
3683
3684 rtx
3685 expand_builtin_va_arg (valist, type)
3686      tree valist, type;
3687 {
3688   rtx addr, result;
3689   tree promoted_type, want_va_type, have_va_type;
3690
3691   /* Verify that valist is of the proper type.  */
3692
3693   want_va_type = va_list_type_node;
3694   have_va_type = TREE_TYPE (valist);
3695   if (TREE_CODE (want_va_type) == ARRAY_TYPE)
3696     {
3697       /* If va_list is an array type, the argument may have decayed
3698          to a pointer type, e.g. by being passed to another function.
3699          In that case, unwrap both types so that we can compare the
3700          underlying records.  */
3701       if (TREE_CODE (have_va_type) == ARRAY_TYPE
3702           || TREE_CODE (have_va_type) == POINTER_TYPE)
3703         {
3704           want_va_type = TREE_TYPE (want_va_type);
3705           have_va_type = TREE_TYPE (have_va_type);
3706         }
3707     }
3708   if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
3709     {
3710       error ("first argument to `va_arg' not of type `va_list'");
3711       addr = const0_rtx;
3712     }
3713
3714   /* Generate a diagnostic for requesting data of a type that cannot
3715      be passed through `...' due to type promotion at the call site.  */
3716   else if ((promoted_type = (*lang_hooks.types.type_promotes_to) (type))
3717            != type)
3718     {
3719       const char *name = "<anonymous type>", *pname = 0;
3720       static bool gave_help;
3721
3722       if (TYPE_NAME (type))
3723         {
3724           if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
3725             name = IDENTIFIER_POINTER (TYPE_NAME (type));
3726           else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
3727                    && DECL_NAME (TYPE_NAME (type)))
3728             name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
3729         }
3730       if (TYPE_NAME (promoted_type))
3731         {
3732           if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
3733             pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
3734           else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
3735                    && DECL_NAME (TYPE_NAME (promoted_type)))
3736             pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
3737         }
3738
3739       /* Unfortunately, this is merely undefined, rather than a constraint
3740          violation, so we cannot make this an error.  If this call is never
3741          executed, the program is still strictly conforming.  */
3742       warning ("`%s' is promoted to `%s' when passed through `...'",
3743                name, pname);
3744       if (! gave_help)
3745         {
3746           gave_help = true;
3747           warning ("(so you should pass `%s' not `%s' to `va_arg')",
3748                    pname, name);
3749         }
3750
3751       /* We can, however, treat "undefined" any way we please.
3752          Call abort to encourage the user to fix the program.  */
3753       expand_builtin_trap ();
3754
3755       /* This is dead code, but go ahead and finish so that the
3756          mode of the result comes out right.  */
3757       addr = const0_rtx;
3758     }
3759   else
3760     {
3761       /* Make it easier for the backends by protecting the valist argument
3762          from multiple evaluations.  */
3763       valist = stabilize_va_list (valist, 0);
3764
3765 #ifdef EXPAND_BUILTIN_VA_ARG
3766       addr = EXPAND_BUILTIN_VA_ARG (valist, type);
3767 #else
3768       addr = std_expand_builtin_va_arg (valist, type);
3769 #endif
3770     }
3771
3772 #ifdef POINTERS_EXTEND_UNSIGNED
3773   if (GET_MODE (addr) != Pmode)
3774     addr = convert_memory_address (Pmode, addr);
3775 #endif
3776
3777   result = gen_rtx_MEM (TYPE_MODE (type), addr);
3778   set_mem_alias_set (result, get_varargs_alias_set ());
3779
3780   return result;
3781 }
3782
3783 /* Expand ARGLIST, from a call to __builtin_va_end.  */
3784
3785 static rtx
3786 expand_builtin_va_end (arglist)
3787      tree arglist;
3788 {
3789   tree valist = TREE_VALUE (arglist);
3790
3791 #ifdef EXPAND_BUILTIN_VA_END
3792   valist = stabilize_va_list (valist, 0);
3793   EXPAND_BUILTIN_VA_END (arglist);
3794 #else
3795   /* Evaluate for side effects, if needed.  I hate macros that don't
3796      do that.  */
3797   if (TREE_SIDE_EFFECTS (valist))
3798     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
3799 #endif
3800
3801   return const0_rtx;
3802 }
3803
3804 /* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a
3805    builtin rather than just as an assignment in stdarg.h because of the
3806    nastiness of array-type va_list types.  */
3807
3808 static rtx
3809 expand_builtin_va_copy (arglist)
3810      tree arglist;
3811 {
3812   tree dst, src, t;
3813
3814   dst = TREE_VALUE (arglist);
3815   src = TREE_VALUE (TREE_CHAIN (arglist));
3816
3817   dst = stabilize_va_list (dst, 1);
3818   src = stabilize_va_list (src, 0);
3819
3820   if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
3821     {
3822       t = build (MODIFY_EXPR, va_list_type_node, dst, src);
3823       TREE_SIDE_EFFECTS (t) = 1;
3824       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3825     }
3826   else
3827     {
3828       rtx dstb, srcb, size;
3829
3830       /* Evaluate to pointers.  */
3831       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
3832       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
3833       size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
3834                           VOIDmode, EXPAND_NORMAL);
3835
3836 #ifdef POINTERS_EXTEND_UNSIGNED
3837       if (GET_MODE (dstb) != Pmode)
3838         dstb = convert_memory_address (Pmode, dstb);
3839
3840       if (GET_MODE (srcb) != Pmode)
3841         srcb = convert_memory_address (Pmode, srcb);
3842 #endif
3843
3844       /* "Dereference" to BLKmode memories.  */
3845       dstb = gen_rtx_MEM (BLKmode, dstb);
3846       set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
3847       set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
3848       srcb = gen_rtx_MEM (BLKmode, srcb);
3849       set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
3850       set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
3851
3852       /* Copy.  */
3853       emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
3854     }
3855
3856   return const0_rtx;
3857 }
3858
3859 /* Expand a call to one of the builtin functions __builtin_frame_address or
3860    __builtin_return_address.  */
3861
3862 static rtx
3863 expand_builtin_frame_address (fndecl, arglist)
3864      tree fndecl, arglist;
3865 {
3866   /* The argument must be a nonnegative integer constant.
3867      It counts the number of frames to scan up the stack.
3868      The value is the return address saved in that frame.  */
3869   if (arglist == 0)
3870     /* Warning about missing arg was already issued.  */
3871     return const0_rtx;
3872   else if (! host_integerp (TREE_VALUE (arglist), 1))
3873     {
3874       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3875         error ("invalid arg to `__builtin_frame_address'");
3876       else
3877         error ("invalid arg to `__builtin_return_address'");
3878       return const0_rtx;
3879     }
3880   else
3881     {
3882       rtx tem
3883         = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
3884                                       tree_low_cst (TREE_VALUE (arglist), 1),
3885                                       hard_frame_pointer_rtx);
3886
3887       /* Some ports cannot access arbitrary stack frames.  */
3888       if (tem == NULL)
3889         {
3890           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3891             warning ("unsupported arg to `__builtin_frame_address'");
3892           else
3893             warning ("unsupported arg to `__builtin_return_address'");
3894           return const0_rtx;
3895         }
3896
3897       /* For __builtin_frame_address, return what we've got.  */
3898       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3899         return tem;
3900
3901       if (GET_CODE (tem) != REG
3902           && ! CONSTANT_P (tem))
3903         tem = copy_to_mode_reg (Pmode, tem);
3904       return tem;
3905     }
3906 }
3907
3908 /* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
3909    we failed and the caller should emit a normal call, otherwise try to get
3910    the result in TARGET, if convenient.  */
3911
3912 static rtx
3913 expand_builtin_alloca (arglist, target)
3914      tree arglist;
3915      rtx target;
3916 {
3917   rtx op0;
3918   rtx result;
3919
3920   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3921     return 0;
3922
3923   /* Compute the argument.  */
3924   op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
3925
3926   /* Allocate the desired space.  */
3927   result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
3928
3929 #ifdef POINTERS_EXTEND_UNSIGNED
3930   if (GET_MODE (result) != ptr_mode)
3931     result = convert_memory_address (ptr_mode, result);
3932 #endif
3933
3934   return result;
3935 }
3936
3937 /* Expand a call to a unary builtin.  The arguments are in ARGLIST.
3938    Return 0 if a normal call should be emitted rather than expanding the
3939    function in-line.  If convenient, the result should be placed in TARGET.
3940    SUBTARGET may be used as the target for computing one of EXP's operands.  */
3941
3942 static rtx
3943 expand_builtin_unop (target_mode, arglist, target, subtarget, op_optab)
3944      enum machine_mode target_mode;
3945      tree arglist;
3946      rtx target, subtarget;
3947      optab op_optab;
3948 {
3949   rtx op0;
3950   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3951     return 0;
3952
3953   /* Compute the argument.  */
3954   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
3955   /* Compute op, into TARGET if possible.
3956      Set TARGET to wherever the result comes back.  */
3957   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
3958                         op_optab, op0, target, 1);
3959   if (target == 0)
3960     abort ();
3961
3962   return convert_to_mode (target_mode, target, 0);
3963 }
3964
3965 /* If the string passed to fputs is a constant and is one character
3966    long, we attempt to transform this call into __builtin_fputc().  */
3967
3968 static rtx
3969 expand_builtin_fputs (arglist, ignore, unlocked)
3970      tree arglist;
3971      int ignore;
3972      int unlocked;
3973 {
3974   tree len, fn;
3975   tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
3976     : implicit_built_in_decls[BUILT_IN_FPUTC];
3977   tree fn_fwrite = unlocked ? implicit_built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
3978     : implicit_built_in_decls[BUILT_IN_FWRITE];
3979
3980   /* If the return value is used, or the replacement _DECL isn't
3981      initialized, don't do the transformation.  */
3982   if (!ignore || !fn_fputc || !fn_fwrite)
3983     return 0;
3984
3985   /* Verify the arguments in the original call.  */
3986   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3987     return 0;
3988
3989   /* Get the length of the string passed to fputs.  If the length
3990      can't be determined, punt.  */
3991   if (!(len = c_strlen (TREE_VALUE (arglist)))
3992       || TREE_CODE (len) != INTEGER_CST)
3993     return 0;
3994
3995   switch (compare_tree_int (len, 1))
3996     {
3997     case -1: /* length is 0, delete the call entirely .  */
3998       {
3999         /* Evaluate and ignore the argument in case it has
4000            side-effects.  */
4001         expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
4002                      VOIDmode, EXPAND_NORMAL);
4003         return const0_rtx;
4004       }
4005     case 0: /* length is 1, call fputc.  */
4006       {
4007         const char *p = c_getstr (TREE_VALUE (arglist));
4008
4009         if (p != NULL)
4010           {
4011             /* New argument list transforming fputs(string, stream) to
4012                fputc(string[0], stream).  */
4013             arglist =
4014               build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
4015             arglist =
4016               tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
4017             fn = fn_fputc;
4018             break;
4019           }
4020       }
4021       /* FALLTHROUGH */
4022     case 1: /* length is greater than 1, call fwrite.  */
4023       {
4024         tree string_arg;
4025
4026         /* If optimizing for size keep fputs. */
4027         if (optimize_size)
4028           return 0;
4029         string_arg = TREE_VALUE (arglist);
4030         /* New argument list transforming fputs(string, stream) to
4031            fwrite(string, 1, len, stream).  */
4032         arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
4033         arglist = tree_cons (NULL_TREE, len, arglist);
4034         arglist = tree_cons (NULL_TREE, size_one_node, arglist);
4035         arglist = tree_cons (NULL_TREE, string_arg, arglist);
4036         fn = fn_fwrite;
4037         break;
4038       }
4039     default:
4040       abort ();
4041     }
4042
4043   return expand_expr (build_function_call_expr (fn, arglist),
4044                       (ignore ? const0_rtx : NULL_RTX),
4045                       VOIDmode, EXPAND_NORMAL);
4046 }
4047
4048 /* Expand a call to __builtin_expect.  We return our argument and emit a
4049    NOTE_INSN_EXPECTED_VALUE note.  This is the expansion of __builtin_expect in
4050    a non-jump context.  */
4051
4052 static rtx
4053 expand_builtin_expect (arglist, target)
4054      tree arglist;
4055      rtx target;
4056 {
4057   tree exp, c;
4058   rtx note, rtx_c;
4059
4060   if (arglist == NULL_TREE
4061       || TREE_CHAIN (arglist) == NULL_TREE)
4062     return const0_rtx;
4063   exp = TREE_VALUE (arglist);
4064   c = TREE_VALUE (TREE_CHAIN (arglist));
4065
4066   if (TREE_CODE (c) != INTEGER_CST)
4067     {
4068       error ("second arg to `__builtin_expect' must be a constant");
4069       c = integer_zero_node;
4070     }
4071
4072   target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
4073
4074   /* Don't bother with expected value notes for integral constants.  */
4075   if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
4076     {
4077       /* We do need to force this into a register so that we can be
4078          moderately sure to be able to correctly interpret the branch
4079          condition later.  */
4080       target = force_reg (GET_MODE (target), target);
4081
4082       rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
4083
4084       note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
4085       NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
4086     }
4087
4088   return target;
4089 }
4090
4091 /* Like expand_builtin_expect, except do this in a jump context.  This is
4092    called from do_jump if the conditional is a __builtin_expect.  Return either
4093    a list of insns to emit the jump or NULL if we cannot optimize
4094    __builtin_expect.  We need to optimize this at jump time so that machines
4095    like the PowerPC don't turn the test into a SCC operation, and then jump
4096    based on the test being 0/1.  */
4097
4098 rtx
4099 expand_builtin_expect_jump (exp, if_false_label, if_true_label)
4100      tree exp;
4101      rtx if_false_label;
4102      rtx if_true_label;
4103 {
4104   tree arglist = TREE_OPERAND (exp, 1);
4105   tree arg0 = TREE_VALUE (arglist);
4106   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4107   rtx ret = NULL_RTX;
4108
4109   /* Only handle __builtin_expect (test, 0) and
4110      __builtin_expect (test, 1).  */
4111   if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
4112       && (integer_zerop (arg1) || integer_onep (arg1)))
4113     {
4114       int num_jumps = 0;
4115       rtx insn;
4116
4117       /* If we fail to locate an appropriate conditional jump, we'll
4118          fall back to normal evaluation.  Ensure that the expression
4119          can be re-evaluated.  */
4120       switch (unsafe_for_reeval (arg0))
4121         {
4122         case 0: /* Safe.  */
4123           break;
4124
4125         case 1: /* Mildly unsafe.  */
4126           arg0 = unsave_expr (arg0);
4127           break;
4128
4129         case 2: /* Wildly unsafe.  */
4130           return NULL_RTX;
4131         }
4132
4133       /* Expand the jump insns.  */
4134       start_sequence ();
4135       do_jump (arg0, if_false_label, if_true_label);
4136       ret = get_insns ();
4137       end_sequence ();
4138
4139       /* Now that the __builtin_expect has been validated, go through and add
4140          the expect's to each of the conditional jumps.  If we run into an
4141          error, just give up and generate the 'safe' code of doing a SCC
4142          operation and then doing a branch on that.  */
4143       insn = ret;
4144       while (insn != NULL_RTX)
4145         {
4146           rtx next = NEXT_INSN (insn);
4147           rtx pattern;
4148
4149           if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn)
4150               && (pattern = pc_set (insn)) != NULL_RTX)
4151             {
4152               rtx ifelse = SET_SRC (pattern);
4153               rtx label;
4154               int taken;
4155
4156               if (GET_CODE (ifelse) != IF_THEN_ELSE)
4157                 goto do_next_insn;
4158
4159               if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF)
4160                 {
4161                   taken = 1;
4162                   label = XEXP (XEXP (ifelse, 1), 0);
4163                 }
4164               /* An inverted jump reverses the probabilities.  */
4165               else if (GET_CODE (XEXP (ifelse, 2)) == LABEL_REF)
4166                 {
4167                   taken = 0;
4168                   label = XEXP (XEXP (ifelse, 2), 0);
4169                 }
4170               /* We shouldn't have to worry about conditional returns during
4171                  the expansion stage, but handle it gracefully anyway.  */
4172               else if (GET_CODE (XEXP (ifelse, 1)) == RETURN)
4173                 {
4174                   taken = 1;
4175                   label = NULL_RTX;
4176                 }
4177               /* An inverted return reverses the probabilities.  */
4178               else if (GET_CODE (XEXP (ifelse, 2)) == RETURN)
4179                 {
4180                   taken = 0;
4181                   label = NULL_RTX;
4182                 }
4183               else
4184                 goto do_next_insn;
4185
4186               /* If the test is expected to fail, reverse the
4187                  probabilities.  */
4188               if (integer_zerop (arg1))
4189                 taken = 1 - taken;
4190
4191               /* If we are jumping to the false label, reverse the
4192                  probabilities.  */
4193               if (label == NULL_RTX)
4194                 ;               /* conditional return */
4195               else if (label == if_false_label)
4196                 taken = 1 - taken;
4197               else if (label != if_true_label)
4198                 goto do_next_insn;
4199
4200               num_jumps++;
4201               predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
4202             }
4203
4204         do_next_insn:
4205           insn = next;
4206         }
4207
4208       /* If no jumps were modified, fail and do __builtin_expect the normal
4209          way.  */
4210       if (num_jumps == 0)
4211         ret = NULL_RTX;
4212     }
4213
4214   return ret;
4215 }
4216
4217 void
4218 expand_builtin_trap ()
4219 {
4220 #ifdef HAVE_trap
4221   if (HAVE_trap)
4222     emit_insn (gen_trap ());
4223   else
4224 #endif
4225     emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
4226   emit_barrier ();
4227 }
4228 \f
4229 /* Expand an expression EXP that calls a built-in function,
4230    with result going to TARGET if that's convenient
4231    (and in mode MODE if that's convenient).
4232    SUBTARGET may be used as the target for computing one of EXP's operands.
4233    IGNORE is nonzero if the value is to be ignored.  */
4234
4235 rtx
4236 expand_builtin (exp, target, subtarget, mode, ignore)
4237      tree exp;
4238      rtx target;
4239      rtx subtarget;
4240      enum machine_mode mode;
4241      int ignore;
4242 {
4243   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4244   tree arglist = TREE_OPERAND (exp, 1);
4245   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
4246   enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
4247
4248   /* Perform postincrements before expanding builtin functions. Â */
4249   emit_queue ();
4250
4251   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
4252     return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore);
4253
4254   /* When not optimizing, generate calls to library functions for a certain
4255      set of builtins.  */
4256   if (!optimize && !CALLED_AS_BUILT_IN (fndecl))
4257     switch (fcode)
4258       {
4259       case BUILT_IN_SQRT:
4260       case BUILT_IN_SQRTF:
4261       case BUILT_IN_SQRTL:
4262       case BUILT_IN_SIN:
4263       case BUILT_IN_SINF:
4264       case BUILT_IN_SINL:
4265       case BUILT_IN_COS:
4266       case BUILT_IN_COSF:
4267       case BUILT_IN_COSL:
4268       case BUILT_IN_EXP:
4269       case BUILT_IN_EXPF:
4270       case BUILT_IN_EXPL:
4271       case BUILT_IN_LOG:
4272       case BUILT_IN_LOGF:
4273       case BUILT_IN_LOGL:
4274       case BUILT_IN_POW:
4275       case BUILT_IN_POWF:
4276       case BUILT_IN_POWL:
4277       case BUILT_IN_ATAN2:
4278       case BUILT_IN_ATAN2F:
4279       case BUILT_IN_ATAN2L:
4280       case BUILT_IN_MEMSET:
4281       case BUILT_IN_MEMCPY:
4282       case BUILT_IN_MEMCMP:
4283       case BUILT_IN_MEMPCPY:
4284       case BUILT_IN_MEMMOVE:
4285       case BUILT_IN_BCMP:
4286       case BUILT_IN_BZERO:
4287       case BUILT_IN_BCOPY:
4288       case BUILT_IN_INDEX:
4289       case BUILT_IN_RINDEX:
4290       case BUILT_IN_STPCPY:
4291       case BUILT_IN_STRCHR:
4292       case BUILT_IN_STRRCHR:
4293       case BUILT_IN_STRLEN:
4294       case BUILT_IN_STRCPY:
4295       case BUILT_IN_STRNCPY:
4296       case BUILT_IN_STRNCMP:
4297       case BUILT_IN_STRSTR:
4298       case BUILT_IN_STRPBRK:
4299       case BUILT_IN_STRCAT:
4300       case BUILT_IN_STRNCAT:
4301       case BUILT_IN_STRSPN:
4302       case BUILT_IN_STRCSPN:
4303       case BUILT_IN_STRCMP:
4304       case BUILT_IN_FFS:
4305       case BUILT_IN_PUTCHAR:
4306       case BUILT_IN_PUTS:
4307       case BUILT_IN_PRINTF:
4308       case BUILT_IN_FPUTC:
4309       case BUILT_IN_FPUTS:
4310       case BUILT_IN_FWRITE:
4311       case BUILT_IN_PUTCHAR_UNLOCKED:
4312       case BUILT_IN_PUTS_UNLOCKED:
4313       case BUILT_IN_PRINTF_UNLOCKED:
4314       case BUILT_IN_FPUTC_UNLOCKED:
4315       case BUILT_IN_FPUTS_UNLOCKED:
4316       case BUILT_IN_FWRITE_UNLOCKED:
4317       case BUILT_IN_FLOOR:
4318       case BUILT_IN_FLOORF:
4319       case BUILT_IN_FLOORL:
4320       case BUILT_IN_CEIL:
4321       case BUILT_IN_CEILF:
4322       case BUILT_IN_CEILL:
4323       case BUILT_IN_TRUNC:
4324       case BUILT_IN_TRUNCF:
4325       case BUILT_IN_TRUNCL:
4326       case BUILT_IN_ROUND:
4327       case BUILT_IN_ROUNDF:
4328       case BUILT_IN_ROUNDL:
4329       case BUILT_IN_NEARBYINT:
4330       case BUILT_IN_NEARBYINTF:
4331       case BUILT_IN_NEARBYINTL:
4332         return expand_call (exp, target, ignore);
4333
4334       default:
4335         break;
4336       }
4337
4338   /* The built-in function expanders test for target == const0_rtx
4339      to determine whether the function's result will be ignored.  */
4340   if (ignore)
4341     target = const0_rtx;
4342
4343   /* If the result of a pure or const built-in function is ignored, and
4344      none of its arguments are volatile, we can avoid expanding the
4345      built-in call and just evaluate the arguments for side-effects.  */
4346   if (target == const0_rtx
4347       && (DECL_IS_PURE (fndecl) || TREE_READONLY (fndecl)))
4348     {
4349       bool volatilep = false;
4350       tree arg;
4351
4352       for (arg = arglist; arg; arg = TREE_CHAIN (arg))
4353         if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
4354           {
4355             volatilep = true;
4356             break;
4357           }
4358
4359       if (! volatilep)
4360         {
4361           for (arg = arglist; arg; arg = TREE_CHAIN (arg))
4362             expand_expr (TREE_VALUE (arg), const0_rtx,
4363                          VOIDmode, EXPAND_NORMAL);
4364           return const0_rtx;
4365         }
4366     }
4367
4368   switch (fcode)
4369     {
4370     case BUILT_IN_ABS:
4371     case BUILT_IN_LABS:
4372     case BUILT_IN_LLABS:
4373     case BUILT_IN_IMAXABS:
4374     case BUILT_IN_FABS:
4375     case BUILT_IN_FABSF:
4376     case BUILT_IN_FABSL:
4377       /* build_function_call changes these into ABS_EXPR.  */
4378       abort ();
4379
4380     case BUILT_IN_CONJ:
4381     case BUILT_IN_CONJF:
4382     case BUILT_IN_CONJL:
4383     case BUILT_IN_CREAL:
4384     case BUILT_IN_CREALF:
4385     case BUILT_IN_CREALL:
4386     case BUILT_IN_CIMAG:
4387     case BUILT_IN_CIMAGF:
4388     case BUILT_IN_CIMAGL:
4389       /* expand_tree_builtin changes these into CONJ_EXPR, REALPART_EXPR
4390          and IMAGPART_EXPR.  */
4391       abort ();
4392
4393     case BUILT_IN_SIN:
4394     case BUILT_IN_SINF:
4395     case BUILT_IN_SINL:
4396     case BUILT_IN_COS:
4397     case BUILT_IN_COSF:
4398     case BUILT_IN_COSL:
4399     case BUILT_IN_EXP:
4400     case BUILT_IN_EXPF:
4401     case BUILT_IN_EXPL:
4402     case BUILT_IN_LOG:
4403     case BUILT_IN_LOGF:
4404     case BUILT_IN_LOGL:
4405       /* Treat these like sqrt only if unsafe math optimizations are allowed,
4406          because of possible accuracy problems.  */
4407       if (! flag_unsafe_math_optimizations)
4408         break;
4409     case BUILT_IN_SQRT:
4410     case BUILT_IN_SQRTF:
4411     case BUILT_IN_SQRTL:
4412     case BUILT_IN_FLOOR:
4413     case BUILT_IN_FLOORF:
4414     case BUILT_IN_FLOORL:
4415     case BUILT_IN_CEIL:
4416     case BUILT_IN_CEILF:
4417     case BUILT_IN_CEILL:
4418     case BUILT_IN_TRUNC:
4419     case BUILT_IN_TRUNCF:
4420     case BUILT_IN_TRUNCL:
4421     case BUILT_IN_ROUND:
4422     case BUILT_IN_ROUNDF:
4423     case BUILT_IN_ROUNDL:
4424     case BUILT_IN_NEARBYINT:
4425     case BUILT_IN_NEARBYINTF:
4426     case BUILT_IN_NEARBYINTL:
4427       target = expand_builtin_mathfn (exp, target, subtarget);
4428       if (target)
4429         return target;
4430       break;
4431
4432     case BUILT_IN_POW:
4433     case BUILT_IN_POWF:
4434     case BUILT_IN_POWL:
4435     case BUILT_IN_ATAN2:
4436     case BUILT_IN_ATAN2F:
4437     case BUILT_IN_ATAN2L:
4438       if (! flag_unsafe_math_optimizations)
4439         break;
4440       target = expand_builtin_mathfn_2 (exp, target, subtarget);
4441       if (target)
4442         return target;
4443       break;
4444
4445     case BUILT_IN_APPLY_ARGS:
4446       return expand_builtin_apply_args ();
4447
4448       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
4449          FUNCTION with a copy of the parameters described by
4450          ARGUMENTS, and ARGSIZE.  It returns a block of memory
4451          allocated on the stack into which is stored all the registers
4452          that might possibly be used for returning the result of a
4453          function.  ARGUMENTS is the value returned by
4454          __builtin_apply_args.  ARGSIZE is the number of bytes of
4455          arguments that must be copied.  ??? How should this value be
4456          computed?  We'll also need a safe worst case value for varargs
4457          functions.  */
4458     case BUILT_IN_APPLY:
4459       if (!validate_arglist (arglist, POINTER_TYPE,
4460                              POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
4461           && !validate_arglist (arglist, REFERENCE_TYPE,
4462                                 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4463         return const0_rtx;
4464       else
4465         {
4466           int i;
4467           tree t;
4468           rtx ops[3];
4469
4470           for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
4471             ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
4472
4473           return expand_builtin_apply (ops[0], ops[1], ops[2]);
4474         }
4475
4476       /* __builtin_return (RESULT) causes the function to return the
4477          value described by RESULT.  RESULT is address of the block of
4478          memory returned by __builtin_apply.  */
4479     case BUILT_IN_RETURN:
4480       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
4481         expand_builtin_return (expand_expr (TREE_VALUE (arglist),
4482                                             NULL_RTX, VOIDmode, 0));
4483       return const0_rtx;
4484
4485     case BUILT_IN_SAVEREGS:
4486       return expand_builtin_saveregs ();
4487
4488     case BUILT_IN_ARGS_INFO:
4489       return expand_builtin_args_info (arglist);
4490
4491       /* Return the address of the first anonymous stack arg.  */
4492     case BUILT_IN_NEXT_ARG:
4493       return expand_builtin_next_arg (arglist);
4494
4495     case BUILT_IN_CLASSIFY_TYPE:
4496       return expand_builtin_classify_type (arglist);
4497
4498     case BUILT_IN_CONSTANT_P:
4499       return expand_builtin_constant_p (arglist, target_mode);
4500
4501     case BUILT_IN_FRAME_ADDRESS:
4502     case BUILT_IN_RETURN_ADDRESS:
4503       return expand_builtin_frame_address (fndecl, arglist);
4504
4505     /* Returns the address of the area where the structure is returned.
4506        0 otherwise.  */
4507     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
4508       if (arglist != 0
4509           || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
4510           || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
4511         return const0_rtx;
4512       else
4513         return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
4514
4515     case BUILT_IN_ALLOCA:
4516       target = expand_builtin_alloca (arglist, target);
4517       if (target)
4518         return target;
4519       break;
4520
4521     case BUILT_IN_FFS:
4522     case BUILT_IN_FFSL:
4523     case BUILT_IN_FFSLL:
4524       target = expand_builtin_unop (target_mode, arglist, target,
4525                                     subtarget, ffs_optab);
4526       if (target)
4527         return target;
4528       break;
4529
4530     case BUILT_IN_CLZ:
4531     case BUILT_IN_CLZL:
4532     case BUILT_IN_CLZLL:
4533       target = expand_builtin_unop (target_mode, arglist, target,
4534                                     subtarget, clz_optab);
4535       if (target)
4536         return target;
4537       break;
4538
4539     case BUILT_IN_CTZ:
4540     case BUILT_IN_CTZL:
4541     case BUILT_IN_CTZLL:
4542       target = expand_builtin_unop (target_mode, arglist, target,
4543                                     subtarget, ctz_optab);
4544       if (target)
4545         return target;
4546       break;
4547
4548     case BUILT_IN_POPCOUNT:
4549     case BUILT_IN_POPCOUNTL:
4550     case BUILT_IN_POPCOUNTLL:
4551       target = expand_builtin_unop (target_mode, arglist, target,
4552                                     subtarget, popcount_optab);
4553       if (target)
4554         return target;
4555       break;
4556
4557     case BUILT_IN_PARITY:
4558     case BUILT_IN_PARITYL:
4559     case BUILT_IN_PARITYLL:
4560       target = expand_builtin_unop (target_mode, arglist, target,
4561                                     subtarget, parity_optab);
4562       if (target)
4563         return target;
4564       break;
4565
4566     case BUILT_IN_STRLEN:
4567       target = expand_builtin_strlen (arglist, target, target_mode);
4568       if (target)
4569         return target;
4570       break;
4571
4572     case BUILT_IN_STRCPY:
4573       target = expand_builtin_strcpy (arglist, target, mode);
4574       if (target)
4575         return target;
4576       break;
4577
4578     case BUILT_IN_STRNCPY:
4579       target = expand_builtin_strncpy (arglist, target, mode);
4580       if (target)
4581         return target;
4582       break;
4583
4584     case BUILT_IN_STPCPY:
4585       target = expand_builtin_stpcpy (arglist, target, mode);
4586       if (target)
4587         return target;
4588       break;
4589
4590     case BUILT_IN_STRCAT:
4591       target = expand_builtin_strcat (arglist, target, mode);
4592       if (target)
4593         return target;
4594       break;
4595
4596     case BUILT_IN_STRNCAT:
4597       target = expand_builtin_strncat (arglist, target, mode);
4598       if (target)
4599         return target;
4600       break;
4601
4602     case BUILT_IN_STRSPN:
4603       target = expand_builtin_strspn (arglist, target, mode);
4604       if (target)
4605         return target;
4606       break;
4607
4608     case BUILT_IN_STRCSPN:
4609       target = expand_builtin_strcspn (arglist, target, mode);
4610       if (target)
4611         return target;
4612       break;
4613
4614     case BUILT_IN_STRSTR:
4615       target = expand_builtin_strstr (arglist, target, mode);
4616       if (target)
4617         return target;
4618       break;
4619
4620     case BUILT_IN_STRPBRK:
4621       target = expand_builtin_strpbrk (arglist, target, mode);
4622       if (target)
4623         return target;
4624       break;
4625
4626     case BUILT_IN_INDEX:
4627     case BUILT_IN_STRCHR:
4628       target = expand_builtin_strchr (arglist, target, mode);
4629       if (target)
4630         return target;
4631       break;
4632
4633     case BUILT_IN_RINDEX:
4634     case BUILT_IN_STRRCHR:
4635       target = expand_builtin_strrchr (arglist, target, mode);
4636       if (target)
4637         return target;
4638       break;
4639
4640     case BUILT_IN_MEMCPY:
4641       target = expand_builtin_memcpy (arglist, target, mode, /*endp=*/0);
4642       if (target)
4643         return target;
4644       break;
4645
4646     case BUILT_IN_MEMPCPY:
4647       target = expand_builtin_mempcpy (arglist, target, mode);
4648       if (target)
4649         return target;
4650       break;
4651
4652     case BUILT_IN_MEMMOVE:
4653       target = expand_builtin_memmove (arglist, target, mode);
4654       if (target)
4655         return target;
4656       break;
4657
4658     case BUILT_IN_BCOPY:
4659       target = expand_builtin_bcopy (arglist);
4660       if (target)
4661         return target;
4662       break;
4663
4664     case BUILT_IN_MEMSET:
4665       target = expand_builtin_memset (arglist, target, mode);
4666       if (target)
4667         return target;
4668       break;
4669
4670     case BUILT_IN_BZERO:
4671       target = expand_builtin_bzero (arglist);
4672       if (target)
4673         return target;
4674       break;
4675
4676     case BUILT_IN_STRCMP:
4677       target = expand_builtin_strcmp (exp, target, mode);
4678       if (target)
4679         return target;
4680       break;
4681
4682     case BUILT_IN_STRNCMP:
4683       target = expand_builtin_strncmp (exp, target, mode);
4684       if (target)
4685         return target;
4686       break;
4687
4688     case BUILT_IN_BCMP:
4689     case BUILT_IN_MEMCMP:
4690       target = expand_builtin_memcmp (exp, arglist, target, mode);
4691       if (target)
4692         return target;
4693       break;
4694
4695     case BUILT_IN_SETJMP:
4696       target = expand_builtin_setjmp (arglist, target);
4697       if (target)
4698         return target;
4699       break;
4700
4701       /* __builtin_longjmp is passed a pointer to an array of five words.
4702          It's similar to the C library longjmp function but works with
4703          __builtin_setjmp above.  */
4704     case BUILT_IN_LONGJMP:
4705       if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
4706         break;
4707       else
4708         {
4709           rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
4710                                       VOIDmode, 0);
4711           rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
4712                                    NULL_RTX, VOIDmode, 0);
4713
4714           if (value != const1_rtx)
4715             {
4716               error ("__builtin_longjmp second argument must be 1");
4717               return const0_rtx;
4718             }
4719
4720           expand_builtin_longjmp (buf_addr, value);
4721           return const0_rtx;
4722         }
4723
4724     case BUILT_IN_TRAP:
4725       expand_builtin_trap ();
4726       return const0_rtx;
4727
4728     case BUILT_IN_FPUTS:
4729       target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 0);
4730       if (target)
4731         return target;
4732       break;
4733     case BUILT_IN_FPUTS_UNLOCKED:
4734       target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 1);
4735       if (target)
4736         return target;
4737       break;
4738
4739       /* Various hooks for the DWARF 2 __throw routine.  */
4740     case BUILT_IN_UNWIND_INIT:
4741       expand_builtin_unwind_init ();
4742       return const0_rtx;
4743     case BUILT_IN_DWARF_CFA:
4744       return virtual_cfa_rtx;
4745 #ifdef DWARF2_UNWIND_INFO
4746     case BUILT_IN_DWARF_SP_COLUMN:
4747       return expand_builtin_dwarf_sp_column ();
4748     case BUILT_IN_INIT_DWARF_REG_SIZES:
4749       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
4750       return const0_rtx;
4751 #endif
4752     case BUILT_IN_FROB_RETURN_ADDR:
4753       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
4754     case BUILT_IN_EXTRACT_RETURN_ADDR:
4755       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
4756     case BUILT_IN_EH_RETURN:
4757       expand_builtin_eh_return (TREE_VALUE (arglist),
4758                                 TREE_VALUE (TREE_CHAIN (arglist)));
4759       return const0_rtx;
4760 #ifdef EH_RETURN_DATA_REGNO
4761     case BUILT_IN_EH_RETURN_DATA_REGNO:
4762       return expand_builtin_eh_return_data_regno (arglist);
4763 #endif
4764     case BUILT_IN_VA_START:
4765     case BUILT_IN_STDARG_START:
4766       return expand_builtin_va_start (arglist);
4767     case BUILT_IN_VA_END:
4768       return expand_builtin_va_end (arglist);
4769     case BUILT_IN_VA_COPY:
4770       return expand_builtin_va_copy (arglist);
4771     case BUILT_IN_EXPECT:
4772       return expand_builtin_expect (arglist, target);
4773     case BUILT_IN_PREFETCH:
4774       expand_builtin_prefetch (arglist);
4775       return const0_rtx;
4776
4777
4778     default:    /* just do library call, if unknown builtin */
4779       if (!DECL_ASSEMBLER_NAME_SET_P (fndecl))
4780         error ("built-in function `%s' not currently supported",
4781                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
4782     }
4783
4784   /* The switch statement above can drop through to cause the function
4785      to be called normally.  */
4786   return expand_call (exp, target, ignore);
4787 }
4788
4789 /* Determine whether a tree node represents a call to a built-in
4790    math function.  If the tree T is a call to a built-in function
4791    taking a single real argument, then the return value is the
4792    DECL_FUNCTION_CODE of the call, e.g. BUILT_IN_SQRT.  Otherwise
4793    the return value is END_BUILTINS.  */
4794    
4795 enum built_in_function
4796 builtin_mathfn_code (t)
4797      tree t;
4798 {
4799   tree fndecl, arglist;
4800
4801   if (TREE_CODE (t) != CALL_EXPR
4802       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
4803     return END_BUILTINS;
4804
4805   fndecl = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
4806   if (TREE_CODE (fndecl) != FUNCTION_DECL
4807       || ! DECL_BUILT_IN (fndecl)
4808       || DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
4809     return END_BUILTINS;
4810
4811   arglist = TREE_OPERAND (t, 1);
4812   if (! arglist
4813       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
4814     return END_BUILTINS;
4815
4816   arglist = TREE_CHAIN (arglist);
4817   switch (DECL_FUNCTION_CODE (fndecl))
4818     {
4819     case BUILT_IN_POW:
4820     case BUILT_IN_POWF:
4821     case BUILT_IN_POWL:
4822     case BUILT_IN_ATAN2:
4823     case BUILT_IN_ATAN2F:
4824     case BUILT_IN_ATAN2L:
4825       if (! arglist
4826           || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE
4827           || TREE_CHAIN (arglist))
4828         return END_BUILTINS;
4829       break;
4830
4831     default:
4832       if (arglist)
4833         return END_BUILTINS;
4834       break;
4835     }
4836
4837   return DECL_FUNCTION_CODE (fndecl);
4838 }
4839
4840 /* Fold a call to __builtin_constant_p, if we know it will evaluate to a
4841    constant.  ARGLIST is the argument list of the call.  */
4842
4843 static tree
4844 fold_builtin_constant_p (arglist)
4845      tree arglist;
4846 {
4847   if (arglist == 0)
4848     return 0;
4849
4850   arglist = TREE_VALUE (arglist);
4851
4852   /* We return 1 for a numeric type that's known to be a constant
4853      value at compile-time or for an aggregate type that's a
4854      literal constant.  */
4855   STRIP_NOPS (arglist);
4856
4857   /* If we know this is a constant, emit the constant of one.  */
4858   if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
4859       || (TREE_CODE (arglist) == CONSTRUCTOR
4860           && TREE_CONSTANT (arglist))
4861       || (TREE_CODE (arglist) == ADDR_EXPR
4862           && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
4863     return integer_one_node;
4864
4865   /* If we aren't going to be running CSE or this expression
4866      has side effects, show we don't know it to be a constant.
4867      Likewise if it's a pointer or aggregate type since in those
4868      case we only want literals, since those are only optimized
4869      when generating RTL, not later.
4870      And finally, if we are compiling an initializer, not code, we
4871      need to return a definite result now; there's not going to be any
4872      more optimization done.  */
4873   if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected
4874       || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
4875       || POINTER_TYPE_P (TREE_TYPE (arglist))
4876       || cfun == 0)
4877     return integer_zero_node;
4878
4879   return 0;
4880 }
4881
4882 /* Fold a call to __builtin_classify_type.  */
4883
4884 static tree
4885 fold_builtin_classify_type (arglist)
4886      tree arglist;
4887 {
4888   if (arglist == 0)
4889     return build_int_2 (no_type_class, 0);
4890
4891   return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
4892 }
4893
4894 /* Fold a call to __builtin_inf or __builtin_huge_val.  */
4895
4896 static tree
4897 fold_builtin_inf (type, warn)
4898      tree type;
4899      int warn;
4900 {
4901   REAL_VALUE_TYPE real;
4902
4903   if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
4904     warning ("target format does not support infinity");
4905
4906   real_inf (&real);
4907   return build_real (type, real);
4908 }
4909
4910 /* Fold a call to __builtin_nan or __builtin_nans.  */
4911
4912 static tree
4913 fold_builtin_nan (arglist, type, quiet)
4914      tree arglist, type;
4915      int quiet;
4916 {
4917   REAL_VALUE_TYPE real;
4918   const char *str;
4919
4920   if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
4921     return 0;
4922   str = c_getstr (TREE_VALUE (arglist));
4923   if (!str)
4924     return 0;
4925
4926   if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
4927     return 0;
4928
4929   return build_real (type, real);
4930 }
4931
4932 /* EXP is assumed to me builtin call where truncation can be propagated
4933    across (for instance floor((double)f) == (double)floorf (f).
4934    Do the transformation.  */
4935 static tree
4936 fold_trunc_transparent_mathfn (exp)
4937      tree exp;
4938 {
4939   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4940   tree arglist = TREE_OPERAND (exp, 1);
4941   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
4942
4943   if (optimize && validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
4944     {
4945       tree arg0 = strip_float_extensions (TREE_VALUE (arglist));
4946       tree ftype = TREE_TYPE (exp);
4947       tree newtype = TREE_TYPE (arg0);
4948       tree decl;
4949
4950       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
4951           && (decl = mathfn_built_in (newtype, fcode)))
4952         {
4953           arglist =
4954             build_tree_list (NULL_TREE, fold (convert (newtype, arg0)));
4955           return convert (ftype,
4956                           build_function_call_expr (decl, arglist));
4957         }
4958     }
4959   return 0;
4960 }
4961
4962 /* Used by constant folding to eliminate some builtin calls early.  EXP is
4963    the CALL_EXPR of a call to a builtin function.  */
4964
4965 tree
4966 fold_builtin (exp)
4967      tree exp;
4968 {
4969   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4970   tree arglist = TREE_OPERAND (exp, 1);
4971   tree type = TREE_TYPE (TREE_TYPE (fndecl));
4972
4973   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
4974     return 0;
4975
4976   switch (DECL_FUNCTION_CODE (fndecl))
4977     {
4978     case BUILT_IN_CONSTANT_P:
4979       return fold_builtin_constant_p (arglist);
4980
4981     case BUILT_IN_CLASSIFY_TYPE:
4982       return fold_builtin_classify_type (arglist);
4983
4984     case BUILT_IN_STRLEN:
4985       if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
4986         {
4987           tree len = c_strlen (TREE_VALUE (arglist));
4988           if (len)
4989             {
4990               /* Convert from the internal "sizetype" type to "size_t".  */
4991               if (size_type_node)
4992                 len = convert (size_type_node, len);
4993               return len;
4994             }
4995         }
4996       break;
4997
4998     case BUILT_IN_SQRT:
4999     case BUILT_IN_SQRTF:
5000     case BUILT_IN_SQRTL:
5001       if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5002         {
5003           enum built_in_function fcode;
5004           tree arg = TREE_VALUE (arglist);
5005
5006           /* Optimize sqrt of constant value.  */
5007           if (TREE_CODE (arg) == REAL_CST
5008               && ! TREE_CONSTANT_OVERFLOW (arg))
5009             {
5010               enum machine_mode mode;
5011               REAL_VALUE_TYPE r, x;
5012
5013               x = TREE_REAL_CST (arg);
5014               mode = TYPE_MODE (type);
5015               if (real_sqrt (&r, mode, &x)
5016                   || (!flag_trapping_math && !flag_errno_math))
5017                 return build_real (type, r);
5018             }
5019
5020           /* Optimize sqrt(exp(x)) = exp(x*0.5).  */
5021           fcode = builtin_mathfn_code (arg);
5022           if (flag_unsafe_math_optimizations
5023               && (fcode == BUILT_IN_EXP
5024                   || fcode == BUILT_IN_EXPF
5025                   || fcode == BUILT_IN_EXPL))
5026             {
5027               tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
5028               arg = fold (build (MULT_EXPR, type,
5029                                  TREE_VALUE (TREE_OPERAND (arg, 1)),
5030                                  build_real (type, dconsthalf)));
5031               arglist = build_tree_list (NULL_TREE, arg);
5032               return build_function_call_expr (expfn, arglist);
5033             }
5034
5035           /* Optimize sqrt(pow(x,y)) = pow(x,y*0.5).  */
5036           if (flag_unsafe_math_optimizations
5037               && (fcode == BUILT_IN_POW
5038                   || fcode == BUILT_IN_POWF
5039                   || fcode == BUILT_IN_POWL))
5040             {
5041               tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
5042               tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
5043               tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
5044               tree narg1 = fold (build (MULT_EXPR, type, arg1,
5045                                         build_real (type, dconsthalf)));
5046               arglist = tree_cons (NULL_TREE, arg0,
5047                                    build_tree_list (NULL_TREE, narg1));
5048               return build_function_call_expr (powfn, arglist);
5049             }
5050         }
5051       break;
5052
5053     case BUILT_IN_SIN:
5054     case BUILT_IN_SINF:
5055     case BUILT_IN_SINL:
5056       if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5057         {
5058           tree arg = TREE_VALUE (arglist);
5059
5060           /* Optimize sin(0.0) = 0.0.  */
5061           if (real_zerop (arg))
5062             return build_real (type, dconst0);
5063         }
5064       break;
5065
5066     case BUILT_IN_COS:
5067     case BUILT_IN_COSF:
5068     case BUILT_IN_COSL:
5069       if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5070         {
5071           tree arg = TREE_VALUE (arglist);
5072
5073           /* Optimize cos(0.0) = 1.0.  */
5074           if (real_zerop (arg))
5075             return build_real (type, dconst1);
5076         }
5077       break;
5078
5079     case BUILT_IN_EXP:
5080     case BUILT_IN_EXPF:
5081     case BUILT_IN_EXPL:
5082       if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5083         {
5084           enum built_in_function fcode;
5085           tree arg = TREE_VALUE (arglist);
5086
5087           /* Optimize exp(0.0) = 1.0.  */
5088           if (real_zerop (arg))
5089             return build_real (type, dconst1);
5090
5091           /* Optimize exp(log(x)) = x.  */
5092           fcode = builtin_mathfn_code (arg);
5093           if (flag_unsafe_math_optimizations
5094               && (fcode == BUILT_IN_LOG
5095                   || fcode == BUILT_IN_LOGF
5096                   || fcode == BUILT_IN_LOGL))
5097             return TREE_VALUE (TREE_OPERAND (arg, 1));
5098         }
5099       break;
5100
5101     case BUILT_IN_LOG:
5102     case BUILT_IN_LOGF:
5103     case BUILT_IN_LOGL:
5104       if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
5105         {
5106           enum built_in_function fcode;
5107           tree arg = TREE_VALUE (arglist);
5108
5109           /* Optimize log(1.0) = 0.0.  */
5110           if (real_onep (arg))
5111             return build_real (type, dconst0);
5112
5113           /* Optimize log(exp(x)) = x.  */
5114           fcode = builtin_mathfn_code (arg);
5115           if (flag_unsafe_math_optimizations
5116               && (fcode == BUILT_IN_EXP
5117                   || fcode == BUILT_IN_EXPF
5118                   || fcode == BUILT_IN_EXPL))
5119             return TREE_VALUE (TREE_OPERAND (arg, 1));
5120
5121           /* Optimize log(sqrt(x)) = log(x)*0.5.  */
5122           if (flag_unsafe_math_optimizations
5123               && (fcode == BUILT_IN_SQRT
5124                   || fcode == BUILT_IN_SQRTF
5125                   || fcode == BUILT_IN_SQRTL))
5126             {
5127               tree logfn = build_function_call_expr (fndecl,
5128                                                      TREE_OPERAND (arg, 1));
5129               return fold (build (MULT_EXPR, type, logfn,
5130                                   build_real (type, dconsthalf)));
5131             }
5132
5133           /* Optimize log(pow(x,y)) = y*log(x).  */
5134           if (flag_unsafe_math_optimizations
5135               && (fcode == BUILT_IN_POW
5136                   || fcode == BUILT_IN_POWF
5137                   || fcode == BUILT_IN_POWL))
5138             {
5139               tree arg0, arg1, logfn;
5140
5141               arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
5142               arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
5143               arglist = build_tree_list (NULL_TREE, arg0);
5144               logfn = build_function_call_expr (fndecl, arglist);
5145               return fold (build (MULT_EXPR, type, arg1, logfn));
5146             }
5147         }
5148       break;
5149
5150     case BUILT_IN_POW:
5151     case BUILT_IN_POWF:
5152     case BUILT_IN_POWL:
5153       if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
5154         {
5155           enum built_in_function fcode;
5156           tree arg0 = TREE_VALUE (arglist);
5157           tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
5158
5159           /* Optimize pow(1.0,y) = 1.0.  */
5160           if (real_onep (arg0))
5161             return omit_one_operand (type, build_real (type, dconst1), arg1);
5162
5163           if (TREE_CODE (arg1) == REAL_CST
5164               && ! TREE_CONSTANT_OVERFLOW (arg1))
5165             {
5166               REAL_VALUE_TYPE c;
5167               c = TREE_REAL_CST (arg1);
5168
5169               /* Optimize pow(x,0.0) = 1.0.  */
5170               if (REAL_VALUES_EQUAL (c, dconst0))
5171                 return omit_one_operand (type, build_real (type, dconst1),
5172                                          arg0);
5173
5174               /* Optimize pow(x,1.0) = x.  */
5175               if (REAL_VALUES_EQUAL (c, dconst1))
5176                 return arg0;
5177
5178               /* Optimize pow(x,-1.0) = 1.0/x.  */
5179               if (REAL_VALUES_EQUAL (c, dconstm1))
5180                 return fold (build (RDIV_EXPR, type,
5181                                     build_real (type, dconst1),
5182                                     arg0));
5183
5184               /* Optimize pow(x,2.0) = x*x.  */
5185               if (REAL_VALUES_EQUAL (c, dconst2)
5186                   && (*lang_hooks.decls.global_bindings_p) () == 0
5187                   && ! contains_placeholder_p (arg0))
5188                 {
5189                   arg0 = save_expr (arg0);
5190                   return fold (build (MULT_EXPR, type, arg0, arg0));
5191                 }
5192
5193               /* Optimize pow(x,-2.0) = 1.0/(x*x).  */
5194               if (flag_unsafe_math_optimizations
5195                   && REAL_VALUES_EQUAL (c, dconstm2)
5196                   && (*lang_hooks.decls.global_bindings_p) () == 0
5197                   && ! contains_placeholder_p (arg0))
5198                 {
5199                   arg0 = save_expr (arg0);
5200                   return fold (build (RDIV_EXPR, type,
5201                                       build_real (type, dconst1),
5202                                       fold (build (MULT_EXPR, type,
5203                                                    arg0, arg0))));
5204                 }
5205
5206               /* Optimize pow(x,0.5) = sqrt(x).  */
5207               if (flag_unsafe_math_optimizations
5208                   && REAL_VALUES_EQUAL (c, dconsthalf))
5209                 {
5210                   tree sqrtfn;
5211
5212                   fcode = DECL_FUNCTION_CODE (fndecl);
5213                   if (fcode == BUILT_IN_POW)
5214                     sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
5215                   else if (fcode == BUILT_IN_POWF)
5216                     sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
5217                   else if (fcode == BUILT_IN_POWL)
5218                     sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
5219                   else
5220                     sqrtfn = NULL_TREE;
5221
5222                   if (sqrtfn != NULL_TREE)
5223                     {
5224                       tree arglist = build_tree_list (NULL_TREE, arg0);
5225                       return build_function_call_expr (sqrtfn, arglist);
5226                     }
5227                 }
5228             }
5229
5230           /* Optimize pow(exp(x),y) = exp(x*y).  */
5231           fcode = builtin_mathfn_code (arg0);
5232           if (flag_unsafe_math_optimizations
5233               && (fcode == BUILT_IN_EXP
5234                   || fcode == BUILT_IN_EXPF
5235                   || fcode == BUILT_IN_EXPL))
5236             {
5237               tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
5238               tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
5239               arg = fold (build (MULT_EXPR, type, arg, arg1));
5240               arglist = build_tree_list (NULL_TREE, arg);
5241               return build_function_call_expr (expfn, arglist);
5242             }
5243
5244           /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
5245           if (flag_unsafe_math_optimizations
5246               && (fcode == BUILT_IN_SQRT
5247                   || fcode == BUILT_IN_SQRTF
5248                   || fcode == BUILT_IN_SQRTL))
5249             {
5250               tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
5251               tree narg1 = fold (build (MULT_EXPR, type, arg1,
5252                                         build_real (type, dconsthalf)));
5253
5254               arglist = tree_cons (NULL_TREE, narg0,
5255                                    build_tree_list (NULL_TREE, narg1));
5256               return build_function_call_expr (fndecl, arglist);
5257             }
5258
5259           /* Optimize pow(pow(x,y),z) = pow(x,y*z).  */
5260           if (flag_unsafe_math_optimizations
5261               && (fcode == BUILT_IN_POW
5262                   || fcode == BUILT_IN_POWF
5263                   || fcode == BUILT_IN_POWL))
5264             {
5265               tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
5266               tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
5267               tree narg1 = fold (build (MULT_EXPR, type, arg01, arg1));
5268               arglist = tree_cons (NULL_TREE, arg00,
5269                                    build_tree_list (NULL_TREE, narg1));
5270               return build_function_call_expr (fndecl, arglist);
5271             }
5272         }
5273       break;
5274
5275     case BUILT_IN_INF:
5276     case BUILT_IN_INFF:
5277     case BUILT_IN_INFL:
5278       return fold_builtin_inf (type, true);
5279
5280     case BUILT_IN_HUGE_VAL:
5281     case BUILT_IN_HUGE_VALF:
5282     case BUILT_IN_HUGE_VALL:
5283       return fold_builtin_inf (type, false);
5284
5285     case BUILT_IN_NAN:
5286     case BUILT_IN_NANF:
5287     case BUILT_IN_NANL:
5288       return fold_builtin_nan (arglist, type, true);
5289
5290     case BUILT_IN_NANS:
5291     case BUILT_IN_NANSF:
5292     case BUILT_IN_NANSL:
5293       return fold_builtin_nan (arglist, type, false);
5294
5295     case BUILT_IN_FLOOR:
5296     case BUILT_IN_FLOORF:
5297     case BUILT_IN_FLOORL:
5298     case BUILT_IN_CEIL:
5299     case BUILT_IN_CEILF:
5300     case BUILT_IN_CEILL:
5301     case BUILT_IN_TRUNC:
5302     case BUILT_IN_TRUNCF:
5303     case BUILT_IN_TRUNCL:
5304     case BUILT_IN_ROUND:
5305     case BUILT_IN_ROUNDF:
5306     case BUILT_IN_ROUNDL:
5307     case BUILT_IN_NEARBYINT:
5308     case BUILT_IN_NEARBYINTF:
5309     case BUILT_IN_NEARBYINTL:
5310       return fold_trunc_transparent_mathfn (exp);
5311
5312     default:
5313       break;
5314     }
5315
5316   return 0;
5317 }
5318
5319 /* Conveniently construct a function call expression.  */
5320
5321 tree
5322 build_function_call_expr (fn, arglist)
5323      tree fn, arglist;
5324 {
5325   tree call_expr;
5326
5327   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
5328   call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
5329                      call_expr, arglist);
5330   TREE_SIDE_EFFECTS (call_expr) = 1;
5331   return fold (call_expr);
5332 }
5333
5334 /* This function validates the types of a function call argument list
5335    represented as a tree chain of parameters against a specified list
5336    of tree_codes.  If the last specifier is a 0, that represents an
5337    ellipses, otherwise the last specifier must be a VOID_TYPE.  */
5338
5339 static int
5340 validate_arglist VPARAMS ((tree arglist, ...))
5341 {
5342   enum tree_code code;
5343   int res = 0;
5344
5345   VA_OPEN (ap, arglist);
5346   VA_FIXEDARG (ap, tree, arglist);
5347
5348   do
5349     {
5350       code = va_arg (ap, enum tree_code);
5351       switch (code)
5352         {
5353         case 0:
5354           /* This signifies an ellipses, any further arguments are all ok.  */
5355           res = 1;
5356           goto end;
5357         case VOID_TYPE:
5358           /* This signifies an endlink, if no arguments remain, return
5359              true, otherwise return false.  */
5360           res = arglist == 0;
5361           goto end;
5362         default:
5363           /* If no parameters remain or the parameter's code does not
5364              match the specified code, return false.  Otherwise continue
5365              checking any remaining arguments.  */
5366           if (arglist == 0
5367               || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
5368             goto end;
5369           break;
5370         }
5371       arglist = TREE_CHAIN (arglist);
5372     }
5373   while (1);
5374
5375   /* We need gotos here since we can only have one VA_CLOSE in a
5376      function.  */
5377  end: ;
5378   VA_CLOSE (ap);
5379
5380   return res;
5381 }
5382
5383 /* Default version of target-specific builtin setup that does nothing.  */
5384
5385 void
5386 default_init_builtins ()
5387 {
5388 }
5389
5390 /* Default target-specific builtin expander that does nothing.  */
5391
5392 rtx
5393 default_expand_builtin (exp, target, subtarget, mode, ignore)
5394      tree exp ATTRIBUTE_UNUSED;
5395      rtx target ATTRIBUTE_UNUSED;
5396      rtx subtarget ATTRIBUTE_UNUSED;
5397      enum machine_mode mode ATTRIBUTE_UNUSED;
5398      int ignore ATTRIBUTE_UNUSED;
5399 {
5400   return NULL_RTX;
5401 }
5402
5403 /* Instantiate all remaining CONSTANT_P_RTX nodes.  */
5404
5405 void
5406 purge_builtin_constant_p ()
5407 {
5408   rtx insn, set, arg, new, note;
5409
5410   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5411     if (INSN_P (insn)
5412         && (set = single_set (insn)) != NULL_RTX
5413         && (GET_CODE (arg = SET_SRC (set)) == CONSTANT_P_RTX
5414             || (GET_CODE (arg) == SUBREG
5415                 && (GET_CODE (arg = SUBREG_REG (arg))
5416                     == CONSTANT_P_RTX))))
5417       {
5418         arg = XEXP (arg, 0);
5419         new = CONSTANT_P (arg) ? const1_rtx : const0_rtx;
5420         validate_change (insn, &SET_SRC (set), new, 0);
5421
5422         /* Remove the REG_EQUAL note from the insn.  */
5423         if ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0)
5424           remove_note (insn, note);
5425       }
5426 }
5427