OSDN Git Service

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