builtins.c revision 97826
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 97826 2002-06-04 18:04:27Z obrien $ */
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      /* Give up for non-constant lengths.  They are broken on at least
2200	 i386's.  */
2201      if (GET_CODE (len_rtx) != CONST_INT)
2202	return 0;
2203
2204      dest_mem = get_memory_rtx (dest);
2205      set_mem_align (dest_mem, dest_align);
2206      dest_addr = clear_storage (dest_mem, len_rtx);
2207
2208      if (dest_addr == 0)
2209	dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2210
2211      return dest_addr;
2212    }
2213}
2214
2215/* Expand expression EXP, which is a call to the bzero builtin.  Return 0
2216   if we failed the caller should emit a normal call.  */
2217
2218static rtx
2219expand_builtin_bzero (exp)
2220     tree exp;
2221{
2222  tree arglist = TREE_OPERAND (exp, 1);
2223  tree dest, size, newarglist;
2224  rtx result;
2225
2226  if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2227    return NULL_RTX;
2228
2229  dest = TREE_VALUE (arglist);
2230  size = TREE_VALUE (TREE_CHAIN (arglist));
2231
2232  /* New argument list transforming bzero(ptr x, int y) to
2233     memset(ptr x, int 0, size_t y).   This is done this way
2234     so that if it isn't expanded inline, we fallback to
2235     calling bzero instead of memset.  */
2236
2237  newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
2238  newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
2239  newarglist = tree_cons (NULL_TREE, dest, newarglist);
2240
2241  TREE_OPERAND (exp, 1) = newarglist;
2242  result = expand_builtin_memset (exp, const0_rtx, VOIDmode);
2243
2244  /* Always restore the original arguments.  */
2245  TREE_OPERAND (exp, 1) = arglist;
2246
2247  return result;
2248}
2249
2250/* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
2251   ARGLIST is the argument list for this call.  Return 0 if we failed and the
2252   caller should emit a normal call, otherwise try to get the result in
2253   TARGET, if convenient (and in mode MODE, if that's convenient).  */
2254
2255static rtx
2256expand_builtin_memcmp (exp, arglist, target, mode)
2257     tree exp ATTRIBUTE_UNUSED;
2258     tree arglist;
2259     rtx target;
2260     enum machine_mode mode;
2261{
2262  tree arg1, arg2, len;
2263  const char *p1, *p2;
2264
2265  if (!validate_arglist (arglist,
2266		      POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2267    return 0;
2268
2269  arg1 = TREE_VALUE (arglist);
2270  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2271  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2272
2273  /* If the len parameter is zero, return zero.  */
2274  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
2275    {
2276      /* Evaluate and ignore arg1 and arg2 in case they have
2277         side-effects.  */
2278      expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2279      expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2280      return const0_rtx;
2281    }
2282
2283  p1 = c_getstr (arg1);
2284  p2 = c_getstr (arg2);
2285
2286  /* If all arguments are constant, and the value of len is not greater
2287     than the lengths of arg1 and arg2, evaluate at compile-time.  */
2288  if (host_integerp (len, 1) && p1 && p2
2289      && compare_tree_int (len, strlen (p1) + 1) <= 0
2290      && compare_tree_int (len, strlen (p2) + 1) <= 0)
2291    {
2292      const int r = memcmp (p1, p2, tree_low_cst (len, 1));
2293
2294      return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2295    }
2296
2297  /* If len parameter is one, return an expression corresponding to
2298     (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
2299  if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
2300    {
2301      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2302      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2303      tree ind1 =
2304      fold (build1 (CONVERT_EXPR, integer_type_node,
2305                    build1 (INDIRECT_REF, cst_uchar_node,
2306                            build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2307      tree ind2 =
2308      fold (build1 (CONVERT_EXPR, integer_type_node,
2309                    build1 (INDIRECT_REF, cst_uchar_node,
2310                            build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2311      tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2312      return expand_expr (result, target, mode, EXPAND_NORMAL);
2313    }
2314
2315#ifdef HAVE_cmpstrsi
2316  {
2317    rtx arg1_rtx, arg2_rtx, arg3_rtx;
2318    rtx result;
2319    rtx insn;
2320
2321    int arg1_align
2322      = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2323    int arg2_align
2324      = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2325    enum machine_mode insn_mode
2326      = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
2327
2328    /* If we don't have POINTER_TYPE, call the function.  */
2329    if (arg1_align == 0 || arg2_align == 0)
2330      return 0;
2331
2332    /* Make a place to write the result of the instruction.  */
2333    result = target;
2334    if (! (result != 0
2335	   && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
2336	   && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2337      result = gen_reg_rtx (insn_mode);
2338
2339    arg1_rtx = get_memory_rtx (arg1);
2340    arg2_rtx = get_memory_rtx (arg2);
2341    arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2342    if (!HAVE_cmpstrsi)
2343      insn = NULL_RTX;
2344    else
2345      insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
2346			   GEN_INT (MIN (arg1_align, arg2_align)));
2347
2348    if (insn)
2349      emit_insn (insn);
2350    else
2351      emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
2352			       TYPE_MODE (integer_type_node), 3,
2353			       XEXP (arg1_rtx, 0), Pmode,
2354			       XEXP (arg2_rtx, 0), Pmode,
2355			       convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
2356						TREE_UNSIGNED (sizetype)),
2357			       TYPE_MODE (sizetype));
2358
2359    /* Return the value in the proper mode for this function.  */
2360    mode = TYPE_MODE (TREE_TYPE (exp));
2361    if (GET_MODE (result) == mode)
2362      return result;
2363    else if (target != 0)
2364      {
2365	convert_move (target, result, 0);
2366	return target;
2367      }
2368    else
2369      return convert_to_mode (mode, result, 0);
2370  }
2371#endif
2372
2373  return 0;
2374}
2375
2376/* Expand expression EXP, which is a call to the strcmp builtin.  Return 0
2377   if we failed the caller should emit a normal call, otherwise try to get
2378   the result in TARGET, if convenient.  */
2379
2380static rtx
2381expand_builtin_strcmp (exp, target, mode)
2382     tree exp;
2383     rtx target;
2384     enum machine_mode mode;
2385{
2386  tree arglist = TREE_OPERAND (exp, 1);
2387  tree arg1, arg2, len, len2, fn;
2388  const char *p1, *p2;
2389
2390  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2391    return 0;
2392
2393  arg1 = TREE_VALUE (arglist);
2394  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2395
2396  p1 = c_getstr (arg1);
2397  p2 = c_getstr (arg2);
2398
2399  if (p1 && p2)
2400    {
2401      const int i = strcmp (p1, p2);
2402      return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
2403    }
2404
2405  /* If either arg is "", return an expression corresponding to
2406     (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
2407  if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2408    {
2409      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2410      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2411      tree ind1 =
2412	fold (build1 (CONVERT_EXPR, integer_type_node,
2413		      build1 (INDIRECT_REF, cst_uchar_node,
2414			      build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2415      tree ind2 =
2416	fold (build1 (CONVERT_EXPR, integer_type_node,
2417		      build1 (INDIRECT_REF, cst_uchar_node,
2418			      build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2419      tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2420      return expand_expr (result, target, mode, EXPAND_NORMAL);
2421    }
2422
2423  len = c_strlen (arg1);
2424  len2 = c_strlen (arg2);
2425
2426  if (len)
2427    len = size_binop (PLUS_EXPR, ssize_int (1), len);
2428
2429  if (len2)
2430    len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
2431
2432  /* If we don't have a constant length for the first, use the length
2433     of the second, if we know it.  We don't require a constant for
2434     this case; some cost analysis could be done if both are available
2435     but neither is constant.  For now, assume they're equally cheap
2436     unless one has side effects.
2437
2438     If both strings have constant lengths, use the smaller.  This
2439     could arise if optimization results in strcpy being called with
2440     two fixed strings, or if the code was machine-generated.  We should
2441     add some code to the `memcmp' handler below to deal with such
2442     situations, someday.  */
2443
2444  if (!len || TREE_CODE (len) != INTEGER_CST)
2445    {
2446      if (len2 && !TREE_SIDE_EFFECTS (len2))
2447        len = len2;
2448      else if (len == 0)
2449        return 0;
2450    }
2451  else if (len2 && TREE_CODE (len2) == INTEGER_CST
2452           && tree_int_cst_lt (len2, len))
2453    len = len2;
2454
2455  /* If both arguments have side effects, we cannot optimize.  */
2456  if (TREE_SIDE_EFFECTS (len))
2457    return 0;
2458
2459  fn = built_in_decls[BUILT_IN_MEMCMP];
2460  if (!fn)
2461    return 0;
2462
2463  chainon (arglist, build_tree_list (NULL_TREE, len));
2464  return expand_expr (build_function_call_expr (fn, arglist),
2465                      target, mode, EXPAND_NORMAL);
2466}
2467
2468/* Expand expression EXP, which is a call to the strncmp builtin.  Return 0
2469   if we failed the caller should emit a normal call, otherwise try to get
2470   the result in TARGET, if convenient.  */
2471
2472static rtx
2473expand_builtin_strncmp (exp, target, mode)
2474     tree exp;
2475     rtx target;
2476     enum machine_mode mode;
2477{
2478  tree arglist = TREE_OPERAND (exp, 1);
2479  tree fn, newarglist, len = 0;
2480  tree arg1, arg2, arg3;
2481  const char *p1, *p2;
2482
2483  if (!validate_arglist (arglist,
2484			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2485    return 0;
2486
2487  arg1 = TREE_VALUE (arglist);
2488  arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2489  arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2490
2491  /* If the len parameter is zero, return zero.  */
2492  if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0)
2493  {
2494    /* Evaluate and ignore arg1 and arg2 in case they have
2495       side-effects.  */
2496    expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2497    expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2498    return const0_rtx;
2499  }
2500
2501  p1 = c_getstr (arg1);
2502  p2 = c_getstr (arg2);
2503
2504  /* If all arguments are constant, evaluate at compile-time.  */
2505  if (host_integerp (arg3, 1) && p1 && p2)
2506  {
2507    const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
2508    return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2509  }
2510
2511  /* If len == 1 or (either string parameter is "" and (len >= 1)),
2512      return (*(const u_char*)arg1 - *(const u_char*)arg2).  */
2513  if (host_integerp (arg3, 1)
2514      && (tree_low_cst (arg3, 1) == 1
2515	  || (tree_low_cst (arg3, 1) > 1
2516	      && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
2517    {
2518      tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2519      tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2520      tree ind1 =
2521	fold (build1 (CONVERT_EXPR, integer_type_node,
2522		      build1 (INDIRECT_REF, cst_uchar_node,
2523			      build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2524      tree ind2 =
2525	fold (build1 (CONVERT_EXPR, integer_type_node,
2526		      build1 (INDIRECT_REF, cst_uchar_node,
2527			      build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2528      tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2529      return expand_expr (result, target, mode, EXPAND_NORMAL);
2530    }
2531
2532  /* If c_strlen can determine an expression for one of the string
2533     lengths, and it doesn't have side effects, then call
2534     expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3).  */
2535
2536  /* Perhaps one of the strings is really constant, if so prefer
2537     that constant length over the other string's length.  */
2538  if (p1)
2539    len = c_strlen (arg1);
2540  else if (p2)
2541    len = c_strlen (arg2);
2542
2543  /* If we still don't have a len, try either string arg as long
2544     as they don't have side effects.  */
2545  if (!len && !TREE_SIDE_EFFECTS (arg1))
2546    len = c_strlen (arg1);
2547  if (!len && !TREE_SIDE_EFFECTS (arg2))
2548    len = c_strlen (arg2);
2549  /* If we still don't have a length, punt.  */
2550  if (!len)
2551    return 0;
2552
2553  fn = built_in_decls[BUILT_IN_MEMCMP];
2554  if (!fn)
2555    return 0;
2556
2557  /* Add one to the string length.  */
2558  len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
2559
2560  /* The actual new length parameter is MIN(len,arg3).  */
2561  len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
2562
2563  newarglist = build_tree_list (NULL_TREE, len);
2564  newarglist = tree_cons (NULL_TREE, arg2, newarglist);
2565  newarglist = tree_cons (NULL_TREE, arg1, newarglist);
2566  return expand_expr (build_function_call_expr (fn, newarglist),
2567                      target, mode, EXPAND_NORMAL);
2568}
2569
2570/* Expand expression EXP, which is a call to the strcat builtin.
2571   Return 0 if we failed the caller should emit a normal call,
2572   otherwise try to get the result in TARGET, if convenient.  */
2573
2574static rtx
2575expand_builtin_strcat (arglist, target, mode)
2576     tree arglist;
2577     rtx target;
2578     enum machine_mode mode;
2579{
2580  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2581    return 0;
2582  else
2583    {
2584      tree dst = TREE_VALUE (arglist),
2585	src = TREE_VALUE (TREE_CHAIN (arglist));
2586      const char *p = c_getstr (src);
2587
2588      /* If the string length is zero, return the dst parameter.  */
2589      if (p && *p == '\0')
2590	return expand_expr (dst, target, mode, EXPAND_NORMAL);
2591
2592      return 0;
2593    }
2594}
2595
2596/* Expand expression EXP, which is a call to the strncat builtin.
2597   Return 0 if we failed the caller should emit a normal call,
2598   otherwise try to get the result in TARGET, if convenient.  */
2599
2600static rtx
2601expand_builtin_strncat (arglist, target, mode)
2602     tree arglist;
2603     rtx target;
2604     enum machine_mode mode;
2605{
2606  if (!validate_arglist (arglist,
2607			 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2608    return 0;
2609  else
2610    {
2611      tree dst = TREE_VALUE (arglist),
2612	src = TREE_VALUE (TREE_CHAIN (arglist)),
2613	len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2614      const char *p = c_getstr (src);
2615
2616      /* If the requested length is zero, or the src parameter string
2617          length is zero, return the dst parameter.  */
2618      if (integer_zerop (len) || (p && *p == '\0'))
2619        {
2620	  /* Evaluate and ignore the src and len parameters in case
2621	     they have side-effects.  */
2622	  expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2623	  expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2624	  return expand_expr (dst, target, mode, EXPAND_NORMAL);
2625	}
2626
2627      /* If the requested len is greater than or equal to the string
2628         length, call strcat.  */
2629      if (TREE_CODE (len) == INTEGER_CST && p
2630	  && compare_tree_int (len, strlen (p)) >= 0)
2631        {
2632	  tree newarglist
2633	    = tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
2634	  tree fn = built_in_decls[BUILT_IN_STRCAT];
2635
2636	  /* If the replacement _DECL isn't initialized, don't do the
2637	     transformation.  */
2638	  if (!fn)
2639	    return 0;
2640
2641	  return expand_expr (build_function_call_expr (fn, newarglist),
2642			      target, mode, EXPAND_NORMAL);
2643	}
2644      return 0;
2645    }
2646}
2647
2648/* Expand expression EXP, which is a call to the strspn builtin.
2649   Return 0 if we failed the caller should emit a normal call,
2650   otherwise try to get the result in TARGET, if convenient.  */
2651
2652static rtx
2653expand_builtin_strspn (arglist, target, mode)
2654     tree arglist;
2655     rtx target;
2656     enum machine_mode mode;
2657{
2658  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2659    return 0;
2660  else
2661    {
2662      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2663      const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2664
2665      /* If both arguments are constants, evaluate at compile-time.  */
2666      if (p1 && p2)
2667        {
2668	  const size_t r = strspn (p1, p2);
2669	  return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2670	}
2671
2672      /* If either argument is "", return 0.  */
2673      if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2674        {
2675	  /* Evaluate and ignore both arguments in case either one has
2676	     side-effects.  */
2677	  expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2678	  expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2679	  return const0_rtx;
2680	}
2681      return 0;
2682    }
2683}
2684
2685/* Expand expression EXP, which is a call to the strcspn builtin.
2686   Return 0 if we failed the caller should emit a normal call,
2687   otherwise try to get the result in TARGET, if convenient.  */
2688
2689static rtx
2690expand_builtin_strcspn (arglist, target, mode)
2691     tree arglist;
2692     rtx target;
2693     enum machine_mode mode;
2694{
2695  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2696    return 0;
2697  else
2698    {
2699      tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2700      const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2701
2702      /* If both arguments are constants, evaluate at compile-time.  */
2703      if (p1 && p2)
2704        {
2705	  const size_t r = strcspn (p1, p2);
2706	  return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2707	}
2708
2709      /* If the first argument is "", return 0.  */
2710      if (p1 && *p1 == '\0')
2711        {
2712	  /* Evaluate and ignore argument s2 in case it has
2713	     side-effects.  */
2714	  expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2715	  return const0_rtx;
2716	}
2717
2718      /* If the second argument is "", return __builtin_strlen(s1).  */
2719      if (p2 && *p2 == '\0')
2720        {
2721	  tree newarglist = build_tree_list (NULL_TREE, s1),
2722	    fn = built_in_decls[BUILT_IN_STRLEN];
2723
2724	  /* If the replacement _DECL isn't initialized, don't do the
2725	     transformation.  */
2726	  if (!fn)
2727	    return 0;
2728
2729	  return expand_expr (build_function_call_expr (fn, newarglist),
2730			      target, mode, EXPAND_NORMAL);
2731	}
2732      return 0;
2733    }
2734}
2735
2736/* Expand a call to __builtin_saveregs, generating the result in TARGET,
2737   if that's convenient.  */
2738
2739rtx
2740expand_builtin_saveregs ()
2741{
2742  rtx val, seq;
2743
2744  /* Don't do __builtin_saveregs more than once in a function.
2745     Save the result of the first call and reuse it.  */
2746  if (saveregs_value != 0)
2747    return saveregs_value;
2748
2749  /* When this function is called, it means that registers must be
2750     saved on entry to this function.  So we migrate the call to the
2751     first insn of this function.  */
2752
2753  start_sequence ();
2754
2755#ifdef EXPAND_BUILTIN_SAVEREGS
2756  /* Do whatever the machine needs done in this case.  */
2757  val = EXPAND_BUILTIN_SAVEREGS ();
2758#else
2759  /* ??? We used to try and build up a call to the out of line function,
2760     guessing about what registers needed saving etc.  This became much
2761     harder with __builtin_va_start, since we don't have a tree for a
2762     call to __builtin_saveregs to fall back on.  There was exactly one
2763     port (i860) that used this code, and I'm unconvinced it could actually
2764     handle the general case.  So we no longer try to handle anything
2765     weird and make the backend absorb the evil.  */
2766
2767  error ("__builtin_saveregs not supported by this target");
2768  val = const0_rtx;
2769#endif
2770
2771  seq = get_insns ();
2772  end_sequence ();
2773
2774  saveregs_value = val;
2775
2776  /* Put the sequence after the NOTE that starts the function.  If this
2777     is inside a SEQUENCE, make the outer-level insn chain current, so
2778     the code is placed at the start of the function.  */
2779  push_topmost_sequence ();
2780  emit_insns_after (seq, get_insns ());
2781  pop_topmost_sequence ();
2782
2783  return val;
2784}
2785
2786/* __builtin_args_info (N) returns word N of the arg space info
2787   for the current function.  The number and meanings of words
2788   is controlled by the definition of CUMULATIVE_ARGS.  */
2789
2790static rtx
2791expand_builtin_args_info (exp)
2792     tree exp;
2793{
2794  tree arglist = TREE_OPERAND (exp, 1);
2795  int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
2796  int *word_ptr = (int *) &current_function_args_info;
2797#if 0
2798  /* These are used by the code below that is if 0'ed away */
2799  int i;
2800  tree type, elts, result;
2801#endif
2802
2803  if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
2804    abort ();
2805
2806  if (arglist != 0)
2807    {
2808      if (!host_integerp (TREE_VALUE (arglist), 0))
2809	error ("argument of `__builtin_args_info' must be constant");
2810      else
2811	{
2812	  HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
2813
2814	  if (wordnum < 0 || wordnum >= nwords)
2815	    error ("argument of `__builtin_args_info' out of range");
2816	  else
2817	    return GEN_INT (word_ptr[wordnum]);
2818	}
2819    }
2820  else
2821    error ("missing argument in `__builtin_args_info'");
2822
2823  return const0_rtx;
2824
2825#if 0
2826  for (i = 0; i < nwords; i++)
2827    elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
2828
2829  type = build_array_type (integer_type_node,
2830			   build_index_type (build_int_2 (nwords, 0)));
2831  result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
2832  TREE_CONSTANT (result) = 1;
2833  TREE_STATIC (result) = 1;
2834  result = build1 (INDIRECT_REF, build_pointer_type (type), result);
2835  TREE_CONSTANT (result) = 1;
2836  return expand_expr (result, NULL_RTX, VOIDmode, 0);
2837#endif
2838}
2839
2840/* Expand ARGLIST, from a call to __builtin_next_arg.  */
2841
2842static rtx
2843expand_builtin_next_arg (arglist)
2844     tree arglist;
2845{
2846  tree fntype = TREE_TYPE (current_function_decl);
2847
2848  if ((TYPE_ARG_TYPES (fntype) == 0
2849       || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2850	   == void_type_node))
2851      && ! current_function_varargs)
2852    {
2853      error ("`va_start' used in function with fixed args");
2854      return const0_rtx;
2855    }
2856
2857  if (arglist)
2858    {
2859      tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
2860      tree arg = TREE_VALUE (arglist);
2861
2862      /* Strip off all nops for the sake of the comparison.  This
2863	 is not quite the same as STRIP_NOPS.  It does more.
2864	 We must also strip off INDIRECT_EXPR for C++ reference
2865	 parameters.  */
2866      while (TREE_CODE (arg) == NOP_EXPR
2867	     || TREE_CODE (arg) == CONVERT_EXPR
2868	     || TREE_CODE (arg) == NON_LVALUE_EXPR
2869	     || TREE_CODE (arg) == INDIRECT_REF)
2870	arg = TREE_OPERAND (arg, 0);
2871      if (arg != last_parm)
2872	warning ("second parameter of `va_start' not last named argument");
2873    }
2874  else if (! current_function_varargs)
2875    /* Evidently an out of date version of <stdarg.h>; can't validate
2876       va_start's second argument, but can still work as intended.  */
2877    warning ("`__builtin_next_arg' called without an argument");
2878
2879  return expand_binop (Pmode, add_optab,
2880		       current_function_internal_arg_pointer,
2881		       current_function_arg_offset_rtx,
2882		       NULL_RTX, 0, OPTAB_LIB_WIDEN);
2883}
2884
2885/* Make it easier for the backends by protecting the valist argument
2886   from multiple evaluations.  */
2887
2888static tree
2889stabilize_va_list (valist, needs_lvalue)
2890     tree valist;
2891     int needs_lvalue;
2892{
2893  if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
2894    {
2895      if (TREE_SIDE_EFFECTS (valist))
2896	valist = save_expr (valist);
2897
2898      /* For this case, the backends will be expecting a pointer to
2899	 TREE_TYPE (va_list_type_node), but it's possible we've
2900	 actually been given an array (an actual va_list_type_node).
2901	 So fix it.  */
2902      if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
2903	{
2904	  tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
2905	  tree p2 = build_pointer_type (va_list_type_node);
2906
2907	  valist = build1 (ADDR_EXPR, p2, valist);
2908	  valist = fold (build1 (NOP_EXPR, p1, valist));
2909	}
2910    }
2911  else
2912    {
2913      tree pt;
2914
2915      if (! needs_lvalue)
2916	{
2917	  if (! TREE_SIDE_EFFECTS (valist))
2918	    return valist;
2919
2920	  pt = build_pointer_type (va_list_type_node);
2921	  valist = fold (build1 (ADDR_EXPR, pt, valist));
2922	  TREE_SIDE_EFFECTS (valist) = 1;
2923	}
2924
2925      if (TREE_SIDE_EFFECTS (valist))
2926	valist = save_expr (valist);
2927      valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
2928			     valist));
2929    }
2930
2931  return valist;
2932}
2933
2934/* The "standard" implementation of va_start: just assign `nextarg' to
2935   the variable.  */
2936
2937void
2938std_expand_builtin_va_start (stdarg_p, valist, nextarg)
2939     int stdarg_p;
2940     tree valist;
2941     rtx nextarg;
2942{
2943  tree t;
2944
2945  if (! stdarg_p)
2946    {
2947      /* The dummy named parameter is declared as a 'word' sized
2948	 object, but if a 'word' is smaller than an 'int', it would
2949	 have been promoted to int when it was added to the arglist.  */
2950      int align = PARM_BOUNDARY / BITS_PER_UNIT;
2951      int size = MAX (UNITS_PER_WORD,
2952		      GET_MODE_SIZE (TYPE_MODE (integer_type_node)));
2953      int offset = ((size + align - 1) / align) * align;
2954      nextarg = plus_constant (nextarg, -offset);
2955    }
2956
2957  t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2958	     make_tree (ptr_type_node, nextarg));
2959  TREE_SIDE_EFFECTS (t) = 1;
2960
2961  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2962}
2963
2964/* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
2965   __builtin_varargs_va_start, depending on STDARG_P.  */
2966
2967static rtx
2968expand_builtin_va_start (stdarg_p, arglist)
2969     int stdarg_p;
2970     tree arglist;
2971{
2972  rtx nextarg;
2973  tree chain = arglist, valist;
2974
2975  if (stdarg_p)
2976    nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
2977  else
2978    nextarg = expand_builtin_next_arg (NULL_TREE);
2979
2980  if (TREE_CHAIN (chain))
2981    error ("too many arguments to function `va_start'");
2982
2983  valist = stabilize_va_list (TREE_VALUE (arglist), 1);
2984
2985#ifdef EXPAND_BUILTIN_VA_START
2986  EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
2987#else
2988  std_expand_builtin_va_start (stdarg_p, valist, nextarg);
2989#endif
2990
2991  return const0_rtx;
2992}
2993
2994/* The "standard" implementation of va_arg: read the value from the
2995   current (padded) address and increment by the (padded) size.  */
2996
2997rtx
2998std_expand_builtin_va_arg (valist, type)
2999     tree valist, type;
3000{
3001  tree addr_tree, t, type_size = NULL;
3002  tree align, alignm1;
3003  tree rounded_size;
3004  rtx addr;
3005
3006  /* Compute the rounded size of the type.  */
3007  align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
3008  alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
3009  if (type == error_mark_node
3010      || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
3011      || TREE_OVERFLOW (type_size))
3012    rounded_size = size_zero_node;
3013  else
3014    rounded_size = fold (build (MULT_EXPR, sizetype,
3015				fold (build (TRUNC_DIV_EXPR, sizetype,
3016					     fold (build (PLUS_EXPR, sizetype,
3017							  type_size, alignm1)),
3018					     align)),
3019				align));
3020
3021  /* Get AP.  */
3022  addr_tree = valist;
3023  if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size))
3024    {
3025      /* Small args are padded downward.  */
3026      addr_tree = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
3027			       fold (build (COND_EXPR, sizetype,
3028					    fold (build (GT_EXPR, sizetype,
3029							 rounded_size,
3030							 align)),
3031					    size_zero_node,
3032					    fold (build (MINUS_EXPR, sizetype,
3033							 rounded_size,
3034							 type_size))))));
3035    }
3036
3037  addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
3038  addr = copy_to_reg (addr);
3039
3040  /* Compute new value for AP.  */
3041  if (! integer_zerop (rounded_size))
3042    {
3043      t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
3044		 build (PLUS_EXPR, TREE_TYPE (valist), valist,
3045			rounded_size));
3046      TREE_SIDE_EFFECTS (t) = 1;
3047      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3048    }
3049
3050  return addr;
3051}
3052
3053/* Expand __builtin_va_arg, which is not really a builtin function, but
3054   a very special sort of operator.  */
3055
3056rtx
3057expand_builtin_va_arg (valist, type)
3058     tree valist, type;
3059{
3060  rtx addr, result;
3061  tree promoted_type, want_va_type, have_va_type;
3062
3063  /* Verify that valist is of the proper type.  */
3064
3065  want_va_type = va_list_type_node;
3066  have_va_type = TREE_TYPE (valist);
3067  if (TREE_CODE (want_va_type) == ARRAY_TYPE)
3068    {
3069      /* If va_list is an array type, the argument may have decayed
3070	 to a pointer type, e.g. by being passed to another function.
3071         In that case, unwrap both types so that we can compare the
3072	 underlying records.  */
3073      if (TREE_CODE (have_va_type) == ARRAY_TYPE
3074	  || TREE_CODE (have_va_type) == POINTER_TYPE)
3075	{
3076	  want_va_type = TREE_TYPE (want_va_type);
3077	  have_va_type = TREE_TYPE (have_va_type);
3078	}
3079    }
3080  if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
3081    {
3082      error ("first argument to `va_arg' not of type `va_list'");
3083      addr = const0_rtx;
3084    }
3085
3086  /* Generate a diagnostic for requesting data of a type that cannot
3087     be passed through `...' due to type promotion at the call site.  */
3088  else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
3089    {
3090      const char *name = "<anonymous type>", *pname = 0;
3091      static bool gave_help;
3092
3093      if (TYPE_NAME (type))
3094	{
3095	  if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
3096	    name = IDENTIFIER_POINTER (TYPE_NAME (type));
3097	  else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
3098		   && DECL_NAME (TYPE_NAME (type)))
3099	    name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
3100	}
3101      if (TYPE_NAME (promoted_type))
3102	{
3103	  if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
3104	    pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
3105	  else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
3106		   && DECL_NAME (TYPE_NAME (promoted_type)))
3107	    pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
3108	}
3109
3110      /* Unfortunately, this is merely undefined, rather than a constraint
3111	 violation, so we cannot make this an error.  If this call is never
3112	 executed, the program is still strictly conforming.  */
3113      warning ("`%s' is promoted to `%s' when passed through `...'",
3114	       name, pname);
3115      if (! gave_help)
3116	{
3117	  gave_help = true;
3118	  warning ("(so you should pass `%s' not `%s' to `va_arg')",
3119		   pname, name);
3120	}
3121
3122      /* We can, however, treat "undefined" any way we please.
3123	 Call abort to encourage the user to fix the program.  */
3124      expand_builtin_trap ();
3125
3126      /* This is dead code, but go ahead and finish so that the
3127	 mode of the result comes out right.  */
3128      addr = const0_rtx;
3129    }
3130  else
3131    {
3132      /* Make it easier for the backends by protecting the valist argument
3133         from multiple evaluations.  */
3134      valist = stabilize_va_list (valist, 0);
3135
3136#ifdef EXPAND_BUILTIN_VA_ARG
3137      addr = EXPAND_BUILTIN_VA_ARG (valist, type);
3138#else
3139      addr = std_expand_builtin_va_arg (valist, type);
3140#endif
3141    }
3142
3143#ifdef POINTERS_EXTEND_UNSIGNED
3144  if (GET_MODE (addr) != Pmode)
3145    addr = convert_memory_address (Pmode, addr);
3146#endif
3147
3148  result = gen_rtx_MEM (TYPE_MODE (type), addr);
3149  set_mem_alias_set (result, get_varargs_alias_set ());
3150
3151  return result;
3152}
3153
3154/* Expand ARGLIST, from a call to __builtin_va_end.  */
3155
3156static rtx
3157expand_builtin_va_end (arglist)
3158     tree arglist;
3159{
3160  tree valist = TREE_VALUE (arglist);
3161
3162#ifdef EXPAND_BUILTIN_VA_END
3163  valist = stabilize_va_list (valist, 0);
3164  EXPAND_BUILTIN_VA_END(arglist);
3165#else
3166  /* Evaluate for side effects, if needed.  I hate macros that don't
3167     do that.  */
3168  if (TREE_SIDE_EFFECTS (valist))
3169    expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
3170#endif
3171
3172  return const0_rtx;
3173}
3174
3175/* Expand ARGLIST, from a call to __builtin_va_copy.  We do this as a
3176   builtin rather than just as an assignment in stdarg.h because of the
3177   nastiness of array-type va_list types.  */
3178
3179static rtx
3180expand_builtin_va_copy (arglist)
3181     tree arglist;
3182{
3183  tree dst, src, t;
3184
3185  dst = TREE_VALUE (arglist);
3186  src = TREE_VALUE (TREE_CHAIN (arglist));
3187
3188  dst = stabilize_va_list (dst, 1);
3189  src = stabilize_va_list (src, 0);
3190
3191  if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
3192    {
3193      t = build (MODIFY_EXPR, va_list_type_node, dst, src);
3194      TREE_SIDE_EFFECTS (t) = 1;
3195      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3196    }
3197  else
3198    {
3199      rtx dstb, srcb, size;
3200
3201      /* Evaluate to pointers.  */
3202      dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
3203      srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
3204      size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
3205			  VOIDmode, EXPAND_NORMAL);
3206
3207#ifdef POINTERS_EXTEND_UNSIGNED
3208      if (GET_MODE (dstb) != Pmode)
3209	dstb = convert_memory_address (Pmode, dstb);
3210
3211      if (GET_MODE (srcb) != Pmode)
3212	srcb = convert_memory_address (Pmode, srcb);
3213#endif
3214
3215      /* "Dereference" to BLKmode memories.  */
3216      dstb = gen_rtx_MEM (BLKmode, dstb);
3217      set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst))));
3218      set_mem_align (dstb, TYPE_ALIGN (va_list_type_node));
3219      srcb = gen_rtx_MEM (BLKmode, srcb);
3220      set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src))));
3221      set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
3222
3223      /* Copy.  */
3224      emit_block_move (dstb, srcb, size);
3225    }
3226
3227  return const0_rtx;
3228}
3229
3230/* Expand a call to one of the builtin functions __builtin_frame_address or
3231   __builtin_return_address.  */
3232
3233static rtx
3234expand_builtin_frame_address (exp)
3235     tree exp;
3236{
3237  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3238  tree arglist = TREE_OPERAND (exp, 1);
3239
3240  /* The argument must be a nonnegative integer constant.
3241     It counts the number of frames to scan up the stack.
3242     The value is the return address saved in that frame.  */
3243  if (arglist == 0)
3244    /* Warning about missing arg was already issued.  */
3245    return const0_rtx;
3246  else if (! host_integerp (TREE_VALUE (arglist), 1))
3247    {
3248      if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3249	error ("invalid arg to `__builtin_frame_address'");
3250      else
3251	error ("invalid arg to `__builtin_return_address'");
3252      return const0_rtx;
3253    }
3254  else
3255    {
3256      rtx tem
3257	= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
3258				      tree_low_cst (TREE_VALUE (arglist), 1),
3259				      hard_frame_pointer_rtx);
3260
3261      /* Some ports cannot access arbitrary stack frames.  */
3262      if (tem == NULL)
3263	{
3264	  if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3265	    warning ("unsupported arg to `__builtin_frame_address'");
3266	  else
3267	    warning ("unsupported arg to `__builtin_return_address'");
3268	  return const0_rtx;
3269	}
3270
3271      /* For __builtin_frame_address, return what we've got.  */
3272      if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3273	return tem;
3274
3275      if (GET_CODE (tem) != REG
3276	  && ! CONSTANT_P (tem))
3277	tem = copy_to_mode_reg (Pmode, tem);
3278      return tem;
3279    }
3280}
3281
3282/* Expand a call to the alloca builtin, with arguments ARGLIST.  Return 0 if
3283   we failed and the caller should emit a normal call, otherwise try to get
3284   the result in TARGET, if convenient.  */
3285
3286static rtx
3287expand_builtin_alloca (arglist, target)
3288     tree arglist;
3289     rtx target;
3290{
3291  rtx op0;
3292  rtx result;
3293
3294  if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3295    return 0;
3296
3297  /* Compute the argument.  */
3298  op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
3299
3300  /* Allocate the desired space.  */
3301  result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
3302
3303#ifdef POINTERS_EXTEND_UNSIGNED
3304  if (GET_MODE (result) != ptr_mode)
3305    result = convert_memory_address (ptr_mode, result);
3306#endif
3307
3308  return result;
3309}
3310
3311/* Expand a call to the ffs builtin.  The arguments are in ARGLIST.
3312   Return 0 if a normal call should be emitted rather than expanding the
3313   function in-line.  If convenient, the result should be placed in TARGET.
3314   SUBTARGET may be used as the target for computing one of EXP's operands.  */
3315
3316static rtx
3317expand_builtin_ffs (arglist, target, subtarget)
3318     tree arglist;
3319     rtx target, subtarget;
3320{
3321  rtx op0;
3322  if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3323    return 0;
3324
3325  /* Compute the argument.  */
3326  op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
3327  /* Compute ffs, into TARGET if possible.
3328     Set TARGET to wherever the result comes back.  */
3329  target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
3330			ffs_optab, op0, target, 1);
3331  if (target == 0)
3332    abort ();
3333  return target;
3334}
3335
3336/* If the string passed to fputs is a constant and is one character
3337   long, we attempt to transform this call into __builtin_fputc().  */
3338
3339static rtx
3340expand_builtin_fputs (arglist, ignore, unlocked)
3341     tree arglist;
3342     int ignore;
3343     int unlocked;
3344{
3345  tree len, fn;
3346  tree fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
3347    : built_in_decls[BUILT_IN_FPUTC];
3348  tree fn_fwrite = unlocked ? built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
3349    : built_in_decls[BUILT_IN_FWRITE];
3350
3351  /* If the return value is used, or the replacement _DECL isn't
3352     initialized, don't do the transformation.  */
3353  if (!ignore || !fn_fputc || !fn_fwrite)
3354    return 0;
3355
3356  /* Verify the arguments in the original call.  */
3357  if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
3358    return 0;
3359
3360  /* Get the length of the string passed to fputs.  If the length
3361     can't be determined, punt.  */
3362  if (!(len = c_strlen (TREE_VALUE (arglist)))
3363      || TREE_CODE (len) != INTEGER_CST)
3364    return 0;
3365
3366  switch (compare_tree_int (len, 1))
3367    {
3368    case -1: /* length is 0, delete the call entirely .  */
3369      {
3370	/* Evaluate and ignore the argument in case it has
3371           side-effects.  */
3372	expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
3373		     VOIDmode, EXPAND_NORMAL);
3374	return const0_rtx;
3375      }
3376    case 0: /* length is 1, call fputc.  */
3377      {
3378	const char *p = c_getstr (TREE_VALUE (arglist));
3379
3380	if (p != NULL)
3381	  {
3382	    /* New argument list transforming fputs(string, stream) to
3383	       fputc(string[0], stream).  */
3384	    arglist =
3385	      build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3386	    arglist =
3387	      tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
3388	    fn = fn_fputc;
3389	    break;
3390	  }
3391      }
3392      /* FALLTHROUGH */
3393    case 1: /* length is greater than 1, call fwrite.  */
3394      {
3395	tree string_arg = TREE_VALUE (arglist);
3396
3397	/* New argument list transforming fputs(string, stream) to
3398	   fwrite(string, 1, len, stream).  */
3399	arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3400	arglist = tree_cons (NULL_TREE, len, arglist);
3401	arglist = tree_cons (NULL_TREE, size_one_node, arglist);
3402	arglist = tree_cons (NULL_TREE, string_arg, arglist);
3403	fn = fn_fwrite;
3404	break;
3405      }
3406    default:
3407      abort ();
3408    }
3409
3410  return expand_expr (build_function_call_expr (fn, arglist),
3411		      (ignore ? const0_rtx : NULL_RTX),
3412		      VOIDmode, EXPAND_NORMAL);
3413}
3414
3415/* Expand a call to __builtin_expect.  We return our argument and emit a
3416   NOTE_INSN_EXPECTED_VALUE note.  This is the expansion of __builtin_expect in
3417   a non-jump context.  */
3418
3419static rtx
3420expand_builtin_expect (arglist, target)
3421     tree arglist;
3422     rtx target;
3423{
3424  tree exp, c;
3425  rtx note, rtx_c;
3426
3427  if (arglist == NULL_TREE
3428      || TREE_CHAIN (arglist) == NULL_TREE)
3429    return const0_rtx;
3430  exp = TREE_VALUE (arglist);
3431  c = TREE_VALUE (TREE_CHAIN (arglist));
3432
3433  if (TREE_CODE (c) != INTEGER_CST)
3434    {
3435      error ("second arg to `__builtin_expect' must be a constant");
3436      c = integer_zero_node;
3437    }
3438
3439  target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
3440
3441  /* Don't bother with expected value notes for integral constants.  */
3442  if (GET_CODE (target) != CONST_INT)
3443    {
3444      /* We do need to force this into a register so that we can be
3445	 moderately sure to be able to correctly interpret the branch
3446	 condition later.  */
3447      target = force_reg (GET_MODE (target), target);
3448
3449      rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
3450
3451      note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
3452      NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
3453    }
3454
3455  return target;
3456}
3457
3458/* Like expand_builtin_expect, except do this in a jump context.  This is
3459   called from do_jump if the conditional is a __builtin_expect.  Return either
3460   a SEQUENCE of insns to emit the jump or NULL if we cannot optimize
3461   __builtin_expect.  We need to optimize this at jump time so that machines
3462   like the PowerPC don't turn the test into a SCC operation, and then jump
3463   based on the test being 0/1.  */
3464
3465rtx
3466expand_builtin_expect_jump (exp, if_false_label, if_true_label)
3467     tree exp;
3468     rtx if_false_label;
3469     rtx if_true_label;
3470{
3471  tree arglist = TREE_OPERAND (exp, 1);
3472  tree arg0 = TREE_VALUE (arglist);
3473  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
3474  rtx ret = NULL_RTX;
3475
3476  /* Only handle __builtin_expect (test, 0) and
3477     __builtin_expect (test, 1).  */
3478  if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
3479      && (integer_zerop (arg1) || integer_onep (arg1)))
3480    {
3481      int j;
3482      int num_jumps = 0;
3483
3484      /* If we fail to locate an appropriate conditional jump, we'll
3485	 fall back to normal evaluation.  Ensure that the expression
3486	 can be re-evaluated.  */
3487      switch (unsafe_for_reeval (arg0))
3488	{
3489	case 0: /* Safe.  */
3490	  break;
3491
3492	case 1: /* Mildly unsafe.  */
3493	  arg0 = unsave_expr (arg0);
3494	  break;
3495
3496	case 2: /* Wildly unsafe.  */
3497	  return NULL_RTX;
3498	}
3499
3500      /* Expand the jump insns.  */
3501      start_sequence ();
3502      do_jump (arg0, if_false_label, if_true_label);
3503      ret = gen_sequence ();
3504      end_sequence ();
3505
3506      /* Now that the __builtin_expect has been validated, go through and add
3507	 the expect's to each of the conditional jumps.  If we run into an
3508	 error, just give up and generate the 'safe' code of doing a SCC
3509	 operation and then doing a branch on that.  */
3510      for (j = 0; j < XVECLEN (ret, 0); j++)
3511	{
3512	  rtx insn = XVECEXP (ret, 0, j);
3513	  rtx pattern;
3514
3515	  if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn)
3516	      && (pattern = pc_set (insn)) != NULL_RTX)
3517	    {
3518	      rtx ifelse = SET_SRC (pattern);
3519	      rtx label;
3520	      int taken;
3521
3522	      if (GET_CODE (ifelse) != IF_THEN_ELSE)
3523		continue;
3524
3525	      if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF)
3526		{
3527		  taken = 1;
3528		  label = XEXP (XEXP (ifelse, 1), 0);
3529		}
3530	      /* An inverted jump reverses the probabilities.  */
3531	      else if (GET_CODE (XEXP (ifelse, 2)) == LABEL_REF)
3532		{
3533		  taken = 0;
3534		  label = XEXP (XEXP (ifelse, 2), 0);
3535		}
3536	      /* We shouldn't have to worry about conditional returns during
3537		 the expansion stage, but handle it gracefully anyway.  */
3538	      else if (GET_CODE (XEXP (ifelse, 1)) == RETURN)
3539		{
3540		  taken = 1;
3541		  label = NULL_RTX;
3542		}
3543	      /* An inverted return reverses the probabilities.  */
3544	      else if (GET_CODE (XEXP (ifelse, 2)) == RETURN)
3545		{
3546		  taken = 0;
3547		  label = NULL_RTX;
3548		}
3549	      else
3550		continue;
3551
3552	      /* If the test is expected to fail, reverse the
3553		 probabilities.  */
3554	      if (integer_zerop (arg1))
3555		taken = 1 - taken;
3556
3557	      /* If we are jumping to the false label, reverse the
3558		 probabilities.  */
3559	      if (label == NULL_RTX)
3560		;		/* conditional return */
3561	      else if (label == if_false_label)
3562		taken = 1 - taken;
3563	      else if (label != if_true_label)
3564		continue;
3565
3566	      num_jumps++;
3567	      predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
3568	    }
3569	}
3570
3571      /* If no jumps were modified, fail and do __builtin_expect the normal
3572	 way.  */
3573      if (num_jumps == 0)
3574	ret = NULL_RTX;
3575    }
3576
3577  return ret;
3578}
3579
3580void
3581expand_builtin_trap ()
3582{
3583#ifdef HAVE_trap
3584  if (HAVE_trap)
3585    emit_insn (gen_trap ());
3586  else
3587#endif
3588    emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
3589  emit_barrier ();
3590}
3591
3592/* Expand an expression EXP that calls a built-in function,
3593   with result going to TARGET if that's convenient
3594   (and in mode MODE if that's convenient).
3595   SUBTARGET may be used as the target for computing one of EXP's operands.
3596   IGNORE is nonzero if the value is to be ignored.  */
3597
3598rtx
3599expand_builtin (exp, target, subtarget, mode, ignore)
3600     tree exp;
3601     rtx target;
3602     rtx subtarget;
3603     enum machine_mode mode;
3604     int ignore;
3605{
3606  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3607  tree arglist = TREE_OPERAND (exp, 1);
3608  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
3609
3610  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
3611    return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore);
3612
3613  /* When not optimizing, generate calls to library functions for a certain
3614     set of builtins.  */
3615  if (!optimize && !CALLED_AS_BUILT_IN (fndecl))
3616    switch (fcode)
3617      {
3618      case BUILT_IN_SIN:
3619      case BUILT_IN_COS:
3620      case BUILT_IN_SQRT:
3621      case BUILT_IN_SQRTF:
3622      case BUILT_IN_SQRTL:
3623      case BUILT_IN_MEMSET:
3624      case BUILT_IN_MEMCPY:
3625      case BUILT_IN_MEMCMP:
3626      case BUILT_IN_BCMP:
3627      case BUILT_IN_BZERO:
3628      case BUILT_IN_INDEX:
3629      case BUILT_IN_RINDEX:
3630      case BUILT_IN_STRCHR:
3631      case BUILT_IN_STRRCHR:
3632      case BUILT_IN_STRLEN:
3633      case BUILT_IN_STRCPY:
3634      case BUILT_IN_STRNCPY:
3635      case BUILT_IN_STRNCMP:
3636      case BUILT_IN_STRSTR:
3637      case BUILT_IN_STRPBRK:
3638      case BUILT_IN_STRCAT:
3639      case BUILT_IN_STRNCAT:
3640      case BUILT_IN_STRSPN:
3641      case BUILT_IN_STRCSPN:
3642      case BUILT_IN_STRCMP:
3643      case BUILT_IN_FFS:
3644      case BUILT_IN_PUTCHAR:
3645      case BUILT_IN_PUTS:
3646      case BUILT_IN_PRINTF:
3647      case BUILT_IN_FPUTC:
3648      case BUILT_IN_FPUTS:
3649      case BUILT_IN_FWRITE:
3650      case BUILT_IN_PUTCHAR_UNLOCKED:
3651      case BUILT_IN_PUTS_UNLOCKED:
3652      case BUILT_IN_PRINTF_UNLOCKED:
3653      case BUILT_IN_FPUTC_UNLOCKED:
3654      case BUILT_IN_FPUTS_UNLOCKED:
3655      case BUILT_IN_FWRITE_UNLOCKED:
3656        return expand_call (exp, target, ignore);
3657
3658      default:
3659        break;
3660    }
3661
3662  switch (fcode)
3663    {
3664    case BUILT_IN_ABS:
3665    case BUILT_IN_LABS:
3666    case BUILT_IN_LLABS:
3667    case BUILT_IN_IMAXABS:
3668    case BUILT_IN_FABS:
3669    case BUILT_IN_FABSF:
3670    case BUILT_IN_FABSL:
3671      /* build_function_call changes these into ABS_EXPR.  */
3672      abort ();
3673
3674    case BUILT_IN_CONJ:
3675    case BUILT_IN_CONJF:
3676    case BUILT_IN_CONJL:
3677    case BUILT_IN_CREAL:
3678    case BUILT_IN_CREALF:
3679    case BUILT_IN_CREALL:
3680    case BUILT_IN_CIMAG:
3681    case BUILT_IN_CIMAGF:
3682    case BUILT_IN_CIMAGL:
3683      /* expand_tree_builtin changes these into CONJ_EXPR, REALPART_EXPR
3684	 and IMAGPART_EXPR.  */
3685      abort ();
3686
3687    case BUILT_IN_SIN:
3688    case BUILT_IN_SINF:
3689    case BUILT_IN_SINL:
3690    case BUILT_IN_COS:
3691    case BUILT_IN_COSF:
3692    case BUILT_IN_COSL:
3693      /* Treat these like sqrt only if unsafe math optimizations are allowed,
3694	 because of possible accuracy problems.  */
3695      if (! flag_unsafe_math_optimizations)
3696	break;
3697    case BUILT_IN_SQRT:
3698    case BUILT_IN_SQRTF:
3699    case BUILT_IN_SQRTL:
3700      target = expand_builtin_mathfn (exp, target, subtarget);
3701      if (target)
3702	return target;
3703      break;
3704
3705    case BUILT_IN_FMOD:
3706      break;
3707
3708    case BUILT_IN_APPLY_ARGS:
3709      return expand_builtin_apply_args ();
3710
3711      /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
3712	 FUNCTION with a copy of the parameters described by
3713	 ARGUMENTS, and ARGSIZE.  It returns a block of memory
3714	 allocated on the stack into which is stored all the registers
3715	 that might possibly be used for returning the result of a
3716	 function.  ARGUMENTS is the value returned by
3717	 __builtin_apply_args.  ARGSIZE is the number of bytes of
3718	 arguments that must be copied.  ??? How should this value be
3719	 computed?  We'll also need a safe worst case value for varargs
3720	 functions.  */
3721    case BUILT_IN_APPLY:
3722      if (!validate_arglist (arglist, POINTER_TYPE,
3723			     POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
3724	  && !validate_arglist (arglist, REFERENCE_TYPE,
3725				POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3726	return const0_rtx;
3727      else
3728	{
3729	  int i;
3730	  tree t;
3731	  rtx ops[3];
3732
3733	  for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
3734	    ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
3735
3736	  return expand_builtin_apply (ops[0], ops[1], ops[2]);
3737	}
3738
3739      /* __builtin_return (RESULT) causes the function to return the
3740	 value described by RESULT.  RESULT is address of the block of
3741	 memory returned by __builtin_apply.  */
3742    case BUILT_IN_RETURN:
3743      if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
3744	expand_builtin_return (expand_expr (TREE_VALUE (arglist),
3745					    NULL_RTX, VOIDmode, 0));
3746      return const0_rtx;
3747
3748    case BUILT_IN_SAVEREGS:
3749      return expand_builtin_saveregs ();
3750
3751    case BUILT_IN_ARGS_INFO:
3752      return expand_builtin_args_info (exp);
3753
3754      /* Return the address of the first anonymous stack arg.  */
3755    case BUILT_IN_NEXT_ARG:
3756      return expand_builtin_next_arg (arglist);
3757
3758    case BUILT_IN_CLASSIFY_TYPE:
3759      return expand_builtin_classify_type (arglist);
3760
3761    case BUILT_IN_CONSTANT_P:
3762      return expand_builtin_constant_p (exp);
3763
3764    case BUILT_IN_FRAME_ADDRESS:
3765    case BUILT_IN_RETURN_ADDRESS:
3766      return expand_builtin_frame_address (exp);
3767
3768    /* Returns the address of the area where the structure is returned.
3769       0 otherwise.  */
3770    case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
3771      if (arglist != 0
3772          || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
3773          || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
3774        return const0_rtx;
3775      else
3776        return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
3777
3778    case BUILT_IN_ALLOCA:
3779      target = expand_builtin_alloca (arglist, target);
3780      if (target)
3781	return target;
3782      break;
3783
3784    case BUILT_IN_FFS:
3785      target = expand_builtin_ffs (arglist, target, subtarget);
3786      if (target)
3787	return target;
3788      break;
3789
3790    case BUILT_IN_STRLEN:
3791      target = expand_builtin_strlen (exp, target);
3792      if (target)
3793	return target;
3794      break;
3795
3796    case BUILT_IN_STRCPY:
3797      target = expand_builtin_strcpy (exp, target, mode);
3798      if (target)
3799	return target;
3800      break;
3801
3802    case BUILT_IN_STRNCPY:
3803      target = expand_builtin_strncpy (arglist, target, mode);
3804      if (target)
3805	return target;
3806      break;
3807
3808    case BUILT_IN_STRCAT:
3809      target = expand_builtin_strcat (arglist, target, mode);
3810      if (target)
3811	return target;
3812      break;
3813
3814    case BUILT_IN_STRNCAT:
3815      target = expand_builtin_strncat (arglist, target, mode);
3816      if (target)
3817	return target;
3818      break;
3819
3820    case BUILT_IN_STRSPN:
3821      target = expand_builtin_strspn (arglist, target, mode);
3822      if (target)
3823	return target;
3824      break;
3825
3826    case BUILT_IN_STRCSPN:
3827      target = expand_builtin_strcspn (arglist, target, mode);
3828      if (target)
3829	return target;
3830      break;
3831
3832    case BUILT_IN_STRSTR:
3833      target = expand_builtin_strstr (arglist, target, mode);
3834      if (target)
3835	return target;
3836      break;
3837
3838    case BUILT_IN_STRPBRK:
3839      target = expand_builtin_strpbrk (arglist, target, mode);
3840      if (target)
3841	return target;
3842      break;
3843
3844    case BUILT_IN_INDEX:
3845    case BUILT_IN_STRCHR:
3846      target = expand_builtin_strchr (arglist, target, mode);
3847      if (target)
3848	return target;
3849      break;
3850
3851    case BUILT_IN_RINDEX:
3852    case BUILT_IN_STRRCHR:
3853      target = expand_builtin_strrchr (arglist, target, mode);
3854      if (target)
3855	return target;
3856      break;
3857
3858    case BUILT_IN_MEMCPY:
3859      target = expand_builtin_memcpy (arglist, target, mode);
3860      if (target)
3861	return target;
3862      break;
3863
3864    case BUILT_IN_MEMSET:
3865      target = expand_builtin_memset (exp, target, mode);
3866      if (target)
3867	return target;
3868      break;
3869
3870    case BUILT_IN_BZERO:
3871      target = expand_builtin_bzero (exp);
3872      if (target)
3873	return target;
3874      break;
3875
3876    case BUILT_IN_STRCMP:
3877      target = expand_builtin_strcmp (exp, target, mode);
3878      if (target)
3879	return target;
3880      break;
3881
3882    case BUILT_IN_STRNCMP:
3883      target = expand_builtin_strncmp (exp, target, mode);
3884      if (target)
3885	return target;
3886      break;
3887
3888    case BUILT_IN_BCMP:
3889    case BUILT_IN_MEMCMP:
3890      target = expand_builtin_memcmp (exp, arglist, target, mode);
3891      if (target)
3892	return target;
3893      break;
3894
3895    case BUILT_IN_SETJMP:
3896      target = expand_builtin_setjmp (arglist, target);
3897      if (target)
3898	return target;
3899      break;
3900
3901      /* __builtin_longjmp is passed a pointer to an array of five words.
3902	 It's similar to the C library longjmp function but works with
3903	 __builtin_setjmp above.  */
3904    case BUILT_IN_LONGJMP:
3905      if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3906	break;
3907      else
3908	{
3909	  rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
3910				      VOIDmode, 0);
3911	  rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
3912				   NULL_RTX, VOIDmode, 0);
3913
3914	  if (value != const1_rtx)
3915	    {
3916	      error ("__builtin_longjmp second argument must be 1");
3917	      return const0_rtx;
3918	    }
3919
3920	  expand_builtin_longjmp (buf_addr, value);
3921	  return const0_rtx;
3922	}
3923
3924    case BUILT_IN_TRAP:
3925      expand_builtin_trap ();
3926      return const0_rtx;
3927
3928    case BUILT_IN_PUTCHAR:
3929    case BUILT_IN_PUTS:
3930    case BUILT_IN_FPUTC:
3931    case BUILT_IN_FWRITE:
3932    case BUILT_IN_PUTCHAR_UNLOCKED:
3933    case BUILT_IN_PUTS_UNLOCKED:
3934    case BUILT_IN_FPUTC_UNLOCKED:
3935    case BUILT_IN_FWRITE_UNLOCKED:
3936      break;
3937    case BUILT_IN_FPUTS:
3938      target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 0);
3939      if (target)
3940	return target;
3941      break;
3942    case BUILT_IN_FPUTS_UNLOCKED:
3943      target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 1);
3944      if (target)
3945	return target;
3946      break;
3947
3948      /* Various hooks for the DWARF 2 __throw routine.  */
3949    case BUILT_IN_UNWIND_INIT:
3950      expand_builtin_unwind_init ();
3951      return const0_rtx;
3952    case BUILT_IN_DWARF_CFA:
3953      return virtual_cfa_rtx;
3954#ifdef DWARF2_UNWIND_INFO
3955    case BUILT_IN_DWARF_FP_REGNUM:
3956      return expand_builtin_dwarf_fp_regnum ();
3957    case BUILT_IN_INIT_DWARF_REG_SIZES:
3958      expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
3959      return const0_rtx;
3960#endif
3961    case BUILT_IN_FROB_RETURN_ADDR:
3962      return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
3963    case BUILT_IN_EXTRACT_RETURN_ADDR:
3964      return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
3965    case BUILT_IN_EH_RETURN:
3966      expand_builtin_eh_return (TREE_VALUE (arglist),
3967				TREE_VALUE (TREE_CHAIN (arglist)));
3968      return const0_rtx;
3969#ifdef EH_RETURN_DATA_REGNO
3970    case BUILT_IN_EH_RETURN_DATA_REGNO:
3971      return expand_builtin_eh_return_data_regno (arglist);
3972#endif
3973    case BUILT_IN_VARARGS_START:
3974      return expand_builtin_va_start (0, arglist);
3975    case BUILT_IN_STDARG_START:
3976      return expand_builtin_va_start (1, arglist);
3977    case BUILT_IN_VA_END:
3978      return expand_builtin_va_end (arglist);
3979    case BUILT_IN_VA_COPY:
3980      return expand_builtin_va_copy (arglist);
3981    case BUILT_IN_EXPECT:
3982      return expand_builtin_expect (arglist, target);
3983    case BUILT_IN_PREFETCH:
3984      expand_builtin_prefetch (arglist);
3985      return const0_rtx;
3986
3987
3988    default:			/* just do library call, if unknown builtin */
3989      error ("built-in function `%s' not currently supported",
3990	     IDENTIFIER_POINTER (DECL_NAME (fndecl)));
3991    }
3992
3993  /* The switch statement above can drop through to cause the function
3994     to be called normally.  */
3995  return expand_call (exp, target, ignore);
3996}
3997
3998/* Fold a call to __builtin_constant_p, if we know it will evaluate to a
3999   constant.  ARGLIST is the argument list of the call.  */
4000
4001static tree
4002fold_builtin_constant_p (arglist)
4003     tree arglist;
4004{
4005  if (arglist == 0)
4006    return 0;
4007
4008  arglist = TREE_VALUE (arglist);
4009
4010  /* We return 1 for a numeric type that's known to be a constant
4011     value at compile-time or for an aggregate type that's a
4012     literal constant.  */
4013  STRIP_NOPS (arglist);
4014
4015  /* If we know this is a constant, emit the constant of one.  */
4016  if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
4017      || (TREE_CODE (arglist) == CONSTRUCTOR
4018	  && TREE_CONSTANT (arglist))
4019      || (TREE_CODE (arglist) == ADDR_EXPR
4020	  && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
4021    return integer_one_node;
4022
4023  /* If we aren't going to be running CSE or this expression
4024     has side effects, show we don't know it to be a constant.
4025     Likewise if it's a pointer or aggregate type since in those
4026     case we only want literals, since those are only optimized
4027     when generating RTL, not later.
4028     And finally, if we are compiling an initializer, not code, we
4029     need to return a definite result now; there's not going to be any
4030     more optimization done.  */
4031  if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected
4032      || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
4033      || POINTER_TYPE_P (TREE_TYPE (arglist))
4034      || cfun == 0)
4035    return integer_zero_node;
4036
4037  return 0;
4038}
4039
4040/* Fold a call to __builtin_classify_type.  */
4041
4042static tree
4043fold_builtin_classify_type (arglist)
4044     tree arglist;
4045{
4046  if (arglist == 0)
4047    return build_int_2 (no_type_class, 0);
4048
4049  return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
4050}
4051
4052/* Used by constant folding to eliminate some builtin calls early.  EXP is
4053   the CALL_EXPR of a call to a builtin function.  */
4054
4055tree
4056fold_builtin (exp)
4057     tree exp;
4058{
4059  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4060  tree arglist = TREE_OPERAND (exp, 1);
4061  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
4062
4063  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
4064    return 0;
4065
4066  switch (fcode)
4067    {
4068    case BUILT_IN_CONSTANT_P:
4069      return fold_builtin_constant_p (arglist);
4070
4071    case BUILT_IN_CLASSIFY_TYPE:
4072      return fold_builtin_classify_type (arglist);
4073
4074    case BUILT_IN_STRLEN:
4075      if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
4076	{
4077	  tree len = c_strlen (TREE_VALUE (arglist));
4078	  if (len != 0)
4079	    return len;
4080	}
4081      break;
4082
4083    default:
4084      break;
4085    }
4086
4087  return 0;
4088}
4089
4090static tree
4091build_function_call_expr (fn, arglist)
4092     tree fn, arglist;
4093{
4094  tree call_expr;
4095
4096  call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
4097  call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
4098		     call_expr, arglist);
4099  TREE_SIDE_EFFECTS (call_expr) = 1;
4100  return fold (call_expr);
4101}
4102
4103/* This function validates the types of a function call argument list
4104   represented as a tree chain of parameters against a specified list
4105   of tree_codes.  If the last specifier is a 0, that represents an
4106   ellipses, otherwise the last specifier must be a VOID_TYPE.  */
4107
4108static int
4109validate_arglist VPARAMS ((tree arglist, ...))
4110{
4111  enum tree_code code;
4112  int res = 0;
4113
4114  VA_OPEN (ap, arglist);
4115  VA_FIXEDARG (ap, tree, arglist);
4116
4117  do {
4118    code = va_arg (ap, enum tree_code);
4119    switch (code)
4120    {
4121    case 0:
4122      /* This signifies an ellipses, any further arguments are all ok.  */
4123      res = 1;
4124      goto end;
4125    case VOID_TYPE:
4126      /* This signifies an endlink, if no arguments remain, return
4127         true, otherwise return false.  */
4128      res = arglist == 0;
4129      goto end;
4130    default:
4131      /* If no parameters remain or the parameter's code does not
4132         match the specified code, return false.  Otherwise continue
4133         checking any remaining arguments.  */
4134      if (arglist == 0 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
4135	goto end;
4136      break;
4137    }
4138    arglist = TREE_CHAIN (arglist);
4139  } while (1);
4140
4141  /* We need gotos here since we can only have one VA_CLOSE in a
4142     function.  */
4143 end: ;
4144  VA_CLOSE (ap);
4145
4146  return res;
4147}
4148
4149/* Default version of target-specific builtin setup that does nothing.  */
4150
4151void
4152default_init_builtins ()
4153{
4154}
4155
4156/* Default target-specific builtin expander that does nothing.  */
4157
4158rtx
4159default_expand_builtin (exp, target, subtarget, mode, ignore)
4160     tree exp ATTRIBUTE_UNUSED;
4161     rtx target ATTRIBUTE_UNUSED;
4162     rtx subtarget ATTRIBUTE_UNUSED;
4163     enum machine_mode mode ATTRIBUTE_UNUSED;
4164     int ignore ATTRIBUTE_UNUSED;
4165{
4166  return NULL_RTX;
4167}
4168