OSDN Git Service

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