OSDN Git Service

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