OSDN Git Service

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