OSDN Git Service

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