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

Last change on this file since 2 was 2, checked in by bird, 22 years ago

Initial revision

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