OSDN Git Service

* builtins.c (expand_builtin_strlen): Force the source to
[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   else if (!HAVE_cmpstrsi)
1632     return 0;
1633
1634   {
1635     enum machine_mode mode;
1636     tree arg1 = TREE_VALUE (arglist);
1637     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
1638     tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1639     rtx result;
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     emit_insn (gen_cmpstrsi (result, get_memory_rtx (arg1),
1660                              get_memory_rtx (arg2),
1661                              expand_expr (len, NULL_RTX, VOIDmode, 0),
1662                              GEN_INT (MIN (arg1_align, arg2_align))));
1663
1664     /* Return the value in the proper mode for this function.  */
1665     mode = TYPE_MODE (TREE_TYPE (exp));
1666     if (GET_MODE (result) == mode)
1667       return result;
1668     else if (target != 0)
1669       {
1670         convert_move (target, result, 0);
1671         return target;
1672       }
1673     else
1674       return convert_to_mode (mode, result, 0);
1675   }
1676 }
1677
1678 /* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
1679    if we failed the caller should emit a normal call, otherwise try to get
1680    the result in TARGET, if convenient.  */
1681
1682 static rtx
1683 expand_builtin_strcmp (exp, target)
1684      tree exp;
1685      rtx target;
1686 {
1687   tree arglist = TREE_OPERAND (exp, 1);
1688
1689   /* If we need to check memory accesses, call the library function.  */
1690   if (current_function_check_memory_usage)
1691     return 0;
1692
1693   if (arglist == 0
1694       /* Arg could be non-pointer if user redeclared this fcn wrong.  */
1695       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1696       || TREE_CHAIN (arglist) == 0
1697       || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1698           != POINTER_TYPE))
1699     return 0;
1700
1701   else if (! HAVE_cmpstrsi)
1702     return 0;
1703   {
1704     tree arg1 = TREE_VALUE (arglist);
1705     tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
1706     tree len = c_strlen (arg1);
1707     tree len2 = c_strlen (arg2);
1708     rtx result;
1709
1710     if (len)
1711       len = size_binop (PLUS_EXPR, ssize_int (1), len);
1712
1713     if (len2)
1714       len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
1715
1716     /* If we don't have a constant length for the first, use the length
1717        of the second, if we know it.  We don't require a constant for
1718        this case; some cost analysis could be done if both are available
1719        but neither is constant.  For now, assume they're equally cheap.
1720
1721        If both strings have constant lengths, use the smaller.  This
1722        could arise if optimization results in strcpy being called with
1723        two fixed strings, or if the code was machine-generated.  We should
1724        add some code to the `memcmp' handler below to deal with such
1725        situations, someday.  */
1726
1727     if (!len || TREE_CODE (len) != INTEGER_CST)
1728       {
1729         if (len2)
1730           len = len2;
1731         else if (len == 0)
1732           return 0;
1733       }
1734     else if (len2 && TREE_CODE (len2) == INTEGER_CST
1735              && tree_int_cst_lt (len2, len))
1736       len = len2;
1737
1738     chainon (arglist, build_tree_list (NULL_TREE, len));
1739     result = expand_builtin_memcmp (exp, arglist, target);
1740     if (! result)
1741       TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
1742
1743     return result;
1744   }
1745 }
1746 #endif
1747
1748 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
1749    if that's convenient.  */
1750
1751 rtx
1752 expand_builtin_saveregs ()
1753 {
1754   rtx val, seq;
1755
1756   /* Don't do __builtin_saveregs more than once in a function.
1757      Save the result of the first call and reuse it.  */
1758   if (saveregs_value != 0)
1759     return saveregs_value;
1760
1761   /* When this function is called, it means that registers must be
1762      saved on entry to this function.  So we migrate the call to the
1763      first insn of this function.  */
1764
1765   start_sequence ();
1766
1767 #ifdef EXPAND_BUILTIN_SAVEREGS
1768   /* Do whatever the machine needs done in this case.  */
1769   val = EXPAND_BUILTIN_SAVEREGS ();
1770 #else
1771   /* ??? We used to try and build up a call to the out of line function,
1772      guessing about what registers needed saving etc.  This became much
1773      harder with __builtin_va_start, since we don't have a tree for a
1774      call to __builtin_saveregs to fall back on.  There was exactly one
1775      port (i860) that used this code, and I'm unconvinced it could actually
1776      handle the general case.  So we no longer try to handle anything
1777      weird and make the backend absorb the evil.  */
1778
1779   error ("__builtin_saveregs not supported by this target");
1780   val = const0_rtx;
1781 #endif
1782
1783   seq = get_insns ();
1784   end_sequence ();
1785
1786   saveregs_value = val;
1787
1788   /* Put the sequence after the NOTE that starts the function.  If this
1789      is inside a SEQUENCE, make the outer-level insn chain current, so
1790      the code is placed at the start of the function.  */
1791   push_topmost_sequence ();
1792   emit_insns_after (seq, get_insns ());
1793   pop_topmost_sequence ();
1794
1795   return val;
1796 }
1797
1798 /* __builtin_args_info (N) returns word N of the arg space info
1799    for the current function.  The number and meanings of words
1800    is controlled by the definition of CUMULATIVE_ARGS.  */
1801 static rtx
1802 expand_builtin_args_info (exp)
1803      tree exp;
1804 {
1805   tree arglist = TREE_OPERAND (exp, 1);
1806   int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
1807   int *word_ptr = (int *) &current_function_args_info;
1808 #if 0   
1809   /* These are used by the code below that is if 0'ed away */
1810   int i;
1811   tree type, elts, result;
1812 #endif
1813
1814   if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
1815     abort ();
1816
1817   if (arglist != 0)
1818     {
1819       tree arg = TREE_VALUE (arglist);
1820       if (TREE_CODE (arg) != INTEGER_CST)
1821         error ("argument of `__builtin_args_info' must be constant");
1822       else
1823         {
1824           int wordnum = TREE_INT_CST_LOW (arg);
1825
1826           if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg))
1827             error ("argument of `__builtin_args_info' out of range");
1828           else
1829             return GEN_INT (word_ptr[wordnum]);
1830         }
1831     }
1832   else
1833     error ("missing argument in `__builtin_args_info'");
1834
1835   return const0_rtx;
1836
1837 #if 0
1838   for (i = 0; i < nwords; i++)
1839     elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
1840
1841   type = build_array_type (integer_type_node,
1842                            build_index_type (build_int_2 (nwords, 0)));
1843   result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
1844   TREE_CONSTANT (result) = 1;
1845   TREE_STATIC (result) = 1;
1846   result = build1 (INDIRECT_REF, build_pointer_type (type), result);
1847   TREE_CONSTANT (result) = 1;
1848   return expand_expr (result, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD);
1849 #endif
1850 }
1851
1852 /* Expand ARGLIST, from a call to __builtin_next_arg.  */
1853 static rtx
1854 expand_builtin_next_arg (arglist)
1855      tree arglist;
1856 {
1857   tree fntype = TREE_TYPE (current_function_decl);
1858
1859   if ((TYPE_ARG_TYPES (fntype) == 0
1860        || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1861            == void_type_node))
1862       && ! current_function_varargs)
1863     {
1864       error ("`va_start' used in function with fixed args");
1865       return const0_rtx;
1866     }
1867
1868   if (arglist)
1869     {
1870       tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
1871       tree arg = TREE_VALUE (arglist);
1872
1873       /* Strip off all nops for the sake of the comparison.  This
1874          is not quite the same as STRIP_NOPS.  It does more.  
1875          We must also strip off INDIRECT_EXPR for C++ reference
1876          parameters.  */
1877       while (TREE_CODE (arg) == NOP_EXPR
1878              || TREE_CODE (arg) == CONVERT_EXPR
1879              || TREE_CODE (arg) == NON_LVALUE_EXPR
1880              || TREE_CODE (arg) == INDIRECT_REF)
1881         arg = TREE_OPERAND (arg, 0);
1882       if (arg != last_parm)
1883         warning ("second parameter of `va_start' not last named argument");
1884     }
1885   else if (! current_function_varargs)
1886     /* Evidently an out of date version of <stdarg.h>; can't validate
1887        va_start's second argument, but can still work as intended.  */
1888     warning ("`__builtin_next_arg' called without an argument");
1889
1890   return expand_binop (Pmode, add_optab,
1891                        current_function_internal_arg_pointer,
1892                        current_function_arg_offset_rtx,
1893                        NULL_RTX, 0, OPTAB_LIB_WIDEN);
1894 }
1895
1896 /* Make it easier for the backends by protecting the valist argument
1897    from multiple evaluations.  */
1898
1899 static tree
1900 stabilize_va_list (valist, needs_lvalue)
1901      tree valist;
1902      int needs_lvalue;
1903 {
1904   if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
1905     {
1906       if (TREE_SIDE_EFFECTS (valist))
1907         valist = save_expr (valist);
1908
1909       /* For this case, the backends will be expecting a pointer to
1910          TREE_TYPE (va_list_type_node), but it's possible we've
1911          actually been given an array (an actual va_list_type_node).
1912          So fix it.  */
1913       if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
1914         {
1915           tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
1916           tree p2 = build_pointer_type (va_list_type_node);
1917
1918           valist = build1 (ADDR_EXPR, p2, valist);
1919           valist = fold (build1 (NOP_EXPR, p1, valist));
1920         }
1921     }
1922   else
1923     {
1924       tree pt;
1925
1926       if (! needs_lvalue)
1927         {
1928           if (! TREE_SIDE_EFFECTS (valist))
1929             return valist;
1930           
1931           pt = build_pointer_type (va_list_type_node);
1932           valist = fold (build1 (ADDR_EXPR, pt, valist));
1933           TREE_SIDE_EFFECTS (valist) = 1;
1934         }
1935
1936       if (TREE_SIDE_EFFECTS (valist))
1937         valist = save_expr (valist);
1938       valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
1939                              valist));
1940     }
1941
1942   return valist;
1943 }
1944
1945 /* The "standard" implementation of va_start: just assign `nextarg' to
1946    the variable.  */
1947 void
1948 std_expand_builtin_va_start (stdarg_p, valist, nextarg)
1949      int stdarg_p ATTRIBUTE_UNUSED;
1950      tree valist;
1951      rtx nextarg;
1952 {
1953   tree t;
1954
1955   if (!stdarg_p)
1956     nextarg = plus_constant (nextarg, -UNITS_PER_WORD);
1957
1958   t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
1959              make_tree (ptr_type_node, nextarg));
1960   TREE_SIDE_EFFECTS (t) = 1;
1961
1962   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1963 }
1964
1965 /* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
1966    __builtin_varargs_va_start, depending on STDARG_P.  */
1967 static rtx
1968 expand_builtin_va_start (stdarg_p, arglist)
1969      int stdarg_p;
1970      tree arglist;
1971 {
1972   rtx nextarg;
1973   tree chain = arglist, valist;
1974
1975   if (stdarg_p)
1976     nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
1977   else
1978     nextarg = expand_builtin_next_arg (NULL_TREE);
1979
1980   if (TREE_CHAIN (chain))
1981     error ("too many arguments to function `va_start'");
1982
1983   valist = stabilize_va_list (TREE_VALUE (arglist), 1);
1984
1985 #ifdef EXPAND_BUILTIN_VA_START
1986   EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
1987 #else
1988   std_expand_builtin_va_start (stdarg_p, valist, nextarg);
1989 #endif
1990
1991   return const0_rtx;
1992 }
1993
1994 /* Allocate an alias set for use in storing and reading from the varargs
1995    spill area.  */
1996 int
1997 get_varargs_alias_set ()
1998 {
1999   static int set = -1;
2000   if (set == -1)
2001     set = new_alias_set ();
2002   return set;
2003 }
2004
2005 /* The "standard" implementation of va_arg: read the value from the
2006    current (padded) address and increment by the (padded) size.  */
2007 rtx
2008 std_expand_builtin_va_arg (valist, type)
2009      tree valist, type;
2010 {
2011   tree addr_tree, t;
2012   HOST_WIDE_INT align;
2013   HOST_WIDE_INT rounded_size;
2014   rtx addr;
2015
2016   /* Compute the rounded size of the type.  */
2017   align = PARM_BOUNDARY / BITS_PER_UNIT;
2018   rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
2019
2020   /* Get AP.  */
2021   addr_tree = valist;
2022   if (PAD_VARARGS_DOWN)
2023     {
2024       /* Small args are padded downward.  */
2025
2026       HOST_WIDE_INT adj;
2027       adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT;
2028       if (rounded_size > align)
2029         adj = rounded_size;
2030
2031       addr_tree = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
2032                          build_int_2 (rounded_size - adj, 0));
2033     }
2034
2035   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2036   addr = copy_to_reg (addr);
2037
2038   /* Compute new value for AP.  */
2039   t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2040              build (PLUS_EXPR, TREE_TYPE (valist), valist,
2041                     build_int_2 (rounded_size, 0)));
2042   TREE_SIDE_EFFECTS (t) = 1;
2043   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2044
2045   return addr;
2046 }
2047
2048 /* Expand __builtin_va_arg, which is not really a builtin function, but
2049    a very special sort of operator.  */
2050 rtx
2051 expand_builtin_va_arg (valist, type)
2052      tree valist, type;
2053 {
2054   rtx addr, result;
2055   tree promoted_type, want_va_type, have_va_type;
2056
2057   /* Verify that valist is of the proper type.  */
2058
2059   want_va_type = va_list_type_node;
2060   have_va_type = TREE_TYPE (valist);
2061   if (TREE_CODE (want_va_type) == ARRAY_TYPE)
2062     {
2063       /* If va_list is an array type, the argument may have decayed 
2064          to a pointer type, e.g. by being passed to another function.
2065          In that case, unwrap both types so that we can compare the
2066          underlying records.  */
2067       if (TREE_CODE (have_va_type) == ARRAY_TYPE
2068           || TREE_CODE (have_va_type) == POINTER_TYPE)
2069         {
2070           want_va_type = TREE_TYPE (want_va_type);
2071           have_va_type = TREE_TYPE (have_va_type);
2072         }
2073     }
2074   if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
2075     {
2076       error ("first argument to `va_arg' not of type `va_list'");
2077       addr = const0_rtx;
2078     }
2079
2080   /* Generate a diagnostic for requesting data of a type that cannot
2081      be passed through `...' due to type promotion at the call site.  */
2082   else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
2083     {
2084       const char *name = "<anonymous type>", *pname = 0;
2085       static int gave_help;
2086
2087       if (TYPE_NAME (type))
2088         {
2089           if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
2090             name = IDENTIFIER_POINTER (TYPE_NAME (type));
2091           else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
2092                    && DECL_NAME (TYPE_NAME (type)))
2093             name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
2094         }
2095       if (TYPE_NAME (promoted_type))
2096         {
2097           if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
2098             pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
2099           else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
2100                    && DECL_NAME (TYPE_NAME (promoted_type)))
2101             pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
2102         }
2103
2104       error ("`%s' is promoted to `%s' when passed through `...'", name, pname);
2105       if (! gave_help)
2106         {
2107           gave_help = 1;
2108           error ("(so you should pass `%s' not `%s' to `va_arg')", pname, name);
2109         }
2110
2111       addr = const0_rtx;
2112     }
2113   else
2114     {
2115       /* Make it easier for the backends by protecting the valist argument
2116          from multiple evaluations.  */
2117       valist = stabilize_va_list (valist, 0);
2118
2119 #ifdef EXPAND_BUILTIN_VA_ARG
2120       addr = EXPAND_BUILTIN_VA_ARG (valist, type);
2121 #else
2122       addr = std_expand_builtin_va_arg (valist, type);
2123 #endif
2124     }
2125
2126   result = gen_rtx_MEM (TYPE_MODE (type), addr);
2127   MEM_ALIAS_SET (result) = get_varargs_alias_set ();
2128
2129   return result;
2130 }
2131
2132 /* Expand ARGLIST, from a call to __builtin_va_end.  */
2133 static rtx
2134 expand_builtin_va_end (arglist)
2135      tree arglist;
2136 {
2137   tree valist = TREE_VALUE (arglist);
2138
2139 #ifdef EXPAND_BUILTIN_VA_END
2140   valist = stabilize_va_list (valist, 0);
2141   EXPAND_BUILTIN_VA_END(arglist);
2142 #else
2143   /* Evaluate for side effects, if needed.  I hate macros that don't
2144      do that.  */
2145   if (TREE_SIDE_EFFECTS (valist))
2146     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
2147 #endif
2148
2149   return const0_rtx;
2150 }
2151
2152 /* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a 
2153    builtin rather than just as an assignment in stdarg.h because of the
2154    nastiness of array-type va_list types.  */
2155 static rtx
2156 expand_builtin_va_copy (arglist)
2157      tree arglist;
2158 {
2159   tree dst, src, t;
2160
2161   dst = TREE_VALUE (arglist);
2162   src = TREE_VALUE (TREE_CHAIN (arglist));
2163
2164   dst = stabilize_va_list (dst, 1);
2165   src = stabilize_va_list (src, 0);
2166
2167   if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
2168     {
2169       t = build (MODIFY_EXPR, va_list_type_node, dst, src);
2170       TREE_SIDE_EFFECTS (t) = 1;
2171       expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2172     }
2173   else
2174     {
2175       rtx dstb, srcb, size;
2176
2177       /* Evaluate to pointers.  */
2178       dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
2179       srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
2180       size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
2181                           VOIDmode, EXPAND_NORMAL);
2182
2183       /* "Dereference" to BLKmode memories.  */
2184       dstb = gen_rtx_MEM (BLKmode, dstb);
2185       MEM_ALIAS_SET (dstb) = get_alias_set (TREE_TYPE (TREE_TYPE (dst)));
2186       srcb = gen_rtx_MEM (BLKmode, srcb);
2187       MEM_ALIAS_SET (srcb) = get_alias_set (TREE_TYPE (TREE_TYPE (src)));
2188
2189       /* Copy.  */
2190       emit_block_move (dstb, srcb, size, TYPE_ALIGN (va_list_type_node));
2191     }
2192
2193   return const0_rtx;
2194 }
2195
2196 /* Expand a call to one of the builtin functions __builtin_frame_address or
2197    __builtin_return_address.  */
2198 static rtx
2199 expand_builtin_frame_address (exp)
2200      tree exp;
2201 {
2202   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2203   tree arglist = TREE_OPERAND (exp, 1);
2204
2205   /* The argument must be a nonnegative integer constant.
2206      It counts the number of frames to scan up the stack.
2207      The value is the return address saved in that frame.  */
2208   if (arglist == 0)
2209     /* Warning about missing arg was already issued.  */
2210     return const0_rtx;
2211   else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST
2212            || tree_int_cst_sgn (TREE_VALUE (arglist)) < 0)
2213     {
2214       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2215         error ("invalid arg to `__builtin_frame_address'");
2216       else
2217         error ("invalid arg to `__builtin_return_address'");
2218       return const0_rtx;
2219     }
2220   else
2221     {
2222       rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
2223                                             TREE_INT_CST_LOW (TREE_VALUE (arglist)),
2224                                             hard_frame_pointer_rtx);
2225
2226       /* Some ports cannot access arbitrary stack frames.  */
2227       if (tem == NULL)
2228         {
2229           if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2230             warning ("unsupported arg to `__builtin_frame_address'");
2231           else
2232             warning ("unsupported arg to `__builtin_return_address'");
2233           return const0_rtx;
2234         }
2235
2236       /* For __builtin_frame_address, return what we've got.  */
2237       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
2238         return tem;
2239
2240       if (GET_CODE (tem) != REG
2241           && ! CONSTANT_P (tem))
2242         tem = copy_to_mode_reg (Pmode, tem);
2243       return tem;
2244     }
2245 }
2246
2247 /* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
2248    we failed and the caller should emit a normal call, otherwise try to get
2249    the result in TARGET, if convenient.  */
2250 static rtx
2251 expand_builtin_alloca (arglist, target)
2252      tree arglist;
2253      rtx target;
2254 {
2255   rtx op0;
2256
2257   if (arglist == 0
2258       /* Arg could be non-integer if user redeclared this fcn wrong.  */
2259       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
2260     return 0;
2261
2262   /* Compute the argument.  */
2263   op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
2264
2265   /* Allocate the desired space.  */
2266   return allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
2267 }
2268
2269 /* Expand a call to the ffs builtin.  The arguments are in ARGLIST.
2270    Return 0 if a normal call should be emitted rather than expanding the
2271    function in-line.  If convenient, the result should be placed in TARGET.
2272    SUBTARGET may be used as the target for computing one of EXP's operands.  */
2273 static rtx
2274 expand_builtin_ffs (arglist, target, subtarget)
2275      tree arglist;
2276      rtx target, subtarget;
2277 {
2278   rtx op0;
2279   if (arglist == 0
2280       /* Arg could be non-integer if user redeclared this fcn wrong.  */
2281       || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
2282     return 0;
2283
2284   /* Compute the argument.  */
2285   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
2286   /* Compute ffs, into TARGET if possible.
2287      Set TARGET to wherever the result comes back.  */
2288   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
2289                         ffs_optab, op0, target, 1);
2290   if (target == 0)
2291     abort ();
2292   return target;
2293 }
2294 \f
2295 /* Expand an expression EXP that calls a built-in function,
2296    with result going to TARGET if that's convenient
2297    (and in mode MODE if that's convenient).
2298    SUBTARGET may be used as the target for computing one of EXP's operands.
2299    IGNORE is nonzero if the value is to be ignored.  */
2300
2301 rtx
2302 expand_builtin (exp, target, subtarget, mode, ignore)
2303      tree exp;
2304      rtx target;
2305      rtx subtarget;
2306      enum machine_mode mode;
2307      int ignore;
2308 {
2309   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2310   tree arglist = TREE_OPERAND (exp, 1);
2311   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
2312
2313 #ifdef MD_EXPAND_BUILTIN
2314   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
2315     return MD_EXPAND_BUILTIN (exp, target, subtarget, mode, ignore);
2316 #endif
2317   
2318   /* When not optimizing, generate calls to library functions for a certain
2319      set of builtins.  */
2320   if (! optimize && ! CALLED_AS_BUILT_IN (fndecl)
2321       && (fcode == BUILT_IN_SIN || fcode == BUILT_IN_COS
2322           || fcode == BUILT_IN_FSQRT || fcode == BUILT_IN_MEMSET
2323           || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
2324           || fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO
2325           || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
2326           || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS))
2327     return expand_call (exp, target, ignore);
2328
2329   switch (fcode)
2330     {
2331     case BUILT_IN_ABS:
2332     case BUILT_IN_LABS:
2333     case BUILT_IN_FABS:
2334       /* build_function_call changes these into ABS_EXPR.  */
2335       abort ();
2336
2337     case BUILT_IN_SIN:
2338     case BUILT_IN_COS:
2339       /* Treat these like sqrt, but only if the user asks for them.  */
2340       if (! flag_fast_math)
2341         break;
2342     case BUILT_IN_FSQRT:
2343       target = expand_builtin_mathfn (exp, target, subtarget);
2344       if (target)
2345         return target;
2346       break;
2347
2348     case BUILT_IN_FMOD:
2349       break;
2350
2351     case BUILT_IN_APPLY_ARGS:
2352       return expand_builtin_apply_args ();
2353
2354       /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
2355          FUNCTION with a copy of the parameters described by
2356          ARGUMENTS, and ARGSIZE.  It returns a block of memory
2357          allocated on the stack into which is stored all the registers
2358          that might possibly be used for returning the result of a
2359          function.  ARGUMENTS is the value returned by
2360          __builtin_apply_args.  ARGSIZE is the number of bytes of
2361          arguments that must be copied.  ??? How should this value be
2362          computed?  We'll also need a safe worst case value for varargs
2363          functions.  */
2364     case BUILT_IN_APPLY:
2365       if (arglist == 0
2366           /* Arg could be non-pointer if user redeclared this fcn wrong.  */
2367           || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
2368           || TREE_CHAIN (arglist) == 0
2369           || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
2370           || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
2371           || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
2372         return const0_rtx;
2373       else
2374         {
2375           int i;
2376           tree t;
2377           rtx ops[3];
2378
2379           for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
2380             ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
2381
2382           return expand_builtin_apply (ops[0], ops[1], ops[2]);
2383         }
2384
2385       /* __builtin_return (RESULT) causes the function to return the
2386          value described by RESULT.  RESULT is address of the block of
2387          memory returned by __builtin_apply.  */
2388     case BUILT_IN_RETURN:
2389       if (arglist
2390           /* Arg could be non-pointer if user redeclared this fcn wrong.  */
2391           && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
2392         expand_builtin_return (expand_expr (TREE_VALUE (arglist),
2393                                             NULL_RTX, VOIDmode, 0));
2394       return const0_rtx;
2395
2396     case BUILT_IN_SAVEREGS:
2397       return expand_builtin_saveregs ();
2398
2399     case BUILT_IN_ARGS_INFO:
2400       return expand_builtin_args_info (exp);
2401
2402       /* Return the address of the first anonymous stack arg.  */
2403     case BUILT_IN_NEXT_ARG:
2404       return expand_builtin_next_arg (arglist);
2405
2406     case BUILT_IN_CLASSIFY_TYPE:
2407       return expand_builtin_classify_type (arglist);
2408
2409     case BUILT_IN_CONSTANT_P:
2410       return expand_builtin_constant_p (exp);
2411
2412     case BUILT_IN_FRAME_ADDRESS:
2413     case BUILT_IN_RETURN_ADDRESS:
2414       return expand_builtin_frame_address (exp);
2415
2416     /* Returns the address of the area where the structure is returned.
2417        0 otherwise.  */
2418     case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
2419       if (arglist != 0
2420           || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
2421           || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
2422         return const0_rtx;
2423       else
2424         return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
2425
2426     case BUILT_IN_ALLOCA:
2427       target = expand_builtin_alloca (arglist, target);
2428       if (target)
2429         return target;
2430       break;
2431
2432     case BUILT_IN_FFS:
2433       target = expand_builtin_ffs (arglist, target, subtarget);
2434       if (target)
2435         return target;
2436       break;
2437
2438     case BUILT_IN_STRLEN:
2439       target = expand_builtin_strlen (exp, target, mode);
2440       if (target)
2441         return target;
2442       break;
2443
2444     case BUILT_IN_STRCPY:
2445       target = expand_builtin_strcpy (exp);
2446       if (target)
2447         return target;
2448       break;
2449       
2450     case BUILT_IN_MEMCPY:
2451       target = expand_builtin_memcpy (arglist);
2452       if (target)
2453         return target;
2454       break;
2455
2456     case BUILT_IN_MEMSET:
2457       target = expand_builtin_memset (exp);
2458       if (target)
2459         return target;
2460       break;
2461
2462     case BUILT_IN_BZERO:
2463       target = expand_builtin_bzero (exp);
2464       if (target)
2465         return target;
2466       break;
2467
2468 /* These comparison functions need an instruction that returns an actual
2469    index.  An ordinary compare that just sets the condition codes
2470    is not enough.  */
2471 #ifdef HAVE_cmpstrsi
2472     case BUILT_IN_STRCMP:
2473       target = expand_builtin_strcmp (exp, target);
2474       if (target)
2475         return target;
2476       break;
2477
2478     case BUILT_IN_BCMP:
2479     case BUILT_IN_MEMCMP:
2480       target = expand_builtin_memcmp (exp, arglist, target);
2481       if (target)
2482         return target;
2483       break;
2484 #else
2485     case BUILT_IN_STRCMP:
2486     case BUILT_IN_BCMP:
2487     case BUILT_IN_MEMCMP:
2488       break;
2489 #endif
2490
2491     case BUILT_IN_SETJMP:
2492       if (arglist == 0
2493           || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
2494         break;
2495       else
2496         {
2497           rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
2498                                       VOIDmode, 0);
2499           rtx lab = gen_label_rtx ();
2500           rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab);
2501           emit_label (lab);
2502           return ret;
2503         }
2504
2505       /* __builtin_longjmp is passed a pointer to an array of five words.
2506          It's similar to the C library longjmp function but works with
2507          __builtin_setjmp above.  */
2508     case BUILT_IN_LONGJMP:
2509       if (arglist == 0 || TREE_CHAIN (arglist) == 0
2510           || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
2511         break;
2512       else
2513         {
2514           rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
2515                                       VOIDmode, 0);
2516           rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
2517                                    NULL_RTX, VOIDmode, 0);
2518
2519           if (value != const1_rtx)
2520             {
2521               error ("__builtin_longjmp second argument must be 1");
2522               return const0_rtx;
2523             }
2524
2525           expand_builtin_longjmp (buf_addr, value);
2526           return const0_rtx;
2527         }
2528
2529     case BUILT_IN_TRAP:
2530 #ifdef HAVE_trap
2531       if (HAVE_trap)
2532         emit_insn (gen_trap ());
2533       else
2534 #endif
2535         error ("__builtin_trap not supported by this target");
2536       emit_barrier ();
2537       return const0_rtx;
2538
2539       /* Various hooks for the DWARF 2 __throw routine.  */
2540     case BUILT_IN_UNWIND_INIT:
2541       expand_builtin_unwind_init ();
2542       return const0_rtx;
2543     case BUILT_IN_DWARF_CFA:
2544       return virtual_cfa_rtx;
2545 #ifdef DWARF2_UNWIND_INFO
2546     case BUILT_IN_DWARF_FP_REGNUM:
2547       return expand_builtin_dwarf_fp_regnum ();
2548     case BUILT_IN_INIT_DWARF_REG_SIZES:
2549       expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
2550       return const0_rtx;
2551 #endif
2552     case BUILT_IN_FROB_RETURN_ADDR:
2553       return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
2554     case BUILT_IN_EXTRACT_RETURN_ADDR:
2555       return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
2556     case BUILT_IN_EH_RETURN:
2557       expand_builtin_eh_return (TREE_VALUE (arglist),
2558                                 TREE_VALUE (TREE_CHAIN (arglist)),
2559                                 TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
2560       return const0_rtx;
2561     case BUILT_IN_VARARGS_START:
2562       return expand_builtin_va_start (0, arglist);
2563     case BUILT_IN_STDARG_START:
2564       return expand_builtin_va_start (1, arglist);
2565     case BUILT_IN_VA_END:
2566       return expand_builtin_va_end (arglist);
2567     case BUILT_IN_VA_COPY:
2568       return expand_builtin_va_copy (arglist);
2569
2570     default:                    /* just do library call, if unknown builtin */
2571       error ("built-in function `%s' not currently supported",
2572              IDENTIFIER_POINTER (DECL_NAME (fndecl)));
2573     }
2574
2575   /* The switch statement above can drop through to cause the function
2576      to be called normally.  */
2577   return expand_call (exp, target, ignore);
2578 }