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