OSDN Git Service

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