OSDN Git Service

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