OSDN Git Service

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