OSDN Git Service

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