OSDN Git Service

Daily bump.
[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
562   /* memcpy, memset and other builtin stringops can alias with anything. */
563   MEM_ALIAS_SET (mem) = 0;
564   return mem;
565 }
566 \f
567 /* Built-in functions to perform an untyped call and return.  */
568
569 /* For each register that may be used for calling a function, this
570    gives a mode used to copy the register's value.  VOIDmode indicates
571    the register is not used for calling a function.  If the machine
572    has register windows, this gives only the outbound registers.
573    INCOMING_REGNO gives the corresponding inbound register.  */
574 static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
575
576 /* For each register that may be used for returning values, this gives
577    a mode used to copy the register's value.  VOIDmode indicates the
578    register is not used for returning values.  If the machine has
579    register windows, this gives only the outbound registers.
580    INCOMING_REGNO gives the corresponding inbound register.  */
581 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
582
583 /* For each register that may be used for calling a function, this
584    gives the offset of that register into the block returned by
585    __builtin_apply_args.  0 indicates that the register is not
586    used for calling a function.  */
587 static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
588
589 /* Return the offset of register REGNO into the block returned by 
590    __builtin_apply_args.  This is not declared static, since it is
591    needed in objc-act.c.  */
592
593 int 
594 apply_args_register_offset (regno)
595      int regno;
596 {
597   apply_args_size ();
598
599   /* Arguments are always put in outgoing registers (in the argument
600      block) if such make sense.  */
601 #ifdef OUTGOING_REGNO
602   regno = OUTGOING_REGNO(regno);
603 #endif
604   return apply_args_reg_offset[regno];
605 }
606
607 /* Return the size required for the block returned by __builtin_apply_args,
608    and initialize apply_args_mode.  */
609
610 static int
611 apply_args_size ()
612 {
613   static int size = -1;
614   int align, regno;
615   enum machine_mode mode;
616
617   /* The values computed by this function never change.  */
618   if (size < 0)
619     {
620       /* The first value is the incoming arg-pointer.  */
621       size = GET_MODE_SIZE (Pmode);
622
623       /* The second value is the structure value address unless this is
624          passed as an "invisible" first argument.  */
625       if (struct_value_rtx)
626         size += GET_MODE_SIZE (Pmode);
627
628       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
629         if (FUNCTION_ARG_REGNO_P (regno))
630           {
631             /* Search for the proper mode for copying this register's
632                value.  I'm not sure this is right, but it works so far.  */
633             enum machine_mode best_mode = VOIDmode;
634
635             for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
636                  mode != VOIDmode;
637                  mode = GET_MODE_WIDER_MODE (mode))
638               if (HARD_REGNO_MODE_OK (regno, mode)
639                   && HARD_REGNO_NREGS (regno, mode) == 1)
640                 best_mode = mode;
641
642             if (best_mode == VOIDmode)
643               for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
644                    mode != VOIDmode;
645                    mode = GET_MODE_WIDER_MODE (mode))
646                 if (HARD_REGNO_MODE_OK (regno, mode)
647                     && (mov_optab->handlers[(int) mode].insn_code
648                         != CODE_FOR_nothing))
649                   best_mode = mode;
650
651             mode = best_mode;
652             if (mode == VOIDmode)
653               abort ();
654
655             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
656             if (size % align != 0)
657               size = CEIL (size, align) * align;
658             apply_args_reg_offset[regno] = size;
659             size += GET_MODE_SIZE (mode);
660             apply_args_mode[regno] = mode;
661           }
662         else
663           {
664             apply_args_mode[regno] = VOIDmode;
665             apply_args_reg_offset[regno] = 0;
666           }
667     }
668   return size;
669 }
670
671 /* Return the size required for the block returned by __builtin_apply,
672    and initialize apply_result_mode.  */
673
674 static int
675 apply_result_size ()
676 {
677   static int size = -1;
678   int align, regno;
679   enum machine_mode mode;
680
681   /* The values computed by this function never change.  */
682   if (size < 0)
683     {
684       size = 0;
685
686       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
687         if (FUNCTION_VALUE_REGNO_P (regno))
688           {
689             /* Search for the proper mode for copying this register's
690                value.  I'm not sure this is right, but it works so far.  */
691             enum machine_mode best_mode = VOIDmode;
692
693             for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
694                  mode != TImode;
695                  mode = GET_MODE_WIDER_MODE (mode))
696               if (HARD_REGNO_MODE_OK (regno, mode))
697                 best_mode = mode;
698
699             if (best_mode == VOIDmode)
700               for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
701                    mode != VOIDmode;
702                    mode = GET_MODE_WIDER_MODE (mode))
703                 if (HARD_REGNO_MODE_OK (regno, mode)
704                     && (mov_optab->handlers[(int) mode].insn_code
705                         != CODE_FOR_nothing))
706                   best_mode = mode;
707
708             mode = best_mode;
709             if (mode == VOIDmode)
710               abort ();
711
712             align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
713             if (size % align != 0)
714               size = CEIL (size, align) * align;
715             size += GET_MODE_SIZE (mode);
716             apply_result_mode[regno] = mode;
717           }
718         else
719           apply_result_mode[regno] = VOIDmode;
720
721       /* Allow targets that use untyped_call and untyped_return to override
722          the size so that machine-specific information can be stored here.  */
723 #ifdef APPLY_RESULT_SIZE
724       size = APPLY_RESULT_SIZE;
725 #endif
726     }
727   return size;
728 }
729
730 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
731 /* Create a vector describing the result block RESULT.  If SAVEP is true,
732    the result block is used to save the values; otherwise it is used to
733    restore the values.  */
734
735 static rtx
736 result_vector (savep, result)
737      int savep;
738      rtx result;
739 {
740   int regno, size, align, nelts;
741   enum machine_mode mode;
742   rtx reg, mem;
743   rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
744   
745   size = nelts = 0;
746   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
747     if ((mode = apply_result_mode[regno]) != VOIDmode)
748       {
749         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
750         if (size % align != 0)
751           size = CEIL (size, align) * align;
752         reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
753         mem = change_address (result, mode,
754                               plus_constant (XEXP (result, 0), size));
755         savevec[nelts++] = (savep
756                             ? gen_rtx_SET (VOIDmode, mem, reg)
757                             : gen_rtx_SET (VOIDmode, reg, mem));
758         size += GET_MODE_SIZE (mode);
759       }
760   return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
761 }
762 #endif /* HAVE_untyped_call or HAVE_untyped_return */
763
764 /* Save the state required to perform an untyped call with the same
765    arguments as were passed to the current function.  */
766
767 static rtx
768 expand_builtin_apply_args_1 ()
769 {
770   rtx registers;
771   int size, align, regno;
772   enum machine_mode mode;
773
774   /* Create a block where the arg-pointer, structure value address,
775      and argument registers can be saved.  */
776   registers = assign_stack_local (BLKmode, apply_args_size (), -1);
777
778   /* Walk past the arg-pointer and structure value address.  */
779   size = GET_MODE_SIZE (Pmode);
780   if (struct_value_rtx)
781     size += GET_MODE_SIZE (Pmode);
782
783   /* Save each register used in calling a function to the block.  */
784   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
785     if ((mode = apply_args_mode[regno]) != VOIDmode)
786       {
787         rtx tem;
788
789         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
790         if (size % align != 0)
791           size = CEIL (size, align) * align;
792
793         tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
794
795         emit_move_insn (change_address (registers, mode,
796                                         plus_constant (XEXP (registers, 0),
797                                                        size)),
798                         tem);
799         size += GET_MODE_SIZE (mode);
800       }
801
802   /* Save the arg pointer to the block.  */
803   emit_move_insn (change_address (registers, Pmode, XEXP (registers, 0)),
804                   copy_to_reg (virtual_incoming_args_rtx));
805   size = GET_MODE_SIZE (Pmode);
806
807   /* Save the structure value address unless this is passed as an
808      "invisible" first argument.  */
809   if (struct_value_incoming_rtx)
810     {
811       emit_move_insn (change_address (registers, Pmode,
812                                       plus_constant (XEXP (registers, 0),
813                                                      size)),
814                       copy_to_reg (struct_value_incoming_rtx));
815       size += GET_MODE_SIZE (Pmode);
816     }
817
818   /* Return the address of the block.  */
819   return copy_addr_to_reg (XEXP (registers, 0));
820 }
821
822 /* __builtin_apply_args returns block of memory allocated on
823    the stack into which is stored the arg pointer, structure
824    value address, static chain, and all the registers that might
825    possibly be used in performing a function call.  The code is
826    moved to the start of the function so the incoming values are
827    saved.  */
828 static rtx
829 expand_builtin_apply_args ()
830 {
831   /* Don't do __builtin_apply_args more than once in a function.
832      Save the result of the first call and reuse it.  */
833   if (apply_args_value != 0)
834     return apply_args_value;
835   {
836     /* When this function is called, it means that registers must be
837        saved on entry to this function.  So we migrate the
838        call to the first insn of this function.  */
839     rtx temp;
840     rtx seq;
841
842     start_sequence ();
843     temp = expand_builtin_apply_args_1 ();
844     seq = get_insns ();
845     end_sequence ();
846
847     apply_args_value = temp;
848
849     /* Put the sequence after the NOTE that starts the function.
850        If this is inside a SEQUENCE, make the outer-level insn
851        chain current, so the code is placed at the start of the
852        function.  */
853     push_topmost_sequence ();
854     emit_insns_before (seq, NEXT_INSN (get_insns ()));
855     pop_topmost_sequence ();
856     return temp;
857   }
858 }
859
860 /* Perform an untyped call and save the state required to perform an
861    untyped return of whatever value was returned by the given function.  */
862
863 static rtx
864 expand_builtin_apply (function, arguments, argsize)
865      rtx function, arguments, argsize;
866 {
867   int size, align, regno;
868   enum machine_mode mode;
869   rtx incoming_args, result, reg, dest, call_insn;
870   rtx old_stack_level = 0;
871   rtx call_fusage = 0;
872
873   /* Create a block where the return registers can be saved.  */
874   result = assign_stack_local (BLKmode, apply_result_size (), -1);
875
876   /* Fetch the arg pointer from the ARGUMENTS block.  */
877   incoming_args = gen_reg_rtx (Pmode);
878   emit_move_insn (incoming_args,
879                   gen_rtx_MEM (Pmode, arguments));
880 #ifndef STACK_GROWS_DOWNWARD
881   incoming_args = expand_binop (Pmode, sub_optab, incoming_args, argsize,
882                                 incoming_args, 0, OPTAB_LIB_WIDEN);
883 #endif
884
885   /* Perform postincrements before actually calling the function.  */
886   emit_queue ();
887
888   /* Push a new argument block and copy the arguments.  */
889   do_pending_stack_adjust ();
890
891   /* Save the stack with nonlocal if available */
892 #ifdef HAVE_save_stack_nonlocal
893   if (HAVE_save_stack_nonlocal)
894     emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
895   else
896 #endif
897     emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
898
899   /* Push a block of memory onto the stack to store the memory arguments.
900      Save the address in a register, and copy the memory arguments.  ??? I
901      haven't figured out how the calling convention macros effect this,
902      but it's likely that the source and/or destination addresses in
903      the block copy will need updating in machine specific ways.  */
904   dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
905   emit_block_move (gen_rtx_MEM (BLKmode, dest),
906                    gen_rtx_MEM (BLKmode, incoming_args),
907                    argsize, PARM_BOUNDARY);
908
909   /* Refer to the argument block.  */
910   apply_args_size ();
911   arguments = gen_rtx_MEM (BLKmode, arguments);
912
913   /* Walk past the arg-pointer and structure value address.  */
914   size = GET_MODE_SIZE (Pmode);
915   if (struct_value_rtx)
916     size += GET_MODE_SIZE (Pmode);
917
918   /* Restore each of the registers previously saved.  Make USE insns
919      for each of these registers for use in making the call.  */
920   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
921     if ((mode = apply_args_mode[regno]) != VOIDmode)
922       {
923         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
924         if (size % align != 0)
925           size = CEIL (size, align) * align;
926         reg = gen_rtx_REG (mode, regno);
927         emit_move_insn (reg,
928                         change_address (arguments, mode,
929                                         plus_constant (XEXP (arguments, 0),
930                                                        size)));
931
932         use_reg (&call_fusage, reg);
933         size += GET_MODE_SIZE (mode);
934       }
935
936   /* Restore the structure value address unless this is passed as an
937      "invisible" first argument.  */
938   size = GET_MODE_SIZE (Pmode);
939   if (struct_value_rtx)
940     {
941       rtx value = gen_reg_rtx (Pmode);
942       emit_move_insn (value,
943                       change_address (arguments, Pmode,
944                                       plus_constant (XEXP (arguments, 0),
945                                                      size)));
946       emit_move_insn (struct_value_rtx, value);
947       if (GET_CODE (struct_value_rtx) == REG)
948           use_reg (&call_fusage, struct_value_rtx);
949       size += GET_MODE_SIZE (Pmode);
950     }
951
952   /* All arguments and registers used for the call are set up by now!  */
953   function = prepare_call_address (function, NULL_TREE, &call_fusage, 0);
954
955   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
956      and we don't want to load it into a register as an optimization,
957      because prepare_call_address already did it if it should be done.  */
958   if (GET_CODE (function) != SYMBOL_REF)
959     function = memory_address (FUNCTION_MODE, function);
960
961   /* Generate the actual call instruction and save the return value.  */
962 #ifdef HAVE_untyped_call
963   if (HAVE_untyped_call)
964     emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
965                                       result, result_vector (1, result)));
966   else
967 #endif
968 #ifdef HAVE_call_value
969   if (HAVE_call_value)
970     {
971       rtx valreg = 0;
972
973       /* Locate the unique return register.  It is not possible to
974          express a call that sets more than one return register using
975          call_value; use untyped_call for that.  In fact, untyped_call
976          only needs to save the return registers in the given block.  */
977       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
978         if ((mode = apply_result_mode[regno]) != VOIDmode)
979           {
980             if (valreg)
981               abort (); /* HAVE_untyped_call required.  */
982             valreg = gen_rtx_REG (mode, regno);
983           }
984
985       emit_call_insn (GEN_CALL_VALUE (valreg,
986                                       gen_rtx_MEM (FUNCTION_MODE, function),
987                                       const0_rtx, NULL_RTX, const0_rtx));
988
989       emit_move_insn (change_address (result, GET_MODE (valreg),
990                                       XEXP (result, 0)),
991                       valreg);
992     }
993   else
994 #endif
995     abort ();
996
997   /* Find the CALL insn we just emitted.  */
998   for (call_insn = get_last_insn ();
999        call_insn && GET_CODE (call_insn) != CALL_INSN;
1000        call_insn = PREV_INSN (call_insn))
1001     ;
1002
1003   if (! call_insn)
1004     abort ();
1005
1006   /* Put the register usage information on the CALL.  If there is already
1007      some usage information, put ours at the end.  */
1008   if (CALL_INSN_FUNCTION_USAGE (call_insn))
1009     {
1010       rtx link;
1011
1012       for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
1013            link = XEXP (link, 1))
1014         ;
1015
1016       XEXP (link, 1) = call_fusage;
1017     }
1018   else
1019     CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
1020
1021   /* Restore the stack.  */
1022 #ifdef HAVE_save_stack_nonlocal
1023   if (HAVE_save_stack_nonlocal)
1024     emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1025   else
1026 #endif
1027     emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1028
1029   /* Return the address of the result block.  */
1030   return copy_addr_to_reg (XEXP (result, 0));
1031 }
1032
1033 /* Perform an untyped return.  */
1034
1035 static void
1036 expand_builtin_return (result)
1037      rtx result;
1038 {
1039   int size, align, regno;
1040   enum machine_mode mode;
1041   rtx reg;
1042   rtx call_fusage = 0;
1043
1044   apply_result_size ();
1045   result = gen_rtx_MEM (BLKmode, result);
1046
1047 #ifdef HAVE_untyped_return
1048   if (HAVE_untyped_return)
1049     {
1050       emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1051       emit_barrier ();
1052       return;
1053     }
1054 #endif
1055
1056   /* Restore the return value and note that each value is used.  */
1057   size = 0;
1058   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1059     if ((mode = apply_result_mode[regno]) != VOIDmode)
1060       {
1061         align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1062         if (size % align != 0)
1063           size = CEIL (size, align) * align;
1064         reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1065         emit_move_insn (reg,
1066                         change_address (result, mode,
1067                                         plus_constant (XEXP (result, 0),
1068                                                        size)));
1069
1070         push_to_sequence (call_fusage);
1071         emit_insn (gen_rtx_USE (VOIDmode, reg));
1072         call_fusage = get_insns ();
1073         end_sequence ();
1074         size += GET_MODE_SIZE (mode);
1075       }
1076
1077   /* Put the USE insns before the return.  */
1078   emit_insns (call_fusage);
1079
1080   /* Return whatever values was restored by jumping directly to the end
1081      of the function.  */
1082   expand_null_return ();
1083 }
1084
1085 /* Expand a call to __builtin_classify_type with arguments found in
1086    ARGLIST.  */
1087 static rtx
1088 expand_builtin_classify_type (arglist)
1089      tree arglist;
1090 {
1091   if (arglist != 0)
1092     {
1093       tree type = TREE_TYPE (TREE_VALUE (arglist));
1094       enum tree_code code = TREE_CODE (type);
1095       if (code == VOID_TYPE)
1096         return GEN_INT (void_type_class);
1097       if (code == INTEGER_TYPE)
1098         return GEN_INT (integer_type_class);
1099       if (code == CHAR_TYPE)
1100         return GEN_INT (char_type_class);
1101       if (code == ENUMERAL_TYPE)
1102         return GEN_INT (enumeral_type_class);
1103       if (code == BOOLEAN_TYPE)
1104         return GEN_INT (boolean_type_class);
1105       if (code == POINTER_TYPE)
1106         return GEN_INT (pointer_type_class);
1107       if (code == REFERENCE_TYPE)
1108         return GEN_INT (reference_type_class);
1109       if (code == OFFSET_TYPE)
1110         return GEN_INT (offset_type_class);
1111       if (code == REAL_TYPE)
1112         return GEN_INT (real_type_class);
1113       if (code == COMPLEX_TYPE)
1114         return GEN_INT (complex_type_class);
1115       if (code == FUNCTION_TYPE)
1116         return GEN_INT (function_type_class);
1117       if (code == METHOD_TYPE)
1118         return GEN_INT (method_type_class);
1119       if (code == RECORD_TYPE)
1120         return GEN_INT (record_type_class);
1121       if (code == UNION_TYPE || code == QUAL_UNION_TYPE)
1122         return GEN_INT (union_type_class);
1123       if (code == ARRAY_TYPE)
1124         {
1125           if (TYPE_STRING_FLAG (type))
1126             return GEN_INT (string_type_class);
1127           else
1128             return GEN_INT (array_type_class);
1129         }
1130       if (code == SET_TYPE)
1131         return GEN_INT (set_type_class);
1132       if (code == FILE_TYPE)
1133         return GEN_INT (file_type_class);
1134       if (code == LANG_TYPE)
1135         return GEN_INT (lang_type_class);
1136     }
1137   return GEN_INT (no_type_class);
1138 }
1139
1140 /* Expand expression EXP, which is a call to __builtin_constant_p.  */
1141 static rtx
1142 expand_builtin_constant_p (exp)
1143      tree exp;
1144 {
1145   tree arglist = TREE_OPERAND (exp, 1);
1146   enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1147
1148   if (arglist == 0)
1149     return const0_rtx;
1150   else
1151     {
1152       tree arg = TREE_VALUE (arglist);
1153       rtx tmp;
1154
1155       /* We return 1 for a numeric type that's known to be a constant
1156          value at compile-time or for an aggregate type that's a
1157          literal constant.  */
1158       STRIP_NOPS (arg);
1159
1160       /* If we know this is a constant, emit the constant of one.  */
1161       if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'c'
1162           || (TREE_CODE (arg) == CONSTRUCTOR
1163               && TREE_CONSTANT (arg))
1164           || (TREE_CODE (arg) == ADDR_EXPR
1165               && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST))
1166         return const1_rtx;
1167
1168       /* If we aren't going to be running CSE or this expression
1169          has side effects, show we don't know it to be a constant.
1170          Likewise if it's a pointer or aggregate type since in those
1171          case we only want literals, since those are only optimized
1172          when generating RTL, not later.  */
1173       if (TREE_SIDE_EFFECTS (arg) || cse_not_expected
1174           || AGGREGATE_TYPE_P (TREE_TYPE (arg))
1175           || POINTER_TYPE_P (TREE_TYPE (arg)))
1176         return const0_rtx;
1177
1178       /* Otherwise, emit (constant_p_rtx (ARG)) and let CSE get a
1179          chance to see if it can deduce whether ARG is constant.  */
1180
1181       tmp = expand_expr (arg, NULL_RTX, VOIDmode, 0);
1182       tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
1183       return tmp;
1184     }
1185 }
1186
1187 /* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1188    Return 0 if a normal call should be emitted rather than expanding the
1189    function in-line.  EXP is the expression that is a call to the builtin
1190    function; if convenient, the result should be placed in TARGET.
1191    SUBTARGET may be used as the target for computing one of EXP's operands.  */
1192 static rtx
1193 expand_builtin_mathfn (exp, target, subtarget)
1194      tree exp;
1195      rtx target, subtarget;
1196 {
1197   optab builtin_optab;  
1198   rtx op0, insns;
1199   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1200   tree arglist = TREE_OPERAND (exp, 1);
1201
1202   if (arglist == 0
1203       /* Arg could be wrong type if user redeclared this fcn wrong.  */
1204       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
1205     return 0;
1206
1207   /* Stabilize and compute the argument.  */
1208   if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
1209       && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
1210     {
1211       exp = copy_node (exp);
1212       TREE_OPERAND (exp, 1) = arglist;
1213       /* Wrap the computation of the argument in a SAVE_EXPR.  That
1214          way, if we need to expand the argument again (as in the
1215          flag_errno_math case below where we cannot directly set
1216          errno), we will not perform side-effects more than once.
1217          Note that here we're mutating the original EXP as well as the
1218          copy; that's the right thing to do in case the original EXP
1219          is expanded later.  */
1220       TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
1221       arglist = copy_node (arglist);
1222     }
1223   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
1224
1225   /* Make a suitable register to place result in.  */
1226   target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
1227
1228   emit_queue ();
1229   start_sequence ();
1230
1231   switch (DECL_FUNCTION_CODE (fndecl))
1232     {
1233      case BUILT_IN_SIN:
1234       builtin_optab = sin_optab; break;
1235      case BUILT_IN_COS:
1236       builtin_optab = cos_optab; break;
1237      case BUILT_IN_FSQRT:
1238       builtin_optab = sqrt_optab; break;
1239      default:
1240       abort ();
1241     }
1242
1243   /* Compute into TARGET.
1244      Set TARGET to wherever the result comes back.  */
1245   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
1246                         builtin_optab, op0, target, 0);
1247
1248   /* If we were unable to expand via the builtin, stop the
1249      sequence (without outputting the insns) and return 0, causing
1250      a call to the library function.  */
1251   if (target == 0)
1252     {
1253       end_sequence ();
1254       return 0;
1255     }
1256
1257   /* Check the results by default.  But if flag_fast_math is turned on,
1258      then assume sqrt will always be called with valid arguments.  */
1259
1260   if (flag_errno_math && ! flag_fast_math)
1261     {
1262       rtx lab1;
1263
1264       /* Don't define the builtin FP instructions
1265          if your machine is not IEEE.  */
1266       if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
1267         abort ();
1268
1269       lab1 = gen_label_rtx ();
1270
1271       /* Test the result; if it is NaN, set errno=EDOM because
1272          the argument was not in the domain.  */
1273       emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1274                                0, 0, lab1);
1275
1276 #ifdef TARGET_EDOM
1277         {
1278 #ifdef GEN_ERRNO_RTX
1279           rtx errno_rtx = GEN_ERRNO_RTX;
1280 #else
1281           rtx errno_rtx
1282             = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1283 #endif
1284
1285           emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1286         }
1287 #else
1288       /* We can't set errno=EDOM directly; let the library call do it.
1289          Pop the arguments right away in case the call gets deleted.  */
1290       NO_DEFER_POP;
1291       expand_call (exp, target, 0);
1292       OK_DEFER_POP;
1293 #endif
1294
1295       emit_label (lab1);
1296     }
1297
1298   /* Output the entire sequence.  */
1299   insns = get_insns ();
1300   end_sequence ();
1301   emit_insns (insns);
1302  
1303   return target;
1304 }
1305
1306 /* Expand expression EXP which is a call to the strlen builtin.  Return 0
1307    if we failed the caller should emit a normal call, otherwise
1308    try to get the result in TARGET, if convenient (and in mode MODE if that's
1309    convenient).  */
1310
1311 static rtx
1312 expand_builtin_strlen (exp, target, mode)
1313      tree exp;
1314      rtx target;
1315      enum machine_mode mode;
1316 {
1317   tree arglist = TREE_OPERAND (exp, 1);
1318   enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1319
1320   if (arglist == 0
1321       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1322       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
1323     return 0;
1324   else
1325     {
1326       rtx pat;
1327       tree src = TREE_VALUE (arglist);
1328       tree len = c_strlen (src);
1329
1330       int align
1331         = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1332
1333       rtx result, src_reg, char_rtx, before_strlen;
1334       enum machine_mode insn_mode = value_mode, char_mode;
1335       enum insn_code icode = CODE_FOR_nothing;
1336
1337       /* If the length is known, just return it.  */
1338       if (len != 0)
1339         return expand_expr (len, target, mode, EXPAND_MEMORY_USE_BAD);
1340
1341       /* If SRC is not a pointer type, don't do this operation inline.  */
1342       if (align == 0)
1343         return 0;
1344
1345       /* Bail out if we can't compute strlen in the right mode.  */
1346       while (insn_mode != VOIDmode)
1347         {
1348           icode = strlen_optab->handlers[(int) insn_mode].insn_code;
1349           if (icode != CODE_FOR_nothing)
1350             break;
1351
1352           insn_mode = GET_MODE_WIDER_MODE (insn_mode);
1353         }
1354       if (insn_mode == VOIDmode)
1355         return 0;
1356
1357       /* Make a place to write the result of the instruction.  */
1358       result = target;
1359       if (! (result != 0
1360              && GET_CODE (result) == REG
1361              && GET_MODE (result) == insn_mode
1362              && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1363         result = gen_reg_rtx (insn_mode);
1364
1365       /* Make a place to hold the source address.  We will not expand
1366          the actual source until we are sure that the expansion will
1367          not fail -- there are trees that cannot be expanded twice.  */
1368       src_reg = gen_reg_rtx (Pmode);
1369
1370       /* Mark the beginning of the strlen sequence so we can emit the
1371          source operand later.  */
1372       before_strlen = get_last_insn();
1373
1374       /* Check the string is readable and has an end.  */
1375       if (current_function_check_memory_usage)
1376         emit_library_call (chkr_check_str_libfunc, 1, VOIDmode, 2,
1377                            src_reg, Pmode,
1378                            GEN_INT (MEMORY_USE_RO),
1379                            TYPE_MODE (integer_type_node));
1380
1381       char_rtx = const0_rtx;
1382       char_mode = insn_data[(int) icode].operand[2].mode;
1383       if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
1384                                                             char_mode))
1385         char_rtx = copy_to_mode_reg (char_mode, char_rtx);
1386
1387       pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
1388                              char_rtx, GEN_INT (align));
1389       if (! pat)
1390         return 0;
1391       emit_insn (pat);
1392
1393       /* Now that we are assured of success, expand the source.  */
1394       start_sequence ();
1395       pat = memory_address (BLKmode, 
1396                             expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
1397       if (pat != src_reg)
1398         emit_move_insn (src_reg, pat);
1399       pat = gen_sequence ();
1400       end_sequence ();
1401
1402       if (before_strlen)
1403         emit_insn_after (pat, before_strlen);
1404       else
1405         emit_insn_before (pat, get_insns ());
1406
1407       /* Return the value in the proper mode for this function.  */
1408       if (GET_MODE (result) == value_mode)
1409         target = result;
1410       else if (target != 0)
1411         convert_move (target, result, 0);
1412       else
1413         target = convert_to_mode (value_mode, result, 0);
1414
1415       return target;
1416     }
1417 }
1418
1419 /* Expand a call to the memcpy builtin, with arguments in ARGLIST.  */
1420 static rtx
1421 expand_builtin_memcpy (arglist)
1422      tree arglist;
1423 {
1424   if (arglist == 0
1425       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1426       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1427       || TREE_CHAIN (arglist) == 0
1428       || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1429           != POINTER_TYPE)
1430       || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1431       || (TREE_CODE (TREE_TYPE (TREE_VALUE
1432                                 (TREE_CHAIN (TREE_CHAIN (arglist)))))
1433           != INTEGER_TYPE))
1434     return 0;
1435   else
1436     {
1437       tree dest = TREE_VALUE (arglist);
1438       tree src = TREE_VALUE (TREE_CHAIN (arglist));
1439       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1440
1441       int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
1442       int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
1443       rtx dest_mem, src_mem, dest_addr, len_rtx;
1444
1445       /* If either SRC or DEST is not a pointer type, don't do
1446          this operation in-line.  */
1447       if (src_align == 0 || dest_align == 0)
1448         return 0;
1449
1450       dest_mem = get_memory_rtx (dest);
1451       src_mem = get_memory_rtx (src);
1452       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1453
1454       /* Just copy the rights of SRC to the rights of DEST.  */
1455       if (current_function_check_memory_usage)
1456         emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
1457                            XEXP (dest_mem, 0), Pmode,
1458                            XEXP (src_mem, 0), Pmode,
1459                            len_rtx, TYPE_MODE (sizetype));
1460
1461       /* Copy word part most expediently.  */
1462       dest_addr
1463         = emit_block_move (dest_mem, src_mem, len_rtx,
1464                            MIN (src_align, dest_align));
1465
1466       if (dest_addr == 0)
1467         dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
1468
1469       return dest_addr;
1470     }
1471 }
1472
1473 /* Expand expression EXP, which is a call to the strcpy builtin.  Return 0
1474    if we failed the caller should emit a normal call.  */
1475
1476 static rtx
1477 expand_builtin_strcpy (exp)
1478      tree exp;
1479 {
1480   tree arglist = TREE_OPERAND (exp, 1);
1481   rtx result;
1482
1483   if (arglist == 0
1484       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1485       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1486       || TREE_CHAIN (arglist) == 0
1487       || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1488           != POINTER_TYPE))
1489     return 0;
1490   else
1491     {
1492       tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
1493
1494       if (len == 0)
1495         return 0;
1496
1497       len = size_binop (PLUS_EXPR, len, ssize_int (1));
1498       chainon (arglist, build_tree_list (NULL_TREE, len));
1499     }
1500
1501   result = expand_builtin_memcpy (arglist);
1502
1503   if (! result)
1504     TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
1505   return result;
1506 }
1507
1508 /* Expand expression EXP, which is a call to the memset builtin.  Return 0
1509    if we failed the caller should emit a normal call.  */
1510
1511 static rtx
1512 expand_builtin_memset (exp)
1513      tree exp;
1514 {
1515   tree arglist = TREE_OPERAND (exp, 1);
1516
1517   if (arglist == 0
1518       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1519       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1520       || TREE_CHAIN (arglist) == 0
1521       || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1522           != INTEGER_TYPE)
1523       || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1524       || (INTEGER_TYPE
1525           != (TREE_CODE (TREE_TYPE
1526                          (TREE_VALUE
1527                           (TREE_CHAIN (TREE_CHAIN (arglist))))))))
1528     return 0;
1529   else
1530     {
1531       tree dest = TREE_VALUE (arglist);
1532       tree val = TREE_VALUE (TREE_CHAIN (arglist));
1533       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1534
1535       int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
1536       rtx dest_mem, dest_addr, len_rtx;
1537
1538       /* If DEST is not a pointer type, don't do this 
1539          operation in-line.  */
1540       if (dest_align == 0)
1541         return 0;
1542
1543       /* If the arguments have side-effects, then we can only evaluate
1544          them at most once.  The following code evaluates them twice if
1545          they are not constants because we break out to expand_call
1546          in that case.  They can't be constants if they have side-effects
1547          so we can check for that first.  Alternatively, we could call
1548          save_expr to make multiple evaluation safe.  */
1549       if (TREE_SIDE_EFFECTS (val) || TREE_SIDE_EFFECTS (len))
1550         return 0;
1551
1552       /* If VAL is not 0, don't do this operation in-line. */
1553       if (expand_expr (val, NULL_RTX, VOIDmode, 0) != const0_rtx)
1554         return 0;
1555
1556       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1557
1558       dest_mem = get_memory_rtx (dest);
1559            
1560       /* Just check DST is writable and mark it as readable.  */
1561       if (current_function_check_memory_usage)
1562         emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
1563                            XEXP (dest_mem, 0), Pmode,
1564                            len_rtx, TYPE_MODE (sizetype),
1565                            GEN_INT (MEMORY_USE_WO),
1566                            TYPE_MODE (integer_type_node));
1567
1568
1569       dest_addr = clear_storage (dest_mem, len_rtx, dest_align);
1570
1571       if (dest_addr == 0)
1572         dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
1573
1574       return dest_addr;
1575     }
1576 }
1577
1578 /* Expand expression EXP, which is a call to the bzero builtin.  Return 0
1579    if we failed the caller should emit a normal call.  */
1580 static rtx
1581 expand_builtin_bzero (exp)
1582      tree exp;
1583 {
1584   tree arglist = TREE_OPERAND (exp, 1);
1585   tree dest, size, newarglist;
1586   rtx result;
1587
1588   if (arglist == 0
1589       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1590       || TREE_CODE (TREE_TYPE (dest = TREE_VALUE (arglist))) != POINTER_TYPE
1591       || TREE_CHAIN (arglist) == 0
1592       || (TREE_CODE (TREE_TYPE (size = TREE_VALUE (TREE_CHAIN (arglist))))
1593           != INTEGER_TYPE))
1594     return NULL_RTX;
1595
1596   /* New argument list transforming bzero(ptr x, int y) to
1597      memset(ptr x, int 0, size_t y).  */
1598   
1599   newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
1600   newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
1601   newarglist = tree_cons (NULL_TREE, dest, newarglist);
1602
1603   TREE_OPERAND (exp, 1) = newarglist;
1604   result = expand_builtin_memset(exp);
1605       
1606   /* Always restore the original arguments.  */
1607   TREE_OPERAND (exp, 1) = arglist;
1608
1609   return result;
1610 }
1611
1612 #ifdef HAVE_cmpstrsi
1613 /* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
1614    ARGLIST is the argument list for this call.  Return 0 if we failed and the
1615    caller should emit a normal call, otherwise try to get the result in
1616    TARGET, if convenient.  */
1617 static rtx
1618 expand_builtin_memcmp (exp, arglist, target)
1619      tree exp;
1620      tree arglist;
1621      rtx target;
1622 {
1623   /* If we need to check memory accesses, call the library function.  */
1624   if (current_function_check_memory_usage)
1625     return 0;
1626
1627   if (arglist == 0
1628       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1629       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1630       || TREE_CHAIN (arglist) == 0
1631       || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
1632       || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1633       || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
1634     return 0;
1635
1636   {
1637     enum machine_mode mode;
1638     tree arg1 = TREE_VALUE (arglist);
1639     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
1640     tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1641     rtx arg1_rtx, arg2_rtx, arg3_rtx;
1642     rtx result;
1643     rtx insn;
1644
1645     int arg1_align
1646       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1647     int arg2_align
1648       = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1649     enum machine_mode insn_mode
1650       = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
1651
1652     /* If we don't have POINTER_TYPE, call the function.  */
1653     if (arg1_align == 0 || arg2_align == 0)
1654       return 0;
1655
1656     /* Make a place to write the result of the instruction.  */
1657     result = target;
1658     if (! (result != 0
1659            && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
1660            && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1661       result = gen_reg_rtx (insn_mode);
1662
1663     arg1_rtx = get_memory_rtx (arg1);
1664     arg2_rtx = get_memory_rtx (arg2);
1665     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1666     if (!HAVE_cmpstrsi)
1667       insn = NULL_RTX;
1668     else
1669       insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
1670                            GEN_INT (MIN (arg1_align, arg2_align)));
1671
1672     if (insn)
1673       emit_insn (insn);
1674     else
1675       emit_library_call_value (memcmp_libfunc, result, 2,
1676                                TYPE_MODE (integer_type_node), 3,
1677                                XEXP (arg1_rtx, 0), Pmode,
1678                                XEXP (arg2_rtx, 0), Pmode,
1679                                convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
1680                                                 TREE_UNSIGNED (sizetype)),
1681                                TYPE_MODE (sizetype));
1682
1683     /* Return the value in the proper mode for this function.  */
1684     mode = TYPE_MODE (TREE_TYPE (exp));
1685     if (GET_MODE (result) == mode)
1686       return result;
1687     else if (target != 0)
1688       {
1689         convert_move (target, result, 0);
1690         return target;
1691       }
1692     else
1693       return convert_to_mode (mode, result, 0);
1694   }
1695 }
1696
1697 /* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
1698    if we failed the caller should emit a normal call, otherwise try to get
1699    the result in TARGET, if convenient.  */
1700
1701 static rtx
1702 expand_builtin_strcmp (exp, target)
1703      tree exp;
1704      rtx target;
1705 {
1706   tree arglist = TREE_OPERAND (exp, 1);
1707
1708   /* If we need to check memory accesses, call the library function.  */
1709   if (current_function_check_memory_usage)
1710     return 0;
1711
1712   if (arglist == 0
1713       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1714       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1715       || TREE_CHAIN (arglist) == 0
1716       || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1717           != POINTER_TYPE))
1718     return 0;
1719
1720   else if (! HAVE_cmpstrsi)
1721     return 0;
1722   {
1723     tree arg1 = TREE_VALUE (arglist);
1724     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
1725     tree len = c_strlen (arg1);
1726     tree len2 = c_strlen (arg2);
1727     rtx result;
1728
1729     if (len)
1730       len = size_binop (PLUS_EXPR, ssize_int (1), len);
1731
1732     if (len2)
1733       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
1734
1735     /* If we don't have a constant length for the first, use the length
1736        of the second, if we know it.  We don't require a constant for
1737        this case; some cost analysis could be done if both are available
1738        but neither is constant.  For now, assume they're equally cheap.
1739
1740        If both strings have constant lengths, use the smaller.  This
1741        could arise if optimization results in strcpy being called with
1742        two fixed strings, or if the code was machine-generated.  We should
1743        add some code to the `memcmp' handler below to deal with such
1744        situations, someday.  */
1745
1746     if (!len || TREE_CODE (len) != INTEGER_CST)
1747       {
1748         if (len2)
1749           len = len2;
1750         else if (len == 0)
1751           return 0;
1752       }
1753     else if (len2 && TREE_CODE (len2) == INTEGER_CST
1754              && tree_int_cst_lt (len2, len))
1755       len = len2;
1756
1757     chainon (arglist, build_tree_list (NULL_TREE, len));
1758     result = expand_builtin_memcmp (exp, arglist, target);
1759     if (! result)
1760       TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
1761
1762     return result;
1763   }
1764 }
1765 #endif
1766
1767 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
1768    if that's convenient.  */
1769
1770 rtx
1771 expand_builtin_saveregs ()
1772 {
1773   rtx val, seq;
1774
1775   /* Don't do __builtin_saveregs more than once in a function.
1776      Save the result of the first call and reuse it.  */
1777   if (saveregs_value != 0)
1778     return saveregs_value;
1779
1780   /* When this function is called, it means that registers must be
1781      saved on entry to this function.  So we migrate the call to the
1782      first insn of this function.  */
1783
1784   start_sequence ();
1785
1786 #ifdef EXPAND_BUILTIN_SAVEREGS
1787   /* Do whatever the machine needs done in this case.  */
1788   val = EXPAND_BUILTIN_SAVEREGS ();
1789 #else
1790   /* ??? We used to try and build up a call to the out of line function,
1791      guessing about what registers needed saving etc.  This became much
1792      harder with __builtin_va_start, since we don't have a tree for a
1793      call to __builtin_saveregs to fall back on.  There was exactly one
1794      port (i860) that used this code, and I'm unconvinced it could actually
1795      handle the general case.  So we no longer try to handle anything
1796      weird and make the backend absorb the evil.  */
1797
1798   error ("__builtin_saveregs not supported by this target");
1799   val = const0_rtx;
1800 #endif
1801
1802   seq = get_insns ();
1803   end_sequence ();
1804
1805   saveregs_value = val;
1806
1807   /* Put the sequence after the NOTE that starts the function.  If this
1808      is inside a SEQUENCE, make the outer-level insn chain current, so
1809      the code is placed at the start of the function.  */
1810   push_topmost_sequence ();
1811   emit_insns_after (seq, get_insns ());
1812   pop_topmost_sequence ();
1813
1814   return val;
1815 }
1816
1817 /* __builtin_args_info (N) returns word N of the arg space info
1818    for the current function.  The number and meanings of words
1819    is controlled by the definition of CUMULATIVE_ARGS.  */
1820
1821 static rtx
1822 expand_builtin_args_info (exp)
1823      tree exp;
1824 {
1825   tree arglist = TREE_OPERAND (exp, 1);
1826   int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
1827   int *word_ptr = (int *) &current_function_args_info;
1828 #if 0   
1829   /* These are used by the code below that is if 0'ed away */
1830   int i;
1831   tree type, elts, result;
1832 #endif
1833
1834   if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
1835     abort ();
1836
1837   if (arglist != 0)
1838     {
1839       tree arg = TREE_VALUE (arglist);
1840       if (TREE_CODE (arg) != INTEGER_CST)
1841         error ("argument of `__builtin_args_info' must be constant");
1842       else
1843         {
1844           int wordnum = TREE_INT_CST_LOW (arg);
1845
1846           if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg))
1847             error ("argument of `__builtin_args_info' out of range");
1848           else
1849             return GEN_INT (word_ptr[wordnum]);
1850         }
1851     }
1852   else
1853     error ("missing argument in `__builtin_args_info'");
1854
1855   return const0_rtx;
1856
1857 #if 0
1858   for (i = 0; i < nwords; i++)
1859     elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
1860
1861   type = build_array_type (integer_type_node,
1862                            build_index_type (build_int_2 (nwords, 0)));
1863   result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
1864   TREE_CONSTANT (result) = 1;
1865   TREE_STATIC (result) = 1;
1866   result = build1 (INDIRECT_REF, build_pointer_type (type), result);
1867   TREE_CONSTANT (result) = 1;
1868   return expand_expr (result, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD);
1869 #endif
1870 }
1871
1872 /* Expand ARGLIST, from a call to __builtin_next_arg.  */
1873 static rtx
1874 expand_builtin_next_arg (arglist)
1875      tree arglist;
1876 {
1877   tree fntype = TREE_TYPE (current_function_decl);
1878
1879   if ((TYPE_ARG_TYPES (fntype) == 0
1880        || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1881            == void_type_node))
1882       && ! current_function_varargs)
1883     {
1884       error ("`va_start' used in function with fixed args");
1885       return const0_rtx;
1886     }
1887
1888   if (arglist)
1889     {
1890       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
1891       tree arg = TREE_VALUE (arglist);
1892
1893       /* Strip off all nops for the sake of the comparison.  This
1894          is not quite the same as STRIP_NOPS.  It does more.  
1895          We must also strip off INDIRECT_EXPR for C++ reference
1896          parameters.  */
1897       while (TREE_CODE (arg) == NOP_EXPR
1898              || TREE_CODE (arg) == CONVERT_EXPR
1899              || TREE_CODE (arg) == NON_LVALUE_EXPR
1900              || TREE_CODE (arg) == INDIRECT_REF)
1901         arg = TREE_OPERAND (arg, 0);
1902       if (arg != last_parm)
1903         warning ("second parameter of `va_start' not last named argument");
1904     }
1905   else if (! current_function_varargs)
1906     /* Evidently an out of date version of <stdarg.h>; can't validate
1907        va_start's second argument, but can still work as intended.  */
1908     warning ("`__builtin_next_arg' called without an argument");
1909
1910   return expand_binop (Pmode, add_optab,
1911                        current_function_internal_arg_pointer,
1912                        current_function_arg_offset_rtx,
1913                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
1914 }
1915
1916 /* Make it easier for the backends by protecting the valist argument
1917    from multiple evaluations.  */
1918
1919 static tree
1920 stabilize_va_list (valist, needs_lvalue)
1921      tree valist;
1922      int needs_lvalue;
1923 {
1924   if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
1925     {
1926       if (TREE_SIDE_EFFECTS (valist))
1927         valist = save_expr (valist);
1928
1929       /* For this case, the backends will be expecting a pointer to
1930          TREE_TYPE (va_list_type_node), but it's possible we've
1931          actually been given an array (an actual va_list_type_node).
1932          So fix it.  */
1933       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
1934         {
1935           tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
1936           tree p2 = build_pointer_type (va_list_type_node);
1937
1938           valist = build1 (ADDR_EXPR, p2, valist);
1939           valist = fold (build1 (NOP_EXPR, p1, valist));
1940         }
1941     }
1942   else
1943     {
1944       tree pt;
1945
1946       if (! needs_lvalue)
1947         {
1948           if (! TREE_SIDE_EFFECTS (valist))
1949             return valist;
1950           
1951           pt = build_pointer_type (va_list_type_node);
1952           valist = fold (build1 (ADDR_EXPR, pt, valist));
1953           TREE_SIDE_EFFECTS (valist) = 1;
1954         }
1955
1956       if (TREE_SIDE_EFFECTS (valist))
1957         valist = save_expr (valist);
1958       valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
1959                              valist));
1960     }
1961
1962   return valist;
1963 }
1964
1965 /* The "standard" implementation of va_start: just assign `nextarg' to
1966    the variable.  */
1967 void
1968 std_expand_builtin_va_start (stdarg_p, valist, nextarg)
1969      int stdarg_p ATTRIBUTE_UNUSED;
1970      tree valist;
1971      rtx nextarg;
1972 {
1973   tree t;
1974
1975   if (!stdarg_p)
1976     nextarg = plus_constant (nextarg, -UNITS_PER_WORD);
1977
1978   t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
1979              make_tree (ptr_type_node, nextarg));
1980   TREE_SIDE_EFFECTS (t) = 1;
1981
1982   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1983 }
1984
1985 /* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
1986    __builtin_varargs_va_start, depending on STDARG_P.  */
1987 static rtx
1988 expand_builtin_va_start (stdarg_p, arglist)
1989      int stdarg_p;
1990      tree arglist;
1991 {
1992   rtx nextarg;
1993   tree chain = arglist, valist;
1994
1995   if (stdarg_p)
1996     nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
1997   else
1998     nextarg = expand_builtin_next_arg (NULL_TREE);
1999
2000   if (TREE_CHAIN (chain))
2001     error ("too many arguments to function `va_start'");
2002
2003   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
2004
2005 #ifdef EXPAND_BUILTIN_VA_START
2006   EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
2007 #else
2008   std_expand_builtin_va_start (stdarg_p, valist, nextarg);
2009 #endif
2010
2011   return const0_rtx;
2012 }
2013
2014 /* The "standard" implementation of va_arg: read the value from the
2015    current (padded) address and increment by the (padded) size.  */
2016
2017 rtx
2018 std_expand_builtin_va_arg (valist, type)
2019      tree valist, type;
2020 {
2021   tree addr_tree, t;
2022   HOST_WIDE_INT align;
2023   HOST_WIDE_INT rounded_size;
2024   rtx addr;
2025
2026   /* Compute the rounded size of the type.  */
2027   align = PARM_BOUNDARY / BITS_PER_UNIT;
2028   rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
2029
2030   /* Get AP.  */
2031   addr_tree = valist;
2032   if (PAD_VARARGS_DOWN)
2033     {
2034       /* Small args are padded downward.  */
2035
2036       HOST_WIDE_INT adj;
2037       adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT;
2038       if (rounded_size > align)
2039         adj = rounded_size;
2040
2041       addr_tree = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
2042                          build_int_2 (rounded_size - adj, 0));
2043     }
2044
2045   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2046   addr = copy_to_reg (addr);
2047
2048   /* Compute new value for AP.  */
2049   t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2050              build (PLUS_EXPR, TREE_TYPE (valist), valist,
2051                     build_int_2 (rounded_size, 0)));
2052   TREE_SIDE_EFFECTS (t) = 1;
2053   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2054
2055   return addr;
2056 }
2057
2058 /* Expand __builtin_va_arg, which is not really a builtin function, but
2059    a very special sort of operator.  */
2060
2061 rtx
2062 expand_builtin_va_arg (valist, type)
2063      tree valist, type;
2064 {
2065   rtx addr, result;
2066   tree promoted_type, want_va_type, have_va_type;
2067
2068   /* Verify that valist is of the proper type.  */
2069
2070   want_va_type = va_list_type_node;
2071   have_va_type = TREE_TYPE (valist);
2072   if (TREE_CODE (want_va_type) == ARRAY_TYPE)
2073     {
2074       /* If va_list is an array type, the argument may have decayed 
2075          to a pointer type, e.g. by being passed to another function.
2076          In that case, unwrap both types so that we can compare the
2077          underlying records.  */
2078       if (TREE_CODE (have_va_type) == ARRAY_TYPE
2079           || TREE_CODE (have_va_type) == POINTER_TYPE)
2080         {
2081           want_va_type = TREE_TYPE (want_va_type);
2082           have_va_type = TREE_TYPE (have_va_type);
2083         }
2084     }
2085   if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
2086     {
2087       error ("first argument to `va_arg' not of type `va_list'");
2088       addr = const0_rtx;
2089     }
2090
2091   /* Generate a diagnostic for requesting data of a type that cannot
2092      be passed through `...' due to type promotion at the call site.  */
2093   else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
2094     {
2095       const char *name = "<anonymous type>", *pname = 0;
2096       static int gave_help;
2097
2098       if (TYPE_NAME (type))
2099         {
2100           if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
2101             name = IDENTIFIER_POINTER (TYPE_NAME (type));
2102           else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
2103                    && DECL_NAME (TYPE_NAME (type)))
2104             name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
2105         }
2106       if (TYPE_NAME (promoted_type))
2107         {
2108           if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
2109             pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
2110           else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
2111                    && DECL_NAME (TYPE_NAME (promoted_type)))
2112             pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
2113         }
2114
2115       error ("`%s' is promoted to `%s' when passed through `...'", name, pname);
2116       if (! gave_help)
2117         {
2118           gave_help = 1;
2119           error ("(so you should pass `%s' not `%s' to `va_arg')", pname, name);
2120         }
2121
2122       addr = const0_rtx;
2123     }
2124   else
2125     {
2126       /* Make it easier for the backends by protecting the valist argument
2127          from multiple evaluations.  */
2128       valist = stabilize_va_list (valist, 0);
2129
2130 #ifdef EXPAND_BUILTIN_VA_ARG
2131       addr = EXPAND_BUILTIN_VA_ARG (valist, type);
2132 #else
2133       addr = std_expand_builtin_va_arg (valist, type);
2134 #endif
2135     }
2136
2137   result = gen_rtx_MEM (TYPE_MODE (type), addr);
2138   MEM_ALIAS_SET (result) = get_varargs_alias_set ();
2139
2140   return result;
2141 }
2142
2143 /* Expand ARGLIST, from a call to __builtin_va_end.  */
2144
2145 static rtx
2146 expand_builtin_va_end (arglist)
2147      tree arglist;
2148 {
2149   tree valist = TREE_VALUE (arglist);
2150
2151 #ifdef EXPAND_BUILTIN_VA_END
2152   valist = stabilize_va_list (valist, 0);
2153   EXPAND_BUILTIN_VA_END(arglist);
2154 #else
2155   /* Evaluate for side effects, if needed.  I hate macros that don't
2156      do that.  */
2157   if (TREE_SIDE_EFFECTS (valist))
2158     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
2159 #endif
2160
2161   return const0_rtx;
2162 }
2163
2164 /* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a 
2165    builtin rather than just as an assignment in stdarg.h because of the
2166    nastiness of array-type va_list types.  */
2167
2168 static rtx
2169 expand_builtin_va_copy (arglist)
2170      tree arglist;
2171 {
2172   tree dst, src, t;
2173
2174   dst = TREE_VALUE (arglist);
2175   src = TREE_VALUE (TREE_CHAIN (arglist));
2176
2177   dst = stabilize_va_list (dst, 1);
2178   src = stabilize_va_list (src, 0);
2179
2180   if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
2181     {
2182       t = build (MODIFY_EXPR, va_list_type_node, dst, src);
2183       TREE_SIDE_EFFECTS (t) = 1;
2184       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2185     }
2186   else
2187     {
2188       rtx dstb, srcb, size;
2189
2190       /* Evaluate to pointers.  */
2191       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
2192       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
2193       size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
2194                           VOIDmode, EXPAND_NORMAL);
2195
2196       /* "Dereference" to BLKmode memories.  */
2197       dstb = gen_rtx_MEM (BLKmode, dstb);
2198       MEM_ALIAS_SET (dstb) = get_alias_set (TREE_TYPE (TREE_TYPE (dst)));
2199       srcb = gen_rtx_MEM (BLKmode, srcb);
2200       MEM_ALIAS_SET (srcb) = get_alias_set (TREE_TYPE (TREE_TYPE (src)));
2201
2202       /* Copy.  */
2203       emit_block_move (dstb, srcb, size, TYPE_ALIGN (va_list_type_node));
2204     }
2205
2206   return const0_rtx;
2207 }
2208
2209 /* Expand a call to one of the builtin functions __builtin_frame_address or
2210    __builtin_return_address.  */
2211 static rtx
2212 expand_builtin_frame_address (exp)
2213      tree exp;
2214 {
2215   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2216   tree arglist = TREE_OPERAND (exp, 1);
2217
2218   /* The argument must be a nonnegative integer constant.
2219      It counts the number of frames to scan up the stack.
2220      The value is the return address saved in that frame.  */
2221   if (arglist == 0)
2222     /* Warning about missing arg was already issued.  */
2223     return const0_rtx;
2224   else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST
2225            || tree_int_cst_sgn (TREE_VALUE (arglist)) < 0)
2226     {
2227       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2228         error ("invalid arg to `__builtin_frame_address'");
2229       else
2230         error ("invalid arg to `__builtin_return_address'");
2231       return const0_rtx;
2232     }
2233   else
2234     {
2235       rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
2236                                             TREE_INT_CST_LOW (TREE_VALUE (arglist)),
2237                                             hard_frame_pointer_rtx);
2238
2239       /* Some ports cannot access arbitrary stack frames.  */
2240       if (tem == NULL)
2241         {
2242           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2243             warning ("unsupported arg to `__builtin_frame_address'");
2244           else
2245             warning ("unsupported arg to `__builtin_return_address'");
2246           return const0_rtx;
2247         }
2248
2249       /* For __builtin_frame_address, return what we've got.  */
2250       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2251         return tem;
2252
2253       if (GET_CODE (tem) != REG
2254           && ! CONSTANT_P (tem))
2255         tem = copy_to_mode_reg (Pmode, tem);
2256       return tem;
2257     }
2258 }
2259
2260 /* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
2261    we failed and the caller should emit a normal call, otherwise try to get
2262    the result in TARGET, if convenient.  */
2263 static rtx
2264 expand_builtin_alloca (arglist, target)
2265      tree arglist;
2266      rtx target;
2267 {
2268   rtx op0;
2269
2270   if (arglist == 0
2271       /* Arg could be non-integer if user redeclared this fcn wrong.  */
2272       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
2273     return 0;
2274
2275   /* Compute the argument.  */
2276   op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
2277
2278   /* Allocate the desired space.  */
2279   return allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
2280 }
2281
2282 /* Expand a call to the ffs builtin.  The arguments are in ARGLIST.
2283    Return 0 if a normal call should be emitted rather than expanding the
2284    function in-line.  If convenient, the result should be placed in TARGET.
2285    SUBTARGET may be used as the target for computing one of EXP's operands.  */
2286 static rtx
2287 expand_builtin_ffs (arglist, target, subtarget)
2288      tree arglist;
2289      rtx target, subtarget;
2290 {
2291   rtx op0;
2292   if (arglist == 0
2293       /* Arg could be non-integer if user redeclared this fcn wrong.  */
2294       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
2295     return 0;
2296
2297   /* Compute the argument.  */
2298   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
2299   /* Compute ffs, into TARGET if possible.
2300      Set TARGET to wherever the result comes back.  */
2301   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
2302                         ffs_optab, op0, target, 1);
2303   if (target == 0)
2304     abort ();
2305   return target;
2306 }
2307
2308 /* Expand a call to __builtin_expect.  We return our argument and
2309    emit a NOTE_INSN_EXPECTED_VALUE note.  */
2310
2311 static rtx
2312 expand_builtin_expect (arglist, target)
2313      tree arglist;
2314      rtx target;
2315 {
2316   tree exp, c;
2317   rtx note, rtx_c;
2318
2319   if (arglist == NULL_TREE
2320       || TREE_CHAIN (arglist) == NULL_TREE)
2321     return const0_rtx;
2322   exp = TREE_VALUE (arglist);
2323   c = TREE_VALUE (TREE_CHAIN (arglist));
2324
2325   if (TREE_CODE (c) != INTEGER_CST)
2326     {
2327       error ("second arg to `__builtin_expect' must be a constant");
2328       c = integer_zero_node;
2329     }
2330
2331   target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
2332
2333   /* Don't bother with expected value notes for integral constants.  */
2334   if (GET_CODE (target) != CONST_INT)
2335     {
2336       /* We do need to force this into a register so that we can be
2337          moderately sure to be able to correctly interpret the branch
2338          condition later.  */
2339       target = force_reg (GET_MODE (target), target);
2340   
2341       rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
2342
2343       note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
2344       NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
2345     }
2346
2347   return target;
2348 }
2349 \f
2350 /* Expand an expression EXP that calls a built-in function,
2351    with result going to TARGET if that's convenient
2352    (and in mode MODE if that's convenient).
2353    SUBTARGET may be used as the target for computing one of EXP's operands.
2354    IGNORE is nonzero if the value is to be ignored.  */
2355
2356 rtx
2357 expand_builtin (exp, target, subtarget, mode, ignore)
2358      tree exp;
2359      rtx target;
2360      rtx subtarget;
2361      enum machine_mode mode;
2362      int ignore;
2363 {
2364   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2365   tree arglist = TREE_OPERAND (exp, 1);
2366   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
2367
2368 #ifdef MD_EXPAND_BUILTIN
2369   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
2370     return MD_EXPAND_BUILTIN (exp, target, subtarget, mode, ignore);
2371 #endif
2372   
2373   /* When not optimizing, generate calls to library functions for a certain
2374      set of builtins.  */
2375   if (! optimize && ! CALLED_AS_BUILT_IN (fndecl)
2376       && (fcode == BUILT_IN_SIN || fcode == BUILT_IN_COS
2377           || fcode == BUILT_IN_FSQRT || fcode == BUILT_IN_MEMSET
2378           || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
2379           || fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO
2380           || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
2381           || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS))
2382     return expand_call (exp, target, ignore);
2383
2384   switch (fcode)
2385     {
2386     case BUILT_IN_ABS:
2387     case BUILT_IN_LABS:
2388     case BUILT_IN_FABS:
2389       /* build_function_call changes these into ABS_EXPR.  */
2390       abort ();
2391
2392     case BUILT_IN_SIN:
2393     case BUILT_IN_COS:
2394       /* Treat these like sqrt, but only if the user asks for them.  */
2395       if (! flag_fast_math)
2396         break;
2397     case BUILT_IN_FSQRT:
2398       target = expand_builtin_mathfn (exp, target, subtarget);
2399       if (target)
2400         return target;
2401       break;
2402
2403     case BUILT_IN_FMOD:
2404       break;
2405
2406     case BUILT_IN_APPLY_ARGS:
2407       return expand_builtin_apply_args ();
2408
2409       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
2410          FUNCTION with a copy of the parameters described by
2411          ARGUMENTS, and ARGSIZE.  It returns a block of memory
2412          allocated on the stack into which is stored all the registers
2413          that might possibly be used for returning the result of a
2414          function.  ARGUMENTS is the value returned by
2415          __builtin_apply_args.  ARGSIZE is the number of bytes of
2416          arguments that must be copied.  ??? How should this value be
2417          computed?  We'll also need a safe worst case value for varargs
2418          functions.  */
2419     case BUILT_IN_APPLY:
2420       if (arglist == 0
2421           /* Arg could be non-pointer if user redeclared this fcn wrong.  */
2422           || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
2423           || TREE_CHAIN (arglist) == 0
2424           || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
2425           || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
2426           || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
2427         return const0_rtx;
2428       else
2429         {
2430           int i;
2431           tree t;
2432           rtx ops[3];
2433
2434           for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
2435             ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
2436
2437           return expand_builtin_apply (ops[0], ops[1], ops[2]);
2438         }
2439
2440       /* __builtin_return (RESULT) causes the function to return the
2441          value described by RESULT.  RESULT is address of the block of
2442          memory returned by __builtin_apply.  */
2443     case BUILT_IN_RETURN:
2444       if (arglist
2445           /* Arg could be non-pointer if user redeclared this fcn wrong.  */
2446           && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
2447         expand_builtin_return (expand_expr (TREE_VALUE (arglist),
2448                                             NULL_RTX, VOIDmode, 0));
2449       return const0_rtx;
2450
2451     case BUILT_IN_SAVEREGS:
2452       return expand_builtin_saveregs ();
2453
2454     case BUILT_IN_ARGS_INFO:
2455       return expand_builtin_args_info (exp);
2456
2457       /* Return the address of the first anonymous stack arg.  */
2458     case BUILT_IN_NEXT_ARG:
2459       return expand_builtin_next_arg (arglist);
2460
2461     case BUILT_IN_CLASSIFY_TYPE:
2462       return expand_builtin_classify_type (arglist);
2463
2464     case BUILT_IN_CONSTANT_P:
2465       return expand_builtin_constant_p (exp);
2466
2467     case BUILT_IN_FRAME_ADDRESS:
2468     case BUILT_IN_RETURN_ADDRESS:
2469       return expand_builtin_frame_address (exp);
2470
2471     /* Returns the address of the area where the structure is returned.
2472        0 otherwise.  */
2473     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
2474       if (arglist != 0
2475           || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
2476           || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
2477         return const0_rtx;
2478       else
2479         return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
2480
2481     case BUILT_IN_ALLOCA:
2482       target = expand_builtin_alloca (arglist, target);
2483       if (target)
2484         return target;
2485       break;
2486
2487     case BUILT_IN_FFS:
2488       target = expand_builtin_ffs (arglist, target, subtarget);
2489       if (target)
2490         return target;
2491       break;
2492
2493     case BUILT_IN_STRLEN:
2494       target = expand_builtin_strlen (exp, target, mode);
2495       if (target)
2496         return target;
2497       break;
2498
2499     case BUILT_IN_STRCPY:
2500       target = expand_builtin_strcpy (exp);
2501       if (target)
2502         return target;
2503       break;
2504       
2505     case BUILT_IN_MEMCPY:
2506       target = expand_builtin_memcpy (arglist);
2507       if (target)
2508         return target;
2509       break;
2510
2511     case BUILT_IN_MEMSET:
2512       target = expand_builtin_memset (exp);
2513       if (target)
2514         return target;
2515       break;
2516
2517     case BUILT_IN_BZERO:
2518       target = expand_builtin_bzero (exp);
2519       if (target)
2520         return target;
2521       break;
2522
2523 /* These comparison functions need an instruction that returns an actual
2524    index.  An ordinary compare that just sets the condition codes
2525    is not enough.  */
2526 #ifdef HAVE_cmpstrsi
2527     case BUILT_IN_STRCMP:
2528       target = expand_builtin_strcmp (exp, target);
2529       if (target)
2530         return target;
2531       break;
2532
2533     case BUILT_IN_BCMP:
2534     case BUILT_IN_MEMCMP:
2535       target = expand_builtin_memcmp (exp, arglist, target);
2536       if (target)
2537         return target;
2538       break;
2539 #else
2540     case BUILT_IN_STRCMP:
2541     case BUILT_IN_BCMP:
2542     case BUILT_IN_MEMCMP:
2543       break;
2544 #endif
2545
2546     case BUILT_IN_SETJMP:
2547       if (arglist == 0
2548           || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
2549         break;
2550       else
2551         {
2552           rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
2553                                       VOIDmode, 0);
2554           rtx lab = gen_label_rtx ();
2555           rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab);
2556           emit_label (lab);
2557           return ret;
2558         }
2559
2560       /* __builtin_longjmp is passed a pointer to an array of five words.
2561          It's similar to the C library longjmp function but works with
2562          __builtin_setjmp above.  */
2563     case BUILT_IN_LONGJMP:
2564       if (arglist == 0 || TREE_CHAIN (arglist) == 0
2565           || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
2566         break;
2567       else
2568         {
2569           rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
2570                                       VOIDmode, 0);
2571           rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
2572                                    NULL_RTX, VOIDmode, 0);
2573
2574           if (value != const1_rtx)
2575             {
2576               error ("__builtin_longjmp second argument must be 1");
2577               return const0_rtx;
2578             }
2579
2580           expand_builtin_longjmp (buf_addr, value);
2581           return const0_rtx;
2582         }
2583
2584     case BUILT_IN_TRAP:
2585 #ifdef HAVE_trap
2586       if (HAVE_trap)
2587         emit_insn (gen_trap ());
2588       else
2589 #endif
2590         error ("__builtin_trap not supported by this target");
2591       emit_barrier ();
2592       return const0_rtx;
2593
2594       /* Various hooks for the DWARF 2 __throw routine.  */
2595     case BUILT_IN_UNWIND_INIT:
2596       expand_builtin_unwind_init ();
2597       return const0_rtx;
2598     case BUILT_IN_DWARF_CFA:
2599       return virtual_cfa_rtx;
2600 #ifdef DWARF2_UNWIND_INFO
2601     case BUILT_IN_DWARF_FP_REGNUM:
2602       return expand_builtin_dwarf_fp_regnum ();
2603     case BUILT_IN_INIT_DWARF_REG_SIZES:
2604       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
2605       return const0_rtx;
2606 #endif
2607     case BUILT_IN_FROB_RETURN_ADDR:
2608       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
2609     case BUILT_IN_EXTRACT_RETURN_ADDR:
2610       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
2611     case BUILT_IN_EH_RETURN:
2612       expand_builtin_eh_return (TREE_VALUE (arglist),
2613                                 TREE_VALUE (TREE_CHAIN (arglist)),
2614                                 TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
2615       return const0_rtx;
2616     case BUILT_IN_VARARGS_START:
2617       return expand_builtin_va_start (0, arglist);
2618     case BUILT_IN_STDARG_START:
2619       return expand_builtin_va_start (1, arglist);
2620     case BUILT_IN_VA_END:
2621       return expand_builtin_va_end (arglist);
2622     case BUILT_IN_VA_COPY:
2623       return expand_builtin_va_copy (arglist);
2624     case BUILT_IN_EXPECT:
2625       return expand_builtin_expect (arglist, target);
2626
2627     default:                    /* just do library call, if unknown builtin */
2628       error ("built-in function `%s' not currently supported",
2629              IDENTIFIER_POINTER (DECL_NAME (fndecl)));
2630     }
2631
2632   /* The switch statement above can drop through to cause the function
2633      to be called normally.  */
2634   return expand_call (exp, target, ignore);
2635 }