OSDN Git Service

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