OSDN Git Service

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