OSDN Git Service

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