OSDN Git Service

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