OSDN Git Service

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