OSDN Git Service

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