OSDN Git Service

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