OSDN Git Service

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