builtins.c revision 110621
1/* Expand builtin functions.
2   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING.  If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-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-config.h"
34#include "expr.h"
35#include "optabs.h"
36#include "libfuncs.h"
37#include "recog.h"
38#include "output.h"
39#include "typeclass.h"
40#include "toplev.h"
41#include "predict.h"
42#include "tm_p.h"
43#include "target.h"
44
45#define CALLED_AS_BUILT_IN(NODE) \
46   (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
47
48/* Register mappings for target machines without register windows.  */
49#ifndef INCOMING_REGNO
50#define INCOMING_REGNO(OUT) (OUT)
51#endif
52#ifndef OUTGOING_REGNO
53#define OUTGOING_REGNO(IN) (IN)
54#endif
55
56#ifndef PAD_VARARGS_DOWN
57#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
58#endif
59
60/* Define the names of the builtin function types and codes.  */
61const char *const built_in_class_names[4]
62  = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
63
64#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA) STRINGX(X),
65const char *const built_in_names[(int) END_BUILTINS] =
66{
67#include "builtins.def"
68};
69#undef DEF_BUILTIN
70
71/* Setup an array of _DECL trees, make sure each element is
72   initialized to NULL_TREE.  */
73tree built_in_decls[(int) END_BUILTINS];
74
75tree (*lang_type_promotes_to) PARAMS ((tree));
76
77static int get_pointer_alignment	PARAMS ((tree, unsigned int));
78static tree c_strlen			PARAMS ((tree));
79static const char *c_getstr		PARAMS ((tree));
80static rtx c_readstr			PARAMS ((const char *,
81						 enum machine_mode));
82static int target_char_cast		PARAMS ((tree, char *));
83static rtx get_memory_rtx		PARAMS ((tree));
84static int apply_args_size		PARAMS ((void));
85static int apply_result_size		PARAMS ((void));
86#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
87static rtx result_vector		PARAMS ((int, rtx));
88#endif
89static rtx expand_builtin_setjmp	PARAMS ((tree, rtx));
90static void expand_builtin_prefetch	PARAMS ((tree));
91static rtx expand_builtin_apply_args	PARAMS ((void));
92static rtx expand_builtin_apply_args_1	PARAMS ((void));
93static rtx expand_builtin_apply		PARAMS ((rtx, rtx, rtx));
94static void expand_builtin_return	PARAMS ((rtx));
95static enum type_class type_to_class	PARAMS ((tree));
96static rtx expand_builtin_classify_type	PARAMS ((tree));
97static rtx expand_builtin_mathfn	PARAMS ((tree, rtx, rtx));
98static rtx expand_builtin_constant_p	PARAMS ((tree));
99static rtx expand_builtin_args_info	PARAMS ((tree));
100static rtx expand_builtin_next_arg	PARAMS ((tree));
101static rtx expand_builtin_va_start	PARAMS ((int, tree));
102static rtx expand_builtin_va_end	PARAMS ((tree));
103static rtx expand_builtin_va_copy	PARAMS ((tree));
104static rtx expand_builtin_memcmp	PARAMS ((tree, tree, rtx,
105                                                 enum machine_mode));
106static rtx expand_builtin_strcmp	PARAMS ((tree, rtx,
107						 enum machine_mode));
108static rtx expand_builtin_strncmp	PARAMS ((tree, rtx,
109						 enum machine_mode));
110static rtx builtin_memcpy_read_str	PARAMS ((PTR, HOST_WIDE_INT,
111						 enum machine_mode));
112static rtx expand_builtin_strcat	PARAMS ((tree, rtx,
113						 enum machine_mode));
114static rtx expand_builtin_strncat	PARAMS ((tree, rtx,
115						 enum machine_mode));
116static rtx expand_builtin_strspn	PARAMS ((tree, rtx,
117						 enum machine_mode));
118static rtx expand_builtin_strcspn	PARAMS ((tree, rtx,
119						 enum machine_mode));
120static rtx expand_builtin_memcpy	PARAMS ((tree, rtx,
121                                                 enum machine_mode));
122static rtx expand_builtin_strcpy	PARAMS ((tree, rtx,
123                                                 enum machine_mode));
124static rtx builtin_strncpy_read_str	PARAMS ((PTR, HOST_WIDE_INT,
125						 enum machine_mode));
126static rtx expand_builtin_strncpy	PARAMS ((tree, rtx,
127						 enum machine_mode));
128static rtx builtin_memset_read_str	PARAMS ((PTR, HOST_WIDE_INT,
129						 enum machine_mode));
130static rtx expand_builtin_memset	PARAMS ((tree, rtx,
131                                                 enum machine_mode));
132static rtx expand_builtin_bzero		PARAMS ((tree));
133static rtx expand_builtin_strlen	PARAMS ((tree, rtx));
134static rtx expand_builtin_strstr	PARAMS ((tree, rtx,
135						 enum machine_mode));
136static rtx expand_builtin_strpbrk	PARAMS ((tree, rtx,
137						 enum machine_mode));
138static rtx expand_builtin_strchr	PARAMS ((tree, rtx,
139						 enum machine_mode));
140static rtx expand_builtin_strrchr	PARAMS ((tree, rtx,
141						 enum machine_mode));
142static rtx expand_builtin_alloca	PARAMS ((tree, rtx));
143static rtx expand_builtin_ffs		PARAMS ((tree, rtx, rtx));
144static rtx expand_builtin_frame_address	PARAMS ((tree));
145static rtx expand_builtin_fputs		PARAMS ((tree, int, int));
146static tree stabilize_va_list		PARAMS ((tree, int));
147static rtx expand_builtin_expect	PARAMS ((tree, rtx));
148static tree fold_builtin_constant_p	PARAMS ((tree));
149static tree fold_builtin_classify_type	PARAMS ((tree));
150static tree build_function_call_expr	PARAMS ((tree, tree));
151static int validate_arglist		PARAMS ((tree, ...));
152
153/* Return the alignment in bits of EXP, a pointer valued expression.
154   But don't return more than MAX_ALIGN no matter what.
155   The alignment returned is, by default, the alignment of the thing that
156   EXP points to.  If it is not a POINTER_TYPE, 0 is returned.
157
158   Otherwise, look at the expression to see if we can do better, i.e., if the
159   expression is actually pointing at an object whose alignment is tighter.  */
160
161static int
162get_pointer_alignment (exp, max_align)
163     tree exp;
164     unsigned int max_align;
165{
166  unsigned int align, inner;
167
168  if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
169    return 0;
170
171  align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
172  align = MIN (align, max_align);
173
174  while (1)
175    {
176      switch (TREE_CODE (exp))
177	{
178	case NOP_EXPR:
179	case CONVERT_EXPR:
180	case NON_LVALUE_EXPR:
181	  exp = TREE_OPERAND (exp, 0);
182	  if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
183	    return align;
184
185	  inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
186	  align = MIN (inner, max_align);
187	  break;
188
189	case PLUS_EXPR:
190	  /* If sum of pointer + int, restrict our maximum alignment to that
191	     imposed by the integer.  If not, we can't do any better than
192	     ALIGN.  */
193	  if (! host_integerp (TREE_OPERAND (exp, 1), 1))
194	    return align;
195
196	  while (((tree_low_cst (TREE_OPERAND (exp, 1), 1))
197		  & (max_align / BITS_PER_UNIT - 1))
198		 != 0)
199	    max_align >>= 1;
200
201	  exp = TREE_OPERAND (exp, 0);
202	  break;
203
204	case ADDR_EXPR:
205	  /* See what we are pointing at and look at its alignment.  */
206	  exp = TREE_OPERAND (exp, 0);
207	  if (TREE_CODE (exp) == FUNCTION_DECL)
208	    align = FUNCTION_BOUNDARY;
209	  else if (DECL_P (exp))
210	    align = DECL_ALIGN (exp);
211#ifdef CONSTANT_ALIGNMENT
212	  else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
213	    align = CONSTANT_ALIGNMENT (exp, align);
214#endif
215	  return MIN (align, max_align);
216
217	default:
218	  return align;
219	}
220    }
221}
222
223/* Compute the length of a C string.  TREE_STRING_LENGTH is not the right
224   way, because it could contain a zero byte in the middle.
225   TREE_STRING_LENGTH is the size of the character array, not the string.
226
227   The value returned is of type `ssizetype'.
228
229   Unfortunately, string_constant can't access the values of const char
230   arrays with initializers, so neither can we do so here.  */
231
232static tree
233c_strlen (src)
234     tree src;
235{
236  tree offset_node;
237  HOST_WIDE_INT offset;
238  int max;
239  const char *ptr;
240
241  src = string_constant (src, &offset_node);
242  if (src == 0)
243    return 0;
244
245  max = TREE_STRING_LENGTH (src) - 1;
246  ptr = TREE_STRING_POINTER (src);
247
248  if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
249    {
250      /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
251	 compute the offset to the following null if we don't know where to
252	 start searching for it.  */
253      int i;
254
255      for (i = 0; i < max; i++)
256	if (ptr[i] == 0)
257	  return 0;
258
259      /* We don't know the starting offset, but we do know that the string
260	 has no internal zero bytes.  We can assume that the offset falls
261	 within the bounds of the string; otherwise, the programmer deserves
262	 what he gets.  Subtract the offset from the length of the string,
263	 and return that.  This would perhaps not be valid if we were dealing
264	 with named arrays in addition to literal string constants.  */
265
266      return size_diffop (size_int (max), offset_node);
267    }
268
269  /* We have a known offset into the string.  Start searching there for
270     a null character if we can represent it as a single HOST_WIDE_INT.  */
271  if (offset_node == 0)
272    offset = 0;
273  else if (! host_integerp (offset_node, 0))
274    offset = -1;
275  else
276    offset = tree_low_cst (offset_node, 0);
277
278  /* If the offset is known to be out of bounds, warn, and call strlen at
279     runtime.  */
280  if (offset < 0 || offset > max)
281    {
282      warning ("offset outside bounds of constant string");
283      return 0;
284    }
285
286  /* Use strlen to search for the first zero byte.  Since any strings
287     constructed with build_string will have nulls appended, we win even
288     if we get handed something like (char[4])"abcd".
289
290     Since OFFSET is our starting index into the string, no further
291     calculation is needed.  */
292  return ssize_int (strlen (ptr + offset));
293}
294
295/* Return a char pointer for a C string if it is a string constant
296   or sum of string constant and integer constant.  */
297
298static const char *
299c_getstr (src)
300     tree src;
301{
302  tree offset_node;
303
304  src = string_constant (src, &offset_node);
305  if (src == 0)
306    return 0;
307
308  if (offset_node == 0)
309    return TREE_STRING_POINTER (src);
310  else if (!host_integerp (offset_node, 1)
311	   || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
312    return 0;
313
314  return TREE_STRING_POINTER (src) + tree_low_cst (offset_node, 1);
315}
316
317/* Return a CONST_INT or CONST_DOUBLE corresponding to target reading
318   GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
319
320static rtx
321c_readstr (str, mode)
322     const char *str;
323     enum machine_mode mode;
324{
325  HOST_WIDE_INT c[2];
326  HOST_WIDE_INT ch;
327  unsigned int i, j;
328
329  if (GET_MODE_CLASS (mode) != MODE_INT)
330    abort ();
331  c[0] = 0;
332  c[1] = 0;
333  ch = 1;
334  for (i = 0; i < GET_MODE_SIZE (mode); i++)
335    {
336      j = i;
337      if (WORDS_BIG_ENDIAN)
338	j = GET_MODE_SIZE (mode) - i - 1;
339      if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
340	  && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
341	j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
342      j *= BITS_PER_UNIT;
343      if (j > 2 * HOST_BITS_PER_WIDE_INT)
344	abort ();
345      if (ch)
346	ch = (unsigned char) str[i];
347      c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
348    }
349  return immed_double_const (c[0], c[1], mode);
350}
351
352/* Cast a target constant CST to target CHAR and if that value fits into
353   host char type, return zero and put that value into variable pointed by
354   P.  */
355
356static int
357target_char_cast (cst, p)
358     tree cst;
359     char *p;
360{
361  unsigned HOST_WIDE_INT val, hostval;
362
363  if (!host_integerp (cst, 1)
364      || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
365    return 1;
366
367  val = tree_low_cst (cst, 1);
368  if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
369    val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
370
371  hostval = val;
372  if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
373    hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
374
375  if (val != hostval)
376    return 1;
377
378  *p = hostval;
379  return 0;
380}
381
382/* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
383   times to get the address of either a higher stack frame, or a return
384   address located within it (depending on FNDECL_CODE).  */
385
386rtx
387expand_builtin_return_addr (fndecl_code, count, tem)
388     enum built_in_function fndecl_code;
389     int count;
390     rtx tem;
391{
392  int i;
393
394  /* Some machines need special handling before we can access
395     arbitrary frames.  For example, on the sparc, we must first flush
396     all register windows to the stack.  */
397#ifdef SETUP_FRAME_ADDRESSES
398  if (count > 0)
399    SETUP_FRAME_ADDRESSES ();
400#endif
401
402  /* On the sparc, the return address is not in the frame, it is in a
403     register.  There is no way to access it off of the current frame
404     pointer, but it can be accessed off the previous frame pointer by
405     reading the value from the register window save area.  */
406#ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
407  if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
408    count--;
409#endif
410
411  /* Scan back COUNT frames to the specified frame.  */
412  for (i = 0; i < count; i++)
413    {
414      /* Assume the dynamic chain pointer is in the word that the
415	 frame address points to, unless otherwise specified.  */
416#ifdef DYNAMIC_CHAIN_ADDRESS
417      tem = DYNAMIC_CHAIN_ADDRESS (tem);
418#endif
419      tem = memory_address (Pmode, tem);
420      tem = gen_rtx_MEM (Pmode, tem);
421      set_mem_alias_set (tem, get_frame_alias_set ());
422      tem = copy_to_reg (tem);
423    }
424
425  /* For __builtin_frame_address, return what we've got.  */
426  if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
427    return tem;
428
429  /* For __builtin_return_address, Get the return address from that
430     frame.  */
431#ifdef RETURN_ADDR_RTX
432  tem = RETURN_ADDR_RTX (count, tem);
433#else
434  tem = memory_address (Pmode,
435			plus_constant (tem, GET_MODE_SIZE (Pmode)));
436  tem = gen_rtx_MEM (Pmode, tem);
437  set_mem_alias_set (tem, get_frame_alias_set ());
438#endif
439  return tem;
440}
441
442/* Alias set used for setjmp buffer.  */
443static HOST_WIDE_INT setjmp_alias_set = -1;
444
445/* Construct the leading half of a __builtin_setjmp call.  Control will
446   return to RECEIVER_LABEL.  This is used directly by sjlj exception
447   handling code.  */
448
449void
450expand_builtin_setjmp_setup (buf_addr, receiver_label)
451     rtx buf_addr;
452     rtx receiver_label;
453{
454  enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
455  rtx stack_save;
456  rtx mem;
457
458  if (setjmp_alias_set == -1)
459    setjmp_alias_set = new_alias_set ();
460
461#ifdef POINTERS_EXTEND_UNSIGNED
462  if (GET_MODE (buf_addr) != Pmode)
463    buf_addr = convert_memory_address (Pmode, buf_addr);
464#endif
465
466  buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
467
468  emit_queue ();
469
470  /* We store the frame pointer and the address of receiver_label in
471     the buffer and use the rest of it for the stack save area, which
472     is machine-dependent.  */
473
474#ifndef BUILTIN_SETJMP_FRAME_VALUE
475#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
476#endif
477
478  mem = gen_rtx_MEM (Pmode, buf_addr);
479  set_mem_alias_set (mem, setjmp_alias_set);
480  emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
481
482  mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
483  set_mem_alias_set (mem, setjmp_alias_set);
484
485  emit_move_insn (validize_mem (mem),
486		  force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
487
488  stack_save = gen_rtx_MEM (sa_mode,
489			    plus_constant (buf_addr,
490					   2 * GET_MODE_SIZE (Pmode)));
491  set_mem_alias_set (stack_save, setjmp_alias_set);
492  emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
493
494  /* If there is further processing to do, do it.  */
495#ifdef HAVE_builtin_setjmp_setup
496  if (HAVE_builtin_setjmp_setup)
497    emit_insn (gen_builtin_setjmp_setup (buf_addr));
498#endif
499
500  /* Tell optimize_save_area_alloca that extra work is going to
501     need to go on during alloca.  */
502  current_function_calls_setjmp = 1;
503
504  /* Set this so all the registers get saved in our frame; we need to be
505     able to copy the saved values for any registers from frames we unwind.  */
506  current_function_has_nonlocal_label = 1;
507}
508
509/* Construct the trailing part of a __builtin_setjmp call.
510   This is used directly by sjlj exception handling code.  */
511
512void
513expand_builtin_setjmp_receiver (receiver_label)
514      rtx receiver_label ATTRIBUTE_UNUSED;
515{
516  /* Clobber the FP when we get here, so we have to make sure it's
517     marked as used by this function.  */
518  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
519
520  /* Mark the static chain as clobbered here so life information
521     doesn't get messed up for it.  */
522  emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
523
524  /* Now put in the code to restore the frame pointer, and argument
525     pointer, if needed.  The code below is from expand_end_bindings
526     in stmt.c; see detailed documentation there.  */
527#ifdef HAVE_nonlocal_goto
528  if (! HAVE_nonlocal_goto)
529#endif
530    emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
531
532#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
533  if (fixed_regs[ARG_POINTER_REGNUM])
534    {
535#ifdef ELIMINABLE_REGS
536      size_t i;
537      static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
538
539      for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
540	if (elim_regs[i].from == ARG_POINTER_REGNUM
541	    && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
542	  break;
543
544      if (i == ARRAY_SIZE (elim_regs))
545#endif
546	{
547	  /* Now restore our arg pointer from the address at which it
548	     was saved in our stack frame.  */
549	  emit_move_insn (virtual_incoming_args_rtx,
550			  copy_to_reg (get_arg_pointer_save_area (cfun)));
551	}
552    }
553#endif
554
555#ifdef HAVE_builtin_setjmp_receiver
556  if (HAVE_builtin_setjmp_receiver)
557    emit_insn (gen_builtin_setjmp_receiver (receiver_label));
558  else
559#endif
560#ifdef HAVE_nonlocal_goto_receiver
561    if (HAVE_nonlocal_goto_receiver)
562      emit_insn (gen_nonlocal_goto_receiver ());
563    else
564#endif
565      { /* Nothing */ }
566
567  /* @@@ This is a kludge.  Not all machine descriptions define a blockage
568     insn, but we must not allow the code we just generated to be reordered
569     by scheduling.  Specifically, the update of the frame pointer must
570     happen immediately, not later.  So emit an ASM_INPUT to act as blockage
571     insn.  */
572  emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
573}
574
575/* __builtin_setjmp is passed a pointer to an array of five words (not
576   all will be used on all machines).  It operates similarly to the C
577   library function of the same name, but is more efficient.  Much of
578   the code below (and for longjmp) is copied from the handling of
579   non-local gotos.
580
581   NOTE: This is intended for use by GNAT and the exception handling
582   scheme in the compiler and will only work in the method used by
583   them.  */
584
585static rtx
586expand_builtin_setjmp (arglist, target)
587     tree arglist;
588     rtx target;
589{
590  rtx buf_addr, next_lab, cont_lab;
591
592  if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
593    return NULL_RTX;
594
595  if (target == 0 || GET_CODE (target) != REG
596      || REGNO (target) < FIRST_PSEUDO_REGISTER)
597    target = gen_reg_rtx (TYPE_MODE (integer_type_node));
598
599  buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
600
601  next_lab = gen_label_rtx ();
602  cont_lab = gen_label_rtx ();
603
604  expand_builtin_setjmp_setup (buf_addr, next_lab);
605
606  /* Set TARGET to zero and branch to the continue label.  */
607  emit_move_insn (target, const0_rtx);
608  emit_jump_insn (gen_jump (cont_lab));
609  emit_barrier ();
610  emit_label (next_lab);
611
612  expand_builtin_setjmp_receiver (next_lab);
613
614  /* Set TARGET to one.  */
615  emit_move_insn (target, const1_rtx);
616  emit_label (cont_lab);
617
618  /* Tell flow about the strange goings on.  Putting `next_lab' on
619     `nonlocal_goto_handler_labels' to indicates that function
620     calls may traverse the arc back to this label.  */
621
622  current_function_has_nonlocal_label = 1;
623  nonlocal_goto_handler_labels
624    = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
625
626  return target;
627}
628
629/* __builtin_longjmp is passed a pointer to an array of five words (not
630   all will be used on all machines).  It operates similarly to the C
631   library function of the same name, but is more efficient.  Much of
632   the code below is copied from the handling of non-local gotos.
633
634   NOTE: This is intended for use by GNAT and the exception handling
635   scheme in the compiler and will only work in the method used by
636   them.  */
637
638void
639expand_builtin_longjmp (buf_addr, value)
640     rtx buf_addr, value;
641{
642  rtx fp, lab, stack, insn;
643  enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
644
645  if (setjmp_alias_set == -1)
646    setjmp_alias_set = new_alias_set ();
647
648#ifdef POINTERS_EXTEND_UNSIGNED
649  if (GET_MODE (buf_addr) != Pmode)
650    buf_addr = convert_memory_address (Pmode, buf_addr);
651#endif
652
653  buf_addr = force_reg (Pmode, buf_addr);
654
655  /* We used to store value in static_chain_rtx, but that fails if pointers
656     are smaller than integers.  We instead require that the user must pass
657     a second argument of 1, because that is what builtin_setjmp will
658     return.  This also makes EH slightly more efficient, since we are no
659     longer copying around a value that we don't care about.  */
660  if (value != const1_rtx)
661    abort ();
662
663  current_function_calls_longjmp = 1;
664
665#ifdef HAVE_builtin_longjmp
666  if (HAVE_builtin_longjmp)
667    emit_insn (gen_builtin_longjmp (buf_addr));
668  else
669#endif
670    {
671      fp = gen_rtx_MEM (Pmode, buf_addr);
672      lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
673					       GET_MODE_SIZE (Pmode)));
674
675      stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
676						   2 * GET_MODE_SIZE (Pmode)));
677      set_mem_alias_set (fp, setjmp_alias_set);
678      set_mem_alias_set (lab, setjmp_alias_set);
679      set_mem_alias_set (stack, setjmp_alias_set);
680
681      /* Pick up FP, label, and SP from the block and jump.  This code is
682	 from expand_goto in stmt.c; see there for detailed comments.  */
683#if HAVE_nonlocal_goto
684      if (HAVE_nonlocal_goto)
685	/* We have to pass a value to the nonlocal_goto pattern that will
686	   get copied into the static_chain pointer, but it does not matter
687	   what that value is, because builtin_setjmp does not use it.  */
688	emit_insn (gen_nonlocal_goto (value, lab, stack, fp));
689      else
690#endif
691	{
692	  lab = copy_to_reg (lab);
693
694	  emit_move_insn (hard_frame_pointer_rtx, fp);
695	  emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
696
697	  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
698	  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
699	  emit_indirect_jump (lab);
700	}
701    }
702
703  /* Search backwards and mark the jump insn as a non-local goto.
704     Note that this precludes the use of __builtin_longjmp to a
705     __builtin_setjmp target in the same function.  However, we've
706     already cautioned the user that these functions are for
707     internal exception handling use only.  */
708  for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
709    {
710      if (GET_CODE (insn) == JUMP_INSN)
711	{
712	  REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
713					      REG_NOTES (insn));
714	  break;
715	}
716      else if (GET_CODE (insn) == CALL_INSN)
717        break;
718    }
719}
720
721/* Expand a call to __builtin_prefetch.  For a target that does not support
722   data prefetch, evaluate the memory address argument in case it has side
723   effects.  */
724
725static void
726expand_builtin_prefetch (arglist)
727     tree arglist;
728{
729  tree arg0, arg1, arg2;
730  rtx op0, op1, op2;
731
732  if (!validate_arglist (arglist, POINTER_TYPE, 0))
733    return;
734
735  arg0 = TREE_VALUE (arglist);
736  /* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
737     zero (read) and argument 2 (locality) defaults to 3 (high degree of
738     locality).  */
739  if (TREE_CHAIN (arglist))
740    {
741      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
742      if (TREE_CHAIN (TREE_CHAIN (arglist)))
743        arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
744      else
745	arg2 = build_int_2 (3, 0);
746    }
747  else
748    {
749      arg1 = integer_zero_node;
750      arg2 = build_int_2 (3, 0);
751    }
752
753  /* Argument 0 is an address.  */
754  op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
755
756  /* Argument 1 (read/write flag) must be a compile-time constant int.  */
757  if (TREE_CODE (arg1) != INTEGER_CST)
758    {
759       error ("second arg to `__builtin_prefetch' must be a constant");
760       arg1 = integer_zero_node;
761    }
762  op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
763  /* Argument 1 must be either zero or one.  */
764  if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
765    {
766      warning ("invalid second arg to __builtin_prefetch; using zero");
767      op1 = const0_rtx;
768    }
769
770  /* Argument 2 (locality) must be a compile-time constant int.  */
771  if (TREE_CODE (arg2) != INTEGER_CST)
772    {
773      error ("third arg to `__builtin_prefetch' must be a constant");
774      arg2 = integer_zero_node;
775    }
776  op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
777  /* Argument 2 must be 0, 1, 2, or 3.  */
778  if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
779    {
780      warning ("invalid third arg to __builtin_prefetch; using zero");
781      op2 = const0_rtx;
782    }
783
784#ifdef HAVE_prefetch
785  if (HAVE_prefetch)
786    {
787      if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate)
788	    (op0,
789	     insn_data[(int)CODE_FOR_prefetch].operand[0].mode))
790        op0 = force_reg (Pmode, op0);
791      emit_insn (gen_prefetch (op0, op1, op2));
792    }
793  else
794#endif
795    op0 = protect_from_queue (op0, 0);
796    /* Don't do anything with direct references to volatile memory, but
797       generate code to handle other side effects.  */
798    if (GET_CODE (op0) != MEM && side_effects_p (op0))
799      emit_insn (op0);
800}
801
802/* Get a MEM rtx for expression EXP which is the address of an operand
803   to be used to be used in a string instruction (cmpstrsi, movstrsi, ..).  */
804
805static rtx
806get_memory_rtx (exp)
807     tree exp;
808{
809  rtx addr = expand_expr (exp, NULL_RTX, ptr_mode, EXPAND_SUM);
810  rtx mem;
811
812#ifdef POINTERS_EXTEND_UNSIGNED
813  if (GET_MODE (addr) != Pmode)
814    addr = convert_memory_address (Pmode, addr);
815#endif
816
817  mem = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
818
819  /* Get an expression we can use to find the attributes to assign to MEM.
820     If it is an ADDR_EXPR, use the operand.  Otherwise, dereference it if
821     we can.  First remove any nops.  */
822  while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
823	 || TREE_CODE (exp) == NON_LVALUE_EXPR)
824	 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
825    exp = TREE_OPERAND (exp, 0);
826
827  if (TREE_CODE (exp) == ADDR_EXPR)
828    {
829      exp = TREE_OPERAND (exp, 0);
830      set_mem_attributes (mem, exp, 0);
831    }
832  else if (POINTER_TYPE_P (TREE_TYPE (exp)))
833    {
834      exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
835      /* memcpy, memset and other builtin stringops can alias with anything.  */
836      set_mem_alias_set (mem, 0);
837    }
838
839  return mem;
840}
841
842/* Built-in functions to perform an untyped call and return.  */
843
844/* For each register that may be used for calling a function, this
845   gives a mode used to copy the register's value.  VOIDmode indicates
846   the register is not used for calling a function.  If the machine
847   has register windows, this gives only the outbound registers.
848   INCOMING_REGNO gives the corresponding inbound register.  */
849static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
850
851/* For each register that may be used for returning values, this gives
852   a mode used to copy the register's value.  VOIDmode indicates the
853   register is not used for returning values.  If the machine has
854   register windows, this gives only the outbound registers.
855   INCOMING_REGNO gives the corresponding inbound register.  */
856static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
857
858/* For each register that may be used for calling a function, this
859   gives the offset of that register into the block returned by
860   __builtin_apply_args.  0 indicates that the register is not
861   used for calling a function.  */
862static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
863
864/* Return the offset of register REGNO into the block returned by
865   __builtin_apply_args.  This is not declared static, since it is
866   needed in objc-act.c.  */
867
868int
869apply_args_register_offset (regno)
870     int regno;
871{
872  apply_args_size ();
873
874  /* Arguments are always put in outgoing registers (in the argument
875     block) if such make sense.  */
876#ifdef OUTGOING_REGNO
877  regno = OUTGOING_REGNO(regno);
878#endif
879  return apply_args_reg_offset[regno];
880}
881
882/* Return the size required for the block returned by __builtin_apply_args,
883   and initialize apply_args_mode.  */
884
885static int
886apply_args_size ()
887{
888  static int size = -1;
889  int align;
890  unsigned int regno;
891  enum machine_mode mode;
892
893  /* The values computed by this function never change.  */
894  if (size < 0)
895    {
896      /* The first value is the incoming arg-pointer.  */
897      size = GET_MODE_SIZE (Pmode);
898
899      /* The second value is the structure value address unless this is
900	 passed as an "invisible" first argument.  */
901      if (struct_value_rtx)
902	size += GET_MODE_SIZE (Pmode);
903
904      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
905	if (FUNCTION_ARG_REGNO_P (regno))
906	  {
907	    /* Search for the proper mode for copying this register's
908	       value.  I'm not sure this is right, but it works so far.  */
909	    enum machine_mode best_mode = VOIDmode;
910
911	    for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
912		 mode != VOIDmode;
913		 mode = GET_MODE_WIDER_MODE (mode))
914	      if (HARD_REGNO_MODE_OK (regno, mode)
915		  && HARD_REGNO_NREGS (regno, mode) == 1)
916		best_mode = mode;
917
918	    if (best_mode == VOIDmode)
919	      for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
920		   mode != VOIDmode;
921		   mode = GET_MODE_WIDER_MODE (mode))
922		if (HARD_REGNO_MODE_OK (regno, mode)
923		    && have_insn_for (SET, mode))
924		  best_mode = mode;
925
926	    if (best_mode == VOIDmode)
927	      for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
928		   mode != VOIDmode;
929		   mode = GET_MODE_WIDER_MODE (mode))
930		if (HARD_REGNO_MODE_OK (regno, mode)
931		    && have_insn_for (SET, mode))
932		  best_mode = mode;
933
934	    if (best_mode == VOIDmode)
935	      for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
936		   mode != VOIDmode;
937		   mode = GET_MODE_WIDER_MODE (mode))
938		if (HARD_REGNO_MODE_OK (regno, mode)
939		    && have_insn_for (SET, mode))
940		  best_mode = mode;
941
942	    mode = best_mode;
943	    if (mode == VOIDmode)
944	      abort ();
945
946	    align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
947	    if (size % align != 0)
948	      size = CEIL (size, align) * align;
949	    apply_args_reg_offset[regno] = size;
950	    size += GET_MODE_SIZE (mode);
951	    apply_args_mode[regno] = mode;
952	  }
953	else
954	  {
955	    apply_args_mode[regno] = VOIDmode;
956	    apply_args_reg_offset[regno] = 0;
957	  }
958    }
959  return size;
960}
961
962/* Return the size required for the block returned by __builtin_apply,
963   and initialize apply_result_mode.  */
964
965static int
966apply_result_size ()
967{
968  static int size = -1;
969  int align, regno;
970  enum machine_mode mode;
971
972  /* The values computed by this function never change.  */
973  if (size < 0)
974    {
975      size = 0;
976
977      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
978	if (FUNCTION_VALUE_REGNO_P (regno))
979	  {
980	    /* Search for the proper mode for copying this register's
981	       value.  I'm not sure this is right, but it works so far.  */
982	    enum machine_mode best_mode = VOIDmode;
983
984	    for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
985		 mode != TImode;
986		 mode = GET_MODE_WIDER_MODE (mode))
987	      if (HARD_REGNO_MODE_OK (regno, mode))
988		best_mode = mode;
989
990	    if (best_mode == VOIDmode)
991	      for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
992		   mode != VOIDmode;
993		   mode = GET_MODE_WIDER_MODE (mode))
994		if (HARD_REGNO_MODE_OK (regno, mode)
995		    && have_insn_for (SET, mode))
996		  best_mode = mode;
997
998	    if (best_mode == VOIDmode)
999	      for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
1000		   mode != VOIDmode;
1001		   mode = GET_MODE_WIDER_MODE (mode))
1002		if (HARD_REGNO_MODE_OK (regno, mode)
1003		    && have_insn_for (SET, mode))
1004		      best_mode = mode;
1005
1006	    if (best_mode == VOIDmode)
1007	      for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
1008		   mode != VOIDmode;
1009		   mode = GET_MODE_WIDER_MODE (mode))
1010		if (HARD_REGNO_MODE_OK (regno, mode)
1011		    && have_insn_for (SET, mode))
1012		  best_mode = mode;
1013
1014	    mode = best_mode;
1015	    if (mode == VOIDmode)
1016	      abort ();
1017
1018	    align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1019	    if (size % align != 0)
1020	      size = CEIL (size, align) * align;
1021	    size += GET_MODE_SIZE (mode);
1022	    apply_result_mode[regno] = mode;
1023	  }
1024	else
1025	  apply_result_mode[regno] = VOIDmode;
1026
1027      /* Allow targets that use untyped_call and untyped_return to override
1028	 the size so that machine-specific information can be stored here.  */
1029#ifdef APPLY_RESULT_SIZE
1030      size = APPLY_RESULT_SIZE;
1031#endif
1032    }
1033  return size;
1034}
1035
1036#if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
1037/* Create a vector describing the result block RESULT.  If SAVEP is true,
1038   the result block is used to save the values; otherwise it is used to
1039   restore the values.  */
1040
1041static rtx
1042result_vector (savep, result)
1043     int savep;
1044     rtx result;
1045{
1046  int regno, size, align, nelts;
1047  enum machine_mode mode;
1048  rtx reg, mem;
1049  rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
1050
1051  size = nelts = 0;
1052  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1053    if ((mode = apply_result_mode[regno]) != VOIDmode)
1054      {
1055	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1056	if (size % align != 0)
1057	  size = CEIL (size, align) * align;
1058	reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
1059	mem = adjust_address (result, mode, size);
1060	savevec[nelts++] = (savep
1061			    ? gen_rtx_SET (VOIDmode, mem, reg)
1062			    : gen_rtx_SET (VOIDmode, reg, mem));
1063	size += GET_MODE_SIZE (mode);
1064      }
1065  return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
1066}
1067#endif /* HAVE_untyped_call or HAVE_untyped_return */
1068
1069/* Save the state required to perform an untyped call with the same
1070   arguments as were passed to the current function.  */
1071
1072static rtx
1073expand_builtin_apply_args_1 ()
1074{
1075  rtx registers;
1076  int size, align, regno;
1077  enum machine_mode mode;
1078
1079  /* Create a block where the arg-pointer, structure value address,
1080     and argument registers can be saved.  */
1081  registers = assign_stack_local (BLKmode, apply_args_size (), -1);
1082
1083  /* Walk past the arg-pointer and structure value address.  */
1084  size = GET_MODE_SIZE (Pmode);
1085  if (struct_value_rtx)
1086    size += GET_MODE_SIZE (Pmode);
1087
1088  /* Save each register used in calling a function to the block.  */
1089  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1090    if ((mode = apply_args_mode[regno]) != VOIDmode)
1091      {
1092	rtx tem;
1093
1094	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1095	if (size % align != 0)
1096	  size = CEIL (size, align) * align;
1097
1098	tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1099
1100	emit_move_insn (adjust_address (registers, mode, size), tem);
1101	size += GET_MODE_SIZE (mode);
1102      }
1103
1104  /* Save the arg pointer to the block.  */
1105  emit_move_insn (adjust_address (registers, Pmode, 0),
1106		  copy_to_reg (virtual_incoming_args_rtx));
1107  size = GET_MODE_SIZE (Pmode);
1108
1109  /* Save the structure value address unless this is passed as an
1110     "invisible" first argument.  */
1111  if (struct_value_incoming_rtx)
1112    {
1113      emit_move_insn (adjust_address (registers, Pmode, size),
1114		      copy_to_reg (struct_value_incoming_rtx));
1115      size += GET_MODE_SIZE (Pmode);
1116    }
1117
1118  /* Return the address of the block.  */
1119  return copy_addr_to_reg (XEXP (registers, 0));
1120}
1121
1122/* __builtin_apply_args returns block of memory allocated on
1123   the stack into which is stored the arg pointer, structure
1124   value address, static chain, and all the registers that might
1125   possibly be used in performing a function call.  The code is
1126   moved to the start of the function so the incoming values are
1127   saved.  */
1128
1129static rtx
1130expand_builtin_apply_args ()
1131{
1132  /* Don't do __builtin_apply_args more than once in a function.
1133     Save the result of the first call and reuse it.  */
1134  if (apply_args_value != 0)
1135    return apply_args_value;
1136  {
1137    /* When this function is called, it means that registers must be
1138       saved on entry to this function.  So we migrate the
1139       call to the first insn of this function.  */
1140    rtx temp;
1141    rtx seq;
1142
1143    start_sequence ();
1144    temp = expand_builtin_apply_args_1 ();
1145    seq = get_insns ();
1146    end_sequence ();
1147
1148    apply_args_value = temp;
1149
1150    /* Put the sequence after the NOTE that starts the function.
1151       If this is inside a SEQUENCE, make the outer-level insn
1152       chain current, so the code is placed at the start of the
1153       function.  */
1154    push_topmost_sequence ();
1155    emit_insns_before (seq, NEXT_INSN (get_insns ()));
1156    pop_topmost_sequence ();
1157    return temp;
1158  }
1159}
1160
1161/* Perform an untyped call and save the state required to perform an
1162   untyped return of whatever value was returned by the given function.  */
1163
1164static rtx
1165expand_builtin_apply (function, arguments, argsize)
1166     rtx function, arguments, argsize;
1167{
1168  int size, align, regno;
1169  enum machine_mode mode;
1170  rtx incoming_args, result, reg, dest, src, call_insn;
1171  rtx old_stack_level = 0;
1172  rtx call_fusage = 0;
1173
1174#ifdef POINTERS_EXTEND_UNSIGNED
1175  if (GET_MODE (arguments) != Pmode)
1176    arguments = convert_memory_address (Pmode, arguments);
1177#endif
1178
1179  /* Create a block where the return registers can be saved.  */
1180  result = assign_stack_local (BLKmode, apply_result_size (), -1);
1181
1182  /* Fetch the arg pointer from the ARGUMENTS block.  */
1183  incoming_args = gen_reg_rtx (Pmode);
1184  emit_move_insn (incoming_args, gen_rtx_MEM (Pmode, arguments));
1185#ifndef STACK_GROWS_DOWNWARD
1186  incoming_args = expand_simple_binop (Pmode, MINUS, incoming_args, argsize,
1187				       incoming_args, 0, OPTAB_LIB_WIDEN);
1188#endif
1189
1190  /* Perform postincrements before actually calling the function.  */
1191  emit_queue ();
1192
1193  /* Push a new argument block and copy the arguments.  Do not allow
1194     the (potential) memcpy call below to interfere with our stack
1195     manipulations.  */
1196  do_pending_stack_adjust ();
1197  NO_DEFER_POP;
1198
1199  /* Save the stack with nonlocal if available */
1200#ifdef HAVE_save_stack_nonlocal
1201  if (HAVE_save_stack_nonlocal)
1202    emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1203  else
1204#endif
1205    emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1206
1207  /* Push a block of memory onto the stack to store the memory arguments.
1208     Save the address in a register, and copy the memory arguments.  ??? I
1209     haven't figured out how the calling convention macros effect this,
1210     but it's likely that the source and/or destination addresses in
1211     the block copy will need updating in machine specific ways.  */
1212  dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1213  dest = gen_rtx_MEM (BLKmode, dest);
1214  set_mem_align (dest, PARM_BOUNDARY);
1215  src = gen_rtx_MEM (BLKmode, incoming_args);
1216  set_mem_align (src, PARM_BOUNDARY);
1217  emit_block_move (dest, src, argsize);
1218
1219  /* Refer to the argument block.  */
1220  apply_args_size ();
1221  arguments = gen_rtx_MEM (BLKmode, arguments);
1222  set_mem_align (arguments, PARM_BOUNDARY);
1223
1224  /* Walk past the arg-pointer and structure value address.  */
1225  size = GET_MODE_SIZE (Pmode);
1226  if (struct_value_rtx)
1227    size += GET_MODE_SIZE (Pmode);
1228
1229  /* Restore each of the registers previously saved.  Make USE insns
1230     for each of these registers for use in making the call.  */
1231  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1232    if ((mode = apply_args_mode[regno]) != VOIDmode)
1233      {
1234	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1235	if (size % align != 0)
1236	  size = CEIL (size, align) * align;
1237	reg = gen_rtx_REG (mode, regno);
1238	emit_move_insn (reg, adjust_address (arguments, mode, size));
1239	use_reg (&call_fusage, reg);
1240	size += GET_MODE_SIZE (mode);
1241      }
1242
1243  /* Restore the structure value address unless this is passed as an
1244     "invisible" first argument.  */
1245  size = GET_MODE_SIZE (Pmode);
1246  if (struct_value_rtx)
1247    {
1248      rtx value = gen_reg_rtx (Pmode);
1249      emit_move_insn (value, adjust_address (arguments, Pmode, size));
1250      emit_move_insn (struct_value_rtx, value);
1251      if (GET_CODE (struct_value_rtx) == REG)
1252	  use_reg (&call_fusage, struct_value_rtx);
1253      size += GET_MODE_SIZE (Pmode);
1254    }
1255
1256  /* All arguments and registers used for the call are set up by now!  */
1257  function = prepare_call_address (function, NULL_TREE, &call_fusage, 0, 0);
1258
1259  /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
1260     and we don't want to load it into a register as an optimization,
1261     because prepare_call_address already did it if it should be done.  */
1262  if (GET_CODE (function) != SYMBOL_REF)
1263    function = memory_address (FUNCTION_MODE, function);
1264
1265  /* Generate the actual call instruction and save the return value.  */
1266#ifdef HAVE_untyped_call
1267  if (HAVE_untyped_call)
1268    emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1269				      result, result_vector (1, result)));
1270  else
1271#endif
1272#ifdef HAVE_call_value
1273  if (HAVE_call_value)
1274    {
1275      rtx valreg = 0;
1276
1277      /* Locate the unique return register.  It is not possible to
1278	 express a call that sets more than one return register using
1279	 call_value; use untyped_call for that.  In fact, untyped_call
1280	 only needs to save the return registers in the given block.  */
1281      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1282	if ((mode = apply_result_mode[regno]) != VOIDmode)
1283	  {
1284	    if (valreg)
1285	      abort (); /* HAVE_untyped_call required.  */
1286	    valreg = gen_rtx_REG (mode, regno);
1287	  }
1288
1289      emit_call_insn (GEN_CALL_VALUE (valreg,
1290				      gen_rtx_MEM (FUNCTION_MODE, function),
1291				      const0_rtx, NULL_RTX, const0_rtx));
1292
1293      emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
1294    }
1295  else
1296#endif
1297    abort ();
1298
1299  /* Find the CALL insn we just emitted.  */
1300  for (call_insn = get_last_insn ();
1301       call_insn && GET_CODE (call_insn) != CALL_INSN;
1302       call_insn = PREV_INSN (call_insn))
1303    ;
1304
1305  if (! call_insn)
1306    abort ();
1307
1308  /* Put the register usage information on the CALL.  If there is already
1309     some usage information, put ours at the end.  */
1310  if (CALL_INSN_FUNCTION_USAGE (call_insn))
1311    {
1312      rtx link;
1313
1314      for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
1315	   link = XEXP (link, 1))
1316	;
1317
1318      XEXP (link, 1) = call_fusage;
1319    }
1320  else
1321    CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
1322
1323  /* Restore the stack.  */
1324#ifdef HAVE_save_stack_nonlocal
1325  if (HAVE_save_stack_nonlocal)
1326    emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1327  else
1328#endif
1329    emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1330
1331  OK_DEFER_POP;
1332
1333  /* Return the address of the result block.  */
1334  return copy_addr_to_reg (XEXP (result, 0));
1335}
1336
1337/* Perform an untyped return.  */
1338
1339static void
1340expand_builtin_return (result)
1341     rtx result;
1342{
1343  int size, align, regno;
1344  enum machine_mode mode;
1345  rtx reg;
1346  rtx call_fusage = 0;
1347
1348#ifdef POINTERS_EXTEND_UNSIGNED
1349  if (GET_MODE (result) != Pmode)
1350    result = convert_memory_address (Pmode, result);
1351#endif
1352
1353  apply_result_size ();
1354  result = gen_rtx_MEM (BLKmode, result);
1355
1356#ifdef HAVE_untyped_return
1357  if (HAVE_untyped_return)
1358    {
1359      emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1360      emit_barrier ();
1361      return;
1362    }
1363#endif
1364
1365  /* Restore the return value and note that each value is used.  */
1366  size = 0;
1367  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1368    if ((mode = apply_result_mode[regno]) != VOIDmode)
1369      {
1370	align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1371	if (size % align != 0)
1372	  size = CEIL (size, align) * align;
1373	reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1374	emit_move_insn (reg, adjust_address (result, mode, size));
1375
1376	push_to_sequence (call_fusage);
1377	emit_insn (gen_rtx_USE (VOIDmode, reg));
1378	call_fusage = get_insns ();
1379	end_sequence ();
1380	size += GET_MODE_SIZE (mode);
1381      }
1382
1383  /* Put the USE insns before the return.  */
1384  emit_insns (call_fusage);
1385
1386  /* Return whatever values was restored by jumping directly to the end
1387     of the function.  */
1388  expand_null_return ();
1389}
1390
1391/* Used by expand_builtin_classify_type and fold_builtin_classify_type.  */
1392
1393static enum type_class
1394type_to_class (type)
1395     tree type;
1396{
1397  switch (TREE_CODE (type))
1398    {
1399    case VOID_TYPE:	   return void_type_class;
1400    case INTEGER_TYPE:	   return integer_type_class;
1401    case CHAR_TYPE:	   return char_type_class;
1402    case ENUMERAL_TYPE:	   return enumeral_type_class;
1403    case BOOLEAN_TYPE:	   return boolean_type_class;
1404    case POINTER_TYPE:	   return pointer_type_class;
1405    case REFERENCE_TYPE:   return reference_type_class;
1406    case OFFSET_TYPE:	   return offset_type_class;
1407    case REAL_TYPE:	   return real_type_class;
1408    case COMPLEX_TYPE:	   return complex_type_class;
1409    case FUNCTION_TYPE:	   return function_type_class;
1410    case METHOD_TYPE:	   return method_type_class;
1411    case RECORD_TYPE:	   return record_type_class;
1412    case UNION_TYPE:
1413    case QUAL_UNION_TYPE:  return union_type_class;
1414    case ARRAY_TYPE:	   return (TYPE_STRING_FLAG (type)
1415				   ? string_type_class : array_type_class);
1416    case SET_TYPE:	   return set_type_class;
1417    case FILE_TYPE:	   return file_type_class;
1418    case LANG_TYPE:	   return lang_type_class;
1419    default:		   return no_type_class;
1420    }
1421}
1422
1423/* Expand a call to __builtin_classify_type with arguments found in
1424   ARGLIST.  */
1425
1426static rtx
1427expand_builtin_classify_type (arglist)
1428     tree arglist;
1429{
1430  if (arglist != 0)
1431    return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
1432  return GEN_INT (no_type_class);
1433}
1434
1435/* Expand expression EXP, which is a call to __builtin_constant_p.  */
1436
1437static rtx
1438expand_builtin_constant_p (exp)
1439     tree exp;
1440{
1441  tree arglist = TREE_OPERAND (exp, 1);
1442  enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1443  rtx tmp;
1444
1445  if (arglist == 0)
1446    return const0_rtx;
1447  arglist = TREE_VALUE (arglist);
1448
1449  /* We have taken care of the easy cases during constant folding.  This
1450     case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE get a
1451     chance to see if it can deduce whether ARGLIST is constant.  */
1452
1453  tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
1454  tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
1455  return tmp;
1456}
1457
1458/* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1459   Return 0 if a normal call should be emitted rather than expanding the
1460   function in-line.  EXP is the expression that is a call to the builtin
1461   function; if convenient, the result should be placed in TARGET.
1462   SUBTARGET may be used as the target for computing one of EXP's operands.  */
1463
1464static rtx
1465expand_builtin_mathfn (exp, target, subtarget)
1466     tree exp;
1467     rtx target, subtarget;
1468{
1469  optab builtin_optab;
1470  rtx op0, insns;
1471  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1472  tree arglist = TREE_OPERAND (exp, 1);
1473
1474  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
1475    return 0;
1476
1477  /* Stabilize and compute the argument.  */
1478  if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
1479      && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
1480    {
1481      exp = copy_node (exp);
1482      TREE_OPERAND (exp, 1) = arglist;
1483      /* Wrap the computation of the argument in a SAVE_EXPR.  That
1484	 way, if we need to expand the argument again (as in the
1485	 flag_errno_math case below where we cannot directly set
1486	 errno), we will not perform side-effects more than once.
1487	 Note that here we're mutating the original EXP as well as the
1488	 copy; that's the right thing to do in case the original EXP
1489	 is expanded later.  */
1490      TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
1491      arglist = copy_node (arglist);
1492    }
1493  op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
1494
1495  /* Make a suitable register to place result in.  */
1496  target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
1497
1498  emit_queue ();
1499  start_sequence ();
1500
1501  switch (DECL_FUNCTION_CODE (fndecl))
1502    {
1503    case BUILT_IN_SIN:
1504    case BUILT_IN_SINF:
1505    case BUILT_IN_SINL:
1506      builtin_optab = sin_optab; break;
1507    case BUILT_IN_COS:
1508    case BUILT_IN_COSF:
1509    case BUILT_IN_COSL:
1510      builtin_optab = cos_optab; break;
1511    case BUILT_IN_SQRT:
1512    case BUILT_IN_SQRTF:
1513    case BUILT_IN_SQRTL:
1514      builtin_optab = sqrt_optab; break;
1515     default:
1516      abort ();
1517    }
1518
1519  /* Compute into TARGET.
1520     Set TARGET to wherever the result comes back.  */
1521  target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
1522			builtin_optab, op0, target, 0);
1523
1524  /* If we were unable to expand via the builtin, stop the
1525     sequence (without outputting the insns) and return 0, causing
1526     a call to the library function.  */
1527  if (target == 0)
1528    {
1529      end_sequence ();
1530      return 0;
1531    }
1532
1533  /* If errno must be maintained and if we are not allowing unsafe
1534     math optimizations, check the result.  */
1535
1536  if (flag_errno_math && ! flag_unsafe_math_optimizations)
1537    {
1538      rtx lab1;
1539
1540      /* Don't define the builtin FP instructions
1541	 if your machine is not IEEE.  */
1542      if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
1543	abort ();
1544
1545      lab1 = gen_label_rtx ();
1546
1547      /* Test the result; if it is NaN, set errno=EDOM because
1548	 the argument was not in the domain.  */
1549      emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1550			       0, lab1);
1551
1552#ifdef TARGET_EDOM
1553	{
1554#ifdef GEN_ERRNO_RTX
1555	  rtx errno_rtx = GEN_ERRNO_RTX;
1556#else
1557	  rtx errno_rtx
1558	    = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1559#endif
1560
1561	  emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1562	}
1563#else
1564      /* We can't set errno=EDOM directly; let the library call do it.
1565	 Pop the arguments right away in case the call gets deleted.  */
1566      NO_DEFER_POP;
1567      expand_call (exp, target, 0);
1568      OK_DEFER_POP;
1569#endif
1570
1571      emit_label (lab1);
1572    }
1573
1574  /* Output the entire sequence.  */
1575  insns = get_insns ();
1576  end_sequence ();
1577  emit_insns (insns);
1578
1579  return target;
1580}
1581
1582/* Expand expression EXP which is a call to the strlen builtin.  Return 0
1583   if we failed the caller should emit a normal call, otherwise
1584   try to get the result in TARGET, if convenient.  */
1585
1586static rtx
1587expand_builtin_strlen (exp, target)
1588     tree exp;
1589     rtx target;
1590{
1591  tree arglist = TREE_OPERAND (exp, 1);
1592  enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1593
1594  if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
1595    return 0;
1596  else
1597    {
1598      rtx pat;
1599      tree src = TREE_VALUE (arglist);
1600
1601      int align
1602	= get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1603
1604      rtx result, src_reg, char_rtx, before_strlen;
1605      enum machine_mode insn_mode = value_mode, char_mode;
1606      enum insn_code icode = CODE_FOR_nothing;
1607
1608      /* If SRC is not a pointer type, don't do this operation inline.  */
1609      if (align == 0)
1610	return 0;
1611
1612      /* Bail out if we can't compute strlen in the right mode.  */
1613      while (insn_mode != VOIDmode)
1614	{
1615	  icode = strlen_optab->handlers[(int) insn_mode].insn_code;
1616	  if (icode != CODE_FOR_nothing)
1617	    break;
1618
1619	  insn_mode = GET_MODE_WIDER_MODE (insn_mode);
1620	}
1621      if (insn_mode == VOIDmode)
1622	return 0;
1623
1624      /* Make a place to write the result of the instruction.  */
1625      result = target;
1626      if (! (result != 0
1627	     && GET_CODE (result) == REG
1628	     && GET_MODE (result) == insn_mode
1629	     && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1630	result = gen_reg_rtx (insn_mode);
1631
1632      /* Make a place to hold the source address.  We will not expand
1633	 the actual source until we are sure that the expansion will
1634	 not fail -- there are trees that cannot be expanded twice.  */
1635      src_reg = gen_reg_rtx (Pmode);
1636
1637      /* Mark the beginning of the strlen sequence so we can emit the
1638	 source operand later.  */
1639      before_strlen = get_last_insn();
1640
1641      char_rtx = const0_rtx;
1642      char_mode = insn_data[(int) icode].operand[2].mode;
1643      if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
1644							    char_mode))
1645	char_rtx = copy_to_mode_reg (char_mode, char_rtx);
1646
1647      pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
1648			     char_rtx, GEN_INT (align));
1649      if (! pat)
1650	return 0;
1651      emit_insn (pat);
1652
1653      /* Now that we are assured of success, expand the source.  */
1654      start_sequence ();
1655      pat = memory_address (BLKmode,
1656			    expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
1657      if (pat != src_reg)
1658	emit_move_insn (src_reg, pat);
1659      pat = gen_sequence ();
1660      end_sequence ();
1661
1662      if (before_strlen)
1663	emit_insn_after (pat, before_strlen);
1664      else
1665	emit_insn_before (pat, get_insns ());
1666
1667      /* Return the value in the proper mode for this function.  */
1668      if (GET_MODE (result) == value_mode)
1669	target = result;
1670      else if (target != 0)
1671	convert_move (target, result, 0);
1672      else
1673	target = convert_to_mode (value_mode, result, 0);
1674
1675      return target;
1676    }
1677}
1678
1679/* Expand a call to the strstr builtin.  Return 0 if we failed the
1680   caller should emit a normal call, otherwise try to get the result
1681   in TARGET, if convenient (and in mode MODE if that's convenient).  */
1682
1683static rtx
1684expand_builtin_strstr (arglist, target, mode)
1685     tree arglist;
1686     rtx target;
1687     enum machine_mode mode;
1688{
1689  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
1690    return 0;
1691  else
1692    {
1693      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1694      tree fn;
1695      const char *p1, *p2;
1696
1697      p2 = c_getstr (s2);
1698      if (p2 == NULL)
1699	return 0;
1700
1701      p1 = c_getstr (s1);
1702      if (p1 != NULL)
1703	{
1704	  const char *r = strstr (p1, p2);
1705
1706	  if (r == NULL)
1707	    return const0_rtx;
1708
1709	  /* Return an offset into the constant string argument.  */
1710	  return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1711					   s1, ssize_int (r - p1))),
1712			      target, mode, EXPAND_NORMAL);
1713	}
1714
1715      if (p2[0] == '\0')
1716	return expand_expr (s1, target, mode, EXPAND_NORMAL);
1717
1718      if (p2[1] != '\0')
1719	return 0;
1720
1721      fn = built_in_decls[BUILT_IN_STRCHR];
1722      if (!fn)
1723	return 0;
1724
1725      /* New argument list transforming strstr(s1, s2) to
1726	 strchr(s1, s2[0]).  */
1727      arglist =
1728	build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
1729      arglist = tree_cons (NULL_TREE, s1, arglist);
1730      return expand_expr (build_function_call_expr (fn, arglist),
1731			  target, mode, EXPAND_NORMAL);
1732    }
1733}
1734
1735/* Expand a call to the strchr builtin.  Return 0 if we failed the
1736   caller should emit a normal call, otherwise try to get the result
1737   in TARGET, if convenient (and in mode MODE if that's convenient).  */
1738
1739static rtx
1740expand_builtin_strchr (arglist, target, mode)
1741     tree arglist;
1742     rtx target;
1743     enum machine_mode mode;
1744{
1745  if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
1746    return 0;
1747  else
1748    {
1749      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1750      const char *p1;
1751
1752      if (TREE_CODE (s2) != INTEGER_CST)
1753	return 0;
1754
1755      p1 = c_getstr (s1);
1756      if (p1 != NULL)
1757	{
1758	  char c;
1759	  const char *r;
1760
1761	  if (target_char_cast (s2, &c))
1762	    return 0;
1763
1764	  r = strchr (p1, c);
1765
1766	  if (r == NULL)
1767	    return const0_rtx;
1768
1769	  /* Return an offset into the constant string argument.  */
1770	  return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1771					   s1, ssize_int (r - p1))),
1772			      target, mode, EXPAND_NORMAL);
1773	}
1774
1775      /* FIXME: Should use here strchrM optab so that ports can optimize
1776	 this.  */
1777      return 0;
1778    }
1779}
1780
1781/* Expand a call to the strrchr builtin.  Return 0 if we failed the
1782   caller should emit a normal call, otherwise try to get the result
1783   in TARGET, if convenient (and in mode MODE if that's convenient).  */
1784
1785static rtx
1786expand_builtin_strrchr (arglist, target, mode)
1787     tree arglist;
1788     rtx target;
1789     enum machine_mode mode;
1790{
1791  if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
1792    return 0;
1793  else
1794    {
1795      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1796      tree fn;
1797      const char *p1;
1798
1799      if (TREE_CODE (s2) != INTEGER_CST)
1800	return 0;
1801
1802      p1 = c_getstr (s1);
1803      if (p1 != NULL)
1804	{
1805	  char c;
1806	  const char *r;
1807
1808	  if (target_char_cast (s2, &c))
1809	    return 0;
1810
1811	  r = strrchr (p1, c);
1812
1813	  if (r == NULL)
1814	    return const0_rtx;
1815
1816	  /* Return an offset into the constant string argument.  */
1817	  return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1818					   s1, ssize_int (r - p1))),
1819			      target, mode, EXPAND_NORMAL);
1820	}
1821
1822      if (! integer_zerop (s2))
1823	return 0;
1824
1825      fn = built_in_decls[BUILT_IN_STRCHR];
1826      if (!fn)
1827	return 0;
1828
1829      /* Transform strrchr(s1, '\0') to strchr(s1, '\0').  */
1830      return expand_expr (build_function_call_expr (fn, arglist),
1831			  target, mode, EXPAND_NORMAL);
1832    }
1833}
1834
1835/* Expand a call to the strpbrk builtin.  Return 0 if we failed the
1836   caller should emit a normal call, otherwise try to get the result
1837   in TARGET, if convenient (and in mode MODE if that's convenient).  */
1838
1839static rtx
1840expand_builtin_strpbrk (arglist, target, mode)
1841     tree arglist;
1842     rtx target;
1843     enum machine_mode mode;
1844{
1845  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
1846    return 0;
1847  else
1848    {
1849      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1850      tree fn;
1851      const char *p1, *p2;
1852
1853      p2 = c_getstr (s2);
1854      if (p2 == NULL)
1855	return 0;
1856
1857      p1 = c_getstr (s1);
1858      if (p1 != NULL)
1859	{
1860	  const char *r = strpbrk (p1, p2);
1861
1862	  if (r == NULL)
1863	    return const0_rtx;
1864
1865	  /* Return an offset into the constant string argument.  */
1866	  return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1867					   s1, ssize_int (r - p1))),
1868			      target, mode, EXPAND_NORMAL);
1869	}
1870
1871      if (p2[0] == '\0')
1872	{
1873	  /* strpbrk(x, "") == NULL.
1874	     Evaluate and ignore the arguments in case they had
1875	     side-effects.  */
1876	  expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
1877	  return const0_rtx;
1878	}
1879
1880      if (p2[1] != '\0')
1881	return 0;  /* Really call strpbrk.  */
1882
1883      fn = built_in_decls[BUILT_IN_STRCHR];
1884      if (!fn)
1885	return 0;
1886
1887      /* New argument list transforming strpbrk(s1, s2) to
1888	 strchr(s1, s2[0]).  */
1889      arglist =
1890	build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
1891      arglist = tree_cons (NULL_TREE, s1, arglist);
1892      return expand_expr (build_function_call_expr (fn, arglist),
1893			  target, mode, EXPAND_NORMAL);
1894    }
1895}
1896
1897/* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
1898   bytes from constant string DATA + OFFSET and return it as target
1899   constant.  */
1900
1901static rtx
1902builtin_memcpy_read_str (data, offset, mode)
1903     PTR data;
1904     HOST_WIDE_INT offset;
1905     enum machine_mode mode;
1906{
1907  const char *str = (const char *) data;
1908
1909  if (offset < 0
1910      || ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
1911	  > strlen (str) + 1))
1912    abort ();  /* Attempt to read past the end of constant string.  */
1913
1914  return c_readstr (str + offset, mode);
1915}
1916
1917/* Expand a call to the memcpy builtin, with arguments in ARGLIST.
1918   Return 0 if we failed, the caller should emit a normal call, otherwise
1919   try to get the result in TARGET, if convenient (and in mode MODE if
1920   that's convenient).  */
1921
1922static rtx
1923expand_builtin_memcpy (arglist, target, mode)
1924     tree arglist;
1925     rtx target;
1926     enum machine_mode mode;
1927{
1928  if (!validate_arglist (arglist,
1929			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
1930    return 0;
1931  else
1932    {
1933      tree dest = TREE_VALUE (arglist);
1934      tree src = TREE_VALUE (TREE_CHAIN (arglist));
1935      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1936      const char *src_str;
1937
1938      unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
1939      unsigned int dest_align
1940	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
1941      rtx dest_mem, src_mem, dest_addr, len_rtx;
1942
1943      /* If DEST is not a pointer type, call the normal function.  */
1944      if (dest_align == 0)
1945        return 0;
1946
1947      /* If the LEN parameter is zero, return DEST.  */
1948      if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
1949        {
1950          /* Evaluate and ignore SRC in case it has side-effects.  */
1951          expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
1952          return expand_expr (dest, target, mode, EXPAND_NORMAL);
1953        }
1954
1955      /* If either SRC is not a pointer type, don't do this
1956         operation in-line.  */
1957      if (src_align == 0)
1958        return 0;
1959
1960      dest_mem = get_memory_rtx (dest);
1961      set_mem_align (dest_mem, dest_align);
1962      len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1963      src_str = c_getstr (src);
1964
1965      /* If SRC is a string constant and block move would be done
1966	 by pieces, we can avoid loading the string from memory
1967	 and only stored the computed constants.  */
1968      if (src_str
1969	  && GET_CODE (len_rtx) == CONST_INT
1970	  && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
1971	  && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
1972				  (PTR) src_str, dest_align))
1973	{
1974	  store_by_pieces (dest_mem, INTVAL (len_rtx),
1975			   builtin_memcpy_read_str,
1976			   (PTR) src_str, dest_align);
1977	  return force_operand (XEXP (dest_mem, 0), NULL_RTX);
1978	}
1979
1980      src_mem = get_memory_rtx (src);
1981      set_mem_align (src_mem, src_align);
1982
1983      /* Copy word part most expediently.  */
1984      dest_addr = emit_block_move (dest_mem, src_mem, len_rtx);
1985
1986      if (dest_addr == 0)
1987	dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
1988
1989      return dest_addr;
1990    }
1991}
1992
1993/* Expand expression EXP, which is a call to the strcpy builtin.  Return 0
1994   if we failed the caller should emit a normal call, otherwise try to get
1995   the result in TARGET, if convenient (and in mode MODE if that's
1996   convenient).  */
1997
1998static rtx
1999expand_builtin_strcpy (exp, target, mode)
2000     tree exp;
2001     rtx target;
2002     enum machine_mode mode;
2003{
2004  tree arglist = TREE_OPERAND (exp, 1);
2005  tree fn, len;
2006
2007  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2008    return 0;
2009
2010  fn = built_in_decls[BUILT_IN_MEMCPY];
2011  if (!fn)
2012    return 0;
2013
2014  len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
2015  if (len == 0)
2016    return 0;
2017
2018  len = size_binop (PLUS_EXPR, len, ssize_int (1));
2019  chainon (arglist, build_tree_list (NULL_TREE, len));
2020  return expand_expr (build_function_call_expr (fn, arglist),
2021                      target, mode, EXPAND_NORMAL);
2022}
2023
2024/* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
2025   bytes from constant string DATA + OFFSET and return it as target
2026   constant.  */
2027
2028static rtx
2029builtin_strncpy_read_str (data, offset, mode)
2030     PTR data;
2031     HOST_WIDE_INT offset;
2032     enum machine_mode mode;
2033{
2034  const char *str = (const char *) data;
2035
2036  if ((unsigned HOST_WIDE_INT) offset > strlen (str))
2037    return const0_rtx;
2038
2039  return c_readstr (str + offset, mode);
2040}
2041
2042/* Expand expression EXP, which is a call to the strncpy builtin.  Return 0
2043   if we failed the caller should emit a normal call.  */
2044
2045static rtx
2046expand_builtin_strncpy (arglist, target, mode)
2047     tree arglist;
2048     rtx target;
2049     enum machine_mode mode;
2050{
2051  if (!validate_arglist (arglist,
2052			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2053    return 0;
2054  else
2055    {
2056      tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
2057      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2058      tree fn;
2059
2060      /* We must be passed a constant len parameter.  */
2061      if (TREE_CODE (len) != INTEGER_CST)
2062	return 0;
2063
2064      /* If the len parameter is zero, return the dst parameter.  */
2065      if (integer_zerop (len))
2066        {
2067	/* Evaluate and ignore the src argument in case it has
2068           side-effects.  */
2069	  expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
2070		       VOIDmode, EXPAND_NORMAL);
2071	  /* Return the dst parameter.  */
2072	  return expand_expr (TREE_VALUE (arglist), target, mode,
2073			      EXPAND_NORMAL);
2074	}
2075
2076      /* Now, we must be passed a constant src ptr parameter.  */
2077      if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
2078	return 0;
2079
2080      slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
2081
2082      /* We're required to pad with trailing zeros if the requested
2083         len is greater than strlen(s2)+1.  In that case try to
2084	 use store_by_pieces, if it fails, punt.  */
2085      if (tree_int_cst_lt (slen, len))
2086	{
2087	  tree dest = TREE_VALUE (arglist);
2088	  unsigned int dest_align
2089	    = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2090	  const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
2091	  rtx dest_mem;
2092
2093	  if (!p || dest_align == 0 || !host_integerp (len, 1)
2094	      || !can_store_by_pieces (tree_low_cst (len, 1),
2095				       builtin_strncpy_read_str,
2096				       (PTR) p, dest_align))
2097	    return 0;
2098
2099	  dest_mem = get_memory_rtx (dest);
2100	  store_by_pieces (dest_mem, tree_low_cst (len, 1),
2101			   builtin_strncpy_read_str,
2102			   (PTR) p, dest_align);
2103	  return force_operand (XEXP (dest_mem, 0), NULL_RTX);
2104	}
2105
2106      /* OK transform into builtin memcpy.  */
2107      fn = built_in_decls[BUILT_IN_MEMCPY];
2108      if (!fn)
2109        return 0;
2110      return expand_expr (build_function_call_expr (fn, arglist),
2111                          target, mode, EXPAND_NORMAL);
2112    }
2113}
2114
2115/* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
2116   bytes from constant string DATA + OFFSET and return it as target
2117   constant.  */
2118
2119static rtx
2120builtin_memset_read_str (data, offset, mode)
2121     PTR data;
2122     HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
2123     enum machine_mode mode;
2124{
2125  const char *c = (const char *) data;
2126  char *p = alloca (GET_MODE_SIZE (mode));
2127
2128  memset (p, *c, GET_MODE_SIZE (mode));
2129
2130  return c_readstr (p, mode);
2131}
2132
2133/* Expand expression EXP, which is a call to the memset builtin.  Return 0
2134   if we failed the caller should emit a normal call, otherwise try to get
2135   the result in TARGET, if convenient (and in mode MODE if that's
2136   convenient).  */
2137
2138static rtx
2139expand_builtin_memset (exp, target, mode)
2140     tree exp;
2141     rtx target;
2142     enum machine_mode mode;
2143{
2144  tree arglist = TREE_OPERAND (exp, 1);
2145
2146  if (!validate_arglist (arglist,
2147			 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
2148    return 0;
2149  else
2150    {
2151      tree dest = TREE_VALUE (arglist);
2152      tree val = TREE_VALUE (TREE_CHAIN (arglist));
2153      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2154      char c;
2155
2156      unsigned int dest_align
2157	= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2158      rtx dest_mem, dest_addr, len_rtx;
2159
2160      /* If DEST is not a pointer type, don't do this
2161	 operation in-line.  */
2162      if (dest_align == 0)
2163	return 0;
2164
2165      /* If the LEN parameter is zero, return DEST.  */
2166      if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
2167        {
2168          /* Evaluate and ignore VAL in case it has side-effects.  */
2169          expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
2170          return expand_expr (dest, target, mode, EXPAND_NORMAL);
2171        }
2172
2173      if (TREE_CODE (val) != INTEGER_CST)
2174	return 0;
2175
2176      if (target_char_cast (val, &c))
2177	return 0;
2178
2179      if (c)
2180	{
2181	  if (!host_integerp (len, 1))
2182	    return 0;
2183	  if (!can_store_by_pieces (tree_low_cst (len, 1),
2184				    builtin_memset_read_str, (PTR) &c,
2185				    dest_align))
2186	    return 0;
2187
2188	  dest_mem = get_memory_rtx (dest);
2189	  store_by_pieces (dest_mem, tree_low_cst (len, 1),
2190			   builtin_memset_read_str,
2191			   (PTR) &c, dest_align);
2192	  return force_operand (XEXP (dest_mem, 0), NULL_RTX);
2193	}
2194
2195      len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2196
2197      dest_mem = get_memory_rtx (dest);
2198      set_mem_align (dest_mem, dest_align);
2199      dest_addr = clear_storage (dest_mem, len_rtx);
2200
2201      if (dest_addr == 0)
2202	dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2203
2204      return dest_addr;
2205    }
2206}
2207
2208/* Expand expression EXP, which is a call to the bzero builtin.  Return 0
2209   if we failed the caller should emit a normal call.  */
2210
2211static rtx
2212expand_builtin_bzero (exp)
2213     tree exp;
2214{
2215  tree arglist = TREE_OPERAND (exp, 1);
2216  tree dest, size, newarglist;
2217  rtx result;
2218
2219  if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2220    return NULL_RTX;
2221
2222  dest = TREE_VALUE (arglist);
2223  size = TREE_VALUE (TREE_CHAIN (arglist));
2224
2225  /* New argument list transforming bzero(ptr x, int y) to
2226     memset(ptr x, int 0, size_t y).   This is done this way
2227     so that if it isn't expanded inline, we fallback to
2228     calling bzero instead of memset.  */
2229
2230  newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
2231  newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
2232  newarglist = tree_cons (NULL_TREE, dest, newarglist);
2233
2234  TREE_OPERAND (exp, 1) = newarglist;
2235  result = expand_builtin_memset (exp, const0_rtx, VOIDmode);
2236
2237  /* Always restore the original arguments.  */
2238  TREE_OPERAND (exp, 1) = arglist;
2239
2240  return result;
2241}
2242
2243/* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
2244   ARGLIST is the argument list for this call.  Return 0 if we failed and the
2245   caller should emit a normal call, otherwise try to get the result in
2246   TARGET, if convenient (and in mode MODE, if that's convenient).  */
2247
2248static rtx
2249expand_builtin_memcmp (exp, arglist, target, mode)
2250     tree exp ATTRIBUTE_UNUSED;
2251     tree arglist;
2252     rtx target;
2253     enum machine_mode mode;
2254{
2255  tree arg1, arg2, len;
2256  const char *p1, *p2;
2257
2258  if (!validate_arglist (arglist,
2259		      POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2260    return 0;
2261
2262  arg1 = TREE_VALUE (arglist);
2263  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2264  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2265
2266  /* If the len parameter is zero, return zero.  */
2267  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
2268    {
2269      /* Evaluate and ignore arg1 and arg2 in case they have
2270         side-effects.  */
2271      expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2272      expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2273      return const0_rtx;
2274    }
2275
2276  p1 = c_getstr (arg1);
2277  p2 = c_getstr (arg2);
2278
2279  /* If all arguments are constant, and the value of len is not greater
2280     than the lengths of arg1 and arg2, evaluate at compile-time.  */
2281  if (host_integerp (len, 1) && p1 && p2
2282      && compare_tree_int (len, strlen (p1) + 1) <= 0
2283      && compare_tree_int (len, strlen (p2) + 1) <= 0)
2284    {
2285      const int r = memcmp (p1, p2, tree_low_cst (len, 1));
2286
2287      return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2288    }
2289
2290  /* If len parameter is one, return an expression corresponding to
2291     (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
2292  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
2293    {
2294      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2295      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2296      tree ind1 =
2297      fold (build1 (CONVERT_EXPR, integer_type_node,
2298                    build1 (INDIRECT_REF, cst_uchar_node,
2299                            build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2300      tree ind2 =
2301      fold (build1 (CONVERT_EXPR, integer_type_node,
2302                    build1 (INDIRECT_REF, cst_uchar_node,
2303                            build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2304      tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2305      return expand_expr (result, target, mode, EXPAND_NORMAL);
2306    }
2307
2308#ifdef HAVE_cmpstrsi
2309  {
2310    rtx arg1_rtx, arg2_rtx, arg3_rtx;
2311    rtx result;
2312    rtx insn;
2313
2314    int arg1_align
2315      = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2316    int arg2_align
2317      = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2318    enum machine_mode insn_mode
2319      = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
2320
2321    /* If we don't have POINTER_TYPE, call the function.  */
2322    if (arg1_align == 0 || arg2_align == 0)
2323      return 0;
2324
2325    /* Make a place to write the result of the instruction.  */
2326    result = target;
2327    if (! (result != 0
2328	   && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
2329	   && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2330      result = gen_reg_rtx (insn_mode);
2331
2332    arg1_rtx = get_memory_rtx (arg1);
2333    arg2_rtx = get_memory_rtx (arg2);
2334    arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2335    if (!HAVE_cmpstrsi)
2336      insn = NULL_RTX;
2337    else
2338      insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
2339			   GEN_INT (MIN (arg1_align, arg2_align)));
2340
2341    if (insn)
2342      emit_insn (insn);
2343    else
2344      emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
2345			       TYPE_MODE (integer_type_node), 3,
2346			       XEXP (arg1_rtx, 0), Pmode,
2347			       XEXP (arg2_rtx, 0), Pmode,
2348			       convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
2349						TREE_UNSIGNED (sizetype)),
2350			       TYPE_MODE (sizetype));
2351
2352    /* Return the value in the proper mode for this function.  */
2353    mode = TYPE_MODE (TREE_TYPE (exp));
2354    if (GET_MODE (result) == mode)
2355      return result;
2356    else if (target != 0)
2357      {
2358	convert_move (target, result, 0);
2359	return target;
2360      }
2361    else
2362      return convert_to_mode (mode, result, 0);
2363  }
2364#endif
2365
2366  return 0;
2367}
2368
2369/* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
2370   if we failed the caller should emit a normal call, otherwise try to get
2371   the result in TARGET, if convenient.  */
2372
2373static rtx
2374expand_builtin_strcmp (exp, target, mode)
2375     tree exp;
2376     rtx target;
2377     enum machine_mode mode;
2378{
2379  tree arglist = TREE_OPERAND (exp, 1);
2380  tree arg1, arg2, len, len2, fn;
2381  const char *p1, *p2;
2382
2383  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2384    return 0;
2385
2386  arg1 = TREE_VALUE (arglist);
2387  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2388
2389  p1 = c_getstr (arg1);
2390  p2 = c_getstr (arg2);
2391
2392  if (p1 && p2)
2393    {
2394      const int i = strcmp (p1, p2);
2395      return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
2396    }
2397
2398  /* If either arg is "", return an expression corresponding to
2399     (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
2400  if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2401    {
2402      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2403      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2404      tree ind1 =
2405	fold (build1 (CONVERT_EXPR, integer_type_node,
2406		      build1 (INDIRECT_REF, cst_uchar_node,
2407			      build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2408      tree ind2 =
2409	fold (build1 (CONVERT_EXPR, integer_type_node,
2410		      build1 (INDIRECT_REF, cst_uchar_node,
2411			      build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2412      tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2413      return expand_expr (result, target, mode, EXPAND_NORMAL);
2414    }
2415
2416  len = c_strlen (arg1);
2417  len2 = c_strlen (arg2);
2418
2419  if (len)
2420    len = size_binop (PLUS_EXPR, ssize_int (1), len);
2421
2422  if (len2)
2423    len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
2424
2425  /* If we don't have a constant length for the first, use the length
2426     of the second, if we know it.  We don't require a constant for
2427     this case; some cost analysis could be done if both are available
2428     but neither is constant.  For now, assume they're equally cheap
2429     unless one has side effects.
2430
2431     If both strings have constant lengths, use the smaller.  This
2432     could arise if optimization results in strcpy being called with
2433     two fixed strings, or if the code was machine-generated.  We should
2434     add some code to the `memcmp' handler below to deal with such
2435     situations, someday.  */
2436
2437  if (!len || TREE_CODE (len) != INTEGER_CST)
2438    {
2439      if (len2 && !TREE_SIDE_EFFECTS (len2))
2440        len = len2;
2441      else if (len == 0)
2442        return 0;
2443    }
2444  else if (len2 && TREE_CODE (len2) == INTEGER_CST
2445           && tree_int_cst_lt (len2, len))
2446    len = len2;
2447
2448  /* If both arguments have side effects, we cannot optimize.  */
2449  if (TREE_SIDE_EFFECTS (len))
2450    return 0;
2451
2452  fn = built_in_decls[BUILT_IN_MEMCMP];
2453  if (!fn)
2454    return 0;
2455
2456  chainon (arglist, build_tree_list (NULL_TREE, len));
2457  return expand_expr (build_function_call_expr (fn, arglist),
2458                      target, mode, EXPAND_NORMAL);
2459}
2460
2461/* Expand expression EXP, which is a call to the strncmp builtin.  Return 0
2462   if we failed the caller should emit a normal call, otherwise try to get
2463   the result in TARGET, if convenient.  */
2464
2465static rtx
2466expand_builtin_strncmp (exp, target, mode)
2467     tree exp;
2468     rtx target;
2469     enum machine_mode mode;
2470{
2471  tree arglist = TREE_OPERAND (exp, 1);
2472  tree fn, newarglist, len = 0;
2473  tree arg1, arg2, arg3;
2474  const char *p1, *p2;
2475
2476  if (!validate_arglist (arglist,
2477			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2478    return 0;
2479
2480  arg1 = TREE_VALUE (arglist);
2481  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2482  arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2483
2484  /* If the len parameter is zero, return zero.  */
2485  if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0)
2486  {
2487    /* Evaluate and ignore arg1 and arg2 in case they have
2488       side-effects.  */
2489    expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2490    expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2491    return const0_rtx;
2492  }
2493
2494  p1 = c_getstr (arg1);
2495  p2 = c_getstr (arg2);
2496
2497  /* If all arguments are constant, evaluate at compile-time.  */
2498  if (host_integerp (arg3, 1) && p1 && p2)
2499  {
2500    const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
2501    return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2502  }
2503
2504  /* If len == 1 or (either string parameter is "" and (len >= 1)),
2505      return (*(const u_char*)arg1 - *(const u_char*)arg2).  */
2506  if (host_integerp (arg3, 1)
2507      && (tree_low_cst (arg3, 1) == 1
2508	  || (tree_low_cst (arg3, 1) > 1
2509	      && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
2510    {
2511      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2512      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2513      tree ind1 =
2514	fold (build1 (CONVERT_EXPR, integer_type_node,
2515		      build1 (INDIRECT_REF, cst_uchar_node,
2516			      build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2517      tree ind2 =
2518	fold (build1 (CONVERT_EXPR, integer_type_node,
2519		      build1 (INDIRECT_REF, cst_uchar_node,
2520			      build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2521      tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2522      return expand_expr (result, target, mode, EXPAND_NORMAL);
2523    }
2524
2525  /* If c_strlen can determine an expression for one of the string
2526     lengths, and it doesn't have side effects, then call
2527     expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3).  */
2528
2529  /* Perhaps one of the strings is really constant, if so prefer
2530     that constant length over the other string's length.  */
2531  if (p1)
2532    len = c_strlen (arg1);
2533  else if (p2)
2534    len = c_strlen (arg2);
2535
2536  /* If we still don't have a len, try either string arg as long
2537     as they don't have side effects.  */
2538  if (!len && !TREE_SIDE_EFFECTS (arg1))
2539    len = c_strlen (arg1);
2540  if (!len && !TREE_SIDE_EFFECTS (arg2))
2541    len = c_strlen (arg2);
2542  /* If we still don't have a length, punt.  */
2543  if (!len)
2544    return 0;
2545
2546  fn = built_in_decls[BUILT_IN_MEMCMP];
2547  if (!fn)
2548    return 0;
2549
2550  /* Add one to the string length.  */
2551  len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
2552
2553  /* The actual new length parameter is MIN(len,arg3).  */
2554  len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
2555
2556  newarglist = build_tree_list (NULL_TREE, len);
2557  newarglist = tree_cons (NULL_TREE, arg2, newarglist);
2558  newarglist = tree_cons (NULL_TREE, arg1, newarglist);
2559  return expand_expr (build_function_call_expr (fn, newarglist),
2560                      target, mode, EXPAND_NORMAL);
2561}
2562
2563/* Expand expression EXP, which is a call to the strcat builtin.
2564   Return 0 if we failed the caller should emit a normal call,
2565   otherwise try to get the result in TARGET, if convenient.  */
2566
2567static rtx
2568expand_builtin_strcat (arglist, target, mode)
2569     tree arglist;
2570     rtx target;
2571     enum machine_mode mode;
2572{
2573  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2574    return 0;
2575  else
2576    {
2577      tree dst = TREE_VALUE (arglist),
2578	src = TREE_VALUE (TREE_CHAIN (arglist));
2579      const char *p = c_getstr (src);
2580
2581      /* If the string length is zero, return the dst parameter.  */
2582      if (p && *p == '\0')
2583	return expand_expr (dst, target, mode, EXPAND_NORMAL);
2584
2585      return 0;
2586    }
2587}
2588
2589/* Expand expression EXP, which is a call to the strncat builtin.
2590   Return 0 if we failed the caller should emit a normal call,
2591   otherwise try to get the result in TARGET, if convenient.  */
2592
2593static rtx
2594expand_builtin_strncat (arglist, target, mode)
2595     tree arglist;
2596     rtx target;
2597     enum machine_mode mode;
2598{
2599  if (!validate_arglist (arglist,
2600			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2601    return 0;
2602  else
2603    {
2604      tree dst = TREE_VALUE (arglist),
2605	src = TREE_VALUE (TREE_CHAIN (arglist)),
2606	len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2607      const char *p = c_getstr (src);
2608
2609      /* If the requested length is zero, or the src parameter string
2610          length is zero, return the dst parameter.  */
2611      if (integer_zerop (len) || (p && *p == '\0'))
2612        {
2613	  /* Evaluate and ignore the src and len parameters in case
2614	     they have side-effects.  */
2615	  expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2616	  expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2617	  return expand_expr (dst, target, mode, EXPAND_NORMAL);
2618	}
2619
2620      /* If the requested len is greater than or equal to the string
2621         length, call strcat.  */
2622      if (TREE_CODE (len) == INTEGER_CST && p
2623	  && compare_tree_int (len, strlen (p)) >= 0)
2624        {
2625	  tree newarglist
2626	    = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
2627	  tree fn = built_in_decls[BUILT_IN_STRCAT];
2628
2629	  /* If the replacement _DECL isn't initialized, don't do the
2630	     transformation.  */
2631	  if (!fn)
2632	    return 0;
2633
2634	  return expand_expr (build_function_call_expr (fn, newarglist),
2635			      target, mode, EXPAND_NORMAL);
2636	}
2637      return 0;
2638    }
2639}
2640
2641/* Expand expression EXP, which is a call to the strspn builtin.
2642   Return 0 if we failed the caller should emit a normal call,
2643   otherwise try to get the result in TARGET, if convenient.  */
2644
2645static rtx
2646expand_builtin_strspn (arglist, target, mode)
2647     tree arglist;
2648     rtx target;
2649     enum machine_mode mode;
2650{
2651  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2652    return 0;
2653  else
2654    {
2655      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2656      const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2657
2658      /* If both arguments are constants, evaluate at compile-time.  */
2659      if (p1 && p2)
2660        {
2661	  const size_t r = strspn (p1, p2);
2662	  return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2663	}
2664
2665      /* If either argument is "", return 0.  */
2666      if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2667        {
2668	  /* Evaluate and ignore both arguments in case either one has
2669	     side-effects.  */
2670	  expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2671	  expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2672	  return const0_rtx;
2673	}
2674      return 0;
2675    }
2676}
2677
2678/* Expand expression EXP, which is a call to the strcspn builtin.
2679   Return 0 if we failed the caller should emit a normal call,
2680   otherwise try to get the result in TARGET, if convenient.  */
2681
2682static rtx
2683expand_builtin_strcspn (arglist, target, mode)
2684     tree arglist;
2685     rtx target;
2686     enum machine_mode mode;
2687{
2688  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2689    return 0;
2690  else
2691    {
2692      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2693      const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2694
2695      /* If both arguments are constants, evaluate at compile-time.  */
2696      if (p1 && p2)
2697        {
2698	  const size_t r = strcspn (p1, p2);
2699	  return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2700	}
2701
2702      /* If the first argument is "", return 0.  */
2703      if (p1 && *p1 == '\0')
2704        {
2705	  /* Evaluate and ignore argument s2 in case it has
2706	     side-effects.  */
2707	  expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2708	  return const0_rtx;
2709	}
2710
2711      /* If the second argument is "", return __builtin_strlen(s1).  */
2712      if (p2 && *p2 == '\0')
2713        {
2714	  tree newarglist = build_tree_list (NULL_TREE, s1),
2715	    fn = built_in_decls[BUILT_IN_STRLEN];
2716
2717	  /* If the replacement _DECL isn't initialized, don't do the
2718	     transformation.  */
2719	  if (!fn)
2720	    return 0;
2721
2722	  return expand_expr (build_function_call_expr (fn, newarglist),
2723			      target, mode, EXPAND_NORMAL);
2724	}
2725      return 0;
2726    }
2727}
2728
2729/* Expand a call to __builtin_saveregs, generating the result in TARGET,
2730   if that's convenient.  */
2731
2732rtx
2733expand_builtin_saveregs ()
2734{
2735  rtx val, seq;
2736
2737  /* Don't do __builtin_saveregs more than once in a function.
2738     Save the result of the first call and reuse it.  */
2739  if (saveregs_value != 0)
2740    return saveregs_value;
2741
2742  /* When this function is called, it means that registers must be
2743     saved on entry to this function.  So we migrate the call to the
2744     first insn of this function.  */
2745
2746  start_sequence ();
2747
2748#ifdef EXPAND_BUILTIN_SAVEREGS
2749  /* Do whatever the machine needs done in this case.  */
2750  val = EXPAND_BUILTIN_SAVEREGS ();
2751#else
2752  /* ??? We used to try and build up a call to the out of line function,
2753     guessing about what registers needed saving etc.  This became much
2754     harder with __builtin_va_start, since we don't have a tree for a
2755     call to __builtin_saveregs to fall back on.  There was exactly one
2756     port (i860) that used this code, and I'm unconvinced it could actually
2757     handle the general case.  So we no longer try to handle anything
2758     weird and make the backend absorb the evil.  */
2759
2760  error ("__builtin_saveregs not supported by this target");
2761  val = const0_rtx;
2762#endif
2763
2764  seq = get_insns ();
2765  end_sequence ();
2766
2767  saveregs_value = val;
2768
2769  /* Put the sequence after the NOTE that starts the function.  If this
2770     is inside a SEQUENCE, make the outer-level insn chain current, so
2771     the code is placed at the start of the function.  */
2772  push_topmost_sequence ();
2773  emit_insns_after (seq, get_insns ());
2774  pop_topmost_sequence ();
2775
2776  return val;
2777}
2778
2779/* __builtin_args_info (N) returns word N of the arg space info
2780   for the current function.  The number and meanings of words
2781   is controlled by the definition of CUMULATIVE_ARGS.  */
2782
2783static rtx
2784expand_builtin_args_info (exp)
2785     tree exp;
2786{
2787  tree arglist = TREE_OPERAND (exp, 1);
2788  int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
2789  int *word_ptr = (int *) &current_function_args_info;
2790#if 0
2791  /* These are used by the code below that is if 0'ed away */
2792  int i;
2793  tree type, elts, result;
2794#endif
2795
2796  if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
2797    abort ();
2798
2799  if (arglist != 0)
2800    {
2801      if (!host_integerp (TREE_VALUE (arglist), 0))
2802	error ("argument of `__builtin_args_info' must be constant");
2803      else
2804	{
2805	  HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
2806
2807	  if (wordnum < 0 || wordnum >= nwords)
2808	    error ("argument of `__builtin_args_info' out of range");
2809	  else
2810	    return GEN_INT (word_ptr[wordnum]);
2811	}
2812    }
2813  else
2814    error ("missing argument in `__builtin_args_info'");
2815
2816  return const0_rtx;
2817
2818#if 0
2819  for (i = 0; i < nwords; i++)
2820    elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
2821
2822  type = build_array_type (integer_type_node,
2823			   build_index_type (build_int_2 (nwords, 0)));
2824  result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
2825  TREE_CONSTANT (result) = 1;
2826  TREE_STATIC (result) = 1;
2827  result = build1 (INDIRECT_REF, build_pointer_type (type), result);
2828  TREE_CONSTANT (result) = 1;
2829  return expand_expr (result, NULL_RTX, VOIDmode, 0);
2830#endif
2831}
2832
2833/* Expand ARGLIST, from a call to __builtin_next_arg.  */
2834
2835static rtx
2836expand_builtin_next_arg (arglist)
2837     tree arglist;
2838{
2839  tree fntype = TREE_TYPE (current_function_decl);
2840
2841  if ((TYPE_ARG_TYPES (fntype) == 0
2842       || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2843	   == void_type_node))
2844      && ! current_function_varargs)
2845    {
2846      error ("`va_start' used in function with fixed args");
2847      return const0_rtx;
2848    }
2849
2850  if (arglist)
2851    {
2852      tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
2853      tree arg = TREE_VALUE (arglist);
2854
2855      /* Strip off all nops for the sake of the comparison.  This
2856	 is not quite the same as STRIP_NOPS.  It does more.
2857	 We must also strip off INDIRECT_EXPR for C++ reference
2858	 parameters.  */
2859      while (TREE_CODE (arg) == NOP_EXPR
2860	     || TREE_CODE (arg) == CONVERT_EXPR
2861	     || TREE_CODE (arg) == NON_LVALUE_EXPR
2862	     || TREE_CODE (arg) == INDIRECT_REF)
2863	arg = TREE_OPERAND (arg, 0);
2864      if (arg != last_parm)
2865	warning ("second parameter of `va_start' not last named argument");
2866    }
2867  else if (! current_function_varargs)
2868    /* Evidently an out of date version of <stdarg.h>; can't validate
2869       va_start's second argument, but can still work as intended.  */
2870    warning ("`__builtin_next_arg' called without an argument");
2871
2872  return expand_binop (Pmode, add_optab,
2873		       current_function_internal_arg_pointer,
2874		       current_function_arg_offset_rtx,
2875		       NULL_RTX, 0, OPTAB_LIB_WIDEN);
2876}
2877
2878/* Make it easier for the backends by protecting the valist argument
2879   from multiple evaluations.  */
2880
2881static tree
2882stabilize_va_list (valist, needs_lvalue)
2883     tree valist;
2884     int needs_lvalue;
2885{
2886  if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
2887    {
2888      if (TREE_SIDE_EFFECTS (valist))
2889	valist = save_expr (valist);
2890
2891      /* For this case, the backends will be expecting a pointer to
2892	 TREE_TYPE (va_list_type_node), but it's possible we've
2893	 actually been given an array (an actual va_list_type_node).
2894	 So fix it.  */
2895      if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
2896	{
2897	  tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
2898	  tree p2 = build_pointer_type (va_list_type_node);
2899
2900	  valist = build1 (ADDR_EXPR, p2, valist);
2901	  valist = fold (build1 (NOP_EXPR, p1, valist));
2902	}
2903    }
2904  else
2905    {
2906      tree pt;
2907
2908      if (! needs_lvalue)
2909	{
2910	  if (! TREE_SIDE_EFFECTS (valist))
2911	    return valist;
2912
2913	  pt = build_pointer_type (va_list_type_node);
2914	  valist = fold (build1 (ADDR_EXPR, pt, valist));
2915	  TREE_SIDE_EFFECTS (valist) = 1;
2916	}
2917
2918      if (TREE_SIDE_EFFECTS (valist))
2919	valist = save_expr (valist);
2920      valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
2921			     valist));
2922    }
2923
2924  return valist;
2925}
2926
2927/* The "standard" implementation of va_start: just assign `nextarg' to
2928   the variable.  */
2929
2930void
2931std_expand_builtin_va_start (stdarg_p, valist, nextarg)
2932     int stdarg_p;
2933     tree valist;
2934     rtx nextarg;
2935{
2936  tree t;
2937
2938  if (! stdarg_p)
2939    {
2940      /* The dummy named parameter is declared as a 'word' sized
2941	 object, but if a 'word' is smaller than an 'int', it would
2942	 have been promoted to int when it was added to the arglist.  */
2943      int align = PARM_BOUNDARY / BITS_PER_UNIT;
2944      int size = MAX (UNITS_PER_WORD,
2945		      GET_MODE_SIZE (TYPE_MODE (integer_type_node)));
2946      int offset = ((size + align - 1) / align) * align;
2947      nextarg = plus_constant (nextarg, -offset);
2948    }
2949
2950  t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2951	     make_tree (ptr_type_node, nextarg));
2952  TREE_SIDE_EFFECTS (t) = 1;
2953
2954  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2955}
2956
2957/* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
2958   __builtin_varargs_va_start, depending on STDARG_P.  */
2959
2960static rtx
2961expand_builtin_va_start (stdarg_p, arglist)
2962     int stdarg_p;
2963     tree arglist;
2964{
2965  rtx nextarg;
2966  tree chain = arglist, valist;
2967
2968  if (stdarg_p)
2969    nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
2970  else
2971    nextarg = expand_builtin_next_arg (NULL_TREE);
2972
2973  if (TREE_CHAIN (chain))
2974    error ("too many arguments to function `va_start'");
2975
2976  valist = stabilize_va_list (TREE_VALUE (arglist), 1);
2977
2978#ifdef EXPAND_BUILTIN_VA_START
2979  EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
2980#else
2981  std_expand_builtin_va_start (stdarg_p, valist, nextarg);
2982#endif
2983
2984  return const0_rtx;
2985}
2986
2987/* The "standard" implementation of va_arg: read the value from the
2988   current (padded) address and increment by the (padded) size.  */
2989
2990rtx
2991std_expand_builtin_va_arg (valist, type)
2992     tree valist, type;
2993{
2994  tree addr_tree, t, type_size = NULL;
2995  tree align, alignm1;
2996  tree rounded_size;
2997  rtx addr;
2998
2999  /* Compute the rounded size of the type.  */
3000  align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
3001  alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
3002  if (type == error_mark_node
3003      || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
3004      || TREE_OVERFLOW (type_size))
3005    rounded_size = size_zero_node;
3006  else
3007    rounded_size = fold (build (MULT_EXPR, sizetype,
3008				fold (build (TRUNC_DIV_EXPR, sizetype,
3009					     fold (build (PLUS_EXPR, sizetype,
3010							  type_size, alignm1)),
3011					     align)),
3012				align));
3013
3014  /* Get AP.  */
3015  addr_tree = valist;
3016  if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size))
3017    {
3018      /* Small args are padded downward.  */
3019      addr_tree = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
3020			       fold (build (COND_EXPR, sizetype,
3021					    fold (build (GT_EXPR, sizetype,
3022							 rounded_size,
3023							 align)),
3024					    size_zero_node,
3025					    fold (build (MINUS_EXPR, sizetype,
3026							 rounded_size,
3027							 type_size))))));
3028    }
3029
3030  addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
3031  addr = copy_to_reg (addr);
3032
3033  /* Compute new value for AP.  */
3034  if (! integer_zerop (rounded_size))
3035    {
3036      t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
3037		 build (PLUS_EXPR, TREE_TYPE (valist), valist,
3038			rounded_size));
3039      TREE_SIDE_EFFECTS (t) = 1;
3040      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3041    }
3042
3043  return addr;
3044}
3045
3046/* Expand __builtin_va_arg, which is not really a builtin function, but
3047   a very special sort of operator.  */
3048
3049rtx
3050expand_builtin_va_arg (valist, type)
3051     tree valist, type;
3052{
3053  rtx addr, result;
3054  tree promoted_type, want_va_type, have_va_type;
3055
3056  /* Verify that valist is of the proper type.  */
3057
3058  want_va_type = va_list_type_node;
3059  have_va_type = TREE_TYPE (valist);
3060  if (TREE_CODE (want_va_type) == ARRAY_TYPE)
3061    {
3062      /* If va_list is an array type, the argument may have decayed
3063	 to a pointer type, e.g. by being passed to another function.
3064         In that case, unwrap both types so that we can compare the
3065	 underlying records.  */
3066      if (TREE_CODE (have_va_type) == ARRAY_TYPE
3067	  || TREE_CODE (have_va_type) == POINTER_TYPE)
3068	{
3069	  want_va_type = TREE_TYPE (want_va_type);
3070	  have_va_type = TREE_TYPE (have_va_type);
3071	}
3072    }
3073  if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
3074    {
3075      error ("first argument to `va_arg' not of type `va_list'");
3076      addr = const0_rtx;
3077    }
3078
3079  /* Generate a diagnostic for requesting data of a type that cannot
3080     be passed through `...' due to type promotion at the call site.  */
3081  else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
3082    {
3083      const char *name = "<anonymous type>", *pname = 0;
3084      static bool gave_help;
3085
3086      if (TYPE_NAME (type))
3087	{
3088	  if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
3089	    name = IDENTIFIER_POINTER (TYPE_NAME (type));
3090	  else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
3091		   && DECL_NAME (TYPE_NAME (type)))
3092	    name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
3093	}
3094      if (TYPE_NAME (promoted_type))
3095	{
3096	  if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
3097	    pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
3098	  else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
3099		   && DECL_NAME (TYPE_NAME (promoted_type)))
3100	    pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
3101	}
3102
3103      /* Unfortunately, this is merely undefined, rather than a constraint
3104	 violation, so we cannot make this an error.  If this call is never
3105	 executed, the program is still strictly conforming.  */
3106      warning ("`%s' is promoted to `%s' when passed through `...'",
3107	       name, pname);
3108      if (! gave_help)
3109	{
3110	  gave_help = true;
3111	  warning ("(so you should pass `%s' not `%s' to `va_arg')",
3112		   pname, name);
3113	}
3114
3115      /* We can, however, treat "undefined" any way we please.
3116	 Call abort to encourage the user to fix the program.  */
3117      expand_builtin_trap ();
3118
3119      /* This is dead code, but go ahead and finish so that the
3120	 mode of the result comes out right.  */
3121      addr = const0_rtx;
3122    }
3123  else
3124    {
3125      /* Make it easier for the backends by protecting the valist argument
3126         from multiple evaluations.  */
3127      valist = stabilize_va_list (valist, 0);
3128
3129#ifdef EXPAND_BUILTIN_VA_ARG
3130      addr = EXPAND_BUILTIN_VA_ARG (valist, type);
3131#else
3132      addr = std_expand_builtin_va_arg (valist, type);
3133#endif
3134    }
3135
3136#ifdef POINTERS_EXTEND_UNSIGNED
3137  if (GET_MODE (addr) != Pmode)
3138    addr = convert_memory_address (Pmode, addr);
3139#endif
3140
3141  result = gen_rtx_MEM (TYPE_MODE (type), addr);
3142  set_mem_alias_set (result, get_varargs_alias_set ());
3143
3144  return result;
3145}
3146
3147/* Expand ARGLIST, from a call to __builtin_va_end.  */
3148
3149static rtx
3150expand_builtin_va_end (arglist)
3151     tree arglist;
3152{
3153  tree valist = TREE_VALUE (arglist);
3154
3155#ifdef EXPAND_BUILTIN_VA_END
3156  valist = stabilize_va_list (valist, 0);
3157  EXPAND_BUILTIN_VA_END(arglist);
3158#else
3159  /* Evaluate for side effects, if needed.  I hate macros that don't
3160     do that.  */
3161  if (TREE_SIDE_EFFECTS (valist))
3162    expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
3163#endif
3164
3165  return const0_rtx;
3166}
3167
3168/* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a
3169   builtin rather than just as an assignment in stdarg.h because of the
3170   nastiness of array-type va_list types.  */
3171
3172static rtx
3173expand_builtin_va_copy (arglist)
3174     tree arglist;
3175{
3176  tree dst, src, t;
3177
3178  dst = TREE_VALUE (arglist);
3179  src = TREE_VALUE (TREE_CHAIN (arglist));
3180
3181  dst = stabilize_va_list (dst, 1);
3182  src = stabilize_va_list (src, 0);
3183
3184  if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
3185    {
3186      t = build (MODIFY_EXPR, va_list_type_node, dst, src);
3187      TREE_SIDE_EFFECTS (t) = 1;
3188      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3189    }
3190  else
3191    {
3192      rtx dstb, srcb, size;
3193
3194      /* Evaluate to pointers.  */
3195      dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
3196      srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
3197      size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
3198			  VOIDmode, EXPAND_NORMAL);
3199
3200#ifdef POINTERS_EXTEND_UNSIGNED
3201      if (GET_MODE (dstb) != Pmode)
3202	dstb = convert_memory_address (Pmode, dstb);
3203
3204      if (GET_MODE (srcb) != Pmode)
3205	srcb = convert_memory_address (Pmode, srcb);
3206#endif
3207
3208      /* "Dereference" to BLKmode memories.  */
3209      dstb = gen_rtx_MEM (BLKmode, dstb);
3210      set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
3211      set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
3212      srcb = gen_rtx_MEM (BLKmode, srcb);
3213      set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
3214      set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
3215
3216      /* Copy.  */
3217      emit_block_move (dstb, srcb, size);
3218    }
3219
3220  return const0_rtx;
3221}
3222
3223/* Expand a call to one of the builtin functions __builtin_frame_address or
3224   __builtin_return_address.  */
3225
3226static rtx
3227expand_builtin_frame_address (exp)
3228     tree exp;
3229{
3230  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3231  tree arglist = TREE_OPERAND (exp, 1);
3232
3233  /* The argument must be a nonnegative integer constant.
3234     It counts the number of frames to scan up the stack.
3235     The value is the return address saved in that frame.  */
3236  if (arglist == 0)
3237    /* Warning about missing arg was already issued.  */
3238    return const0_rtx;
3239  else if (! host_integerp (TREE_VALUE (arglist), 1))
3240    {
3241      if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3242	error ("invalid arg to `__builtin_frame_address'");
3243      else
3244	error ("invalid arg to `__builtin_return_address'");
3245      return const0_rtx;
3246    }
3247  else
3248    {
3249      rtx tem
3250	= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
3251				      tree_low_cst (TREE_VALUE (arglist), 1),
3252				      hard_frame_pointer_rtx);
3253
3254      /* Some ports cannot access arbitrary stack frames.  */
3255      if (tem == NULL)
3256	{
3257	  if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3258	    warning ("unsupported arg to `__builtin_frame_address'");
3259	  else
3260	    warning ("unsupported arg to `__builtin_return_address'");
3261	  return const0_rtx;
3262	}
3263
3264      /* For __builtin_frame_address, return what we've got.  */
3265      if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3266	return tem;
3267
3268      if (GET_CODE (tem) != REG
3269	  && ! CONSTANT_P (tem))
3270	tem = copy_to_mode_reg (Pmode, tem);
3271      return tem;
3272    }
3273}
3274
3275/* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
3276   we failed and the caller should emit a normal call, otherwise try to get
3277   the result in TARGET, if convenient.  */
3278
3279static rtx
3280expand_builtin_alloca (arglist, target)
3281     tree arglist;
3282     rtx target;
3283{
3284  rtx op0;
3285  rtx result;
3286
3287  if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3288    return 0;
3289
3290  /* Compute the argument.  */
3291  op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
3292
3293  /* Allocate the desired space.  */
3294  result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
3295
3296#ifdef POINTERS_EXTEND_UNSIGNED
3297  if (GET_MODE (result) != ptr_mode)
3298    result = convert_memory_address (ptr_mode, result);
3299#endif
3300
3301  return result;
3302}
3303
3304/* Expand a call to the ffs builtin.  The arguments are in ARGLIST.
3305   Return 0 if a normal call should be emitted rather than expanding the
3306   function in-line.  If convenient, the result should be placed in TARGET.
3307   SUBTARGET may be used as the target for computing one of EXP's operands.  */
3308
3309static rtx
3310expand_builtin_ffs (arglist, target, subtarget)
3311     tree arglist;
3312     rtx target, subtarget;
3313{
3314  rtx op0;
3315  if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3316    return 0;
3317
3318  /* Compute the argument.  */
3319  op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
3320  /* Compute ffs, into TARGET if possible.
3321     Set TARGET to wherever the result comes back.  */
3322  target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
3323			ffs_optab, op0, target, 1);
3324  if (target == 0)
3325    abort ();
3326  return target;
3327}
3328
3329/* If the string passed to fputs is a constant and is one character
3330   long, we attempt to transform this call into __builtin_fputc().  */
3331
3332static rtx
3333expand_builtin_fputs (arglist, ignore, unlocked)
3334     tree arglist;
3335     int ignore;
3336     int unlocked;
3337{
3338  tree len, fn;
3339  tree fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
3340    : built_in_decls[BUILT_IN_FPUTC];
3341  tree fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
3342    : built_in_decls[BUILT_IN_FWRITE];
3343
3344  /* If the return value is used, or the replacement _DECL isn't
3345     initialized, don't do the transformation.  */
3346  if (!ignore || !fn_fputc || !fn_fwrite)
3347    return 0;
3348
3349  /* Verify the arguments in the original call.  */
3350  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3351    return 0;
3352
3353  /* Get the length of the string passed to fputs.  If the length
3354     can't be determined, punt.  */
3355  if (!(len = c_strlen (TREE_VALUE (arglist)))
3356      || TREE_CODE (len) != INTEGER_CST)
3357    return 0;
3358
3359  switch (compare_tree_int (len, 1))
3360    {
3361    case -1: /* length is 0, delete the call entirely .  */
3362      {
3363	/* Evaluate and ignore the argument in case it has
3364           side-effects.  */
3365	expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
3366		     VOIDmode, EXPAND_NORMAL);
3367	return const0_rtx;
3368      }
3369    case 0: /* length is 1, call fputc.  */
3370      {
3371	const char *p = c_getstr (TREE_VALUE (arglist));
3372
3373	if (p != NULL)
3374	  {
3375	    /* New argument list transforming fputs(string, stream) to
3376	       fputc(string[0], stream).  */
3377	    arglist =
3378	      build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3379	    arglist =
3380	      tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
3381	    fn = fn_fputc;
3382	    break;
3383	  }
3384      }
3385      /* FALLTHROUGH */
3386    case 1: /* length is greater than 1, call fwrite.  */
3387      {
3388	tree string_arg = TREE_VALUE (arglist);
3389
3390	/* New argument list transforming fputs(string, stream) to
3391	   fwrite(string, 1, len, stream).  */
3392	arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3393	arglist = tree_cons (NULL_TREE, len, arglist);
3394	arglist = tree_cons (NULL_TREE, size_one_node, arglist);
3395	arglist = tree_cons (NULL_TREE, string_arg, arglist);
3396	fn = fn_fwrite;
3397	break;
3398      }
3399    default:
3400      abort ();
3401    }
3402
3403  return expand_expr (build_function_call_expr (fn, arglist),
3404		      (ignore ? const0_rtx : NULL_RTX),
3405		      VOIDmode, EXPAND_NORMAL);
3406}
3407
3408/* Expand a call to __builtin_expect.  We return our argument and emit a
3409   NOTE_INSN_EXPECTED_VALUE note.  This is the expansion of __builtin_expect in
3410   a non-jump context.  */
3411
3412static rtx
3413expand_builtin_expect (arglist, target)
3414     tree arglist;
3415     rtx target;
3416{
3417  tree exp, c;
3418  rtx note, rtx_c;
3419
3420  if (arglist == NULL_TREE
3421      || TREE_CHAIN (arglist) == NULL_TREE)
3422    return const0_rtx;
3423  exp = TREE_VALUE (arglist);
3424  c = TREE_VALUE (TREE_CHAIN (arglist));
3425
3426  if (TREE_CODE (c) != INTEGER_CST)
3427    {
3428      error ("second arg to `__builtin_expect' must be a constant");
3429      c = integer_zero_node;
3430    }
3431
3432  target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
3433
3434  /* Don't bother with expected value notes for integral constants.  */
3435  if (GET_CODE (target) != CONST_INT)
3436    {
3437      /* We do need to force this into a register so that we can be
3438	 moderately sure to be able to correctly interpret the branch
3439	 condition later.  */
3440      target = force_reg (GET_MODE (target), target);
3441
3442      rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
3443
3444      note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
3445      NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
3446    }
3447
3448  return target;
3449}
3450
3451/* Like expand_builtin_expect, except do this in a jump context.  This is
3452   called from do_jump if the conditional is a __builtin_expect.  Return either
3453   a SEQUENCE of insns to emit the jump or NULL if we cannot optimize
3454   __builtin_expect.  We need to optimize this at jump time so that machines
3455   like the PowerPC don't turn the test into a SCC operation, and then jump
3456   based on the test being 0/1.  */
3457
3458rtx
3459expand_builtin_expect_jump (exp, if_false_label, if_true_label)
3460     tree exp;
3461     rtx if_false_label;
3462     rtx if_true_label;
3463{
3464  tree arglist = TREE_OPERAND (exp, 1);
3465  tree arg0 = TREE_VALUE (arglist);
3466  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
3467  rtx ret = NULL_RTX;
3468
3469  /* Only handle __builtin_expect (test, 0) and
3470     __builtin_expect (test, 1).  */
3471  if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
3472      && (integer_zerop (arg1) || integer_onep (arg1)))
3473    {
3474      int j;
3475      int num_jumps = 0;
3476
3477      /* If we fail to locate an appropriate conditional jump, we'll
3478	 fall back to normal evaluation.  Ensure that the expression
3479	 can be re-evaluated.  */
3480      switch (unsafe_for_reeval (arg0))
3481	{
3482	case 0: /* Safe.  */
3483	  break;
3484
3485	case 1: /* Mildly unsafe.  */
3486	  arg0 = unsave_expr (arg0);
3487	  break;
3488
3489	case 2: /* Wildly unsafe.  */
3490	  return NULL_RTX;
3491	}
3492
3493      /* Expand the jump insns.  */
3494      start_sequence ();
3495      do_jump (arg0, if_false_label, if_true_label);
3496      ret = gen_sequence ();
3497      end_sequence ();
3498
3499      /* Now that the __builtin_expect has been validated, go through and add
3500	 the expect's to each of the conditional jumps.  If we run into an
3501	 error, just give up and generate the 'safe' code of doing a SCC
3502	 operation and then doing a branch on that.  */
3503      for (j = 0; j < XVECLEN (ret, 0); j++)
3504	{
3505	  rtx insn = XVECEXP (ret, 0, j);
3506	  rtx pattern;
3507
3508	  if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn)
3509	      && (pattern = pc_set (insn)) != NULL_RTX)
3510	    {
3511	      rtx ifelse = SET_SRC (pattern);
3512	      rtx label;
3513	      int taken;
3514
3515	      if (GET_CODE (ifelse) != IF_THEN_ELSE)
3516		continue;
3517
3518	      if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF)
3519		{
3520		  taken = 1;
3521		  label = XEXP (XEXP (ifelse, 1), 0);
3522		}
3523	      /* An inverted jump reverses the probabilities.  */
3524	      else if (GET_CODE (XEXP (ifelse, 2)) == LABEL_REF)
3525		{
3526		  taken = 0;
3527		  label = XEXP (XEXP (ifelse, 2), 0);
3528		}
3529	      /* We shouldn't have to worry about conditional returns during
3530		 the expansion stage, but handle it gracefully anyway.  */
3531	      else if (GET_CODE (XEXP (ifelse, 1)) == RETURN)
3532		{
3533		  taken = 1;
3534		  label = NULL_RTX;
3535		}
3536	      /* An inverted return reverses the probabilities.  */
3537	      else if (GET_CODE (XEXP (ifelse, 2)) == RETURN)
3538		{
3539		  taken = 0;
3540		  label = NULL_RTX;
3541		}
3542	      else
3543		continue;
3544
3545	      /* If the test is expected to fail, reverse the
3546		 probabilities.  */
3547	      if (integer_zerop (arg1))
3548		taken = 1 - taken;
3549
3550	      /* If we are jumping to the false label, reverse the
3551		 probabilities.  */
3552	      if (label == NULL_RTX)
3553		;		/* conditional return */
3554	      else if (label == if_false_label)
3555		taken = 1 - taken;
3556	      else if (label != if_true_label)
3557		continue;
3558
3559	      num_jumps++;
3560	      predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
3561	    }
3562	}
3563
3564      /* If no jumps were modified, fail and do __builtin_expect the normal
3565	 way.  */
3566      if (num_jumps == 0)
3567	ret = NULL_RTX;
3568    }
3569
3570  return ret;
3571}
3572
3573void
3574expand_builtin_trap ()
3575{
3576#ifdef HAVE_trap
3577  if (HAVE_trap)
3578    emit_insn (gen_trap ());
3579  else
3580#endif
3581    emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
3582  emit_barrier ();
3583}
3584
3585/* Expand an expression EXP that calls a built-in function,
3586   with result going to TARGET if that's convenient
3587   (and in mode MODE if that's convenient).
3588   SUBTARGET may be used as the target for computing one of EXP's operands.
3589   IGNORE is nonzero if the value is to be ignored.  */
3590
3591rtx
3592expand_builtin (exp, target, subtarget, mode, ignore)
3593     tree exp;
3594     rtx target;
3595     rtx subtarget;
3596     enum machine_mode mode;
3597     int ignore;
3598{
3599  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3600  tree arglist = TREE_OPERAND (exp, 1);
3601  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
3602
3603  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
3604    return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore);
3605
3606  /* When not optimizing, generate calls to library functions for a certain
3607     set of builtins.  */
3608  if (!optimize && !CALLED_AS_BUILT_IN (fndecl))
3609    switch (fcode)
3610      {
3611      case BUILT_IN_SIN:
3612      case BUILT_IN_COS:
3613      case BUILT_IN_SQRT:
3614      case BUILT_IN_SQRTF:
3615      case BUILT_IN_SQRTL:
3616      case BUILT_IN_MEMSET:
3617      case BUILT_IN_MEMCPY:
3618      case BUILT_IN_MEMCMP:
3619      case BUILT_IN_BCMP:
3620      case BUILT_IN_BZERO:
3621      case BUILT_IN_INDEX:
3622      case BUILT_IN_RINDEX:
3623      case BUILT_IN_STRCHR:
3624      case BUILT_IN_STRRCHR:
3625      case BUILT_IN_STRLEN:
3626      case BUILT_IN_STRCPY:
3627      case BUILT_IN_STRNCPY:
3628      case BUILT_IN_STRNCMP:
3629      case BUILT_IN_STRSTR:
3630      case BUILT_IN_STRPBRK:
3631      case BUILT_IN_STRCAT:
3632      case BUILT_IN_STRNCAT:
3633      case BUILT_IN_STRSPN:
3634      case BUILT_IN_STRCSPN:
3635      case BUILT_IN_STRCMP:
3636      case BUILT_IN_FFS:
3637      case BUILT_IN_PUTCHAR:
3638      case BUILT_IN_PUTS:
3639      case BUILT_IN_PRINTF:
3640      case BUILT_IN_FPUTC:
3641      case BUILT_IN_FPUTS:
3642      case BUILT_IN_FWRITE:
3643      case BUILT_IN_PUTCHAR_UNLOCKED:
3644      case BUILT_IN_PUTS_UNLOCKED:
3645      case BUILT_IN_PRINTF_UNLOCKED:
3646      case BUILT_IN_FPUTC_UNLOCKED:
3647      case BUILT_IN_FPUTS_UNLOCKED:
3648      case BUILT_IN_FWRITE_UNLOCKED:
3649        return expand_call (exp, target, ignore);
3650
3651      default:
3652        break;
3653    }
3654
3655  switch (fcode)
3656    {
3657    case BUILT_IN_ABS:
3658    case BUILT_IN_LABS:
3659    case BUILT_IN_LLABS:
3660    case BUILT_IN_IMAXABS:
3661    case BUILT_IN_FABS:
3662    case BUILT_IN_FABSF:
3663    case BUILT_IN_FABSL:
3664      /* build_function_call changes these into ABS_EXPR.  */
3665      abort ();
3666
3667    case BUILT_IN_CONJ:
3668    case BUILT_IN_CONJF:
3669    case BUILT_IN_CONJL:
3670    case BUILT_IN_CREAL:
3671    case BUILT_IN_CREALF:
3672    case BUILT_IN_CREALL:
3673    case BUILT_IN_CIMAG:
3674    case BUILT_IN_CIMAGF:
3675    case BUILT_IN_CIMAGL:
3676      /* expand_tree_builtin changes these into CONJ_EXPR, REALPART_EXPR
3677	 and IMAGPART_EXPR.  */
3678      abort ();
3679
3680    case BUILT_IN_SIN:
3681    case BUILT_IN_SINF:
3682    case BUILT_IN_SINL:
3683    case BUILT_IN_COS:
3684    case BUILT_IN_COSF:
3685    case BUILT_IN_COSL:
3686      /* Treat these like sqrt only if unsafe math optimizations are allowed,
3687	 because of possible accuracy problems.  */
3688      if (! flag_unsafe_math_optimizations)
3689	break;
3690    case BUILT_IN_SQRT:
3691    case BUILT_IN_SQRTF:
3692    case BUILT_IN_SQRTL:
3693      target = expand_builtin_mathfn (exp, target, subtarget);
3694      if (target)
3695	return target;
3696      break;
3697
3698    case BUILT_IN_FMOD:
3699      break;
3700
3701    case BUILT_IN_APPLY_ARGS:
3702      return expand_builtin_apply_args ();
3703
3704      /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
3705	 FUNCTION with a copy of the parameters described by
3706	 ARGUMENTS, and ARGSIZE.  It returns a block of memory
3707	 allocated on the stack into which is stored all the registers
3708	 that might possibly be used for returning the result of a
3709	 function.  ARGUMENTS is the value returned by
3710	 __builtin_apply_args.  ARGSIZE is the number of bytes of
3711	 arguments that must be copied.  ??? How should this value be
3712	 computed?  We'll also need a safe worst case value for varargs
3713	 functions.  */
3714    case BUILT_IN_APPLY:
3715      if (!validate_arglist (arglist, POINTER_TYPE,
3716			     POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
3717	  && !validate_arglist (arglist, REFERENCE_TYPE,
3718				POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3719	return const0_rtx;
3720      else
3721	{
3722	  int i;
3723	  tree t;
3724	  rtx ops[3];
3725
3726	  for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
3727	    ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
3728
3729	  return expand_builtin_apply (ops[0], ops[1], ops[2]);
3730	}
3731
3732      /* __builtin_return (RESULT) causes the function to return the
3733	 value described by RESULT.  RESULT is address of the block of
3734	 memory returned by __builtin_apply.  */
3735    case BUILT_IN_RETURN:
3736      if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
3737	expand_builtin_return (expand_expr (TREE_VALUE (arglist),
3738					    NULL_RTX, VOIDmode, 0));
3739      return const0_rtx;
3740
3741    case BUILT_IN_SAVEREGS:
3742      return expand_builtin_saveregs ();
3743
3744    case BUILT_IN_ARGS_INFO:
3745      return expand_builtin_args_info (exp);
3746
3747      /* Return the address of the first anonymous stack arg.  */
3748    case BUILT_IN_NEXT_ARG:
3749      return expand_builtin_next_arg (arglist);
3750
3751    case BUILT_IN_CLASSIFY_TYPE:
3752      return expand_builtin_classify_type (arglist);
3753
3754    case BUILT_IN_CONSTANT_P:
3755      return expand_builtin_constant_p (exp);
3756
3757    case BUILT_IN_FRAME_ADDRESS:
3758    case BUILT_IN_RETURN_ADDRESS:
3759      return expand_builtin_frame_address (exp);
3760
3761    /* Returns the address of the area where the structure is returned.
3762       0 otherwise.  */
3763    case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
3764      if (arglist != 0
3765          || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
3766          || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
3767        return const0_rtx;
3768      else
3769        return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
3770
3771    case BUILT_IN_ALLOCA:
3772      target = expand_builtin_alloca (arglist, target);
3773      if (target)
3774	return target;
3775      break;
3776
3777    case BUILT_IN_FFS:
3778      target = expand_builtin_ffs (arglist, target, subtarget);
3779      if (target)
3780	return target;
3781      break;
3782
3783    case BUILT_IN_STRLEN:
3784      target = expand_builtin_strlen (exp, target);
3785      if (target)
3786	return target;
3787      break;
3788
3789    case BUILT_IN_STRCPY:
3790      target = expand_builtin_strcpy (exp, target, mode);
3791      if (target)
3792	return target;
3793      break;
3794
3795    case BUILT_IN_STRNCPY:
3796      target = expand_builtin_strncpy (arglist, target, mode);
3797      if (target)
3798	return target;
3799      break;
3800
3801    case BUILT_IN_STRCAT:
3802      target = expand_builtin_strcat (arglist, target, mode);
3803      if (target)
3804	return target;
3805      break;
3806
3807    case BUILT_IN_STRNCAT:
3808      target = expand_builtin_strncat (arglist, target, mode);
3809      if (target)
3810	return target;
3811      break;
3812
3813    case BUILT_IN_STRSPN:
3814      target = expand_builtin_strspn (arglist, target, mode);
3815      if (target)
3816	return target;
3817      break;
3818
3819    case BUILT_IN_STRCSPN:
3820      target = expand_builtin_strcspn (arglist, target, mode);
3821      if (target)
3822	return target;
3823      break;
3824
3825    case BUILT_IN_STRSTR:
3826      target = expand_builtin_strstr (arglist, target, mode);
3827      if (target)
3828	return target;
3829      break;
3830
3831    case BUILT_IN_STRPBRK:
3832      target = expand_builtin_strpbrk (arglist, target, mode);
3833      if (target)
3834	return target;
3835      break;
3836
3837    case BUILT_IN_INDEX:
3838    case BUILT_IN_STRCHR:
3839      target = expand_builtin_strchr (arglist, target, mode);
3840      if (target)
3841	return target;
3842      break;
3843
3844    case BUILT_IN_RINDEX:
3845    case BUILT_IN_STRRCHR:
3846      target = expand_builtin_strrchr (arglist, target, mode);
3847      if (target)
3848	return target;
3849      break;
3850
3851    case BUILT_IN_MEMCPY:
3852      target = expand_builtin_memcpy (arglist, target, mode);
3853      if (target)
3854	return target;
3855      break;
3856
3857    case BUILT_IN_MEMSET:
3858      target = expand_builtin_memset (exp, target, mode);
3859      if (target)
3860	return target;
3861      break;
3862
3863    case BUILT_IN_BZERO:
3864      target = expand_builtin_bzero (exp);
3865      if (target)
3866	return target;
3867      break;
3868
3869    case BUILT_IN_STRCMP:
3870      target = expand_builtin_strcmp (exp, target, mode);
3871      if (target)
3872	return target;
3873      break;
3874
3875    case BUILT_IN_STRNCMP:
3876      target = expand_builtin_strncmp (exp, target, mode);
3877      if (target)
3878	return target;
3879      break;
3880
3881    case BUILT_IN_BCMP:
3882    case BUILT_IN_MEMCMP:
3883      target = expand_builtin_memcmp (exp, arglist, target, mode);
3884      if (target)
3885	return target;
3886      break;
3887
3888    case BUILT_IN_SETJMP:
3889      target = expand_builtin_setjmp (arglist, target);
3890      if (target)
3891	return target;
3892      break;
3893
3894      /* __builtin_longjmp is passed a pointer to an array of five words.
3895	 It's similar to the C library longjmp function but works with
3896	 __builtin_setjmp above.  */
3897    case BUILT_IN_LONGJMP:
3898      if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3899	break;
3900      else
3901	{
3902	  rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
3903				      VOIDmode, 0);
3904	  rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
3905				   NULL_RTX, VOIDmode, 0);
3906
3907	  if (value != const1_rtx)
3908	    {
3909	      error ("__builtin_longjmp second argument must be 1");
3910	      return const0_rtx;
3911	    }
3912
3913	  expand_builtin_longjmp (buf_addr, value);
3914	  return const0_rtx;
3915	}
3916
3917    case BUILT_IN_TRAP:
3918      expand_builtin_trap ();
3919      return const0_rtx;
3920
3921    case BUILT_IN_PUTCHAR:
3922    case BUILT_IN_PUTS:
3923    case BUILT_IN_FPUTC:
3924    case BUILT_IN_FWRITE:
3925    case BUILT_IN_PUTCHAR_UNLOCKED:
3926    case BUILT_IN_PUTS_UNLOCKED:
3927    case BUILT_IN_FPUTC_UNLOCKED:
3928    case BUILT_IN_FWRITE_UNLOCKED:
3929      break;
3930    case BUILT_IN_FPUTS:
3931      target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 0);
3932      if (target)
3933	return target;
3934      break;
3935    case BUILT_IN_FPUTS_UNLOCKED:
3936      target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 1);
3937      if (target)
3938	return target;
3939      break;
3940
3941      /* Various hooks for the DWARF 2 __throw routine.  */
3942    case BUILT_IN_UNWIND_INIT:
3943      expand_builtin_unwind_init ();
3944      return const0_rtx;
3945    case BUILT_IN_DWARF_CFA:
3946      return virtual_cfa_rtx;
3947#ifdef DWARF2_UNWIND_INFO
3948    case BUILT_IN_DWARF_FP_REGNUM:
3949      return expand_builtin_dwarf_fp_regnum ();
3950    case BUILT_IN_INIT_DWARF_REG_SIZES:
3951      expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
3952      return const0_rtx;
3953#endif
3954    case BUILT_IN_FROB_RETURN_ADDR:
3955      return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
3956    case BUILT_IN_EXTRACT_RETURN_ADDR:
3957      return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
3958    case BUILT_IN_EH_RETURN:
3959      expand_builtin_eh_return (TREE_VALUE (arglist),
3960				TREE_VALUE (TREE_CHAIN (arglist)));
3961      return const0_rtx;
3962#ifdef EH_RETURN_DATA_REGNO
3963    case BUILT_IN_EH_RETURN_DATA_REGNO:
3964      return expand_builtin_eh_return_data_regno (arglist);
3965#endif
3966    case BUILT_IN_VARARGS_START:
3967      return expand_builtin_va_start (0, arglist);
3968    case BUILT_IN_STDARG_START:
3969      return expand_builtin_va_start (1, arglist);
3970    case BUILT_IN_VA_END:
3971      return expand_builtin_va_end (arglist);
3972    case BUILT_IN_VA_COPY:
3973      return expand_builtin_va_copy (arglist);
3974    case BUILT_IN_EXPECT:
3975      return expand_builtin_expect (arglist, target);
3976    case BUILT_IN_PREFETCH:
3977      expand_builtin_prefetch (arglist);
3978      return const0_rtx;
3979
3980
3981    default:			/* just do library call, if unknown builtin */
3982      error ("built-in function `%s' not currently supported",
3983	     IDENTIFIER_POINTER (DECL_NAME (fndecl)));
3984    }
3985
3986  /* The switch statement above can drop through to cause the function
3987     to be called normally.  */
3988  return expand_call (exp, target, ignore);
3989}
3990
3991/* Fold a call to __builtin_constant_p, if we know it will evaluate to a
3992   constant.  ARGLIST is the argument list of the call.  */
3993
3994static tree
3995fold_builtin_constant_p (arglist)
3996     tree arglist;
3997{
3998  if (arglist == 0)
3999    return 0;
4000
4001  arglist = TREE_VALUE (arglist);
4002
4003  /* We return 1 for a numeric type that's known to be a constant
4004     value at compile-time or for an aggregate type that's a
4005     literal constant.  */
4006  STRIP_NOPS (arglist);
4007
4008  /* If we know this is a constant, emit the constant of one.  */
4009  if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
4010      || (TREE_CODE (arglist) == CONSTRUCTOR
4011	  && TREE_CONSTANT (arglist))
4012      || (TREE_CODE (arglist) == ADDR_EXPR
4013	  && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
4014    return integer_one_node;
4015
4016  /* If we aren't going to be running CSE or this expression
4017     has side effects, show we don't know it to be a constant.
4018     Likewise if it's a pointer or aggregate type since in those
4019     case we only want literals, since those are only optimized
4020     when generating RTL, not later.
4021     And finally, if we are compiling an initializer, not code, we
4022     need to return a definite result now; there's not going to be any
4023     more optimization done.  */
4024  if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected
4025      || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
4026      || POINTER_TYPE_P (TREE_TYPE (arglist))
4027      || cfun == 0)
4028    return integer_zero_node;
4029
4030  return 0;
4031}
4032
4033/* Fold a call to __builtin_classify_type.  */
4034
4035static tree
4036fold_builtin_classify_type (arglist)
4037     tree arglist;
4038{
4039  if (arglist == 0)
4040    return build_int_2 (no_type_class, 0);
4041
4042  return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
4043}
4044
4045/* Used by constant folding to eliminate some builtin calls early.  EXP is
4046   the CALL_EXPR of a call to a builtin function.  */
4047
4048tree
4049fold_builtin (exp)
4050     tree exp;
4051{
4052  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4053  tree arglist = TREE_OPERAND (exp, 1);
4054  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
4055
4056  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
4057    return 0;
4058
4059  switch (fcode)
4060    {
4061    case BUILT_IN_CONSTANT_P:
4062      return fold_builtin_constant_p (arglist);
4063
4064    case BUILT_IN_CLASSIFY_TYPE:
4065      return fold_builtin_classify_type (arglist);
4066
4067    case BUILT_IN_STRLEN:
4068      if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
4069	{
4070	  tree len = c_strlen (TREE_VALUE (arglist));
4071	  if (len)
4072	    {
4073	      /* Convert from the internal "sizetype" type to "size_t".  */
4074	      if (size_type_node)
4075		len = convert (size_type_node, len);
4076	      return len;
4077	    }
4078	}
4079      break;
4080
4081    default:
4082      break;
4083    }
4084
4085  return 0;
4086}
4087
4088static tree
4089build_function_call_expr (fn, arglist)
4090     tree fn, arglist;
4091{
4092  tree call_expr;
4093
4094  call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
4095  call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
4096		     call_expr, arglist);
4097  TREE_SIDE_EFFECTS (call_expr) = 1;
4098  return fold (call_expr);
4099}
4100
4101/* This function validates the types of a function call argument list
4102   represented as a tree chain of parameters against a specified list
4103   of tree_codes.  If the last specifier is a 0, that represents an
4104   ellipses, otherwise the last specifier must be a VOID_TYPE.  */
4105
4106static int
4107validate_arglist VPARAMS ((tree arglist, ...))
4108{
4109  enum tree_code code;
4110  int res = 0;
4111
4112  VA_OPEN (ap, arglist);
4113  VA_FIXEDARG (ap, tree, arglist);
4114
4115  do {
4116    code = va_arg (ap, enum tree_code);
4117    switch (code)
4118    {
4119    case 0:
4120      /* This signifies an ellipses, any further arguments are all ok.  */
4121      res = 1;
4122      goto end;
4123    case VOID_TYPE:
4124      /* This signifies an endlink, if no arguments remain, return
4125         true, otherwise return false.  */
4126      res = arglist == 0;
4127      goto end;
4128    default:
4129      /* If no parameters remain or the parameter's code does not
4130         match the specified code, return false.  Otherwise continue
4131         checking any remaining arguments.  */
4132      if (arglist == 0 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
4133	goto end;
4134      break;
4135    }
4136    arglist = TREE_CHAIN (arglist);
4137  } while (1);
4138
4139  /* We need gotos here since we can only have one VA_CLOSE in a
4140     function.  */
4141 end: ;
4142  VA_CLOSE (ap);
4143
4144  return res;
4145}
4146
4147/* Default version of target-specific builtin setup that does nothing.  */
4148
4149void
4150default_init_builtins ()
4151{
4152}
4153
4154/* Default target-specific builtin expander that does nothing.  */
4155
4156rtx
4157default_expand_builtin (exp, target, subtarget, mode, ignore)
4158     tree exp ATTRIBUTE_UNUSED;
4159     rtx target ATTRIBUTE_UNUSED;
4160     rtx subtarget ATTRIBUTE_UNUSED;
4161     enum machine_mode mode ATTRIBUTE_UNUSED;
4162     int ignore ATTRIBUTE_UNUSED;
4163{
4164  return NULL_RTX;
4165}
4166