OSDN Git Service

* builtins.c (expand_builtin_strlen): Make sure that we have something
[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 const char *const built_in_names[(int) END_BUILTINS] =
64 {"BUILT_IN_ALLOCA", "BUILT_IN_ABS", "BUILT_IN_FABS", "BUILT_IN_LABS",
65   "BUILT_IN_FFS", "BUILT_IN_DIV", "BUILT_IN_LDIV", "BUILT_IN_FFLOOR",
66   "BUILT_IN_FCEIL", "BUILT_IN_FMOD", "BUILT_IN_FREM", "BUILT_IN_MEMCPY",
67   "BUILT_IN_MEMCMP", "BUILT_IN_MEMSET", "BUILT_IN_STRCPY", "BUILT_IN_STRCMP",
68   "BUILT_IN_STRLEN", "BUILT_IN_FSQRT", "BUILT_IN_SIN", "BUILT_IN_COS",
69   "BUILT_IN_GETEXP", "BUILT_IN_GETMAN", "BUILT_IN_SAVEREGS",
70   "BUILT_IN_CLASSIFY_TYPE", "BUILT_IN_NEXT_ARG", "BUILT_IN_ARGS_INFO",
71   "BUILT_IN_CONSTANT_P", "BUILT_IN_FRAME_ADDRESS", "BUILT_IN_RETURN_ADDRESS",
72   "BUILT_IN_AGGREGATE_INCOMING_ADDRESS", "BUILT_IN_APPLY_ARGS",
73   "BUILT_IN_APPLY", "BUILT_IN_RETURN", "BUILT_IN_SETJMP", "BUILT_IN_LONGJMP",
74   "BUILT_IN_TRAP", "BUILT_IN_ISGREATER", "BUILT_IN_ISGREATEREQUAL",
75   "BUILT_IN_ISLESS", "BUILT_IN_ISLESSEQUAL", "BUILT_IN_ISLESSGREATER",
76   "BUILT_IN_ISUNORDERED", "BUILT_IN_UNWIND_INIT", "BUILT_IN_DWARF_CFA",
77   "BUILT_IN_DWARF_FP_REGNUM", "BUILT_IN_INIT_DWARF_REG_SIZES",
78   "BUILT_IN_FROB_RETURN_ADDR", "BUILT_IN_EXTRACT_RETURN_ADDR",
79   "BUILT_IN_EH_RETURN", "BUILT_IN_VARARGS_START", "BUILT_IN_STDARG_START",
80   "BUILT_IN_VA_END", "BUILT_IN_VA_COPY", "BUILT_IN_NEW", "BUILT_IN_VEC_NEW",
81   "BUILT_IN_DELETE", "BUILT_IN_VEC_DELETE" };
82
83 tree (*lang_type_promotes_to) PARAMS ((tree));
84
85 static int get_pointer_alignment        PARAMS ((tree, unsigned));
86 static tree c_strlen                    PARAMS ((tree));
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 static rtx expand_builtin_strcmp        PARAMS ((tree, rtx));
108 #endif
109 static rtx expand_builtin_memcpy        PARAMS ((tree));
110 static rtx expand_builtin_strcpy        PARAMS ((tree));
111 static rtx expand_builtin_memset        PARAMS ((tree));
112 static rtx expand_builtin_strlen        PARAMS ((tree, rtx,
113                                                  enum machine_mode));
114 static rtx expand_builtin_alloca        PARAMS ((tree, rtx));
115 static rtx expand_builtin_ffs           PARAMS ((tree, rtx, rtx));
116 static rtx expand_builtin_frame_address PARAMS ((tree));
117 static tree stabilize_va_list           PARAMS ((tree, int));
118
119 /* Return the alignment in bits of EXP, a pointer valued expression.
120    But don't return more than MAX_ALIGN no matter what.
121    The alignment returned is, by default, the alignment of the thing that
122    EXP points to (if it is not a POINTER_TYPE, 0 is returned).
123
124    Otherwise, look at the expression to see if we can do better, i.e., if the
125    expression is actually pointing at an object whose alignment is tighter.  */
126
127 static int
128 get_pointer_alignment (exp, max_align)
129      tree exp;
130      unsigned max_align;
131 {
132   unsigned align, inner;
133
134   if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
135     return 0;
136
137   align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
138   align = MIN (align, max_align);
139
140   while (1)
141     {
142       switch (TREE_CODE (exp))
143         {
144         case NOP_EXPR:
145         case CONVERT_EXPR:
146         case NON_LVALUE_EXPR:
147           exp = TREE_OPERAND (exp, 0);
148           if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
149             return align;
150           inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
151           align = MIN (inner, max_align);
152           break;
153
154         case PLUS_EXPR:
155           /* If sum of pointer + int, restrict our maximum alignment to that
156              imposed by the integer.  If not, we can't do any better than
157              ALIGN.  */
158           if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST)
159             return align;
160
161           while (((TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT)
162                   & (max_align - 1))
163                  != 0)
164             max_align >>= 1;
165
166           exp = TREE_OPERAND (exp, 0);
167           break;
168
169         case ADDR_EXPR:
170           /* See what we are pointing at and look at its alignment.  */
171           exp = TREE_OPERAND (exp, 0);
172           if (TREE_CODE (exp) == FUNCTION_DECL)
173             align = FUNCTION_BOUNDARY;
174           else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
175             align = DECL_ALIGN (exp);
176 #ifdef CONSTANT_ALIGNMENT
177           else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
178             align = CONSTANT_ALIGNMENT (exp, align);
179 #endif
180           return MIN (align, max_align);
181
182         default:
183           return align;
184         }
185     }
186 }
187
188 /* Compute the length of a C string.  TREE_STRING_LENGTH is not the right
189    way, because it could contain a zero byte in the middle.
190    TREE_STRING_LENGTH is the size of the character array, not the string.
191
192    The value returned is of type `ssizetype'.
193
194    Unfortunately, string_constant can't access the values of const char
195    arrays with initializers, so neither can we do so here.  */
196
197 static tree
198 c_strlen (src)
199      tree src;
200 {
201   tree offset_node;
202   int offset, max;
203   char *ptr;
204
205   src = string_constant (src, &offset_node);
206   if (src == 0)
207     return 0;
208
209   max = TREE_STRING_LENGTH (src);
210   ptr = TREE_STRING_POINTER (src);
211
212   if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
213     {
214       /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
215          compute the offset to the following null if we don't know where to
216          start searching for it.  */
217       int i;
218
219       for (i = 0; i < max; i++)
220         if (ptr[i] == 0)
221           return 0;
222
223       /* We don't know the starting offset, but we do know that the string
224          has no internal zero bytes.  We can assume that the offset falls
225          within the bounds of the string; otherwise, the programmer deserves
226          what he gets.  Subtract the offset from the length of the string,
227          and return that.  This would perhaps not be valid if we were dealing
228          with named arrays in addition to literal string constants.  */
229
230       return size_diffop (size_int (max), offset_node);
231     }
232
233   /* We have a known offset into the string.  Start searching there for
234      a null character.  */
235   if (offset_node == 0)
236     offset = 0;
237   else
238     {
239       /* Did we get a long long offset?  If so, punt.  */
240       if (TREE_INT_CST_HIGH (offset_node) != 0)
241         return 0;
242       offset = TREE_INT_CST_LOW (offset_node);
243     }
244
245   /* If the offset is known to be out of bounds, warn, and call strlen at
246      runtime.  */
247   if (offset < 0 || offset > max)
248     {
249       warning ("offset outside bounds of constant string");
250       return 0;
251     }
252
253   /* Use strlen to search for the first zero byte.  Since any strings
254      constructed with build_string will have nulls appended, we win even
255      if we get handed something like (char[4])"abcd".
256
257      Since OFFSET is our starting index into the string, no further
258      calculation is needed.  */
259   return ssize_int (strlen (ptr + offset));
260 }
261
262 /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
263    times to get the address of either a higher stack frame, or a return
264    address located within it (depending on FNDECL_CODE).  */
265
266 rtx
267 expand_builtin_return_addr (fndecl_code, count, tem)
268      enum built_in_function fndecl_code;
269      int count;
270      rtx tem;
271 {
272   int i;
273
274   /* Some machines need special handling before we can access
275      arbitrary frames.  For example, on the sparc, we must first flush
276      all register windows to the stack.  */
277 #ifdef SETUP_FRAME_ADDRESSES
278   if (count > 0)
279     SETUP_FRAME_ADDRESSES ();
280 #endif
281
282   /* On the sparc, the return address is not in the frame, it is in a
283      register.  There is no way to access it off of the current frame
284      pointer, but it can be accessed off the previous frame pointer by
285      reading the value from the register window save area.  */
286 #ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
287   if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
288     count--;
289 #endif
290
291   /* Scan back COUNT frames to the specified frame.  */
292   for (i = 0; i < count; i++)
293     {
294       /* Assume the dynamic chain pointer is in the word that the
295          frame address points to, unless otherwise specified.  */
296 #ifdef DYNAMIC_CHAIN_ADDRESS
297       tem = DYNAMIC_CHAIN_ADDRESS (tem);
298 #endif
299       tem = memory_address (Pmode, tem);
300       tem = copy_to_reg (gen_rtx_MEM (Pmode, tem));
301     }
302
303   /* For __builtin_frame_address, return what we've got.  */
304   if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
305     return tem;
306
307   /* For __builtin_return_address, Get the return address from that
308      frame.  */
309 #ifdef RETURN_ADDR_RTX
310   tem = RETURN_ADDR_RTX (count, tem);
311 #else
312   tem = memory_address (Pmode,
313                         plus_constant (tem, GET_MODE_SIZE (Pmode)));
314   tem = gen_rtx_MEM (Pmode, tem);
315 #endif
316   return tem;
317 }
318
319 /* __builtin_setjmp is passed a pointer to an array of five words (not
320    all will be used on all machines).  It operates similarly to the C
321    library function of the same name, but is more efficient.  Much of
322    the code below (and for longjmp) is copied from the handling of
323    non-local gotos.
324
325    NOTE: This is intended for use by GNAT and the exception handling
326    scheme in the compiler and will only work in the method used by
327    them.  */
328
329 rtx
330 expand_builtin_setjmp (buf_addr, target, first_label, next_label)
331      rtx buf_addr;
332      rtx target;
333      rtx first_label, next_label;
334 {
335   rtx lab1 = gen_label_rtx ();
336   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
337   enum machine_mode value_mode;
338   rtx stack_save;
339
340   value_mode = TYPE_MODE (integer_type_node);
341
342 #ifdef POINTERS_EXTEND_UNSIGNED
343   buf_addr = convert_memory_address (Pmode, buf_addr);
344 #endif
345
346   buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
347
348   if (target == 0 || GET_CODE (target) != REG
349       || REGNO (target) < FIRST_PSEUDO_REGISTER)
350     target = gen_reg_rtx (value_mode);
351
352   emit_queue ();
353
354   /* We store the frame pointer and the address of lab1 in the buffer
355      and use the rest of it for the stack save area, which is
356      machine-dependent.  */
357
358 #ifndef BUILTIN_SETJMP_FRAME_VALUE
359 #define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
360 #endif
361
362   emit_move_insn (gen_rtx_MEM (Pmode, buf_addr),
363                   BUILTIN_SETJMP_FRAME_VALUE);
364   emit_move_insn (validize_mem
365                   (gen_rtx_MEM (Pmode,
366                                 plus_constant (buf_addr,
367                                                GET_MODE_SIZE (Pmode)))),
368                   force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1)));
369
370   stack_save = gen_rtx_MEM (sa_mode,
371                             plus_constant (buf_addr,
372                                            2 * GET_MODE_SIZE (Pmode)));
373   emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
374
375   /* If there is further processing to do, do it.  */
376 #ifdef HAVE_builtin_setjmp_setup
377   if (HAVE_builtin_setjmp_setup)
378     emit_insn (gen_builtin_setjmp_setup (buf_addr));
379 #endif
380
381   /* Set TARGET to zero and branch to the first-time-through label.  */
382   emit_move_insn (target, const0_rtx);
383   emit_jump_insn (gen_jump (first_label));
384   emit_barrier ();
385   emit_label (lab1);
386
387   /* Tell flow about the strange goings on.  Putting `lab1' on
388      `nonlocal_goto_handler_labels' to indicates that function
389      calls may traverse the arc back to this label.  */
390
391   current_function_has_nonlocal_label = 1;
392   nonlocal_goto_handler_labels =
393     gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels);
394
395   /* Clobber the FP when we get here, so we have to make sure it's
396      marked as used by this function.  */
397   emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
398
399   /* Mark the static chain as clobbered here so life information
400      doesn't get messed up for it.  */
401   emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
402
403   /* Now put in the code to restore the frame pointer, and argument
404      pointer, if needed.  The code below is from expand_end_bindings
405      in stmt.c; see detailed documentation there.  */
406 #ifdef HAVE_nonlocal_goto
407   if (! HAVE_nonlocal_goto)
408 #endif
409     emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
410
411 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
412   if (fixed_regs[ARG_POINTER_REGNUM])
413     {
414 #ifdef ELIMINABLE_REGS
415       size_t i;
416       static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
417
418       for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
419         if (elim_regs[i].from == ARG_POINTER_REGNUM
420             && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
421           break;
422
423       if (i == sizeof elim_regs / sizeof elim_regs [0])
424 #endif
425         {
426           /* Now restore our arg pointer from the address at which it
427              was saved in our stack frame.
428              If there hasn't be space allocated for it yet, make
429              some now.  */
430           if (arg_pointer_save_area == 0)
431             arg_pointer_save_area
432               = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
433           emit_move_insn (virtual_incoming_args_rtx,
434                           copy_to_reg (arg_pointer_save_area));
435         }
436     }
437 #endif
438
439 #ifdef HAVE_builtin_setjmp_receiver
440   if (HAVE_builtin_setjmp_receiver)
441     emit_insn (gen_builtin_setjmp_receiver (lab1));
442   else
443 #endif
444 #ifdef HAVE_nonlocal_goto_receiver
445     if (HAVE_nonlocal_goto_receiver)
446       emit_insn (gen_nonlocal_goto_receiver ());
447     else
448 #endif
449       {
450         ; /* Nothing */
451       }
452
453   /* Set TARGET, and branch to the next-time-through label.  */
454   emit_move_insn (target, const1_rtx);
455   emit_jump_insn (gen_jump (next_label));
456   emit_barrier ();
457
458   return target;
459 }
460
461 /* __builtin_longjmp is passed a pointer to an array of five words (not
462    all will be used on all machines).  It operates similarly to the C
463    library function of the same name, but is more efficient.  Much of
464    the code below is copied from the handling of non-local gotos.
465
466    NOTE: This is intended for use by GNAT and the exception handling
467    scheme in the compiler and will only work in the method used by
468    them.  */
469
470 void
471 expand_builtin_longjmp (buf_addr, value)
472      rtx buf_addr, value;
473 {
474   rtx fp, lab, stack;
475   enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
476
477 #ifdef POINTERS_EXTEND_UNSIGNED
478   buf_addr = convert_memory_address (Pmode, buf_addr);
479 #endif
480   buf_addr = force_reg (Pmode, buf_addr);
481
482   /* We used to store value in static_chain_rtx, but that fails if pointers
483      are smaller than integers.  We instead require that the user must pass
484      a second argument of 1, because that is what builtin_setjmp will
485      return.  This also makes EH slightly more efficient, since we are no
486      longer copying around a value that we don't care about.  */
487   if (value != const1_rtx)
488     abort ();
489
490 #ifdef HAVE_builtin_longjmp
491   if (HAVE_builtin_longjmp)
492     emit_insn (gen_builtin_longjmp (buf_addr));
493   else
494 #endif
495     {
496       fp = gen_rtx_MEM (Pmode, buf_addr);
497       lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
498                                                GET_MODE_SIZE (Pmode)));
499
500       stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
501                                                    2 * GET_MODE_SIZE (Pmode)));
502
503       /* Pick up FP, label, and SP from the block and jump.  This code is
504          from expand_goto in stmt.c; see there for detailed comments.  */
505 #if HAVE_nonlocal_goto
506       if (HAVE_nonlocal_goto)
507         /* We have to pass a value to the nonlocal_goto pattern that will
508            get copied into the static_chain pointer, but it does not matter
509            what that value is, because builtin_setjmp does not use it.  */
510         emit_insn (gen_nonlocal_goto (value, fp, stack, lab));
511       else
512 #endif
513         {
514           lab = copy_to_reg (lab);
515
516           emit_move_insn (hard_frame_pointer_rtx, fp);
517           emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
518
519           emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
520           emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
521           emit_indirect_jump (lab);
522         }
523     }
524 }
525
526 /* Get a MEM rtx for expression EXP which can be used in a string instruction
527    (cmpstrsi, movstrsi, ..).  */
528 static rtx
529 get_memory_rtx (exp)
530      tree exp;
531 {
532   rtx mem;
533   int is_aggregate;
534
535   mem = gen_rtx_MEM (BLKmode,
536                      memory_address (BLKmode,
537                                      expand_expr (exp, NULL_RTX,
538                                                   ptr_mode, EXPAND_SUM)));
539
540   RTX_UNCHANGING_P (mem) = TREE_READONLY (exp);
541
542   /* Figure out the type of the object pointed to.  Set MEM_IN_STRUCT_P
543      if the value is the address of a structure or if the expression is
544      cast to a pointer to structure type.  */
545   is_aggregate = 0;
546
547   while (TREE_CODE (exp) == NOP_EXPR)
548     {
549       tree cast_type = TREE_TYPE (exp);
550       if (TREE_CODE (cast_type) == POINTER_TYPE
551           && AGGREGATE_TYPE_P (TREE_TYPE (cast_type)))
552         {
553           is_aggregate = 1;
554           break;
555         }
556       exp = TREE_OPERAND (exp, 0);
557     }
558
559   if (is_aggregate == 0)
560     {
561       tree type;
562
563       if (TREE_CODE (exp) == ADDR_EXPR)
564         /* If this is the address of an object, check whether the
565            object is an array.  */
566         type = TREE_TYPE (TREE_OPERAND (exp, 0));
567       else
568         type = TREE_TYPE (TREE_TYPE (exp));
569       is_aggregate = AGGREGATE_TYPE_P (type);
570     }
571
572   MEM_SET_IN_STRUCT_P (mem, is_aggregate);
573   return mem;
574 }
575 \f
576 /* Built-in functions to perform an untyped call and return.  */
577
578 /* For each register that may be used for calling a function, this
579    gives a mode used to copy the register's value.  VOIDmode indicates
580    the register is not used for calling a function.  If the machine
581    has register windows, this gives only the outbound registers.
582    INCOMING_REGNO gives the corresponding inbound register.  */
583 static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
584
585 /* For each register that may be used for returning values, this gives
586    a mode used to copy the register's value.  VOIDmode indicates the
587    register is not used for returning values.  If the machine has
588    register windows, this gives only the outbound registers.
589    INCOMING_REGNO gives the corresponding inbound register.  */
590 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
591
592 /* For each register that may be used for calling a function, this
593    gives the offset of that register into the block returned by
594    __builtin_apply_args.  0 indicates that the register is not
595    used for calling a function.  */
596 static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
597
598 /* Return the offset of register REGNO into the block returned by 
599    __builtin_apply_args.  This is not declared static, since it is
600    needed in objc-act.c.  */
601
602 int 
603 apply_args_register_offset (regno)
604      int regno;
605 {
606   apply_args_size ();
607
608   /* Arguments are always put in outgoing registers (in the argument
609      block) if such make sense.  */
610 #ifdef OUTGOING_REGNO
611   regno = OUTGOING_REGNO(regno);
612 #endif
613   return apply_args_reg_offset[regno];
614 }
615
616 /* Return the size required for the block returned by __builtin_apply_args,
617    and initialize apply_args_mode.  */
618
619 static int
620 apply_args_size ()
621 {
622   static int size = -1;
623   int align, regno;
624   enum machine_mode mode;
625
626   /* The values computed by this function never change.  */
627   if (size < 0)
628     {
629       /* The first value is the incoming arg-pointer.  */
630       size = GET_MODE_SIZE (Pmode);
631
632       /* The second value is the structure value address unless this is
633          passed as an "invisible" first argument.  */
634       if (struct_value_rtx)
635         size += GET_MODE_SIZE (Pmode);
636
637       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
638         if (FUNCTION_ARG_REGNO_P (regno))
639           {
640             /* Search for the proper mode for copying this register's
641                value.  I'm not sure this is right, but it works so far.  */
642             enum machine_mode best_mode = VOIDmode;
643
644             for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
645                  mode != VOIDmode;
646                  mode = GET_MODE_WIDER_MODE (mode))
647               if (HARD_REGNO_MODE_OK (regno, mode)
648                   && HARD_REGNO_NREGS (regno, mode) == 1)
649                 best_mode = mode;
650
651             if (best_mode == VOIDmode)
652               for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
653                    mode != VOIDmode;
654                    mode = GET_MODE_WIDER_MODE (mode))
655                 if (HARD_REGNO_MODE_OK (regno, mode)
656                     && (mov_optab->handlers[(int) mode].insn_code
657                         != CODE_FOR_nothing))
658                   best_mode = mode;
659
660             mode = best_mode;
661             if (mode == VOIDmode)
662               abort ();
663
664             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
665             if (size % align != 0)
666               size = CEIL (size, align) * align;
667             apply_args_reg_offset[regno] = size;
668             size += GET_MODE_SIZE (mode);
669             apply_args_mode[regno] = mode;
670           }
671         else
672           {
673             apply_args_mode[regno] = VOIDmode;
674             apply_args_reg_offset[regno] = 0;
675           }
676     }
677   return size;
678 }
679
680 /* Return the size required for the block returned by __builtin_apply,
681    and initialize apply_result_mode.  */
682
683 static int
684 apply_result_size ()
685 {
686   static int size = -1;
687   int align, regno;
688   enum machine_mode mode;
689
690   /* The values computed by this function never change.  */
691   if (size < 0)
692     {
693       size = 0;
694
695       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
696         if (FUNCTION_VALUE_REGNO_P (regno))
697           {
698             /* Search for the proper mode for copying this register's
699                value.  I'm not sure this is right, but it works so far.  */
700             enum machine_mode best_mode = VOIDmode;
701
702             for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
703                  mode != TImode;
704                  mode = GET_MODE_WIDER_MODE (mode))
705               if (HARD_REGNO_MODE_OK (regno, mode))
706                 best_mode = mode;
707
708             if (best_mode == VOIDmode)
709               for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
710                    mode != VOIDmode;
711                    mode = GET_MODE_WIDER_MODE (mode))
712                 if (HARD_REGNO_MODE_OK (regno, mode)
713                     && (mov_optab->handlers[(int) mode].insn_code
714                         != CODE_FOR_nothing))
715                   best_mode = mode;
716
717             mode = best_mode;
718             if (mode == VOIDmode)
719               abort ();
720
721             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
722             if (size % align != 0)
723               size = CEIL (size, align) * align;
724             size += GET_MODE_SIZE (mode);
725             apply_result_mode[regno] = mode;
726           }
727         else
728           apply_result_mode[regno] = VOIDmode;
729
730       /* Allow targets that use untyped_call and untyped_return to override
731          the size so that machine-specific information can be stored here.  */
732 #ifdef APPLY_RESULT_SIZE
733       size = APPLY_RESULT_SIZE;
734 #endif
735     }
736   return size;
737 }
738
739 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
740 /* Create a vector describing the result block RESULT.  If SAVEP is true,
741    the result block is used to save the values; otherwise it is used to
742    restore the values.  */
743
744 static rtx
745 result_vector (savep, result)
746      int savep;
747      rtx result;
748 {
749   int regno, size, align, nelts;
750   enum machine_mode mode;
751   rtx reg, mem;
752   rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
753   
754   size = nelts = 0;
755   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
756     if ((mode = apply_result_mode[regno]) != VOIDmode)
757       {
758         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
759         if (size % align != 0)
760           size = CEIL (size, align) * align;
761         reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
762         mem = change_address (result, mode,
763                               plus_constant (XEXP (result, 0), size));
764         savevec[nelts++] = (savep
765                             ? gen_rtx_SET (VOIDmode, mem, reg)
766                             : gen_rtx_SET (VOIDmode, reg, mem));
767         size += GET_MODE_SIZE (mode);
768       }
769   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
770 }
771 #endif /* HAVE_untyped_call or HAVE_untyped_return */
772
773 /* Save the state required to perform an untyped call with the same
774    arguments as were passed to the current function.  */
775
776 static rtx
777 expand_builtin_apply_args_1 ()
778 {
779   rtx registers;
780   int size, align, regno;
781   enum machine_mode mode;
782
783   /* Create a block where the arg-pointer, structure value address,
784      and argument registers can be saved.  */
785   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
786
787   /* Walk past the arg-pointer and structure value address.  */
788   size = GET_MODE_SIZE (Pmode);
789   if (struct_value_rtx)
790     size += GET_MODE_SIZE (Pmode);
791
792   /* Save each register used in calling a function to the block.  */
793   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
794     if ((mode = apply_args_mode[regno]) != VOIDmode)
795       {
796         rtx tem;
797
798         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
799         if (size % align != 0)
800           size = CEIL (size, align) * align;
801
802         tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
803
804         emit_move_insn (change_address (registers, mode,
805                                         plus_constant (XEXP (registers, 0),
806                                                        size)),
807                         tem);
808         size += GET_MODE_SIZE (mode);
809       }
810
811   /* Save the arg pointer to the block.  */
812   emit_move_insn (change_address (registers, Pmode, XEXP (registers, 0)),
813                   copy_to_reg (virtual_incoming_args_rtx));
814   size = GET_MODE_SIZE (Pmode);
815
816   /* Save the structure value address unless this is passed as an
817      "invisible" first argument.  */
818   if (struct_value_incoming_rtx)
819     {
820       emit_move_insn (change_address (registers, Pmode,
821                                       plus_constant (XEXP (registers, 0),
822                                                      size)),
823                       copy_to_reg (struct_value_incoming_rtx));
824       size += GET_MODE_SIZE (Pmode);
825     }
826
827   /* Return the address of the block.  */
828   return copy_addr_to_reg (XEXP (registers, 0));
829 }
830
831 /* __builtin_apply_args returns block of memory allocated on
832    the stack into which is stored the arg pointer, structure
833    value address, static chain, and all the registers that might
834    possibly be used in performing a function call.  The code is
835    moved to the start of the function so the incoming values are
836    saved.  */
837 static rtx
838 expand_builtin_apply_args ()
839 {
840   /* Don't do __builtin_apply_args more than once in a function.
841      Save the result of the first call and reuse it.  */
842   if (apply_args_value != 0)
843     return apply_args_value;
844   {
845     /* When this function is called, it means that registers must be
846        saved on entry to this function.  So we migrate the
847        call to the first insn of this function.  */
848     rtx temp;
849     rtx seq;
850
851     start_sequence ();
852     temp = expand_builtin_apply_args_1 ();
853     seq = get_insns ();
854     end_sequence ();
855
856     apply_args_value = temp;
857
858     /* Put the sequence after the NOTE that starts the function.
859        If this is inside a SEQUENCE, make the outer-level insn
860        chain current, so the code is placed at the start of the
861        function.  */
862     push_topmost_sequence ();
863     emit_insns_before (seq, NEXT_INSN (get_insns ()));
864     pop_topmost_sequence ();
865     return temp;
866   }
867 }
868
869 /* Perform an untyped call and save the state required to perform an
870    untyped return of whatever value was returned by the given function.  */
871
872 static rtx
873 expand_builtin_apply (function, arguments, argsize)
874      rtx function, arguments, argsize;
875 {
876   int size, align, regno;
877   enum machine_mode mode;
878   rtx incoming_args, result, reg, dest, call_insn;
879   rtx old_stack_level = 0;
880   rtx call_fusage = 0;
881
882   /* Create a block where the return registers can be saved.  */
883   result = assign_stack_local (BLKmode, apply_result_size (), -1);
884
885   /* ??? The argsize value should be adjusted here.  */
886
887   /* Fetch the arg pointer from the ARGUMENTS block.  */
888   incoming_args = gen_reg_rtx (Pmode);
889   emit_move_insn (incoming_args,
890                   gen_rtx_MEM (Pmode, arguments));
891 #ifndef STACK_GROWS_DOWNWARD
892   incoming_args = expand_binop (Pmode, sub_optab, incoming_args, argsize,
893                                 incoming_args, 0, OPTAB_LIB_WIDEN);
894 #endif
895
896   /* Perform postincrements before actually calling the function.  */
897   emit_queue ();
898
899   /* Push a new argument block and copy the arguments.  */
900   do_pending_stack_adjust ();
901
902   /* Save the stack with nonlocal if available */
903 #ifdef HAVE_save_stack_nonlocal
904   if (HAVE_save_stack_nonlocal)
905     emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
906   else
907 #endif
908     emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
909
910   /* Push a block of memory onto the stack to store the memory arguments.
911      Save the address in a register, and copy the memory arguments.  ??? I
912      haven't figured out how the calling convention macros effect this,
913      but it's likely that the source and/or destination addresses in
914      the block copy will need updating in machine specific ways.  */
915   dest = allocate_dynamic_stack_space (argsize, 0, 0);
916   emit_block_move (gen_rtx_MEM (BLKmode, dest),
917                    gen_rtx_MEM (BLKmode, incoming_args),
918                    argsize,
919                    PARM_BOUNDARY / BITS_PER_UNIT);
920
921   /* Refer to the argument block.  */
922   apply_args_size ();
923   arguments = gen_rtx_MEM (BLKmode, arguments);
924
925   /* Walk past the arg-pointer and structure value address.  */
926   size = GET_MODE_SIZE (Pmode);
927   if (struct_value_rtx)
928     size += GET_MODE_SIZE (Pmode);
929
930   /* Restore each of the registers previously saved.  Make USE insns
931      for each of these registers for use in making the call.  */
932   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
933     if ((mode = apply_args_mode[regno]) != VOIDmode)
934       {
935         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
936         if (size % align != 0)
937           size = CEIL (size, align) * align;
938         reg = gen_rtx_REG (mode, regno);
939         emit_move_insn (reg,
940                         change_address (arguments, mode,
941                                         plus_constant (XEXP (arguments, 0),
942                                                        size)));
943
944         use_reg (&call_fusage, reg);
945         size += GET_MODE_SIZE (mode);
946       }
947
948   /* Restore the structure value address unless this is passed as an
949      "invisible" first argument.  */
950   size = GET_MODE_SIZE (Pmode);
951   if (struct_value_rtx)
952     {
953       rtx value = gen_reg_rtx (Pmode);
954       emit_move_insn (value,
955                       change_address (arguments, Pmode,
956                                       plus_constant (XEXP (arguments, 0),
957                                                      size)));
958       emit_move_insn (struct_value_rtx, value);
959       if (GET_CODE (struct_value_rtx) == REG)
960           use_reg (&call_fusage, struct_value_rtx);
961       size += GET_MODE_SIZE (Pmode);
962     }
963
964   /* All arguments and registers used for the call are set up by now!  */
965   function = prepare_call_address (function, NULL_TREE, &call_fusage, 0);
966
967   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
968      and we don't want to load it into a register as an optimization,
969      because prepare_call_address already did it if it should be done.  */
970   if (GET_CODE (function) != SYMBOL_REF)
971     function = memory_address (FUNCTION_MODE, function);
972
973   /* Generate the actual call instruction and save the return value.  */
974 #ifdef HAVE_untyped_call
975   if (HAVE_untyped_call)
976     emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
977                                       result, result_vector (1, result)));
978   else
979 #endif
980 #ifdef HAVE_call_value
981   if (HAVE_call_value)
982     {
983       rtx valreg = 0;
984
985       /* Locate the unique return register.  It is not possible to
986          express a call that sets more than one return register using
987          call_value; use untyped_call for that.  In fact, untyped_call
988          only needs to save the return registers in the given block.  */
989       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
990         if ((mode = apply_result_mode[regno]) != VOIDmode)
991           {
992             if (valreg)
993               abort (); /* HAVE_untyped_call required.  */
994             valreg = gen_rtx_REG (mode, regno);
995           }
996
997       emit_call_insn (gen_call_value (valreg,
998                                       gen_rtx_MEM (FUNCTION_MODE, function),
999                                       const0_rtx, NULL_RTX, const0_rtx));
1000
1001       emit_move_insn (change_address (result, GET_MODE (valreg),
1002                                       XEXP (result, 0)),
1003                       valreg);
1004     }
1005   else
1006 #endif
1007     abort ();
1008
1009   /* Find the CALL insn we just emitted.  */
1010   for (call_insn = get_last_insn ();
1011        call_insn && GET_CODE (call_insn) != CALL_INSN;
1012        call_insn = PREV_INSN (call_insn))
1013     ;
1014
1015   if (! call_insn)
1016     abort ();
1017
1018   /* Put the register usage information on the CALL.  If there is already
1019      some usage information, put ours at the end.  */
1020   if (CALL_INSN_FUNCTION_USAGE (call_insn))
1021     {
1022       rtx link;
1023
1024       for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
1025            link = XEXP (link, 1))
1026         ;
1027
1028       XEXP (link, 1) = call_fusage;
1029     }
1030   else
1031     CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
1032
1033   /* Restore the stack.  */
1034 #ifdef HAVE_save_stack_nonlocal
1035   if (HAVE_save_stack_nonlocal)
1036     emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1037   else
1038 #endif
1039     emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1040
1041   /* Return the address of the result block.  */
1042   return copy_addr_to_reg (XEXP (result, 0));
1043 }
1044
1045 /* Perform an untyped return.  */
1046
1047 static void
1048 expand_builtin_return (result)
1049      rtx result;
1050 {
1051   int size, align, regno;
1052   enum machine_mode mode;
1053   rtx reg;
1054   rtx call_fusage = 0;
1055
1056   apply_result_size ();
1057   result = gen_rtx_MEM (BLKmode, result);
1058
1059 #ifdef HAVE_untyped_return
1060   if (HAVE_untyped_return)
1061     {
1062       emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1063       emit_barrier ();
1064       return;
1065     }
1066 #endif
1067
1068   /* Restore the return value and note that each value is used.  */
1069   size = 0;
1070   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1071     if ((mode = apply_result_mode[regno]) != VOIDmode)
1072       {
1073         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1074         if (size % align != 0)
1075           size = CEIL (size, align) * align;
1076         reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1077         emit_move_insn (reg,
1078                         change_address (result, mode,
1079                                         plus_constant (XEXP (result, 0),
1080                                                        size)));
1081
1082         push_to_sequence (call_fusage);
1083         emit_insn (gen_rtx_USE (VOIDmode, reg));
1084         call_fusage = get_insns ();
1085         end_sequence ();
1086         size += GET_MODE_SIZE (mode);
1087       }
1088
1089   /* Put the USE insns before the return.  */
1090   emit_insns (call_fusage);
1091
1092   /* Return whatever values was restored by jumping directly to the end
1093      of the function.  */
1094   expand_null_return ();
1095 }
1096
1097 /* Expand a call to __builtin_classify_type with arguments found in
1098    ARGLIST.  */
1099 static rtx
1100 expand_builtin_classify_type (arglist)
1101      tree arglist;
1102 {
1103   if (arglist != 0)
1104     {
1105       tree type = TREE_TYPE (TREE_VALUE (arglist));
1106       enum tree_code code = TREE_CODE (type);
1107       if (code == VOID_TYPE)
1108         return GEN_INT (void_type_class);
1109       if (code == INTEGER_TYPE)
1110         return GEN_INT (integer_type_class);
1111       if (code == CHAR_TYPE)
1112         return GEN_INT (char_type_class);
1113       if (code == ENUMERAL_TYPE)
1114         return GEN_INT (enumeral_type_class);
1115       if (code == BOOLEAN_TYPE)
1116         return GEN_INT (boolean_type_class);
1117       if (code == POINTER_TYPE)
1118         return GEN_INT (pointer_type_class);
1119       if (code == REFERENCE_TYPE)
1120         return GEN_INT (reference_type_class);
1121       if (code == OFFSET_TYPE)
1122         return GEN_INT (offset_type_class);
1123       if (code == REAL_TYPE)
1124         return GEN_INT (real_type_class);
1125       if (code == COMPLEX_TYPE)
1126         return GEN_INT (complex_type_class);
1127       if (code == FUNCTION_TYPE)
1128         return GEN_INT (function_type_class);
1129       if (code == METHOD_TYPE)
1130         return GEN_INT (method_type_class);
1131       if (code == RECORD_TYPE)
1132         return GEN_INT (record_type_class);
1133       if (code == UNION_TYPE || code == QUAL_UNION_TYPE)
1134         return GEN_INT (union_type_class);
1135       if (code == ARRAY_TYPE)
1136         {
1137           if (TYPE_STRING_FLAG (type))
1138             return GEN_INT (string_type_class);
1139           else
1140             return GEN_INT (array_type_class);
1141         }
1142       if (code == SET_TYPE)
1143         return GEN_INT (set_type_class);
1144       if (code == FILE_TYPE)
1145         return GEN_INT (file_type_class);
1146       if (code == LANG_TYPE)
1147         return GEN_INT (lang_type_class);
1148     }
1149   return GEN_INT (no_type_class);
1150 }
1151
1152 /* Expand expression EXP, which is a call to __builtin_constant_p.  */
1153 static rtx
1154 expand_builtin_constant_p (exp)
1155      tree exp;
1156 {
1157   tree arglist = TREE_OPERAND (exp, 1);
1158   enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1159
1160   if (arglist == 0)
1161     return const0_rtx;
1162   else
1163     {
1164       tree arg = TREE_VALUE (arglist);
1165       rtx tmp;
1166
1167       /* We return 1 for a numeric type that's known to be a constant
1168          value at compile-time or for an aggregate type that's a
1169          literal constant.  */
1170       STRIP_NOPS (arg);
1171
1172       /* If we know this is a constant, emit the constant of one.  */
1173       if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'c'
1174           || (TREE_CODE (arg) == CONSTRUCTOR
1175               && TREE_CONSTANT (arg))
1176           || (TREE_CODE (arg) == ADDR_EXPR
1177               && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST))
1178         return const1_rtx;
1179
1180       /* If we aren't going to be running CSE or this expression
1181          has side effects, show we don't know it to be a constant.
1182          Likewise if it's a pointer or aggregate type since in those
1183          case we only want literals, since those are only optimized
1184          when generating RTL, not later.  */
1185       if (TREE_SIDE_EFFECTS (arg) || cse_not_expected
1186           || AGGREGATE_TYPE_P (TREE_TYPE (arg))
1187           || POINTER_TYPE_P (TREE_TYPE (arg)))
1188         return const0_rtx;
1189
1190       /* Otherwise, emit (constant_p_rtx (ARG)) and let CSE get a
1191          chance to see if it can deduce whether ARG is constant.  */
1192
1193       tmp = expand_expr (arg, NULL_RTX, VOIDmode, 0);
1194       tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
1195       return tmp;
1196     }
1197 }
1198
1199 /* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1200    Return 0 if a normal call should be emitted rather than expanding the
1201    function in-line.  EXP is the expression that is a call to the builtin
1202    function; if convenient, the result should be placed in TARGET.
1203    SUBTARGET may be used as the target for computing one of EXP's operands.  */
1204 static rtx
1205 expand_builtin_mathfn (exp, target, subtarget)
1206      tree exp;
1207      rtx target, subtarget;
1208 {
1209   optab builtin_optab;  
1210   rtx op0, insns;
1211   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1212   tree arglist = TREE_OPERAND (exp, 1);
1213
1214   if (arglist == 0
1215       /* Arg could be wrong type if user redeclared this fcn wrong.  */
1216       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
1217     return 0;
1218
1219   /* Stabilize and compute the argument.  */
1220   if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
1221       && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
1222     {
1223       exp = copy_node (exp);
1224       TREE_OPERAND (exp, 1) = arglist;
1225       /* Wrap the computation of the argument in a SAVE_EXPR.  That
1226          way, if we need to expand the argument again (as in the
1227          flag_errno_math case below where we cannot directly set
1228          errno), we will not perform side-effects more than once.
1229          Note that here we're mutating the original EXP as well as the
1230          copy; that's the right thing to do in case the original EXP
1231          is expanded later.  */
1232       TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
1233       arglist = copy_node (arglist);
1234     }
1235   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
1236
1237   /* Make a suitable register to place result in.  */
1238   target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
1239
1240   emit_queue ();
1241   start_sequence ();
1242
1243   switch (DECL_FUNCTION_CODE (fndecl))
1244     {
1245      case BUILT_IN_SIN:
1246       builtin_optab = sin_optab; break;
1247      case BUILT_IN_COS:
1248       builtin_optab = cos_optab; break;
1249      case BUILT_IN_FSQRT:
1250       builtin_optab = sqrt_optab; break;
1251      default:
1252       abort ();
1253     }
1254
1255   /* Compute into TARGET.
1256      Set TARGET to wherever the result comes back.  */
1257   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
1258                         builtin_optab, op0, target, 0);
1259
1260   /* If we were unable to expand via the builtin, stop the
1261      sequence (without outputting the insns) and return 0, causing
1262      a call to the library function.  */
1263   if (target == 0)
1264     {
1265       end_sequence ();
1266       return 0;
1267     }
1268
1269   /* Check the results by default.  But if flag_fast_math is turned on,
1270      then assume sqrt will always be called with valid arguments.  */
1271
1272   if (flag_errno_math && ! flag_fast_math)
1273     {
1274       rtx lab1;
1275
1276       /* Don't define the builtin FP instructions
1277          if your machine is not IEEE.  */
1278       if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
1279         abort ();
1280
1281       lab1 = gen_label_rtx ();
1282
1283       /* Test the result; if it is NaN, set errno=EDOM because
1284          the argument was not in the domain.  */
1285       emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1286                                0, 0, lab1);
1287
1288 #ifdef TARGET_EDOM
1289         {
1290 #ifdef GEN_ERRNO_RTX
1291           rtx errno_rtx = GEN_ERRNO_RTX;
1292 #else
1293           rtx errno_rtx
1294             = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1295 #endif
1296
1297           emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1298         }
1299 #else
1300       /* We can't set errno=EDOM directly; let the library call do it.
1301          Pop the arguments right away in case the call gets deleted.  */
1302       NO_DEFER_POP;
1303       expand_call (exp, target, 0);
1304       OK_DEFER_POP;
1305 #endif
1306
1307       emit_label (lab1);
1308     }
1309
1310   /* Output the entire sequence.  */
1311   insns = get_insns ();
1312   end_sequence ();
1313   emit_insns (insns);
1314  
1315   return target;
1316 }
1317
1318 /* Expand expression EXP which is a call to the strlen builtin.  Return 0
1319    if we failed the caller should emit a normal call, otherwise
1320    try to get the result in TARGET, if convenient (and in mode MODE if that's
1321    convenient).  */
1322 static rtx
1323 expand_builtin_strlen (exp, target, mode)
1324      tree exp;
1325      rtx target;
1326      enum machine_mode mode;
1327 {
1328   tree arglist = TREE_OPERAND (exp, 1);
1329   enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1330
1331   if (arglist == 0
1332       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1333       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
1334     return 0;
1335   else
1336     {
1337       rtx pat;
1338       tree src = TREE_VALUE (arglist);
1339       tree len = c_strlen (src);
1340
1341       int align
1342         = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1343
1344       rtx result, src_reg, char_rtx, before_strlen;
1345       enum machine_mode insn_mode = value_mode, char_mode;
1346       enum insn_code icode = CODE_FOR_nothing;
1347
1348       /* If the length is known, just return it.  */
1349       if (len != 0)
1350         return expand_expr (len, target, mode, EXPAND_MEMORY_USE_BAD);
1351
1352       /* If SRC is not a pointer type, don't do this operation inline.  */
1353       if (align == 0)
1354         return 0;
1355
1356       /* Bail out if we can't compute strlen in the right mode.  */
1357       while (insn_mode != VOIDmode)
1358         {
1359           icode = strlen_optab->handlers[(int) insn_mode].insn_code;
1360           if (icode != CODE_FOR_nothing)
1361             break;
1362
1363           insn_mode = GET_MODE_WIDER_MODE (insn_mode);
1364         }
1365       if (insn_mode == VOIDmode)
1366         return 0;
1367
1368       /* Make a place to write the result of the instruction.  */
1369       result = target;
1370       if (! (result != 0
1371              && GET_CODE (result) == REG
1372              && GET_MODE (result) == insn_mode
1373              && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1374         result = gen_reg_rtx (insn_mode);
1375
1376       /* Make a place to hold the source address.  We will not expand
1377          the actual source until we are sure that the expansion will
1378          not fail -- there are trees that cannot be expanded twice.  */
1379       src_reg = gen_reg_rtx (Pmode);
1380
1381       /* Mark the beginning of the strlen sequence so we can emit the
1382          source operand later.  */
1383       before_strlen = get_last_insn();
1384       if (before_strlen == NULL_RTX)
1385         before_strlen = emit_note (0, NOTE_INSN_DELETED);
1386
1387       /* Check the string is readable and has an end.  */
1388       if (current_function_check_memory_usage)
1389         emit_library_call (chkr_check_str_libfunc, 1, VOIDmode, 2,
1390                            src_reg, Pmode,
1391                            GEN_INT (MEMORY_USE_RO),
1392                            TYPE_MODE (integer_type_node));
1393
1394       char_rtx = const0_rtx;
1395       char_mode = insn_data[(int)icode].operand[2].mode;
1396       if (! (*insn_data[(int)icode].operand[2].predicate) (char_rtx, char_mode))
1397         char_rtx = copy_to_mode_reg (char_mode, char_rtx);
1398
1399       pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
1400                              char_rtx, GEN_INT (align));
1401       if (! pat)
1402         return 0;
1403       emit_insn (pat);
1404
1405       /* Now that we are assured of success, expand the source.  */
1406       start_sequence ();
1407       pat = expand_expr (src, src_reg, ptr_mode, EXPAND_SUM);
1408       if (pat != src_reg)
1409         emit_move_insn (src_reg, pat);
1410       pat = gen_sequence ();
1411       end_sequence ();
1412       emit_insn_after (pat, before_strlen);
1413
1414       /* Return the value in the proper mode for this function.  */
1415       if (GET_MODE (result) == value_mode)
1416         target = result;
1417       else if (target != 0)
1418         convert_move (target, result, 0);
1419       else
1420         target = convert_to_mode (value_mode, result, 0);
1421
1422       return target;
1423     }
1424 }
1425
1426 /* Expand a call to the memcpy builtin, with arguments in ARGLIST.  */
1427 static rtx
1428 expand_builtin_memcpy (arglist)
1429      tree arglist;
1430 {
1431   if (arglist == 0
1432       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1433       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1434       || TREE_CHAIN (arglist) == 0
1435       || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1436           != POINTER_TYPE)
1437       || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1438       || (TREE_CODE (TREE_TYPE (TREE_VALUE
1439                                 (TREE_CHAIN (TREE_CHAIN (arglist)))))
1440           != INTEGER_TYPE))
1441     return 0;
1442   else
1443     {
1444       tree dest = TREE_VALUE (arglist);
1445       tree src = TREE_VALUE (TREE_CHAIN (arglist));
1446       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1447
1448       int src_align
1449         = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1450       int dest_align
1451         = get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1452       rtx dest_mem, src_mem, dest_addr, len_rtx;
1453
1454       /* If either SRC or DEST is not a pointer type, don't do
1455          this operation in-line.  */
1456       if (src_align == 0 || dest_align == 0)
1457         return 0;
1458
1459       dest_mem = get_memory_rtx (dest);
1460       src_mem = get_memory_rtx (src);
1461       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1462
1463       /* Just copy the rights of SRC to the rights of DEST.  */
1464       if (current_function_check_memory_usage)
1465         emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
1466                            XEXP (dest_mem, 0), Pmode,
1467                            XEXP (src_mem, 0), Pmode,
1468                            len_rtx, TYPE_MODE (sizetype));
1469
1470       /* Copy word part most expediently.  */
1471       dest_addr
1472         = emit_block_move (dest_mem, src_mem, len_rtx,
1473                            MIN (src_align, dest_align));
1474
1475       if (dest_addr == 0)
1476         dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
1477
1478       return dest_addr;
1479     }
1480 }
1481
1482 /* Expand expression EXP, which is a call to the strcpy builtin.  Return 0
1483    if we failed the caller should emit a normal call.  */
1484
1485 static rtx
1486 expand_builtin_strcpy (exp)
1487      tree exp;
1488 {
1489   tree arglist = TREE_OPERAND (exp, 1);
1490   rtx result;
1491
1492   if (arglist == 0
1493       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1494       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1495       || TREE_CHAIN (arglist) == 0
1496       || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1497           != POINTER_TYPE))
1498     return 0;
1499   else
1500     {
1501       tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
1502
1503       if (len == 0)
1504         return 0;
1505
1506       len = size_binop (PLUS_EXPR, len, ssize_int (1));
1507       chainon (arglist, build_tree_list (NULL_TREE, len));
1508     }
1509
1510   result = expand_builtin_memcpy (arglist);
1511
1512   if (! result)
1513     TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
1514   return result;
1515 }
1516
1517 /* Expand expression EXP, which is a call to the memset builtin.  Return 0
1518    if we failed the caller should emit a normal call.  */
1519
1520 static rtx
1521 expand_builtin_memset (exp)
1522      tree exp;
1523 {
1524   tree arglist = TREE_OPERAND (exp, 1);
1525
1526   if (arglist == 0
1527       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1528       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1529       || TREE_CHAIN (arglist) == 0
1530       || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1531           != INTEGER_TYPE)
1532       || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1533       || (INTEGER_TYPE
1534           != (TREE_CODE (TREE_TYPE
1535                          (TREE_VALUE
1536                           (TREE_CHAIN (TREE_CHAIN (arglist))))))))
1537     return 0;
1538   else
1539     {
1540       tree dest = TREE_VALUE (arglist);
1541       tree val = TREE_VALUE (TREE_CHAIN (arglist));
1542       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1543
1544       int dest_align
1545         = get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1546       rtx dest_mem, dest_addr, len_rtx;
1547
1548       /* If DEST is not a pointer type, don't do this 
1549          operation in-line.  */
1550       if (dest_align == 0)
1551         return 0;
1552
1553       /* If the arguments have side-effects, then we can only evaluate
1554          them at most once.  The following code evaluates them twice if
1555          they are not constants because we break out to expand_call
1556          in that case.  They can't be constants if they have side-effects
1557          so we can check for that first.  Alternatively, we could call
1558          save_expr to make multiple evaluation safe.  */
1559       if (TREE_SIDE_EFFECTS (val) || TREE_SIDE_EFFECTS (len))
1560         return 0;
1561
1562       /* If VAL is not 0, don't do this operation in-line. */
1563       if (expand_expr (val, NULL_RTX, VOIDmode, 0) != const0_rtx)
1564         return 0;
1565
1566       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1567
1568       dest_mem = get_memory_rtx (dest);
1569            
1570       /* Just check DST is writable and mark it as readable.  */
1571       if (current_function_check_memory_usage)
1572         emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
1573                            XEXP (dest_mem, 0), Pmode,
1574                            len_rtx, TYPE_MODE (sizetype),
1575                            GEN_INT (MEMORY_USE_WO),
1576                            TYPE_MODE (integer_type_node));
1577
1578
1579       dest_addr = clear_storage (dest_mem, len_rtx, dest_align);
1580
1581       if (dest_addr == 0)
1582         dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
1583
1584       return dest_addr;
1585     }
1586 }
1587
1588 #ifdef HAVE_cmpstrsi
1589 /* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
1590    ARGLIST is the argument list for this call.  Return 0 if we failed and the
1591    caller should emit a normal call, otherwise try to get the result in
1592    TARGET, if convenient.  */
1593 static rtx
1594 expand_builtin_memcmp (exp, arglist, target)
1595      tree exp;
1596      tree arglist;
1597      rtx target;
1598 {
1599   /* If we need to check memory accesses, call the library function.  */
1600   if (current_function_check_memory_usage)
1601     return 0;
1602
1603   if (arglist == 0
1604       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1605       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1606       || TREE_CHAIN (arglist) == 0
1607       || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
1608       || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1609       || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
1610     return 0;
1611   else if (!HAVE_cmpstrsi)
1612     return 0;
1613
1614   {
1615     enum machine_mode mode;
1616     tree arg1 = TREE_VALUE (arglist);
1617     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
1618     tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1619     rtx result;
1620
1621     int arg1_align
1622       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1623     int arg2_align
1624       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1625     enum machine_mode insn_mode
1626       = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
1627
1628     /* If we don't have POINTER_TYPE, call the function.  */
1629     if (arg1_align == 0 || arg2_align == 0)
1630       return 0;
1631
1632     /* Make a place to write the result of the instruction.  */
1633     result = target;
1634     if (! (result != 0
1635            && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
1636            && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1637       result = gen_reg_rtx (insn_mode);
1638
1639     emit_insn (gen_cmpstrsi (result, get_memory_rtx (arg1),
1640                              get_memory_rtx (arg2),
1641                              expand_expr (len, NULL_RTX, VOIDmode, 0),
1642                              GEN_INT (MIN (arg1_align, arg2_align))));
1643
1644     /* Return the value in the proper mode for this function.  */
1645     mode = TYPE_MODE (TREE_TYPE (exp));
1646     if (GET_MODE (result) == mode)
1647       return result;
1648     else if (target != 0)
1649       {
1650         convert_move (target, result, 0);
1651         return target;
1652       }
1653     else
1654       return convert_to_mode (mode, result, 0);
1655   }
1656 }
1657
1658 /* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
1659    if we failed the caller should emit a normal call, otherwise try to get
1660    the result in TARGET, if convenient.  */
1661
1662 static rtx
1663 expand_builtin_strcmp (exp, target)
1664      tree exp;
1665      rtx target;
1666 {
1667   tree arglist = TREE_OPERAND (exp, 1);
1668
1669   /* If we need to check memory accesses, call the library function.  */
1670   if (current_function_check_memory_usage)
1671     return 0;
1672
1673   if (arglist == 0
1674       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1675       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1676       || TREE_CHAIN (arglist) == 0
1677       || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1678           != POINTER_TYPE))
1679     return 0;
1680
1681   else if (! HAVE_cmpstrsi)
1682     return 0;
1683   {
1684     tree arg1 = TREE_VALUE (arglist);
1685     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
1686     tree len = c_strlen (arg1);
1687     tree len2 = c_strlen (arg2);
1688     rtx result;
1689
1690     if (len)
1691       len = size_binop (PLUS_EXPR, ssize_int (1), len);
1692
1693     if (len2)
1694       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
1695
1696     /* If we don't have a constant length for the first, use the length
1697        of the second, if we know it.  We don't require a constant for
1698        this case; some cost analysis could be done if both are available
1699        but neither is constant.  For now, assume they're equally cheap.
1700
1701        If both strings have constant lengths, use the smaller.  This
1702        could arise if optimization results in strcpy being called with
1703        two fixed strings, or if the code was machine-generated.  We should
1704        add some code to the `memcmp' handler below to deal with such
1705        situations, someday.  */
1706
1707     if (!len || TREE_CODE (len) != INTEGER_CST)
1708       {
1709         if (len2)
1710           len = len2;
1711         else if (len == 0)
1712           return 0;
1713       }
1714     else if (len2 && TREE_CODE (len2) == INTEGER_CST
1715              && tree_int_cst_lt (len2, len))
1716       len = len2;
1717
1718     chainon (arglist, build_tree_list (NULL_TREE, len));
1719     result = expand_builtin_memcmp (exp, arglist, target);
1720     if (! result)
1721       TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
1722
1723     return result;
1724   }
1725 }
1726 #endif
1727
1728 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
1729    if that's convenient.  */
1730
1731 rtx
1732 expand_builtin_saveregs ()
1733 {
1734   rtx val, seq;
1735
1736   /* Don't do __builtin_saveregs more than once in a function.
1737      Save the result of the first call and reuse it.  */
1738   if (saveregs_value != 0)
1739     return saveregs_value;
1740
1741   /* When this function is called, it means that registers must be
1742      saved on entry to this function.  So we migrate the call to the
1743      first insn of this function.  */
1744
1745   start_sequence ();
1746
1747 #ifdef EXPAND_BUILTIN_SAVEREGS
1748   /* Do whatever the machine needs done in this case.  */
1749   val = EXPAND_BUILTIN_SAVEREGS ();
1750 #else
1751   /* ??? We used to try and build up a call to the out of line function,
1752      guessing about what registers needed saving etc.  This became much
1753      harder with __builtin_va_start, since we don't have a tree for a
1754      call to __builtin_saveregs to fall back on.  There was exactly one
1755      port (i860) that used this code, and I'm unconvinced it could actually
1756      handle the general case.  So we no longer try to handle anything
1757      weird and make the backend absorb the evil.  */
1758
1759   error ("__builtin_saveregs not supported by this target");
1760   val = const0_rtx;
1761 #endif
1762
1763   seq = get_insns ();
1764   end_sequence ();
1765
1766   saveregs_value = val;
1767
1768   /* Put the sequence after the NOTE that starts the function.  If this
1769      is inside a SEQUENCE, make the outer-level insn chain current, so
1770      the code is placed at the start of the function.  */
1771   push_topmost_sequence ();
1772   emit_insns_after (seq, get_insns ());
1773   pop_topmost_sequence ();
1774
1775   return val;
1776 }
1777
1778 /* __builtin_args_info (N) returns word N of the arg space info
1779    for the current function.  The number and meanings of words
1780    is controlled by the definition of CUMULATIVE_ARGS.  */
1781 static rtx
1782 expand_builtin_args_info (exp)
1783      tree exp;
1784 {
1785   tree arglist = TREE_OPERAND (exp, 1);
1786   int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
1787   int *word_ptr = (int *) &current_function_args_info;
1788 #if 0   
1789   /* These are used by the code below that is if 0'ed away */
1790   int i;
1791   tree type, elts, result;
1792 #endif
1793
1794   if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
1795     abort ();
1796
1797   if (arglist != 0)
1798     {
1799       tree arg = TREE_VALUE (arglist);
1800       if (TREE_CODE (arg) != INTEGER_CST)
1801         error ("argument of `__builtin_args_info' must be constant");
1802       else
1803         {
1804           int wordnum = TREE_INT_CST_LOW (arg);
1805
1806           if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg))
1807             error ("argument of `__builtin_args_info' out of range");
1808           else
1809             return GEN_INT (word_ptr[wordnum]);
1810         }
1811     }
1812   else
1813     error ("missing argument in `__builtin_args_info'");
1814
1815   return const0_rtx;
1816
1817 #if 0
1818   for (i = 0; i < nwords; i++)
1819     elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
1820
1821   type = build_array_type (integer_type_node,
1822                            build_index_type (build_int_2 (nwords, 0)));
1823   result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
1824   TREE_CONSTANT (result) = 1;
1825   TREE_STATIC (result) = 1;
1826   result = build1 (INDIRECT_REF, build_pointer_type (type), result);
1827   TREE_CONSTANT (result) = 1;
1828   return expand_expr (result, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD);
1829 #endif
1830 }
1831
1832 /* Expand ARGLIST, from a call to __builtin_next_arg.  */
1833 static rtx
1834 expand_builtin_next_arg (arglist)
1835      tree arglist;
1836 {
1837   tree fntype = TREE_TYPE (current_function_decl);
1838
1839   if ((TYPE_ARG_TYPES (fntype) == 0
1840        || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1841            == void_type_node))
1842       && ! current_function_varargs)
1843     {
1844       error ("`va_start' used in function with fixed args");
1845       return const0_rtx;
1846     }
1847
1848   if (arglist)
1849     {
1850       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
1851       tree arg = TREE_VALUE (arglist);
1852
1853       /* Strip off all nops for the sake of the comparison.  This
1854          is not quite the same as STRIP_NOPS.  It does more.  
1855          We must also strip off INDIRECT_EXPR for C++ reference
1856          parameters.  */
1857       while (TREE_CODE (arg) == NOP_EXPR
1858              || TREE_CODE (arg) == CONVERT_EXPR
1859              || TREE_CODE (arg) == NON_LVALUE_EXPR
1860              || TREE_CODE (arg) == INDIRECT_REF)
1861         arg = TREE_OPERAND (arg, 0);
1862       if (arg != last_parm)
1863         warning ("second parameter of `va_start' not last named argument");
1864     }
1865   else if (! current_function_varargs)
1866     /* Evidently an out of date version of <stdarg.h>; can't validate
1867        va_start's second argument, but can still work as intended.  */
1868     warning ("`__builtin_next_arg' called without an argument");
1869
1870   return expand_binop (Pmode, add_optab,
1871                        current_function_internal_arg_pointer,
1872                        current_function_arg_offset_rtx,
1873                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
1874 }
1875
1876 /* Make it easier for the backends by protecting the valist argument
1877    from multiple evaluations.  */
1878
1879 static tree
1880 stabilize_va_list (valist, was_ptr)
1881      tree valist;
1882      int was_ptr;
1883 {
1884   if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
1885     {
1886       /* If stdarg.h took the address of an array-type valist that was passed
1887          as a parameter, we'll have taken the address of the parameter itself
1888          rather than the array as we'd intended.  Undo this mistake.  */
1889
1890       if (was_ptr)
1891         {
1892           STRIP_NOPS (valist);
1893
1894           /* Two cases: either &array, which decomposed to 
1895                 <ptr <array <record> valist>>
1896              or &ptr, which turned into
1897                 <ptr <ptr <record>>>
1898              In the first case we'll need to put the ADDR_EXPR back
1899              after frobbing the types as if &array[0].  */
1900
1901           if (TREE_CODE (valist) != ADDR_EXPR)
1902             abort ();
1903           valist = TREE_OPERAND (valist, 0);
1904         }
1905
1906       if (TYPE_MAIN_VARIANT (TREE_TYPE (valist))
1907           == TYPE_MAIN_VARIANT (va_list_type_node))
1908         {
1909           tree pt = build_pointer_type (TREE_TYPE (va_list_type_node));
1910           valist = build1 (ADDR_EXPR, pt, valist);
1911           TREE_SIDE_EFFECTS (valist)
1912             = TREE_SIDE_EFFECTS (TREE_OPERAND (valist, 0));
1913         }
1914       else
1915         {
1916           if (! POINTER_TYPE_P (TREE_TYPE (valist))
1917               || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (valist)))
1918                   != TYPE_MAIN_VARIANT (TREE_TYPE (va_list_type_node))))
1919             abort ();
1920         }
1921
1922       if (TREE_SIDE_EFFECTS (valist))
1923         valist = save_expr (valist);
1924     }
1925   else
1926     {
1927       if (! was_ptr)
1928         {
1929           tree pt;
1930
1931           if (! TREE_SIDE_EFFECTS (valist))
1932             return valist;
1933
1934           pt = build_pointer_type (va_list_type_node);
1935           valist = fold (build1 (ADDR_EXPR, pt, valist));
1936           TREE_SIDE_EFFECTS (valist) = 1;
1937         }
1938       if (TREE_SIDE_EFFECTS (valist))
1939         valist = save_expr (valist);
1940       valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
1941                              valist));
1942     }
1943
1944   return valist;
1945 }
1946
1947 /* The "standard" implementation of va_start: just assign `nextarg' to
1948    the variable.  */
1949 void
1950 std_expand_builtin_va_start (stdarg_p, valist, nextarg)
1951      int stdarg_p ATTRIBUTE_UNUSED;
1952      tree valist;
1953      rtx nextarg;
1954 {
1955   tree t;
1956
1957   if (!stdarg_p)
1958     nextarg = plus_constant (nextarg, -UNITS_PER_WORD);
1959
1960   t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
1961              make_tree (ptr_type_node, nextarg));
1962   TREE_SIDE_EFFECTS (t) = 1;
1963
1964   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1965 }
1966
1967 /* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
1968    __builtin_varargs_va_start, depending on STDARG_P.  */
1969 static rtx
1970 expand_builtin_va_start (stdarg_p, arglist)
1971      int stdarg_p;
1972      tree arglist;
1973 {
1974   rtx nextarg;
1975   tree chain = arglist, valist;
1976
1977   if (stdarg_p)
1978     nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
1979   else
1980     nextarg = expand_builtin_next_arg (NULL_TREE);
1981
1982   if (TREE_CHAIN (chain))
1983     error ("too many arguments to function `va_start'");
1984
1985   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
1986
1987 #ifdef EXPAND_BUILTIN_VA_START
1988   EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
1989 #else
1990   std_expand_builtin_va_start (stdarg_p, valist, nextarg);
1991 #endif
1992
1993   return const0_rtx;
1994 }
1995
1996 /* Allocate an alias set for use in storing and reading from the varargs
1997    spill area.  */
1998 int
1999 get_varargs_alias_set ()
2000 {
2001   static int set = -1;
2002   if (set == -1)
2003     set = new_alias_set ();
2004   return set;
2005 }
2006
2007 /* The "standard" implementation of va_arg: read the value from the
2008    current (padded) address and increment by the (padded) size.  */
2009 rtx
2010 std_expand_builtin_va_arg (valist, type)
2011      tree valist, type;
2012 {
2013   tree addr_tree, t;
2014   HOST_WIDE_INT align;
2015   HOST_WIDE_INT rounded_size;
2016   rtx addr;
2017
2018   /* Compute the rounded size of the type.  */
2019   align = PARM_BOUNDARY / BITS_PER_UNIT;
2020   rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
2021
2022   /* Get AP.  */
2023   addr_tree = valist;
2024   if (PAD_VARARGS_DOWN)
2025     {
2026       /* Small args are padded downward.  */
2027
2028       HOST_WIDE_INT adj;
2029       adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT;
2030       if (rounded_size > align)
2031         adj = rounded_size;
2032
2033       addr_tree = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
2034                          build_int_2 (rounded_size - adj, 0));
2035     }
2036
2037   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2038   addr = copy_to_reg (addr);
2039
2040   /* Compute new value for AP.  */
2041   t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2042              build (PLUS_EXPR, TREE_TYPE (valist), valist,
2043                     build_int_2 (rounded_size, 0)));
2044   TREE_SIDE_EFFECTS (t) = 1;
2045   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2046
2047   return addr;
2048 }
2049
2050 /* Expand __builtin_va_arg, which is not really a builtin function, but
2051    a very special sort of operator.  */
2052 rtx
2053 expand_builtin_va_arg (valist, type)
2054      tree valist, type;
2055 {
2056   rtx addr, result;
2057   tree promoted_type, want_va_type, have_va_type;
2058
2059   /* Verify that valist is of the proper type.  */
2060
2061   want_va_type = va_list_type_node;
2062   have_va_type = TREE_TYPE (valist);
2063   if (TREE_CODE (want_va_type) == ARRAY_TYPE)
2064     {
2065       /* If va_list is an array type, the argument may have decayed 
2066          to a pointer type, e.g. by being passed to another function.
2067          In that case, unwrap both types so that we can compare the
2068          underlying records.  */
2069       if (TREE_CODE (have_va_type) == ARRAY_TYPE
2070           || TREE_CODE (have_va_type) == POINTER_TYPE)
2071         {
2072           want_va_type = TREE_TYPE (want_va_type);
2073           have_va_type = TREE_TYPE (have_va_type);
2074         }
2075     }
2076   if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
2077     {
2078       error ("first argument to `va_arg' not of type `va_list'");
2079       addr = const0_rtx;
2080     }
2081
2082   /* Generate a diagnostic for requesting data of a type that cannot
2083      be passed through `...' due to type promotion at the call site.  */
2084   else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
2085     {
2086       const char *name = "<anonymous type>", *pname = 0;
2087       static int gave_help;
2088
2089       if (TYPE_NAME (type))
2090         {
2091           if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
2092             name = IDENTIFIER_POINTER (TYPE_NAME (type));
2093           else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
2094                    && DECL_NAME (TYPE_NAME (type)))
2095             name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
2096         }
2097       if (TYPE_NAME (promoted_type))
2098         {
2099           if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
2100             pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
2101           else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
2102                    && DECL_NAME (TYPE_NAME (promoted_type)))
2103             pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
2104         }
2105
2106       error ("`%s' is promoted to `%s' when passed through `...'", name, pname);
2107       if (! gave_help)
2108         {
2109           gave_help = 1;
2110           error ("(so you should pass `%s' not `%s' to `va_arg')", pname, name);
2111         }
2112
2113       addr = const0_rtx;
2114     }
2115   else
2116     {
2117       /* Make it easier for the backends by protecting the valist argument
2118          from multiple evaluations.  */
2119       valist = stabilize_va_list (valist, 0);
2120
2121 #ifdef EXPAND_BUILTIN_VA_ARG
2122       addr = EXPAND_BUILTIN_VA_ARG (valist, type);
2123 #else
2124       addr = std_expand_builtin_va_arg (valist, type);
2125 #endif
2126     }
2127
2128   result = gen_rtx_MEM (TYPE_MODE (type), addr);
2129   MEM_ALIAS_SET (result) = get_varargs_alias_set ();
2130
2131   return result;
2132 }
2133
2134 /* Expand ARGLIST, from a call to __builtin_va_end.  */
2135 static rtx
2136 expand_builtin_va_end (arglist)
2137      tree arglist;
2138 {
2139   tree valist = TREE_VALUE (arglist);
2140
2141 #ifdef EXPAND_BUILTIN_VA_END
2142   valist = stabilize_va_list (valist, 0);
2143   EXPAND_BUILTIN_VA_END(arglist);
2144 #else
2145   /* Evaluate for side effects, if needed.  I hate macros that don't
2146      do that.  */
2147   if (TREE_SIDE_EFFECTS (valist))
2148     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
2149 #endif
2150
2151   return const0_rtx;
2152 }
2153
2154 /* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a 
2155    builtin rather than just as an assignment in stdarg.h because of the
2156    nastiness of array-type va_list types.  */
2157 static rtx
2158 expand_builtin_va_copy (arglist)
2159      tree arglist;
2160 {
2161   tree dst, src, t;
2162
2163   dst = TREE_VALUE (arglist);
2164   src = TREE_VALUE (TREE_CHAIN (arglist));
2165
2166   dst = stabilize_va_list (dst, 1);
2167   src = stabilize_va_list (src, 0);
2168
2169   if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
2170     {
2171       t = build (MODIFY_EXPR, va_list_type_node, dst, src);
2172       TREE_SIDE_EFFECTS (t) = 1;
2173       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2174     }
2175   else
2176     {
2177       rtx dstb, srcb, size;
2178
2179       /* Evaluate to pointers.  */
2180       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
2181       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
2182       size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
2183                           VOIDmode, EXPAND_NORMAL);
2184
2185       /* "Dereference" to BLKmode memories.  */
2186       dstb = gen_rtx_MEM (BLKmode, dstb);
2187       MEM_ALIAS_SET (dstb) = get_alias_set (TREE_TYPE (TREE_TYPE (dst)));
2188       srcb = gen_rtx_MEM (BLKmode, srcb);
2189       MEM_ALIAS_SET (srcb) = get_alias_set (TREE_TYPE (TREE_TYPE (src)));
2190
2191       /* Copy.  */
2192       emit_block_move (dstb, srcb, size, 
2193                        TYPE_ALIGN (va_list_type_node) / BITS_PER_UNIT);
2194     }
2195
2196   return const0_rtx;
2197 }
2198
2199 /* Expand a call to one of the builtin functions __builtin_frame_address or
2200    __builtin_return_address.  */
2201 static rtx
2202 expand_builtin_frame_address (exp)
2203      tree exp;
2204 {
2205   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2206   tree arglist = TREE_OPERAND (exp, 1);
2207
2208   /* The argument must be a nonnegative integer constant.
2209      It counts the number of frames to scan up the stack.
2210      The value is the return address saved in that frame.  */
2211   if (arglist == 0)
2212     /* Warning about missing arg was already issued.  */
2213     return const0_rtx;
2214   else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST
2215            || tree_int_cst_sgn (TREE_VALUE (arglist)) < 0)
2216     {
2217       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2218         error ("invalid arg to `__builtin_frame_address'");
2219       else
2220         error ("invalid arg to `__builtin_return_address'");
2221       return const0_rtx;
2222     }
2223   else
2224     {
2225       rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
2226                                             TREE_INT_CST_LOW (TREE_VALUE (arglist)),
2227                                             hard_frame_pointer_rtx);
2228
2229       /* Some ports cannot access arbitrary stack frames.  */
2230       if (tem == NULL)
2231         {
2232           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2233             warning ("unsupported arg to `__builtin_frame_address'");
2234           else
2235             warning ("unsupported arg to `__builtin_return_address'");
2236           return const0_rtx;
2237         }
2238
2239       /* For __builtin_frame_address, return what we've got.  */
2240       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2241         return tem;
2242
2243       if (GET_CODE (tem) != REG
2244           && ! CONSTANT_P (tem))
2245         tem = copy_to_mode_reg (Pmode, tem);
2246       return tem;
2247     }
2248 }
2249
2250 /* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
2251    we failed and the caller should emit a normal call, otherwise try to get
2252    the result in TARGET, if convenient.  */
2253 static rtx
2254 expand_builtin_alloca (arglist, target)
2255      tree arglist;
2256      rtx target;
2257 {
2258   rtx op0;
2259
2260   if (arglist == 0
2261       /* Arg could be non-integer if user redeclared this fcn wrong.  */
2262       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
2263     return 0;
2264
2265   /* Compute the argument.  */
2266   op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
2267
2268   /* Allocate the desired space.  */
2269   return allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
2270 }
2271
2272 /* Expand a call to the ffs builtin.  The arguments are in ARGLIST.
2273    Return 0 if a normal call should be emitted rather than expanding the
2274    function in-line.  If convenient, the result should be placed in TARGET.
2275    SUBTARGET may be used as the target for computing one of EXP's operands.  */
2276 static rtx
2277 expand_builtin_ffs (arglist, target, subtarget)
2278      tree arglist;
2279      rtx target, subtarget;
2280 {
2281   rtx op0;
2282   if (arglist == 0
2283       /* Arg could be non-integer if user redeclared this fcn wrong.  */
2284       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
2285     return 0;
2286
2287   /* Compute the argument.  */
2288   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
2289   /* Compute ffs, into TARGET if possible.
2290      Set TARGET to wherever the result comes back.  */
2291   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
2292                         ffs_optab, op0, target, 1);
2293   if (target == 0)
2294     abort ();
2295   return target;
2296 }
2297 \f
2298 /* Expand an expression EXP that calls a built-in function,
2299    with result going to TARGET if that's convenient
2300    (and in mode MODE if that's convenient).
2301    SUBTARGET may be used as the target for computing one of EXP's operands.
2302    IGNORE is nonzero if the value is to be ignored.  */
2303
2304 rtx
2305 expand_builtin (exp, target, subtarget, mode, ignore)
2306      tree exp;
2307      rtx target;
2308      rtx subtarget;
2309      enum machine_mode mode;
2310      int ignore;
2311 {
2312   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2313   tree arglist = TREE_OPERAND (exp, 1);
2314   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
2315
2316 #ifdef MD_EXPAND_BUILTIN
2317   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
2318     return MD_EXPAND_BUILTIN (exp, target, subtarget, mode, ignore);
2319 #endif
2320   
2321   /* When not optimizing, generate calls to library functions for a certain
2322      set of builtins.  */
2323   if (! optimize && ! CALLED_AS_BUILT_IN (fndecl)
2324       && (fcode == BUILT_IN_SIN || fcode == BUILT_IN_COS
2325           || fcode == BUILT_IN_FSQRT || fcode == BUILT_IN_MEMSET
2326           || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
2327           || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
2328           || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS))
2329     return expand_call (exp, target, ignore);
2330
2331   switch (fcode)
2332     {
2333     case BUILT_IN_ABS:
2334     case BUILT_IN_LABS:
2335     case BUILT_IN_FABS:
2336       /* build_function_call changes these into ABS_EXPR.  */
2337       abort ();
2338
2339     case BUILT_IN_SIN:
2340     case BUILT_IN_COS:
2341       /* Treat these like sqrt, but only if the user asks for them.  */
2342       if (! flag_fast_math)
2343         break;
2344     case BUILT_IN_FSQRT:
2345       target = expand_builtin_mathfn (exp, target, subtarget);
2346       if (target)
2347         return target;
2348       break;
2349
2350     case BUILT_IN_FMOD:
2351       break;
2352
2353     case BUILT_IN_APPLY_ARGS:
2354       return expand_builtin_apply_args ();
2355
2356       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
2357          FUNCTION with a copy of the parameters described by
2358          ARGUMENTS, and ARGSIZE.  It returns a block of memory
2359          allocated on the stack into which is stored all the registers
2360          that might possibly be used for returning the result of a
2361          function.  ARGUMENTS is the value returned by
2362          __builtin_apply_args.  ARGSIZE is the number of bytes of
2363          arguments that must be copied.  ??? How should this value be
2364          computed?  We'll also need a safe worst case value for varargs
2365          functions.  */
2366     case BUILT_IN_APPLY:
2367       if (arglist == 0
2368           /* Arg could be non-pointer if user redeclared this fcn wrong.  */
2369           || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
2370           || TREE_CHAIN (arglist) == 0
2371           || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
2372           || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
2373           || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
2374         return const0_rtx;
2375       else
2376         {
2377           int i;
2378           tree t;
2379           rtx ops[3];
2380
2381           for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
2382             ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
2383
2384           return expand_builtin_apply (ops[0], ops[1], ops[2]);
2385         }
2386
2387       /* __builtin_return (RESULT) causes the function to return the
2388          value described by RESULT.  RESULT is address of the block of
2389          memory returned by __builtin_apply.  */
2390     case BUILT_IN_RETURN:
2391       if (arglist
2392           /* Arg could be non-pointer if user redeclared this fcn wrong.  */
2393           && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
2394         expand_builtin_return (expand_expr (TREE_VALUE (arglist),
2395                                             NULL_RTX, VOIDmode, 0));
2396       return const0_rtx;
2397
2398     case BUILT_IN_SAVEREGS:
2399       return expand_builtin_saveregs ();
2400
2401     case BUILT_IN_ARGS_INFO:
2402       return expand_builtin_args_info (exp);
2403
2404       /* Return the address of the first anonymous stack arg.  */
2405     case BUILT_IN_NEXT_ARG:
2406       return expand_builtin_next_arg (arglist);
2407
2408     case BUILT_IN_CLASSIFY_TYPE:
2409       return expand_builtin_classify_type (arglist);
2410
2411     case BUILT_IN_CONSTANT_P:
2412       return expand_builtin_constant_p (exp);
2413
2414     case BUILT_IN_FRAME_ADDRESS:
2415     case BUILT_IN_RETURN_ADDRESS:
2416       return expand_builtin_frame_address (exp);
2417
2418     /* Returns the address of the area where the structure is returned.
2419        0 otherwise.  */
2420     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
2421       if (arglist != 0
2422           || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
2423           || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
2424         return const0_rtx;
2425       else
2426         return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
2427
2428     case BUILT_IN_ALLOCA:
2429       target = expand_builtin_alloca (arglist, target);
2430       if (target)
2431         return target;
2432       break;
2433
2434     case BUILT_IN_FFS:
2435       target = expand_builtin_ffs (arglist, target, subtarget);
2436       if (target)
2437         return target;
2438       break;
2439
2440     case BUILT_IN_STRLEN:
2441       target = expand_builtin_strlen (exp, target, mode);
2442       if (target)
2443         return target;
2444       break;
2445
2446     case BUILT_IN_STRCPY:
2447       target = expand_builtin_strcpy (exp);
2448       if (target)
2449         return target;
2450       break;
2451       
2452     case BUILT_IN_MEMCPY:
2453       target = expand_builtin_memcpy (arglist);
2454       if (target)
2455         return target;
2456       break;
2457
2458     case BUILT_IN_MEMSET:
2459       target = expand_builtin_memset (exp);
2460       if (target)
2461         return target;
2462       break;
2463
2464 /* These comparison functions need an instruction that returns an actual
2465    index.  An ordinary compare that just sets the condition codes
2466    is not enough.  */
2467 #ifdef HAVE_cmpstrsi
2468     case BUILT_IN_STRCMP:
2469       target = expand_builtin_strcmp (exp, target);
2470       if (target)
2471         return target;
2472       break;
2473
2474     case BUILT_IN_MEMCMP:
2475       target = expand_builtin_memcmp (exp, arglist, target);
2476       if (target)
2477         return target;
2478       break;
2479 #else
2480     case BUILT_IN_STRCMP:
2481     case BUILT_IN_MEMCMP:
2482       break;
2483 #endif
2484
2485     case BUILT_IN_SETJMP:
2486       if (arglist == 0
2487           || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
2488         break;
2489       else
2490         {
2491           rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
2492                                       VOIDmode, 0);
2493           rtx lab = gen_label_rtx ();
2494           rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab);
2495           emit_label (lab);
2496           return ret;
2497         }
2498
2499       /* __builtin_longjmp is passed a pointer to an array of five words.
2500          It's similar to the C library longjmp function but works with
2501          __builtin_setjmp above.  */
2502     case BUILT_IN_LONGJMP:
2503       if (arglist == 0 || TREE_CHAIN (arglist) == 0
2504           || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
2505         break;
2506       else
2507         {
2508           rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
2509                                       VOIDmode, 0);
2510           rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
2511                                    NULL_RTX, VOIDmode, 0);
2512
2513           if (value != const1_rtx)
2514             {
2515               error ("__builtin_longjmp second argument must be 1");
2516               return const0_rtx;
2517             }
2518
2519           expand_builtin_longjmp (buf_addr, value);
2520           return const0_rtx;
2521         }
2522
2523     case BUILT_IN_TRAP:
2524 #ifdef HAVE_trap
2525       if (HAVE_trap)
2526         emit_insn (gen_trap ());
2527       else
2528 #endif
2529         error ("__builtin_trap not supported by this target");
2530       emit_barrier ();
2531       return const0_rtx;
2532
2533       /* Various hooks for the DWARF 2 __throw routine.  */
2534     case BUILT_IN_UNWIND_INIT:
2535       expand_builtin_unwind_init ();
2536       return const0_rtx;
2537     case BUILT_IN_DWARF_CFA:
2538       return virtual_cfa_rtx;
2539 #ifdef DWARF2_UNWIND_INFO
2540     case BUILT_IN_DWARF_FP_REGNUM:
2541       return expand_builtin_dwarf_fp_regnum ();
2542     case BUILT_IN_INIT_DWARF_REG_SIZES:
2543       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
2544       return const0_rtx;
2545 #endif
2546     case BUILT_IN_FROB_RETURN_ADDR:
2547       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
2548     case BUILT_IN_EXTRACT_RETURN_ADDR:
2549       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
2550     case BUILT_IN_EH_RETURN:
2551       expand_builtin_eh_return (TREE_VALUE (arglist),
2552                                 TREE_VALUE (TREE_CHAIN (arglist)),
2553                                 TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
2554       return const0_rtx;
2555     case BUILT_IN_VARARGS_START:
2556       return expand_builtin_va_start (0, arglist);
2557     case BUILT_IN_STDARG_START:
2558       return expand_builtin_va_start (1, arglist);
2559     case BUILT_IN_VA_END:
2560       return expand_builtin_va_end (arglist);
2561     case BUILT_IN_VA_COPY:
2562       return expand_builtin_va_copy (arglist);
2563
2564     default:                    /* just do library call, if unknown builtin */
2565       error ("built-in function `%s' not currently supported",
2566              IDENTIFIER_POINTER (DECL_NAME (fndecl)));
2567     }
2568
2569   /* The switch statement above can drop through to cause the function
2570      to be called normally.  */
2571   return expand_call (exp, target, ignore);
2572 }