OSDN Git Service

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