OSDN Git Service

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