OSDN Git Service

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