OSDN Git Service

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