OSDN Git Service

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