OSDN Git Service

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