OSDN Git Service

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