source: trunk/src/gcc/gcc/builtins.c@ 1589

Last change on this file since 1589 was 1589, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1588,
which included commits to RCS files with non-trunk default branches.

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