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