* c-common.c (check_function_format): Don't suggest adding format
[official-gcc.git] / gcc / builtins.c
blobcbf9acd55dea0751c86b228323091eebb68371b0
1 /* Expand builtin functions.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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-flags.h"
34 #include "insn-codes.h"
35 #include "insn-config.h"
36 #include "expr.h"
37 #include "recog.h"
38 #include "output.h"
39 #include "typeclass.h"
40 #include "defaults.h"
41 #include "toplev.h"
42 #include "tm_p.h"
44 #define CALLED_AS_BUILT_IN(NODE) \
45 (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
47 /* Register mappings for target machines without register windows. */
48 #ifndef INCOMING_REGNO
49 #define INCOMING_REGNO(OUT) (OUT)
50 #endif
51 #ifndef OUTGOING_REGNO
52 #define OUTGOING_REGNO(IN) (IN)
53 #endif
55 #ifndef PAD_VARARGS_DOWN
56 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
57 #endif
59 /* Define the names of the builtin function types and codes. */
60 const char *const built_in_class_names[4]
61 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
63 #define DEF_BUILTIN(x) STRINGIFY(x),
64 const char *const built_in_names[(int) END_BUILTINS] =
66 #include "builtins.def"
68 #undef DEF_BUILTIN
70 /* Setup an array of _DECL trees, make sure each element is
71 initialized to NULL_TREE. */
72 #define DEF_BUILTIN(x) NULL_TREE,
73 tree built_in_decls[(int) END_BUILTINS] =
75 #include "builtins.def"
77 #undef DEF_BUILTIN
79 tree (*lang_type_promotes_to) PARAMS ((tree));
81 static int get_pointer_alignment PARAMS ((tree, unsigned));
82 static tree c_strlen PARAMS ((tree));
83 static const char *c_getstr PARAMS ((tree));
84 static rtx c_readstr PARAMS ((const char *,
85 enum machine_mode));
86 static int target_char_cast PARAMS ((tree, char *));
87 static rtx get_memory_rtx PARAMS ((tree));
88 static int apply_args_size PARAMS ((void));
89 static int apply_result_size PARAMS ((void));
90 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
91 static rtx result_vector PARAMS ((int, rtx));
92 #endif
93 static rtx expand_builtin_setjmp PARAMS ((tree, rtx));
94 static rtx expand_builtin_apply_args PARAMS ((void));
95 static rtx expand_builtin_apply_args_1 PARAMS ((void));
96 static rtx expand_builtin_apply PARAMS ((rtx, rtx, rtx));
97 static void expand_builtin_return PARAMS ((rtx));
98 static rtx expand_builtin_classify_type PARAMS ((tree));
99 static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx));
100 static rtx expand_builtin_constant_p PARAMS ((tree));
101 static rtx expand_builtin_args_info PARAMS ((tree));
102 static rtx expand_builtin_next_arg PARAMS ((tree));
103 static rtx expand_builtin_va_start PARAMS ((int, tree));
104 static rtx expand_builtin_va_end PARAMS ((tree));
105 static rtx expand_builtin_va_copy PARAMS ((tree));
106 #ifdef HAVE_cmpstrsi
107 static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx));
108 #endif
109 static rtx expand_builtin_strcmp PARAMS ((tree, rtx,
110 enum machine_mode));
111 static rtx expand_builtin_strncmp PARAMS ((tree, rtx,
112 enum machine_mode));
113 static rtx builtin_memcpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
114 enum machine_mode));
115 static rtx expand_builtin_strcat PARAMS ((tree, rtx,
116 enum machine_mode));
117 static rtx expand_builtin_strncat PARAMS ((tree, rtx,
118 enum machine_mode));
119 static rtx expand_builtin_strspn PARAMS ((tree, rtx,
120 enum machine_mode));
121 static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
122 enum machine_mode));
123 static rtx expand_builtin_memcpy PARAMS ((tree));
124 static rtx expand_builtin_strcpy PARAMS ((tree));
125 static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
126 enum machine_mode));
127 static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
128 enum machine_mode));
129 static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT,
130 enum machine_mode));
131 static rtx expand_builtin_memset PARAMS ((tree));
132 static rtx expand_builtin_bzero PARAMS ((tree));
133 static rtx expand_builtin_strlen PARAMS ((tree, rtx));
134 static rtx expand_builtin_strstr PARAMS ((tree, rtx,
135 enum machine_mode));
136 static rtx expand_builtin_strpbrk PARAMS ((tree, rtx,
137 enum machine_mode));
138 static rtx expand_builtin_strchr PARAMS ((tree, rtx,
139 enum machine_mode));
140 static rtx expand_builtin_strrchr PARAMS ((tree, rtx,
141 enum machine_mode));
142 static rtx expand_builtin_alloca PARAMS ((tree, rtx));
143 static rtx expand_builtin_ffs PARAMS ((tree, rtx, rtx));
144 static rtx expand_builtin_frame_address PARAMS ((tree));
145 static rtx expand_builtin_fputs PARAMS ((tree, int));
146 static tree stabilize_va_list PARAMS ((tree, int));
147 static rtx expand_builtin_expect PARAMS ((tree, rtx));
148 static tree fold_builtin_constant_p PARAMS ((tree));
150 /* Return the alignment in bits of EXP, a pointer valued expression.
151 But don't return more than MAX_ALIGN no matter what.
152 The alignment returned is, by default, the alignment of the thing that
153 EXP points to (if it is not a POINTER_TYPE, 0 is returned).
155 Otherwise, look at the expression to see if we can do better, i.e., if the
156 expression is actually pointing at an object whose alignment is tighter. */
158 static int
159 get_pointer_alignment (exp, max_align)
160 tree exp;
161 unsigned max_align;
163 unsigned align, inner;
165 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
166 return 0;
168 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
169 align = MIN (align, max_align);
171 while (1)
173 switch (TREE_CODE (exp))
175 case NOP_EXPR:
176 case CONVERT_EXPR:
177 case NON_LVALUE_EXPR:
178 exp = TREE_OPERAND (exp, 0);
179 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
180 return align;
182 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
183 align = MIN (inner, max_align);
184 break;
186 case PLUS_EXPR:
187 /* If sum of pointer + int, restrict our maximum alignment to that
188 imposed by the integer. If not, we can't do any better than
189 ALIGN. */
190 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
191 return align;
193 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1) * BITS_PER_UNIT)
194 & (max_align - 1))
195 != 0)
196 max_align >>= 1;
198 exp = TREE_OPERAND (exp, 0);
199 break;
201 case ADDR_EXPR:
202 /* See what we are pointing at and look at its alignment. */
203 exp = TREE_OPERAND (exp, 0);
204 if (TREE_CODE (exp) == FUNCTION_DECL)
205 align = FUNCTION_BOUNDARY;
206 else if (DECL_P (exp))
207 align = DECL_ALIGN (exp);
208 #ifdef CONSTANT_ALIGNMENT
209 else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
210 align = CONSTANT_ALIGNMENT (exp, align);
211 #endif
212 return MIN (align, max_align);
214 default:
215 return align;
220 /* Compute the length of a C string. TREE_STRING_LENGTH is not the right
221 way, because it could contain a zero byte in the middle.
222 TREE_STRING_LENGTH is the size of the character array, not the string.
224 The value returned is of type `ssizetype'.
226 Unfortunately, string_constant can't access the values of const char
227 arrays with initializers, so neither can we do so here. */
229 static tree
230 c_strlen (src)
231 tree src;
233 tree offset_node;
234 int offset, max;
235 const char *ptr;
237 src = string_constant (src, &offset_node);
238 if (src == 0)
239 return 0;
241 max = TREE_STRING_LENGTH (src) - 1;
242 ptr = TREE_STRING_POINTER (src);
244 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
246 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
247 compute the offset to the following null if we don't know where to
248 start searching for it. */
249 int i;
251 for (i = 0; i < max; i++)
252 if (ptr[i] == 0)
253 return 0;
255 /* We don't know the starting offset, but we do know that the string
256 has no internal zero bytes. We can assume that the offset falls
257 within the bounds of the string; otherwise, the programmer deserves
258 what he gets. Subtract the offset from the length of the string,
259 and return that. This would perhaps not be valid if we were dealing
260 with named arrays in addition to literal string constants. */
262 return size_diffop (size_int (max), offset_node);
265 /* We have a known offset into the string. Start searching there for
266 a null character. */
267 if (offset_node == 0)
268 offset = 0;
269 else
271 /* Did we get a long long offset? If so, punt. */
272 if (TREE_INT_CST_HIGH (offset_node) != 0)
273 return 0;
274 offset = TREE_INT_CST_LOW (offset_node);
277 /* If the offset is known to be out of bounds, warn, and call strlen at
278 runtime. */
279 if (offset < 0 || offset > max)
281 warning ("offset outside bounds of constant string");
282 return 0;
285 /* Use strlen to search for the first zero byte. Since any strings
286 constructed with build_string will have nulls appended, we win even
287 if we get handed something like (char[4])"abcd".
289 Since OFFSET is our starting index into the string, no further
290 calculation is needed. */
291 return ssize_int (strlen (ptr + offset));
294 /* Return a char pointer for a C string if it is a string constant
295 or sum of string constant and integer constant. */
297 static const char *
298 c_getstr (src)
299 tree src;
301 tree offset_node;
302 int offset, max;
303 const char *ptr;
305 src = string_constant (src, &offset_node);
306 if (src == 0)
307 return 0;
309 max = TREE_STRING_LENGTH (src) - 1;
310 ptr = TREE_STRING_POINTER (src);
312 if (!offset_node)
313 offset = 0;
314 else if (TREE_CODE (offset_node) != INTEGER_CST)
315 return 0;
316 else
318 /* Did we get a long long offset? If so, punt. */
319 if (TREE_INT_CST_HIGH (offset_node) != 0)
320 return 0;
321 offset = TREE_INT_CST_LOW (offset_node);
322 if (offset < 0 || offset > max)
323 return 0;
326 return ptr + offset;
329 /* Return a CONST_INT or CONST_DOUBLE corresponding to target
330 reading GET_MODE_BITSIZE (MODE) bits from string constant
331 STR. */
333 static rtx
334 c_readstr (str, mode)
335 const char *str;
336 enum machine_mode mode;
338 HOST_WIDE_INT c[2];
339 HOST_WIDE_INT ch;
340 unsigned int i, j;
342 if (GET_MODE_CLASS (mode) != MODE_INT)
343 abort ();
344 c[0] = 0;
345 c[1] = 0;
346 ch = 1;
347 for (i = 0; i < GET_MODE_SIZE (mode); i++)
349 j = i;
350 if (WORDS_BIG_ENDIAN)
351 j = GET_MODE_SIZE (mode) - i - 1;
352 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
353 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
354 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
355 j *= BITS_PER_UNIT;
356 if (j > 2 * HOST_BITS_PER_WIDE_INT)
357 abort ();
358 if (ch)
359 ch = (unsigned char) str[i];
360 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
362 return immed_double_const (c[0], c[1], mode);
365 /* Cast a target constant CST to target CHAR and if that value fits into
366 host char type, return zero and put that value into variable pointed by
367 P. */
369 static int
370 target_char_cast (cst, p)
371 tree cst;
372 char *p;
374 unsigned HOST_WIDE_INT val, hostval;
376 if (TREE_CODE (cst) != INTEGER_CST
377 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
378 return 1;
380 val = TREE_INT_CST_LOW (cst);
381 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
382 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
384 hostval = val;
385 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
386 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
388 if (val != hostval)
389 return 1;
391 *p = hostval;
392 return 0;
395 /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
396 times to get the address of either a higher stack frame, or a return
397 address located within it (depending on FNDECL_CODE). */
400 expand_builtin_return_addr (fndecl_code, count, tem)
401 enum built_in_function fndecl_code;
402 int count;
403 rtx tem;
405 int i;
407 /* Some machines need special handling before we can access
408 arbitrary frames. For example, on the sparc, we must first flush
409 all register windows to the stack. */
410 #ifdef SETUP_FRAME_ADDRESSES
411 if (count > 0)
412 SETUP_FRAME_ADDRESSES ();
413 #endif
415 /* On the sparc, the return address is not in the frame, it is in a
416 register. There is no way to access it off of the current frame
417 pointer, but it can be accessed off the previous frame pointer by
418 reading the value from the register window save area. */
419 #ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
420 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
421 count--;
422 #endif
424 /* Scan back COUNT frames to the specified frame. */
425 for (i = 0; i < count; i++)
427 /* Assume the dynamic chain pointer is in the word that the
428 frame address points to, unless otherwise specified. */
429 #ifdef DYNAMIC_CHAIN_ADDRESS
430 tem = DYNAMIC_CHAIN_ADDRESS (tem);
431 #endif
432 tem = memory_address (Pmode, tem);
433 tem = copy_to_reg (gen_rtx_MEM (Pmode, tem));
434 MEM_ALIAS_SET (tem) = get_frame_alias_set ();
437 /* For __builtin_frame_address, return what we've got. */
438 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
439 return tem;
441 /* For __builtin_return_address, Get the return address from that
442 frame. */
443 #ifdef RETURN_ADDR_RTX
444 tem = RETURN_ADDR_RTX (count, tem);
445 #else
446 tem = memory_address (Pmode,
447 plus_constant (tem, GET_MODE_SIZE (Pmode)));
448 tem = gen_rtx_MEM (Pmode, tem);
449 MEM_ALIAS_SET (tem) = get_frame_alias_set ();
450 #endif
451 return tem;
454 /* Alias set used for setjmp buffer. */
455 static HOST_WIDE_INT setjmp_alias_set = -1;
457 /* Construct the leading half of a __builtin_setjmp call. Control will
458 return to RECEIVER_LABEL. This is used directly by sjlj exception
459 handling code. */
461 void
462 expand_builtin_setjmp_setup (buf_addr, receiver_label)
463 rtx buf_addr;
464 rtx receiver_label;
466 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
467 rtx stack_save;
468 rtx mem;
470 if (setjmp_alias_set == -1)
471 setjmp_alias_set = new_alias_set ();
473 #ifdef POINTERS_EXTEND_UNSIGNED
474 buf_addr = convert_memory_address (Pmode, buf_addr);
475 #endif
477 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
479 emit_queue ();
481 /* We store the frame pointer and the address of receiver_label in
482 the buffer and use the rest of it for the stack save area, which
483 is machine-dependent. */
485 #ifndef BUILTIN_SETJMP_FRAME_VALUE
486 #define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
487 #endif
489 mem = gen_rtx_MEM (Pmode, buf_addr);
490 MEM_ALIAS_SET (mem) = setjmp_alias_set;
491 emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
493 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
494 MEM_ALIAS_SET (mem) = setjmp_alias_set;
496 emit_move_insn (validize_mem (mem),
497 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
499 stack_save = gen_rtx_MEM (sa_mode,
500 plus_constant (buf_addr,
501 2 * GET_MODE_SIZE (Pmode)));
502 MEM_ALIAS_SET (stack_save) = setjmp_alias_set;
503 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
505 /* If there is further processing to do, do it. */
506 #ifdef HAVE_builtin_setjmp_setup
507 if (HAVE_builtin_setjmp_setup)
508 emit_insn (gen_builtin_setjmp_setup (buf_addr));
509 #endif
511 /* Tell optimize_save_area_alloca that extra work is going to
512 need to go on during alloca. */
513 current_function_calls_setjmp = 1;
515 /* Set this so all the registers get saved in our frame; we need to be
516 able to copy the saved values for any registers from frames we unwind. */
517 current_function_has_nonlocal_label = 1;
520 /* Construct the trailing part of a __builtin_setjmp call.
521 This is used directly by sjlj exception handling code. */
523 void
524 expand_builtin_setjmp_receiver (receiver_label)
525 rtx receiver_label ATTRIBUTE_UNUSED;
527 /* Clobber the FP when we get here, so we have to make sure it's
528 marked as used by this function. */
529 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
531 /* Mark the static chain as clobbered here so life information
532 doesn't get messed up for it. */
533 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
535 /* Now put in the code to restore the frame pointer, and argument
536 pointer, if needed. The code below is from expand_end_bindings
537 in stmt.c; see detailed documentation there. */
538 #ifdef HAVE_nonlocal_goto
539 if (! HAVE_nonlocal_goto)
540 #endif
541 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
543 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
544 if (fixed_regs[ARG_POINTER_REGNUM])
546 #ifdef ELIMINABLE_REGS
547 size_t i;
548 static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
550 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
551 if (elim_regs[i].from == ARG_POINTER_REGNUM
552 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
553 break;
555 if (i == ARRAY_SIZE (elim_regs))
556 #endif
558 /* Now restore our arg pointer from the address at which it
559 was saved in our stack frame.
560 If there hasn't be space allocated for it yet, make
561 some now. */
562 if (arg_pointer_save_area == 0)
563 arg_pointer_save_area
564 = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
565 emit_move_insn (virtual_incoming_args_rtx,
566 copy_to_reg (arg_pointer_save_area));
569 #endif
571 #ifdef HAVE_builtin_setjmp_receiver
572 if (HAVE_builtin_setjmp_receiver)
573 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
574 else
575 #endif
576 #ifdef HAVE_nonlocal_goto_receiver
577 if (HAVE_nonlocal_goto_receiver)
578 emit_insn (gen_nonlocal_goto_receiver ());
579 else
580 #endif
581 { /* Nothing */ }
584 /* __builtin_setjmp is passed a pointer to an array of five words (not
585 all will be used on all machines). It operates similarly to the C
586 library function of the same name, but is more efficient. Much of
587 the code below (and for longjmp) is copied from the handling of
588 non-local gotos.
590 NOTE: This is intended for use by GNAT and the exception handling
591 scheme in the compiler and will only work in the method used by
592 them. */
594 static rtx
595 expand_builtin_setjmp (arglist, target)
596 tree arglist;
597 rtx target;
599 rtx buf_addr, next_lab, cont_lab;
601 if (arglist == 0
602 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
603 return NULL_RTX;
605 if (target == 0 || GET_CODE (target) != REG
606 || REGNO (target) < FIRST_PSEUDO_REGISTER)
607 target = gen_reg_rtx (TYPE_MODE (integer_type_node));
609 buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
611 next_lab = gen_label_rtx ();
612 cont_lab = gen_label_rtx ();
614 expand_builtin_setjmp_setup (buf_addr, next_lab);
616 /* Set TARGET to zero and branch to the continue label. */
617 emit_move_insn (target, const0_rtx);
618 emit_jump_insn (gen_jump (cont_lab));
619 emit_barrier ();
620 emit_label (next_lab);
622 expand_builtin_setjmp_receiver (next_lab);
624 /* Set TARGET to one. */
625 emit_move_insn (target, const1_rtx);
626 emit_label (cont_lab);
628 /* Tell flow about the strange goings on. Putting `next_lab' on
629 `nonlocal_goto_handler_labels' to indicates that function
630 calls may traverse the arc back to this label. */
632 current_function_has_nonlocal_label = 1;
633 nonlocal_goto_handler_labels
634 = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
636 return target;
639 /* __builtin_longjmp is passed a pointer to an array of five words (not
640 all will be used on all machines). It operates similarly to the C
641 library function of the same name, but is more efficient. Much of
642 the code below is copied from the handling of non-local gotos.
644 NOTE: This is intended for use by GNAT and the exception handling
645 scheme in the compiler and will only work in the method used by
646 them. */
648 void
649 expand_builtin_longjmp (buf_addr, value)
650 rtx buf_addr, value;
652 rtx fp, lab, stack;
653 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
655 if (setjmp_alias_set == -1)
656 setjmp_alias_set = new_alias_set ();
658 #ifdef POINTERS_EXTEND_UNSIGNED
659 buf_addr = convert_memory_address (Pmode, buf_addr);
660 #endif
661 buf_addr = force_reg (Pmode, buf_addr);
663 /* We used to store value in static_chain_rtx, but that fails if pointers
664 are smaller than integers. We instead require that the user must pass
665 a second argument of 1, because that is what builtin_setjmp will
666 return. This also makes EH slightly more efficient, since we are no
667 longer copying around a value that we don't care about. */
668 if (value != const1_rtx)
669 abort ();
671 current_function_calls_longjmp = 1;
673 #ifdef HAVE_builtin_longjmp
674 if (HAVE_builtin_longjmp)
675 emit_insn (gen_builtin_longjmp (buf_addr));
676 else
677 #endif
679 fp = gen_rtx_MEM (Pmode, buf_addr);
680 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
681 GET_MODE_SIZE (Pmode)));
683 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
684 2 * GET_MODE_SIZE (Pmode)));
685 MEM_ALIAS_SET (fp) = MEM_ALIAS_SET (lab) = MEM_ALIAS_SET (stack)
686 = setjmp_alias_set;
688 /* Pick up FP, label, and SP from the block and jump. This code is
689 from expand_goto in stmt.c; see there for detailed comments. */
690 #if HAVE_nonlocal_goto
691 if (HAVE_nonlocal_goto)
692 /* We have to pass a value to the nonlocal_goto pattern that will
693 get copied into the static_chain pointer, but it does not matter
694 what that value is, because builtin_setjmp does not use it. */
695 emit_insn (gen_nonlocal_goto (value, fp, stack, lab));
696 else
697 #endif
699 lab = copy_to_reg (lab);
701 emit_move_insn (hard_frame_pointer_rtx, fp);
702 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
704 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
705 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
706 emit_indirect_jump (lab);
711 /* Get a MEM rtx for expression EXP which is the address of an operand
712 to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */
714 static rtx
715 get_memory_rtx (exp)
716 tree exp;
718 rtx mem = gen_rtx_MEM (BLKmode,
719 memory_address (BLKmode,
720 expand_expr (exp, NULL_RTX,
721 ptr_mode, EXPAND_SUM)));
723 /* Get an expression we can use to find the attributes to assign to MEM.
724 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
725 we can. First remove any nops. */
726 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
727 || TREE_CODE (exp) == NON_LVALUE_EXPR)
728 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
729 exp = TREE_OPERAND (exp, 0);
731 if (TREE_CODE (exp) == ADDR_EXPR)
732 exp = TREE_OPERAND (exp, 0);
733 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
734 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
735 else
736 return mem;
738 set_mem_attributes (mem, exp, 0);
740 /* memcpy, memset and other builtin stringops can alias with anything. */
741 MEM_ALIAS_SET (mem) = 0;
742 return mem;
745 /* Built-in functions to perform an untyped call and return. */
747 /* For each register that may be used for calling a function, this
748 gives a mode used to copy the register's value. VOIDmode indicates
749 the register is not used for calling a function. If the machine
750 has register windows, this gives only the outbound registers.
751 INCOMING_REGNO gives the corresponding inbound register. */
752 static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
754 /* For each register that may be used for returning values, this gives
755 a mode used to copy the register's value. VOIDmode indicates the
756 register is not used for returning values. If the machine has
757 register windows, this gives only the outbound registers.
758 INCOMING_REGNO gives the corresponding inbound register. */
759 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
761 /* For each register that may be used for calling a function, this
762 gives the offset of that register into the block returned by
763 __builtin_apply_args. 0 indicates that the register is not
764 used for calling a function. */
765 static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
767 /* Return the offset of register REGNO into the block returned by
768 __builtin_apply_args. This is not declared static, since it is
769 needed in objc-act.c. */
771 int
772 apply_args_register_offset (regno)
773 int regno;
775 apply_args_size ();
777 /* Arguments are always put in outgoing registers (in the argument
778 block) if such make sense. */
779 #ifdef OUTGOING_REGNO
780 regno = OUTGOING_REGNO(regno);
781 #endif
782 return apply_args_reg_offset[regno];
785 /* Return the size required for the block returned by __builtin_apply_args,
786 and initialize apply_args_mode. */
788 static int
789 apply_args_size ()
791 static int size = -1;
792 int align, regno;
793 enum machine_mode mode;
795 /* The values computed by this function never change. */
796 if (size < 0)
798 /* The first value is the incoming arg-pointer. */
799 size = GET_MODE_SIZE (Pmode);
801 /* The second value is the structure value address unless this is
802 passed as an "invisible" first argument. */
803 if (struct_value_rtx)
804 size += GET_MODE_SIZE (Pmode);
806 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
807 if (FUNCTION_ARG_REGNO_P (regno))
809 /* Search for the proper mode for copying this register's
810 value. I'm not sure this is right, but it works so far. */
811 enum machine_mode best_mode = VOIDmode;
813 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
814 mode != VOIDmode;
815 mode = GET_MODE_WIDER_MODE (mode))
816 if (HARD_REGNO_MODE_OK (regno, mode)
817 && HARD_REGNO_NREGS (regno, mode) == 1)
818 best_mode = mode;
820 if (best_mode == VOIDmode)
821 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
822 mode != VOIDmode;
823 mode = GET_MODE_WIDER_MODE (mode))
824 if (HARD_REGNO_MODE_OK (regno, mode)
825 && (mov_optab->handlers[(int) mode].insn_code
826 != CODE_FOR_nothing))
827 best_mode = mode;
829 mode = best_mode;
830 if (mode == VOIDmode)
831 abort ();
833 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
834 if (size % align != 0)
835 size = CEIL (size, align) * align;
836 apply_args_reg_offset[regno] = size;
837 size += GET_MODE_SIZE (mode);
838 apply_args_mode[regno] = mode;
840 else
842 apply_args_mode[regno] = VOIDmode;
843 apply_args_reg_offset[regno] = 0;
846 return size;
849 /* Return the size required for the block returned by __builtin_apply,
850 and initialize apply_result_mode. */
852 static int
853 apply_result_size ()
855 static int size = -1;
856 int align, regno;
857 enum machine_mode mode;
859 /* The values computed by this function never change. */
860 if (size < 0)
862 size = 0;
864 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
865 if (FUNCTION_VALUE_REGNO_P (regno))
867 /* Search for the proper mode for copying this register's
868 value. I'm not sure this is right, but it works so far. */
869 enum machine_mode best_mode = VOIDmode;
871 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
872 mode != TImode;
873 mode = GET_MODE_WIDER_MODE (mode))
874 if (HARD_REGNO_MODE_OK (regno, mode))
875 best_mode = mode;
877 if (best_mode == VOIDmode)
878 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
879 mode != VOIDmode;
880 mode = GET_MODE_WIDER_MODE (mode))
881 if (HARD_REGNO_MODE_OK (regno, mode)
882 && (mov_optab->handlers[(int) mode].insn_code
883 != CODE_FOR_nothing))
884 best_mode = mode;
886 mode = best_mode;
887 if (mode == VOIDmode)
888 abort ();
890 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
891 if (size % align != 0)
892 size = CEIL (size, align) * align;
893 size += GET_MODE_SIZE (mode);
894 apply_result_mode[regno] = mode;
896 else
897 apply_result_mode[regno] = VOIDmode;
899 /* Allow targets that use untyped_call and untyped_return to override
900 the size so that machine-specific information can be stored here. */
901 #ifdef APPLY_RESULT_SIZE
902 size = APPLY_RESULT_SIZE;
903 #endif
905 return size;
908 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
909 /* Create a vector describing the result block RESULT. If SAVEP is true,
910 the result block is used to save the values; otherwise it is used to
911 restore the values. */
913 static rtx
914 result_vector (savep, result)
915 int savep;
916 rtx result;
918 int regno, size, align, nelts;
919 enum machine_mode mode;
920 rtx reg, mem;
921 rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
923 size = nelts = 0;
924 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
925 if ((mode = apply_result_mode[regno]) != VOIDmode)
927 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
928 if (size % align != 0)
929 size = CEIL (size, align) * align;
930 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
931 mem = change_address (result, mode,
932 plus_constant (XEXP (result, 0), size));
933 savevec[nelts++] = (savep
934 ? gen_rtx_SET (VOIDmode, mem, reg)
935 : gen_rtx_SET (VOIDmode, reg, mem));
936 size += GET_MODE_SIZE (mode);
938 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
940 #endif /* HAVE_untyped_call or HAVE_untyped_return */
942 /* Save the state required to perform an untyped call with the same
943 arguments as were passed to the current function. */
945 static rtx
946 expand_builtin_apply_args_1 ()
948 rtx registers;
949 int size, align, regno;
950 enum machine_mode mode;
952 /* Create a block where the arg-pointer, structure value address,
953 and argument registers can be saved. */
954 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
956 /* Walk past the arg-pointer and structure value address. */
957 size = GET_MODE_SIZE (Pmode);
958 if (struct_value_rtx)
959 size += GET_MODE_SIZE (Pmode);
961 /* Save each register used in calling a function to the block. */
962 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
963 if ((mode = apply_args_mode[regno]) != VOIDmode)
965 rtx tem;
967 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
968 if (size % align != 0)
969 size = CEIL (size, align) * align;
971 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
973 emit_move_insn (change_address (registers, mode,
974 plus_constant (XEXP (registers, 0),
975 size)),
976 tem);
977 size += GET_MODE_SIZE (mode);
980 /* Save the arg pointer to the block. */
981 emit_move_insn (change_address (registers, Pmode, XEXP (registers, 0)),
982 copy_to_reg (virtual_incoming_args_rtx));
983 size = GET_MODE_SIZE (Pmode);
985 /* Save the structure value address unless this is passed as an
986 "invisible" first argument. */
987 if (struct_value_incoming_rtx)
989 emit_move_insn (change_address (registers, Pmode,
990 plus_constant (XEXP (registers, 0),
991 size)),
992 copy_to_reg (struct_value_incoming_rtx));
993 size += GET_MODE_SIZE (Pmode);
996 /* Return the address of the block. */
997 return copy_addr_to_reg (XEXP (registers, 0));
1000 /* __builtin_apply_args returns block of memory allocated on
1001 the stack into which is stored the arg pointer, structure
1002 value address, static chain, and all the registers that might
1003 possibly be used in performing a function call. The code is
1004 moved to the start of the function so the incoming values are
1005 saved. */
1006 static rtx
1007 expand_builtin_apply_args ()
1009 /* Don't do __builtin_apply_args more than once in a function.
1010 Save the result of the first call and reuse it. */
1011 if (apply_args_value != 0)
1012 return apply_args_value;
1014 /* When this function is called, it means that registers must be
1015 saved on entry to this function. So we migrate the
1016 call to the first insn of this function. */
1017 rtx temp;
1018 rtx seq;
1020 start_sequence ();
1021 temp = expand_builtin_apply_args_1 ();
1022 seq = get_insns ();
1023 end_sequence ();
1025 apply_args_value = temp;
1027 /* Put the sequence after the NOTE that starts the function.
1028 If this is inside a SEQUENCE, make the outer-level insn
1029 chain current, so the code is placed at the start of the
1030 function. */
1031 push_topmost_sequence ();
1032 emit_insns_before (seq, NEXT_INSN (get_insns ()));
1033 pop_topmost_sequence ();
1034 return temp;
1038 /* Perform an untyped call and save the state required to perform an
1039 untyped return of whatever value was returned by the given function. */
1041 static rtx
1042 expand_builtin_apply (function, arguments, argsize)
1043 rtx function, arguments, argsize;
1045 int size, align, regno;
1046 enum machine_mode mode;
1047 rtx incoming_args, result, reg, dest, call_insn;
1048 rtx old_stack_level = 0;
1049 rtx call_fusage = 0;
1051 /* Create a block where the return registers can be saved. */
1052 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1054 /* Fetch the arg pointer from the ARGUMENTS block. */
1055 incoming_args = gen_reg_rtx (Pmode);
1056 emit_move_insn (incoming_args,
1057 gen_rtx_MEM (Pmode, arguments));
1058 #ifndef STACK_GROWS_DOWNWARD
1059 incoming_args = expand_binop (Pmode, sub_optab, incoming_args, argsize,
1060 incoming_args, 0, OPTAB_LIB_WIDEN);
1061 #endif
1063 /* Perform postincrements before actually calling the function. */
1064 emit_queue ();
1066 /* Push a new argument block and copy the arguments. Do not allow
1067 the (potential) memcpy call below to interfere with our stack
1068 manipulations. */
1069 do_pending_stack_adjust ();
1070 NO_DEFER_POP;
1072 /* Save the stack with nonlocal if available */
1073 #ifdef HAVE_save_stack_nonlocal
1074 if (HAVE_save_stack_nonlocal)
1075 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1076 else
1077 #endif
1078 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1080 /* Push a block of memory onto the stack to store the memory arguments.
1081 Save the address in a register, and copy the memory arguments. ??? I
1082 haven't figured out how the calling convention macros effect this,
1083 but it's likely that the source and/or destination addresses in
1084 the block copy will need updating in machine specific ways. */
1085 dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1086 emit_block_move (gen_rtx_MEM (BLKmode, dest),
1087 gen_rtx_MEM (BLKmode, incoming_args),
1088 argsize, PARM_BOUNDARY);
1090 /* Refer to the argument block. */
1091 apply_args_size ();
1092 arguments = gen_rtx_MEM (BLKmode, arguments);
1094 /* Walk past the arg-pointer and structure value address. */
1095 size = GET_MODE_SIZE (Pmode);
1096 if (struct_value_rtx)
1097 size += GET_MODE_SIZE (Pmode);
1099 /* Restore each of the registers previously saved. Make USE insns
1100 for each of these registers for use in making the call. */
1101 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1102 if ((mode = apply_args_mode[regno]) != VOIDmode)
1104 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1105 if (size % align != 0)
1106 size = CEIL (size, align) * align;
1107 reg = gen_rtx_REG (mode, regno);
1108 emit_move_insn (reg,
1109 change_address (arguments, mode,
1110 plus_constant (XEXP (arguments, 0),
1111 size)));
1113 use_reg (&call_fusage, reg);
1114 size += GET_MODE_SIZE (mode);
1117 /* Restore the structure value address unless this is passed as an
1118 "invisible" first argument. */
1119 size = GET_MODE_SIZE (Pmode);
1120 if (struct_value_rtx)
1122 rtx value = gen_reg_rtx (Pmode);
1123 emit_move_insn (value,
1124 change_address (arguments, Pmode,
1125 plus_constant (XEXP (arguments, 0),
1126 size)));
1127 emit_move_insn (struct_value_rtx, value);
1128 if (GET_CODE (struct_value_rtx) == REG)
1129 use_reg (&call_fusage, struct_value_rtx);
1130 size += GET_MODE_SIZE (Pmode);
1133 /* All arguments and registers used for the call are set up by now! */
1134 function = prepare_call_address (function, NULL_TREE, &call_fusage, 0);
1136 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1137 and we don't want to load it into a register as an optimization,
1138 because prepare_call_address already did it if it should be done. */
1139 if (GET_CODE (function) != SYMBOL_REF)
1140 function = memory_address (FUNCTION_MODE, function);
1142 /* Generate the actual call instruction and save the return value. */
1143 #ifdef HAVE_untyped_call
1144 if (HAVE_untyped_call)
1145 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1146 result, result_vector (1, result)));
1147 else
1148 #endif
1149 #ifdef HAVE_call_value
1150 if (HAVE_call_value)
1152 rtx valreg = 0;
1154 /* Locate the unique return register. It is not possible to
1155 express a call that sets more than one return register using
1156 call_value; use untyped_call for that. In fact, untyped_call
1157 only needs to save the return registers in the given block. */
1158 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1159 if ((mode = apply_result_mode[regno]) != VOIDmode)
1161 if (valreg)
1162 abort (); /* HAVE_untyped_call required. */
1163 valreg = gen_rtx_REG (mode, regno);
1166 emit_call_insn (GEN_CALL_VALUE (valreg,
1167 gen_rtx_MEM (FUNCTION_MODE, function),
1168 const0_rtx, NULL_RTX, const0_rtx));
1170 emit_move_insn (change_address (result, GET_MODE (valreg),
1171 XEXP (result, 0)),
1172 valreg);
1174 else
1175 #endif
1176 abort ();
1178 /* Find the CALL insn we just emitted. */
1179 for (call_insn = get_last_insn ();
1180 call_insn && GET_CODE (call_insn) != CALL_INSN;
1181 call_insn = PREV_INSN (call_insn))
1184 if (! call_insn)
1185 abort ();
1187 /* Put the register usage information on the CALL. If there is already
1188 some usage information, put ours at the end. */
1189 if (CALL_INSN_FUNCTION_USAGE (call_insn))
1191 rtx link;
1193 for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
1194 link = XEXP (link, 1))
1197 XEXP (link, 1) = call_fusage;
1199 else
1200 CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
1202 /* Restore the stack. */
1203 #ifdef HAVE_save_stack_nonlocal
1204 if (HAVE_save_stack_nonlocal)
1205 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1206 else
1207 #endif
1208 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1210 OK_DEFER_POP;
1212 /* Return the address of the result block. */
1213 return copy_addr_to_reg (XEXP (result, 0));
1216 /* Perform an untyped return. */
1218 static void
1219 expand_builtin_return (result)
1220 rtx result;
1222 int size, align, regno;
1223 enum machine_mode mode;
1224 rtx reg;
1225 rtx call_fusage = 0;
1227 apply_result_size ();
1228 result = gen_rtx_MEM (BLKmode, result);
1230 #ifdef HAVE_untyped_return
1231 if (HAVE_untyped_return)
1233 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1234 emit_barrier ();
1235 return;
1237 #endif
1239 /* Restore the return value and note that each value is used. */
1240 size = 0;
1241 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1242 if ((mode = apply_result_mode[regno]) != VOIDmode)
1244 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1245 if (size % align != 0)
1246 size = CEIL (size, align) * align;
1247 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1248 emit_move_insn (reg,
1249 change_address (result, mode,
1250 plus_constant (XEXP (result, 0),
1251 size)));
1253 push_to_sequence (call_fusage);
1254 emit_insn (gen_rtx_USE (VOIDmode, reg));
1255 call_fusage = get_insns ();
1256 end_sequence ();
1257 size += GET_MODE_SIZE (mode);
1260 /* Put the USE insns before the return. */
1261 emit_insns (call_fusage);
1263 /* Return whatever values was restored by jumping directly to the end
1264 of the function. */
1265 expand_null_return ();
1268 /* Expand a call to __builtin_classify_type with arguments found in
1269 ARGLIST. */
1270 static rtx
1271 expand_builtin_classify_type (arglist)
1272 tree arglist;
1274 if (arglist != 0)
1276 tree type = TREE_TYPE (TREE_VALUE (arglist));
1277 enum tree_code code = TREE_CODE (type);
1278 if (code == VOID_TYPE)
1279 return GEN_INT (void_type_class);
1280 if (code == INTEGER_TYPE)
1281 return GEN_INT (integer_type_class);
1282 if (code == CHAR_TYPE)
1283 return GEN_INT (char_type_class);
1284 if (code == ENUMERAL_TYPE)
1285 return GEN_INT (enumeral_type_class);
1286 if (code == BOOLEAN_TYPE)
1287 return GEN_INT (boolean_type_class);
1288 if (code == POINTER_TYPE)
1289 return GEN_INT (pointer_type_class);
1290 if (code == REFERENCE_TYPE)
1291 return GEN_INT (reference_type_class);
1292 if (code == OFFSET_TYPE)
1293 return GEN_INT (offset_type_class);
1294 if (code == REAL_TYPE)
1295 return GEN_INT (real_type_class);
1296 if (code == COMPLEX_TYPE)
1297 return GEN_INT (complex_type_class);
1298 if (code == FUNCTION_TYPE)
1299 return GEN_INT (function_type_class);
1300 if (code == METHOD_TYPE)
1301 return GEN_INT (method_type_class);
1302 if (code == RECORD_TYPE)
1303 return GEN_INT (record_type_class);
1304 if (code == UNION_TYPE || code == QUAL_UNION_TYPE)
1305 return GEN_INT (union_type_class);
1306 if (code == ARRAY_TYPE)
1308 if (TYPE_STRING_FLAG (type))
1309 return GEN_INT (string_type_class);
1310 else
1311 return GEN_INT (array_type_class);
1313 if (code == SET_TYPE)
1314 return GEN_INT (set_type_class);
1315 if (code == FILE_TYPE)
1316 return GEN_INT (file_type_class);
1317 if (code == LANG_TYPE)
1318 return GEN_INT (lang_type_class);
1320 return GEN_INT (no_type_class);
1323 /* Expand expression EXP, which is a call to __builtin_constant_p. */
1324 static rtx
1325 expand_builtin_constant_p (exp)
1326 tree exp;
1328 tree arglist = TREE_OPERAND (exp, 1);
1329 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1330 rtx tmp;
1332 if (arglist == 0)
1333 return const0_rtx;
1334 arglist = TREE_VALUE (arglist);
1336 /* We have taken care of the easy cases during constant folding. This
1337 case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE get a
1338 chance to see if it can deduce whether ARGLIST is constant. */
1340 tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
1341 tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
1342 return tmp;
1345 /* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1346 Return 0 if a normal call should be emitted rather than expanding the
1347 function in-line. EXP is the expression that is a call to the builtin
1348 function; if convenient, the result should be placed in TARGET.
1349 SUBTARGET may be used as the target for computing one of EXP's operands. */
1350 static rtx
1351 expand_builtin_mathfn (exp, target, subtarget)
1352 tree exp;
1353 rtx target, subtarget;
1355 optab builtin_optab;
1356 rtx op0, insns;
1357 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1358 tree arglist = TREE_OPERAND (exp, 1);
1360 if (arglist == 0
1361 /* Arg could be wrong type if user redeclared this fcn wrong. */
1362 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
1363 return 0;
1365 /* Stabilize and compute the argument. */
1366 if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
1367 && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
1369 exp = copy_node (exp);
1370 TREE_OPERAND (exp, 1) = arglist;
1371 /* Wrap the computation of the argument in a SAVE_EXPR. That
1372 way, if we need to expand the argument again (as in the
1373 flag_errno_math case below where we cannot directly set
1374 errno), we will not perform side-effects more than once.
1375 Note that here we're mutating the original EXP as well as the
1376 copy; that's the right thing to do in case the original EXP
1377 is expanded later. */
1378 TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
1379 arglist = copy_node (arglist);
1381 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
1383 /* Make a suitable register to place result in. */
1384 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
1386 emit_queue ();
1387 start_sequence ();
1389 switch (DECL_FUNCTION_CODE (fndecl))
1391 case BUILT_IN_SIN:
1392 builtin_optab = sin_optab; break;
1393 case BUILT_IN_COS:
1394 builtin_optab = cos_optab; break;
1395 case BUILT_IN_FSQRT:
1396 builtin_optab = sqrt_optab; break;
1397 default:
1398 abort ();
1401 /* Compute into TARGET.
1402 Set TARGET to wherever the result comes back. */
1403 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
1404 builtin_optab, op0, target, 0);
1406 /* If we were unable to expand via the builtin, stop the
1407 sequence (without outputting the insns) and return 0, causing
1408 a call to the library function. */
1409 if (target == 0)
1411 end_sequence ();
1412 return 0;
1415 /* Check the results by default. But if flag_fast_math is turned on,
1416 then assume sqrt will always be called with valid arguments. */
1418 if (flag_errno_math && ! flag_fast_math)
1420 rtx lab1;
1422 /* Don't define the builtin FP instructions
1423 if your machine is not IEEE. */
1424 if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
1425 abort ();
1427 lab1 = gen_label_rtx ();
1429 /* Test the result; if it is NaN, set errno=EDOM because
1430 the argument was not in the domain. */
1431 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1432 0, 0, lab1);
1434 #ifdef TARGET_EDOM
1436 #ifdef GEN_ERRNO_RTX
1437 rtx errno_rtx = GEN_ERRNO_RTX;
1438 #else
1439 rtx errno_rtx
1440 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1441 #endif
1443 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1445 #else
1446 /* We can't set errno=EDOM directly; let the library call do it.
1447 Pop the arguments right away in case the call gets deleted. */
1448 NO_DEFER_POP;
1449 expand_call (exp, target, 0);
1450 OK_DEFER_POP;
1451 #endif
1453 emit_label (lab1);
1456 /* Output the entire sequence. */
1457 insns = get_insns ();
1458 end_sequence ();
1459 emit_insns (insns);
1461 return target;
1464 /* Expand expression EXP which is a call to the strlen builtin. Return 0
1465 if we failed the caller should emit a normal call, otherwise
1466 try to get the result in TARGET, if convenient. */
1468 static rtx
1469 expand_builtin_strlen (exp, target)
1470 tree exp;
1471 rtx target;
1473 tree arglist = TREE_OPERAND (exp, 1);
1474 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1476 if (arglist == 0
1477 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1478 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
1479 return 0;
1480 else
1482 rtx pat;
1483 tree src = TREE_VALUE (arglist);
1485 int align
1486 = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1488 rtx result, src_reg, char_rtx, before_strlen;
1489 enum machine_mode insn_mode = value_mode, char_mode;
1490 enum insn_code icode = CODE_FOR_nothing;
1492 /* If SRC is not a pointer type, don't do this operation inline. */
1493 if (align == 0)
1494 return 0;
1496 /* Bail out if we can't compute strlen in the right mode. */
1497 while (insn_mode != VOIDmode)
1499 icode = strlen_optab->handlers[(int) insn_mode].insn_code;
1500 if (icode != CODE_FOR_nothing)
1501 break;
1503 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
1505 if (insn_mode == VOIDmode)
1506 return 0;
1508 /* Make a place to write the result of the instruction. */
1509 result = target;
1510 if (! (result != 0
1511 && GET_CODE (result) == REG
1512 && GET_MODE (result) == insn_mode
1513 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1514 result = gen_reg_rtx (insn_mode);
1516 /* Make a place to hold the source address. We will not expand
1517 the actual source until we are sure that the expansion will
1518 not fail -- there are trees that cannot be expanded twice. */
1519 src_reg = gen_reg_rtx (Pmode);
1521 /* Mark the beginning of the strlen sequence so we can emit the
1522 source operand later. */
1523 before_strlen = get_last_insn();
1525 /* Check the string is readable and has an end. */
1526 if (current_function_check_memory_usage)
1527 emit_library_call (chkr_check_str_libfunc, LCT_CONST_MAKE_BLOCK,
1528 VOIDmode, 2, src_reg, Pmode,
1529 GEN_INT (MEMORY_USE_RO),
1530 TYPE_MODE (integer_type_node));
1532 char_rtx = const0_rtx;
1533 char_mode = insn_data[(int) icode].operand[2].mode;
1534 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
1535 char_mode))
1536 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
1538 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
1539 char_rtx, GEN_INT (align));
1540 if (! pat)
1541 return 0;
1542 emit_insn (pat);
1544 /* Now that we are assured of success, expand the source. */
1545 start_sequence ();
1546 pat = memory_address (BLKmode,
1547 expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
1548 if (pat != src_reg)
1549 emit_move_insn (src_reg, pat);
1550 pat = gen_sequence ();
1551 end_sequence ();
1553 if (before_strlen)
1554 emit_insn_after (pat, before_strlen);
1555 else
1556 emit_insn_before (pat, get_insns ());
1558 /* Return the value in the proper mode for this function. */
1559 if (GET_MODE (result) == value_mode)
1560 target = result;
1561 else if (target != 0)
1562 convert_move (target, result, 0);
1563 else
1564 target = convert_to_mode (value_mode, result, 0);
1566 return target;
1570 /* Expand a call to the strstr builtin. Return 0 if we failed the
1571 caller should emit a normal call, otherwise try to get the result
1572 in TARGET, if convenient (and in mode MODE if that's convenient). */
1574 static rtx
1575 expand_builtin_strstr (arglist, target, mode)
1576 tree arglist;
1577 rtx target;
1578 enum machine_mode mode;
1580 if (arglist == 0
1581 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1582 || TREE_CHAIN (arglist) == 0
1583 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
1584 || current_function_check_memory_usage)
1585 return 0;
1586 else
1588 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1589 tree call_expr, fn;
1590 const char *p1, *p2;
1592 p2 = c_getstr (s2);
1593 if (p2 == NULL)
1594 return 0;
1596 p1 = c_getstr (s1);
1597 if (p1 != NULL)
1599 const char *r = strstr (p1, p2);
1601 if (r == NULL)
1602 return const0_rtx;
1604 /* Return an offset into the constant string argument. */
1605 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1606 s1, ssize_int (r - p1))),
1607 target, mode, EXPAND_NORMAL);
1610 if (p2[0] == '\0')
1611 return expand_expr (s1, target, mode, EXPAND_NORMAL);
1613 if (p2[1] != '\0')
1614 return 0;
1616 fn = built_in_decls[BUILT_IN_STRCHR];
1617 if (!fn)
1618 return 0;
1620 /* New argument list transforming strstr(s1, s2) to
1621 strchr(s1, s2[0]). */
1622 arglist =
1623 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
1624 arglist = tree_cons (NULL_TREE, s1, arglist);
1625 call_expr = build1 (ADDR_EXPR,
1626 build_pointer_type (TREE_TYPE (fn)), fn);
1627 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
1628 call_expr, arglist, NULL_TREE);
1629 TREE_SIDE_EFFECTS (call_expr) = 1;
1630 return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
1634 /* Expand a call to the strchr builtin. Return 0 if we failed the
1635 caller should emit a normal call, otherwise try to get the result
1636 in TARGET, if convenient (and in mode MODE if that's convenient). */
1638 static rtx
1639 expand_builtin_strchr (arglist, target, mode)
1640 tree arglist;
1641 rtx target;
1642 enum machine_mode mode;
1644 if (arglist == 0
1645 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1646 || TREE_CHAIN (arglist) == 0
1647 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != INTEGER_TYPE
1648 || current_function_check_memory_usage)
1649 return 0;
1650 else
1652 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1653 const char *p1;
1655 if (TREE_CODE (s2) != INTEGER_CST)
1656 return 0;
1658 p1 = c_getstr (s1);
1659 if (p1 != NULL)
1661 char c;
1662 const char *r;
1664 if (target_char_cast (s2, &c))
1665 return 0;
1667 r = strchr (p1, c);
1669 if (r == NULL)
1670 return const0_rtx;
1672 /* Return an offset into the constant string argument. */
1673 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1674 s1, ssize_int (r - p1))),
1675 target, mode, EXPAND_NORMAL);
1678 /* FIXME: Should use here strchrM optab so that ports can optimize
1679 this. */
1680 return 0;
1684 /* Expand a call to the strrchr builtin. Return 0 if we failed the
1685 caller should emit a normal call, otherwise try to get the result
1686 in TARGET, if convenient (and in mode MODE if that's convenient). */
1688 static rtx
1689 expand_builtin_strrchr (arglist, target, mode)
1690 tree arglist;
1691 rtx target;
1692 enum machine_mode mode;
1694 if (arglist == 0
1695 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1696 || TREE_CHAIN (arglist) == 0
1697 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != INTEGER_TYPE
1698 || current_function_check_memory_usage)
1699 return 0;
1700 else
1702 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1703 tree call_expr, fn;
1704 const char *p1;
1706 if (TREE_CODE (s2) != INTEGER_CST)
1707 return 0;
1709 p1 = c_getstr (s1);
1710 if (p1 != NULL)
1712 char c;
1713 const char *r;
1715 if (target_char_cast (s2, &c))
1716 return 0;
1718 r = strrchr (p1, c);
1720 if (r == NULL)
1721 return const0_rtx;
1723 /* Return an offset into the constant string argument. */
1724 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1725 s1, ssize_int (r - p1))),
1726 target, mode, EXPAND_NORMAL);
1729 if (! integer_zerop (s2))
1730 return 0;
1732 fn = built_in_decls[BUILT_IN_STRCHR];
1733 if (!fn)
1734 return 0;
1736 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
1737 call_expr = build1 (ADDR_EXPR,
1738 build_pointer_type (TREE_TYPE (fn)), fn);
1739 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
1740 call_expr, arglist, NULL_TREE);
1741 TREE_SIDE_EFFECTS (call_expr) = 1;
1742 return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
1746 /* Expand a call to the strpbrk builtin. Return 0 if we failed the
1747 caller should emit a normal call, otherwise try to get the result
1748 in TARGET, if convenient (and in mode MODE if that's convenient). */
1750 static rtx
1751 expand_builtin_strpbrk (arglist, target, mode)
1752 tree arglist;
1753 rtx target;
1754 enum machine_mode mode;
1756 if (arglist == 0
1757 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1758 || TREE_CHAIN (arglist) == 0
1759 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
1760 || current_function_check_memory_usage)
1761 return 0;
1762 else
1764 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1765 tree call_expr, fn;
1766 const char *p1, *p2;
1768 p2 = c_getstr (s2);
1769 if (p2 == NULL)
1770 return 0;
1772 p1 = c_getstr (s1);
1773 if (p1 != NULL)
1775 const char *r = strpbrk (p1, p2);
1777 if (r == NULL)
1778 return const0_rtx;
1780 /* Return an offset into the constant string argument. */
1781 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1782 s1, ssize_int (r - p1))),
1783 target, mode, EXPAND_NORMAL);
1786 if (p2[0] == '\0')
1788 /* strpbrk(x, "") == NULL.
1789 Evaluate and ignore the arguments in case they had
1790 side-effects. */
1791 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
1792 return const0_rtx;
1795 if (p2[1] != '\0')
1796 return 0; /* Really call strpbrk. */
1798 fn = built_in_decls[BUILT_IN_STRCHR];
1799 if (!fn)
1800 return 0;
1802 /* New argument list transforming strpbrk(s1, s2) to
1803 strchr(s1, s2[0]). */
1804 arglist =
1805 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
1806 arglist = tree_cons (NULL_TREE, s1, arglist);
1807 call_expr = build1 (ADDR_EXPR,
1808 build_pointer_type (TREE_TYPE (fn)), fn);
1809 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
1810 call_expr, arglist, NULL_TREE);
1811 TREE_SIDE_EFFECTS (call_expr) = 1;
1812 return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
1816 /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
1817 bytes from constant string DATA + OFFSET and return it as target
1818 constant. */
1820 static rtx
1821 builtin_memcpy_read_str (data, offset, mode)
1822 PTR data;
1823 HOST_WIDE_INT offset;
1824 enum machine_mode mode;
1826 const char *str = (const char *) data;
1828 if (offset + GET_MODE_SIZE (mode) > strlen (str) + 1)
1829 abort (); /* Attempt to read past the end of constant string. */
1831 return c_readstr (str + offset, mode);
1834 /* Expand a call to the memcpy builtin, with arguments in ARGLIST. */
1835 static rtx
1836 expand_builtin_memcpy (arglist)
1837 tree arglist;
1839 if (arglist == 0
1840 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1841 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1842 || TREE_CHAIN (arglist) == 0
1843 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1844 != POINTER_TYPE)
1845 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1846 || (TREE_CODE (TREE_TYPE (TREE_VALUE
1847 (TREE_CHAIN (TREE_CHAIN (arglist)))))
1848 != INTEGER_TYPE))
1849 return 0;
1850 else
1852 tree dest = TREE_VALUE (arglist);
1853 tree src = TREE_VALUE (TREE_CHAIN (arglist));
1854 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1855 const char *src_str;
1857 int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
1858 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
1859 rtx dest_mem, src_mem, dest_addr, len_rtx;
1861 /* If either SRC or DEST is not a pointer type, don't do
1862 this operation in-line. */
1863 if (src_align == 0 || dest_align == 0)
1864 return 0;
1866 dest_mem = get_memory_rtx (dest);
1867 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1868 src_str = c_getstr (src);
1870 /* If SRC is a string constant and block move would be done
1871 by pieces, we can avoid loading the string from memory
1872 and only stored the computed constants. */
1873 if (src_str
1874 && !current_function_check_memory_usage
1875 && GET_CODE (len_rtx) == CONST_INT
1876 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
1877 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
1878 (PTR) src_str, dest_align))
1880 store_by_pieces (dest_mem, INTVAL (len_rtx),
1881 builtin_memcpy_read_str,
1882 (PTR) src_str, dest_align);
1883 return force_operand (XEXP (dest_mem, 0), NULL_RTX);
1886 src_mem = get_memory_rtx (src);
1888 /* Just copy the rights of SRC to the rights of DEST. */
1889 if (current_function_check_memory_usage)
1890 emit_library_call (chkr_copy_bitmap_libfunc, LCT_CONST_MAKE_BLOCK,
1891 VOIDmode, 3, XEXP (dest_mem, 0), Pmode,
1892 XEXP (src_mem, 0), Pmode,
1893 len_rtx, TYPE_MODE (sizetype));
1895 /* Copy word part most expediently. */
1896 dest_addr
1897 = emit_block_move (dest_mem, src_mem, len_rtx,
1898 MIN (src_align, dest_align));
1900 if (dest_addr == 0)
1901 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
1903 return dest_addr;
1907 /* Expand expression EXP, which is a call to the strcpy builtin. Return 0
1908 if we failed the caller should emit a normal call. */
1910 static rtx
1911 expand_builtin_strcpy (exp)
1912 tree exp;
1914 tree arglist = TREE_OPERAND (exp, 1);
1915 rtx result;
1917 if (arglist == 0
1918 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1919 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1920 || TREE_CHAIN (arglist) == 0
1921 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1922 != POINTER_TYPE))
1923 return 0;
1924 else
1926 tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
1928 if (len == 0)
1929 return 0;
1931 len = size_binop (PLUS_EXPR, len, ssize_int (1));
1932 chainon (arglist, build_tree_list (NULL_TREE, len));
1935 result = expand_builtin_memcpy (arglist);
1937 if (! result)
1938 TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
1939 return result;
1942 /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
1943 bytes from constant string DATA + OFFSET and return it as target
1944 constant. */
1946 static rtx
1947 builtin_strncpy_read_str (data, offset, mode)
1948 PTR data;
1949 HOST_WIDE_INT offset;
1950 enum machine_mode mode;
1952 const char *str = (const char *) data;
1954 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
1955 return const0_rtx;
1957 return c_readstr (str + offset, mode);
1960 /* Expand expression EXP, which is a call to the strncpy builtin. Return 0
1961 if we failed the caller should emit a normal call. */
1963 static rtx
1964 expand_builtin_strncpy (arglist, target, mode)
1965 tree arglist;
1966 rtx target;
1967 enum machine_mode mode;
1969 if (arglist == 0
1970 /* Arg could be non-pointer if user redeclared this fcn wrong. */
1971 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
1972 || TREE_CHAIN (arglist) == 0
1973 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
1974 != POINTER_TYPE)
1975 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
1976 || (TREE_CODE (TREE_TYPE (TREE_VALUE
1977 (TREE_CHAIN (TREE_CHAIN (arglist)))))
1978 != INTEGER_TYPE))
1979 return 0;
1980 else
1982 tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
1983 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1985 /* We must be passed a constant len parameter. */
1986 if (TREE_CODE (len) != INTEGER_CST)
1987 return 0;
1989 /* If the len parameter is zero, return the dst parameter. */
1990 if (compare_tree_int (len, 0) == 0)
1992 /* Evaluate and ignore the src argument in case it has
1993 side-effects. */
1994 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
1995 VOIDmode, EXPAND_NORMAL);
1996 /* Return the dst parameter. */
1997 return expand_expr (TREE_VALUE (arglist), target, mode,
1998 EXPAND_NORMAL);
2001 /* Now, we must be passed a constant src ptr parameter. */
2002 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
2003 return 0;
2005 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
2007 /* We're required to pad with trailing zeros if the requested
2008 len is greater than strlen(s2)+1. In that case try to
2009 use store_by_pieces, if it fails, punt. */
2010 if (tree_int_cst_lt (slen, len))
2012 tree dest = TREE_VALUE (arglist);
2013 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2014 const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
2015 rtx dest_mem;
2017 if (!p || !dest_align || TREE_INT_CST_HIGH (len)
2018 || !can_store_by_pieces (TREE_INT_CST_LOW (len),
2019 builtin_strncpy_read_str,
2020 (PTR) p, dest_align))
2021 return 0;
2023 dest_mem = get_memory_rtx (dest);
2024 store_by_pieces (dest_mem, TREE_INT_CST_LOW (len),
2025 builtin_strncpy_read_str,
2026 (PTR) p, dest_align);
2027 return force_operand (XEXP (dest_mem, 0), NULL_RTX);
2030 /* OK transform into builtin memcpy. */
2031 return expand_builtin_memcpy (arglist);
2035 /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2036 bytes from constant string DATA + OFFSET and return it as target
2037 constant. */
2039 static rtx
2040 builtin_memset_read_str (data, offset, mode)
2041 PTR data;
2042 HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
2043 enum machine_mode mode;
2045 const char *c = (const char *) data;
2046 char *p = alloca (GET_MODE_SIZE (mode));
2048 memset (p, *c, GET_MODE_SIZE (mode));
2050 return c_readstr (p, mode);
2053 /* Expand expression EXP, which is a call to the memset builtin. Return 0
2054 if we failed the caller should emit a normal call. */
2056 static rtx
2057 expand_builtin_memset (exp)
2058 tree exp;
2060 tree arglist = TREE_OPERAND (exp, 1);
2062 if (arglist == 0
2063 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2064 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
2065 || TREE_CHAIN (arglist) == 0
2066 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
2067 != INTEGER_TYPE)
2068 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
2069 || (INTEGER_TYPE
2070 != (TREE_CODE (TREE_TYPE
2071 (TREE_VALUE
2072 (TREE_CHAIN (TREE_CHAIN (arglist))))))))
2073 return 0;
2074 else
2076 tree dest = TREE_VALUE (arglist);
2077 tree val = TREE_VALUE (TREE_CHAIN (arglist));
2078 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2079 char c;
2081 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2082 rtx dest_mem, dest_addr, len_rtx;
2084 /* If DEST is not a pointer type, don't do this
2085 operation in-line. */
2086 if (dest_align == 0)
2087 return 0;
2089 if (TREE_CODE (val) != INTEGER_CST)
2090 return 0;
2092 if (target_char_cast (val, &c))
2093 return 0;
2095 if (c)
2097 if (TREE_CODE (len) != INTEGER_CST || TREE_INT_CST_HIGH (len))
2098 return 0;
2099 if (current_function_check_memory_usage
2100 || !can_store_by_pieces (TREE_INT_CST_LOW (len),
2101 builtin_memset_read_str,
2102 (PTR) &c, dest_align))
2103 return 0;
2105 dest_mem = get_memory_rtx (dest);
2106 store_by_pieces (dest_mem, TREE_INT_CST_LOW (len),
2107 builtin_memset_read_str,
2108 (PTR) &c, dest_align);
2109 return force_operand (XEXP (dest_mem, 0), NULL_RTX);
2112 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2114 dest_mem = get_memory_rtx (dest);
2116 /* Just check DST is writable and mark it as readable. */
2117 if (current_function_check_memory_usage)
2118 emit_library_call (chkr_check_addr_libfunc, LCT_CONST_MAKE_BLOCK,
2119 VOIDmode, 3, XEXP (dest_mem, 0), Pmode,
2120 len_rtx, TYPE_MODE (sizetype),
2121 GEN_INT (MEMORY_USE_WO),
2122 TYPE_MODE (integer_type_node));
2125 dest_addr = clear_storage (dest_mem, len_rtx, dest_align);
2127 if (dest_addr == 0)
2128 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2130 return dest_addr;
2134 /* Expand expression EXP, which is a call to the bzero builtin. Return 0
2135 if we failed the caller should emit a normal call. */
2136 static rtx
2137 expand_builtin_bzero (exp)
2138 tree exp;
2140 tree arglist = TREE_OPERAND (exp, 1);
2141 tree dest, size, newarglist;
2142 rtx result;
2144 if (arglist == 0
2145 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2146 || TREE_CODE (TREE_TYPE (dest = TREE_VALUE (arglist))) != POINTER_TYPE
2147 || TREE_CHAIN (arglist) == 0
2148 || (TREE_CODE (TREE_TYPE (size = TREE_VALUE (TREE_CHAIN (arglist))))
2149 != INTEGER_TYPE))
2150 return NULL_RTX;
2152 /* New argument list transforming bzero(ptr x, int y) to
2153 memset(ptr x, int 0, size_t y). */
2155 newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
2156 newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
2157 newarglist = tree_cons (NULL_TREE, dest, newarglist);
2159 TREE_OPERAND (exp, 1) = newarglist;
2160 result = expand_builtin_memset(exp);
2162 /* Always restore the original arguments. */
2163 TREE_OPERAND (exp, 1) = arglist;
2165 return result;
2168 #ifdef HAVE_cmpstrsi
2169 /* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
2170 ARGLIST is the argument list for this call. Return 0 if we failed and the
2171 caller should emit a normal call, otherwise try to get the result in
2172 TARGET, if convenient. */
2173 static rtx
2174 expand_builtin_memcmp (exp, arglist, target)
2175 tree exp;
2176 tree arglist;
2177 rtx target;
2179 /* If we need to check memory accesses, call the library function. */
2180 if (current_function_check_memory_usage)
2181 return 0;
2183 if (arglist == 0
2184 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2185 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
2186 || TREE_CHAIN (arglist) == 0
2187 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
2188 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
2189 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
2190 return 0;
2193 enum machine_mode mode;
2194 tree arg1 = TREE_VALUE (arglist);
2195 tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2196 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2197 rtx arg1_rtx, arg2_rtx, arg3_rtx;
2198 rtx result;
2199 rtx insn;
2201 int arg1_align
2202 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2203 int arg2_align
2204 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2205 enum machine_mode insn_mode
2206 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
2208 /* If we don't have POINTER_TYPE, call the function. */
2209 if (arg1_align == 0 || arg2_align == 0)
2210 return 0;
2212 /* Make a place to write the result of the instruction. */
2213 result = target;
2214 if (! (result != 0
2215 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
2216 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2217 result = gen_reg_rtx (insn_mode);
2219 arg1_rtx = get_memory_rtx (arg1);
2220 arg2_rtx = get_memory_rtx (arg2);
2221 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2222 if (!HAVE_cmpstrsi)
2223 insn = NULL_RTX;
2224 else
2225 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
2226 GEN_INT (MIN (arg1_align, arg2_align)));
2228 if (insn)
2229 emit_insn (insn);
2230 else
2231 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
2232 TYPE_MODE (integer_type_node), 3,
2233 XEXP (arg1_rtx, 0), Pmode,
2234 XEXP (arg2_rtx, 0), Pmode,
2235 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
2236 TREE_UNSIGNED (sizetype)),
2237 TYPE_MODE (sizetype));
2239 /* Return the value in the proper mode for this function. */
2240 mode = TYPE_MODE (TREE_TYPE (exp));
2241 if (GET_MODE (result) == mode)
2242 return result;
2243 else if (target != 0)
2245 convert_move (target, result, 0);
2246 return target;
2248 else
2249 return convert_to_mode (mode, result, 0);
2252 #endif
2254 /* Expand expression EXP, which is a call to the strcmp builtin. Return 0
2255 if we failed the caller should emit a normal call, otherwise try to get
2256 the result in TARGET, if convenient. */
2258 static rtx
2259 expand_builtin_strcmp (exp, target, mode)
2260 tree exp;
2261 rtx target;
2262 enum machine_mode mode;
2264 tree arglist = TREE_OPERAND (exp, 1);
2265 tree arg1, arg2;
2266 const char *p1, *p2;
2268 /* If we need to check memory accesses, call the library function. */
2269 if (current_function_check_memory_usage)
2270 return 0;
2272 if (arglist == 0
2273 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2274 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
2275 || TREE_CHAIN (arglist) == 0
2276 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
2277 != POINTER_TYPE))
2278 return 0;
2280 arg1 = TREE_VALUE (arglist);
2281 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2283 p1 = c_getstr (arg1);
2284 p2 = c_getstr (arg2);
2286 if (p1 && p2)
2288 const int i = strcmp (p1, p2);
2289 return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
2292 /* If either arg is "", return an expression corresponding to
2293 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
2294 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2296 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2297 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2298 tree ind1 =
2299 fold (build1 (CONVERT_EXPR, integer_type_node,
2300 build1 (INDIRECT_REF, cst_uchar_node,
2301 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2302 tree ind2 =
2303 fold (build1 (CONVERT_EXPR, integer_type_node,
2304 build1 (INDIRECT_REF, cst_uchar_node,
2305 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2306 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2307 return expand_expr (result, target, mode, EXPAND_NORMAL);
2310 #ifdef HAVE_cmpstrsi
2311 if (! HAVE_cmpstrsi)
2312 return 0;
2315 tree len = c_strlen (arg1);
2316 tree len2 = c_strlen (arg2);
2317 rtx result;
2319 if (len)
2320 len = size_binop (PLUS_EXPR, ssize_int (1), len);
2322 if (len2)
2323 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
2325 /* If we don't have a constant length for the first, use the length
2326 of the second, if we know it. We don't require a constant for
2327 this case; some cost analysis could be done if both are available
2328 but neither is constant. For now, assume they're equally cheap
2329 unless one has side effects.
2331 If both strings have constant lengths, use the smaller. This
2332 could arise if optimization results in strcpy being called with
2333 two fixed strings, or if the code was machine-generated. We should
2334 add some code to the `memcmp' handler below to deal with such
2335 situations, someday. */
2337 if (!len || TREE_CODE (len) != INTEGER_CST)
2339 if (len2 && !TREE_SIDE_EFFECTS (len2))
2340 len = len2;
2341 else if (len == 0)
2342 return 0;
2344 else if (len2 && TREE_CODE (len2) == INTEGER_CST
2345 && tree_int_cst_lt (len2, len))
2346 len = len2;
2348 /* If both arguments have side effects, we cannot optimize. */
2349 if (TREE_SIDE_EFFECTS (len))
2350 return 0;
2352 chainon (arglist, build_tree_list (NULL_TREE, len));
2353 result = expand_builtin_memcmp (exp, arglist, target);
2354 if (! result)
2355 TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
2357 return result;
2359 #else
2360 return 0;
2361 #endif
2364 /* Expand expression EXP, which is a call to the strncmp builtin. Return 0
2365 if we failed the caller should emit a normal call, otherwise try to get
2366 the result in TARGET, if convenient. */
2367 static rtx
2368 expand_builtin_strncmp (exp, target, mode)
2369 tree exp;
2370 rtx target;
2371 enum machine_mode mode;
2373 tree arglist = TREE_OPERAND (exp, 1);
2374 tree arg1, arg2, arg3;
2375 const char *p1, *p2;
2377 /* If we need to check memory accesses, call the library function. */
2378 if (current_function_check_memory_usage)
2379 return 0;
2381 if (arglist == 0
2382 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2383 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
2384 || TREE_CHAIN (arglist) == 0
2385 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
2386 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
2387 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
2388 return 0;
2390 arg1 = TREE_VALUE (arglist);
2391 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2392 arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2394 /* We must be passed a constant len parameter. */
2395 if (TREE_CODE (arg3) != INTEGER_CST)
2396 return 0;
2398 /* If the len parameter is zero, return zero. */
2399 if (compare_tree_int (arg3, 0) == 0)
2401 /* Evaluate and ignore arg1 and arg2 in case they have
2402 side-effects. */
2403 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2404 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2405 return const0_rtx;
2408 p1 = c_getstr (arg1);
2409 p2 = c_getstr (arg2);
2411 /* If all arguments are constant, evaluate at compile-time. */
2412 if (p1 && p2)
2414 const int r = strncmp (p1, p2, TREE_INT_CST_LOW (arg3));
2415 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2418 /* If len == 1 or (either string parameter is "" and (len >= 1)),
2419 return (*(u_char*)arg1 - *(u_char*)arg2). */
2420 if (compare_tree_int (arg3, 1) == 0
2421 || (compare_tree_int (arg3, 1) > 0
2422 && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))))
2424 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2425 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2426 tree ind1 =
2427 fold (build1 (CONVERT_EXPR, integer_type_node,
2428 build1 (INDIRECT_REF, cst_uchar_node,
2429 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2430 tree ind2 =
2431 fold (build1 (CONVERT_EXPR, integer_type_node,
2432 build1 (INDIRECT_REF, cst_uchar_node,
2433 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2434 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2435 return expand_expr (result, target, mode, EXPAND_NORMAL);
2438 #ifdef HAVE_cmpstrsi
2439 /* If the length parameter is constant (checked above) and either
2440 string parameter is constant, call expand_builtin_memcmp() using
2441 a length parameter equal to the lesser of the given length and
2442 the strlen+1 of the constant string. */
2443 if (HAVE_cmpstrsi && (p1 || p2))
2445 /* Exactly one of the strings is constant at this point, because
2446 if both were then we'd have expanded this at compile-time. */
2447 tree string_len = p1 ? c_strlen (arg1) : c_strlen (arg2);
2449 string_len = size_binop (PLUS_EXPR, string_len, ssize_int (1));
2451 if (tree_int_cst_lt (string_len, arg3))
2453 /* The strlen+1 is strictly shorter, use it. */
2454 tree newarglist = build_tree_list (NULL_TREE, string_len);
2455 newarglist = tree_cons (NULL_TREE, arg2, newarglist);
2456 newarglist = tree_cons (NULL_TREE, arg1, newarglist);
2457 return expand_builtin_memcmp (exp, newarglist, target);
2459 else
2460 return expand_builtin_memcmp (exp, arglist, target);
2462 #endif
2464 return 0;
2467 /* Expand expression EXP, which is a call to the strcat builtin.
2468 Return 0 if we failed the caller should emit a normal call,
2469 otherwise try to get the result in TARGET, if convenient. */
2470 static rtx
2471 expand_builtin_strcat (arglist, target, mode)
2472 tree arglist;
2473 rtx target;
2474 enum machine_mode mode;
2476 /* If we need to check memory accesses, call the library function. */
2477 if (current_function_check_memory_usage)
2478 return 0;
2480 if (arglist == 0
2481 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2482 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
2483 || TREE_CHAIN (arglist) == 0
2484 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
2485 != POINTER_TYPE))
2486 return 0;
2487 else
2489 tree dst = TREE_VALUE (arglist),
2490 src = TREE_VALUE (TREE_CHAIN (arglist));
2491 const char *p = c_getstr (src);
2493 /* If the string length is zero, return the dst parameter. */
2494 if (p && *p == '\0')
2495 return expand_expr (dst, target, mode, EXPAND_NORMAL);
2497 return 0;
2501 /* Expand expression EXP, which is a call to the strncat builtin.
2502 Return 0 if we failed the caller should emit a normal call,
2503 otherwise try to get the result in TARGET, if convenient. */
2504 static rtx
2505 expand_builtin_strncat (arglist, target, mode)
2506 tree arglist;
2507 rtx target;
2508 enum machine_mode mode;
2510 /* If we need to check memory accesses, call the library function. */
2511 if (current_function_check_memory_usage)
2512 return 0;
2514 if (arglist == 0
2515 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2516 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
2517 || TREE_CHAIN (arglist) == 0
2518 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
2519 != POINTER_TYPE)
2520 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
2521 || (TREE_CODE (TREE_TYPE (TREE_VALUE
2522 (TREE_CHAIN (TREE_CHAIN (arglist)))))
2523 != INTEGER_TYPE))
2524 return 0;
2525 else
2527 tree dst = TREE_VALUE (arglist),
2528 src = TREE_VALUE (TREE_CHAIN (arglist)),
2529 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2530 const char *p = c_getstr (src);
2532 /* If the requested length is zero, or the src parameter string
2533 length is zero, return the dst parameter. */
2534 if ((TREE_CODE (len) == INTEGER_CST && compare_tree_int (len, 0) == 0)
2535 || (p && *p == '\0'))
2537 /* Evaluate and ignore the src and len parameters in case
2538 they have side-effects. */
2539 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2540 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2541 return expand_expr (dst, target, mode, EXPAND_NORMAL);
2544 /* If the requested len is greater than or equal to the string
2545 length, call strcat. */
2546 if (TREE_CODE (len) == INTEGER_CST && p
2547 && compare_tree_int (len, strlen (p)) >= 0)
2549 tree call_expr, newarglist =
2550 tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src)),
2551 fn = built_in_decls[BUILT_IN_STRCAT];
2553 /* If the replacement _DECL isn't initialized, don't do the
2554 transformation. */
2555 if (!fn)
2556 return 0;
2558 call_expr = build1 (ADDR_EXPR,
2559 build_pointer_type (TREE_TYPE (fn)), fn);
2560 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
2561 call_expr, newarglist, NULL_TREE);
2562 TREE_SIDE_EFFECTS (call_expr) = 1;
2563 return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
2565 return 0;
2569 /* Expand expression EXP, which is a call to the strspn builtin.
2570 Return 0 if we failed the caller should emit a normal call,
2571 otherwise try to get the result in TARGET, if convenient. */
2572 static rtx
2573 expand_builtin_strspn (arglist, target, mode)
2574 tree arglist;
2575 rtx target;
2576 enum machine_mode mode;
2578 /* If we need to check memory accesses, call the library function. */
2579 if (current_function_check_memory_usage)
2580 return 0;
2582 if (arglist == 0
2583 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2584 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
2585 || TREE_CHAIN (arglist) == 0
2586 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
2587 != POINTER_TYPE))
2588 return 0;
2589 else
2591 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2592 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2594 /* If both arguments are constants, evaluate at compile-time. */
2595 if (p1 && p2)
2597 const size_t r = strspn (p1, p2);
2598 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2601 /* If either argument is "", return 0. */
2602 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2604 /* Evaluate and ignore both arguments in case either one has
2605 side-effects. */
2606 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2607 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2608 return const0_rtx;
2610 return 0;
2614 /* Expand expression EXP, which is a call to the strcspn builtin.
2615 Return 0 if we failed the caller should emit a normal call,
2616 otherwise try to get the result in TARGET, if convenient. */
2617 static rtx
2618 expand_builtin_strcspn (arglist, target, mode)
2619 tree arglist;
2620 rtx target;
2621 enum machine_mode mode;
2623 /* If we need to check memory accesses, call the library function. */
2624 if (current_function_check_memory_usage)
2625 return 0;
2627 if (arglist == 0
2628 /* Arg could be non-pointer if user redeclared this fcn wrong. */
2629 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
2630 || TREE_CHAIN (arglist) == 0
2631 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
2632 != POINTER_TYPE))
2633 return 0;
2634 else
2636 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2637 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2639 /* If both arguments are constants, evaluate at compile-time. */
2640 if (p1 && p2)
2642 const size_t r = strcspn (p1, p2);
2643 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2646 /* If the first argument is "", return 0. */
2647 if (p1 && *p1 == '\0')
2649 /* Evaluate and ignore argument s2 in case it has
2650 side-effects. */
2651 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2652 return const0_rtx;
2655 /* If the second argument is "", return __builtin_strlen(s1). */
2656 if (p2 && *p2 == '\0')
2658 tree call_expr, newarglist = build_tree_list (NULL_TREE, s1),
2659 fn = built_in_decls[BUILT_IN_STRLEN];
2661 /* If the replacement _DECL isn't initialized, don't do the
2662 transformation. */
2663 if (!fn)
2664 return 0;
2666 call_expr = build1 (ADDR_EXPR,
2667 build_pointer_type (TREE_TYPE (fn)), fn);
2668 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
2669 call_expr, newarglist, NULL_TREE);
2670 TREE_SIDE_EFFECTS (call_expr) = 1;
2671 return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
2673 return 0;
2677 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
2678 if that's convenient. */
2681 expand_builtin_saveregs ()
2683 rtx val, seq;
2685 /* Don't do __builtin_saveregs more than once in a function.
2686 Save the result of the first call and reuse it. */
2687 if (saveregs_value != 0)
2688 return saveregs_value;
2690 /* When this function is called, it means that registers must be
2691 saved on entry to this function. So we migrate the call to the
2692 first insn of this function. */
2694 start_sequence ();
2696 #ifdef EXPAND_BUILTIN_SAVEREGS
2697 /* Do whatever the machine needs done in this case. */
2698 val = EXPAND_BUILTIN_SAVEREGS ();
2699 #else
2700 /* ??? We used to try and build up a call to the out of line function,
2701 guessing about what registers needed saving etc. This became much
2702 harder with __builtin_va_start, since we don't have a tree for a
2703 call to __builtin_saveregs to fall back on. There was exactly one
2704 port (i860) that used this code, and I'm unconvinced it could actually
2705 handle the general case. So we no longer try to handle anything
2706 weird and make the backend absorb the evil. */
2708 error ("__builtin_saveregs not supported by this target");
2709 val = const0_rtx;
2710 #endif
2712 seq = get_insns ();
2713 end_sequence ();
2715 saveregs_value = val;
2717 /* Put the sequence after the NOTE that starts the function. If this
2718 is inside a SEQUENCE, make the outer-level insn chain current, so
2719 the code is placed at the start of the function. */
2720 push_topmost_sequence ();
2721 emit_insns_after (seq, get_insns ());
2722 pop_topmost_sequence ();
2724 return val;
2727 /* __builtin_args_info (N) returns word N of the arg space info
2728 for the current function. The number and meanings of words
2729 is controlled by the definition of CUMULATIVE_ARGS. */
2731 static rtx
2732 expand_builtin_args_info (exp)
2733 tree exp;
2735 tree arglist = TREE_OPERAND (exp, 1);
2736 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
2737 int *word_ptr = (int *) &current_function_args_info;
2738 #if 0
2739 /* These are used by the code below that is if 0'ed away */
2740 int i;
2741 tree type, elts, result;
2742 #endif
2744 if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
2745 abort ();
2747 if (arglist != 0)
2749 tree arg = TREE_VALUE (arglist);
2750 if (TREE_CODE (arg) != INTEGER_CST)
2751 error ("argument of `__builtin_args_info' must be constant");
2752 else
2754 int wordnum = TREE_INT_CST_LOW (arg);
2756 if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg))
2757 error ("argument of `__builtin_args_info' out of range");
2758 else
2759 return GEN_INT (word_ptr[wordnum]);
2762 else
2763 error ("missing argument in `__builtin_args_info'");
2765 return const0_rtx;
2767 #if 0
2768 for (i = 0; i < nwords; i++)
2769 elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
2771 type = build_array_type (integer_type_node,
2772 build_index_type (build_int_2 (nwords, 0)));
2773 result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
2774 TREE_CONSTANT (result) = 1;
2775 TREE_STATIC (result) = 1;
2776 result = build1 (INDIRECT_REF, build_pointer_type (type), result);
2777 TREE_CONSTANT (result) = 1;
2778 return expand_expr (result, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD);
2779 #endif
2782 /* Expand ARGLIST, from a call to __builtin_next_arg. */
2783 static rtx
2784 expand_builtin_next_arg (arglist)
2785 tree arglist;
2787 tree fntype = TREE_TYPE (current_function_decl);
2789 if ((TYPE_ARG_TYPES (fntype) == 0
2790 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2791 == void_type_node))
2792 && ! current_function_varargs)
2794 error ("`va_start' used in function with fixed args");
2795 return const0_rtx;
2798 if (arglist)
2800 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
2801 tree arg = TREE_VALUE (arglist);
2803 /* Strip off all nops for the sake of the comparison. This
2804 is not quite the same as STRIP_NOPS. It does more.
2805 We must also strip off INDIRECT_EXPR for C++ reference
2806 parameters. */
2807 while (TREE_CODE (arg) == NOP_EXPR
2808 || TREE_CODE (arg) == CONVERT_EXPR
2809 || TREE_CODE (arg) == NON_LVALUE_EXPR
2810 || TREE_CODE (arg) == INDIRECT_REF)
2811 arg = TREE_OPERAND (arg, 0);
2812 if (arg != last_parm)
2813 warning ("second parameter of `va_start' not last named argument");
2815 else if (! current_function_varargs)
2816 /* Evidently an out of date version of <stdarg.h>; can't validate
2817 va_start's second argument, but can still work as intended. */
2818 warning ("`__builtin_next_arg' called without an argument");
2820 return expand_binop (Pmode, add_optab,
2821 current_function_internal_arg_pointer,
2822 current_function_arg_offset_rtx,
2823 NULL_RTX, 0, OPTAB_LIB_WIDEN);
2826 /* Make it easier for the backends by protecting the valist argument
2827 from multiple evaluations. */
2829 static tree
2830 stabilize_va_list (valist, needs_lvalue)
2831 tree valist;
2832 int needs_lvalue;
2834 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
2836 if (TREE_SIDE_EFFECTS (valist))
2837 valist = save_expr (valist);
2839 /* For this case, the backends will be expecting a pointer to
2840 TREE_TYPE (va_list_type_node), but it's possible we've
2841 actually been given an array (an actual va_list_type_node).
2842 So fix it. */
2843 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
2845 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
2846 tree p2 = build_pointer_type (va_list_type_node);
2848 valist = build1 (ADDR_EXPR, p2, valist);
2849 valist = fold (build1 (NOP_EXPR, p1, valist));
2852 else
2854 tree pt;
2856 if (! needs_lvalue)
2858 if (! TREE_SIDE_EFFECTS (valist))
2859 return valist;
2861 pt = build_pointer_type (va_list_type_node);
2862 valist = fold (build1 (ADDR_EXPR, pt, valist));
2863 TREE_SIDE_EFFECTS (valist) = 1;
2866 if (TREE_SIDE_EFFECTS (valist))
2867 valist = save_expr (valist);
2868 valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
2869 valist));
2872 return valist;
2875 /* The "standard" implementation of va_start: just assign `nextarg' to
2876 the variable. */
2877 void
2878 std_expand_builtin_va_start (stdarg_p, valist, nextarg)
2879 int stdarg_p;
2880 tree valist;
2881 rtx nextarg;
2883 tree t;
2885 if (! stdarg_p)
2887 int align = PARM_BOUNDARY / BITS_PER_UNIT;
2888 int offset = (((UNITS_PER_WORD + align - 1) / align) * align);
2889 nextarg = plus_constant (nextarg, -offset);
2892 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2893 make_tree (ptr_type_node, nextarg));
2894 TREE_SIDE_EFFECTS (t) = 1;
2896 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2899 /* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
2900 __builtin_varargs_va_start, depending on STDARG_P. */
2901 static rtx
2902 expand_builtin_va_start (stdarg_p, arglist)
2903 int stdarg_p;
2904 tree arglist;
2906 rtx nextarg;
2907 tree chain = arglist, valist;
2909 if (stdarg_p)
2910 nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
2911 else
2912 nextarg = expand_builtin_next_arg (NULL_TREE);
2914 if (TREE_CHAIN (chain))
2915 error ("too many arguments to function `va_start'");
2917 valist = stabilize_va_list (TREE_VALUE (arglist), 1);
2919 #ifdef EXPAND_BUILTIN_VA_START
2920 EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
2921 #else
2922 std_expand_builtin_va_start (stdarg_p, valist, nextarg);
2923 #endif
2925 return const0_rtx;
2928 /* The "standard" implementation of va_arg: read the value from the
2929 current (padded) address and increment by the (padded) size. */
2932 std_expand_builtin_va_arg (valist, type)
2933 tree valist, type;
2935 tree addr_tree, t;
2936 HOST_WIDE_INT align;
2937 HOST_WIDE_INT rounded_size;
2938 rtx addr;
2940 /* Compute the rounded size of the type. */
2941 align = PARM_BOUNDARY / BITS_PER_UNIT;
2942 rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
2944 /* Get AP. */
2945 addr_tree = valist;
2946 if (PAD_VARARGS_DOWN)
2948 /* Small args are padded downward. */
2950 HOST_WIDE_INT adj;
2951 adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT;
2952 if (rounded_size > align)
2953 adj = rounded_size;
2955 addr_tree = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
2956 build_int_2 (rounded_size - adj, 0));
2959 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2960 addr = copy_to_reg (addr);
2962 /* Compute new value for AP. */
2963 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2964 build (PLUS_EXPR, TREE_TYPE (valist), valist,
2965 build_int_2 (rounded_size, 0)));
2966 TREE_SIDE_EFFECTS (t) = 1;
2967 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2969 return addr;
2972 /* Expand __builtin_va_arg, which is not really a builtin function, but
2973 a very special sort of operator. */
2976 expand_builtin_va_arg (valist, type)
2977 tree valist, type;
2979 rtx addr, result;
2980 tree promoted_type, want_va_type, have_va_type;
2982 /* Verify that valist is of the proper type. */
2984 want_va_type = va_list_type_node;
2985 have_va_type = TREE_TYPE (valist);
2986 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
2988 /* If va_list is an array type, the argument may have decayed
2989 to a pointer type, e.g. by being passed to another function.
2990 In that case, unwrap both types so that we can compare the
2991 underlying records. */
2992 if (TREE_CODE (have_va_type) == ARRAY_TYPE
2993 || TREE_CODE (have_va_type) == POINTER_TYPE)
2995 want_va_type = TREE_TYPE (want_va_type);
2996 have_va_type = TREE_TYPE (have_va_type);
2999 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
3001 error ("first argument to `va_arg' not of type `va_list'");
3002 addr = const0_rtx;
3005 /* Generate a diagnostic for requesting data of a type that cannot
3006 be passed through `...' due to type promotion at the call site. */
3007 else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
3009 const char *name = "<anonymous type>", *pname = 0;
3010 static int gave_help;
3012 if (TYPE_NAME (type))
3014 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
3015 name = IDENTIFIER_POINTER (TYPE_NAME (type));
3016 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
3017 && DECL_NAME (TYPE_NAME (type)))
3018 name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
3020 if (TYPE_NAME (promoted_type))
3022 if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
3023 pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
3024 else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
3025 && DECL_NAME (TYPE_NAME (promoted_type)))
3026 pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
3029 error ("`%s' is promoted to `%s' when passed through `...'", name, pname);
3030 if (! gave_help)
3032 gave_help = 1;
3033 error ("(so you should pass `%s' not `%s' to `va_arg')", pname, name);
3036 addr = const0_rtx;
3038 else
3040 /* Make it easier for the backends by protecting the valist argument
3041 from multiple evaluations. */
3042 valist = stabilize_va_list (valist, 0);
3044 #ifdef EXPAND_BUILTIN_VA_ARG
3045 addr = EXPAND_BUILTIN_VA_ARG (valist, type);
3046 #else
3047 addr = std_expand_builtin_va_arg (valist, type);
3048 #endif
3051 result = gen_rtx_MEM (TYPE_MODE (type), addr);
3052 MEM_ALIAS_SET (result) = get_varargs_alias_set ();
3054 return result;
3057 /* Expand ARGLIST, from a call to __builtin_va_end. */
3059 static rtx
3060 expand_builtin_va_end (arglist)
3061 tree arglist;
3063 tree valist = TREE_VALUE (arglist);
3065 #ifdef EXPAND_BUILTIN_VA_END
3066 valist = stabilize_va_list (valist, 0);
3067 EXPAND_BUILTIN_VA_END(arglist);
3068 #else
3069 /* Evaluate for side effects, if needed. I hate macros that don't
3070 do that. */
3071 if (TREE_SIDE_EFFECTS (valist))
3072 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
3073 #endif
3075 return const0_rtx;
3078 /* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a
3079 builtin rather than just as an assignment in stdarg.h because of the
3080 nastiness of array-type va_list types. */
3082 static rtx
3083 expand_builtin_va_copy (arglist)
3084 tree arglist;
3086 tree dst, src, t;
3088 dst = TREE_VALUE (arglist);
3089 src = TREE_VALUE (TREE_CHAIN (arglist));
3091 dst = stabilize_va_list (dst, 1);
3092 src = stabilize_va_list (src, 0);
3094 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
3096 t = build (MODIFY_EXPR, va_list_type_node, dst, src);
3097 TREE_SIDE_EFFECTS (t) = 1;
3098 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3100 else
3102 rtx dstb, srcb, size;
3104 /* Evaluate to pointers. */
3105 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
3106 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
3107 size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
3108 VOIDmode, EXPAND_NORMAL);
3110 /* "Dereference" to BLKmode memories. */
3111 dstb = gen_rtx_MEM (BLKmode, dstb);
3112 MEM_ALIAS_SET (dstb) = get_alias_set (TREE_TYPE (TREE_TYPE (dst)));
3113 srcb = gen_rtx_MEM (BLKmode, srcb);
3114 MEM_ALIAS_SET (srcb) = get_alias_set (TREE_TYPE (TREE_TYPE (src)));
3116 /* Copy. */
3117 emit_block_move (dstb, srcb, size, TYPE_ALIGN (va_list_type_node));
3120 return const0_rtx;
3123 /* Expand a call to one of the builtin functions __builtin_frame_address or
3124 __builtin_return_address. */
3125 static rtx
3126 expand_builtin_frame_address (exp)
3127 tree exp;
3129 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3130 tree arglist = TREE_OPERAND (exp, 1);
3132 /* The argument must be a nonnegative integer constant.
3133 It counts the number of frames to scan up the stack.
3134 The value is the return address saved in that frame. */
3135 if (arglist == 0)
3136 /* Warning about missing arg was already issued. */
3137 return const0_rtx;
3138 else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST
3139 || tree_int_cst_sgn (TREE_VALUE (arglist)) < 0)
3141 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3142 error ("invalid arg to `__builtin_frame_address'");
3143 else
3144 error ("invalid arg to `__builtin_return_address'");
3145 return const0_rtx;
3147 else
3149 rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
3150 TREE_INT_CST_LOW (TREE_VALUE (arglist)),
3151 hard_frame_pointer_rtx);
3153 /* Some ports cannot access arbitrary stack frames. */
3154 if (tem == NULL)
3156 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3157 warning ("unsupported arg to `__builtin_frame_address'");
3158 else
3159 warning ("unsupported arg to `__builtin_return_address'");
3160 return const0_rtx;
3163 /* For __builtin_frame_address, return what we've got. */
3164 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3165 return tem;
3167 if (GET_CODE (tem) != REG
3168 && ! CONSTANT_P (tem))
3169 tem = copy_to_mode_reg (Pmode, tem);
3170 return tem;
3174 /* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if
3175 we failed and the caller should emit a normal call, otherwise try to get
3176 the result in TARGET, if convenient. */
3177 static rtx
3178 expand_builtin_alloca (arglist, target)
3179 tree arglist;
3180 rtx target;
3182 rtx op0;
3184 if (arglist == 0
3185 /* Arg could be non-integer if user redeclared this fcn wrong. */
3186 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
3187 return 0;
3189 /* Compute the argument. */
3190 op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
3192 /* Allocate the desired space. */
3193 return allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
3196 /* Expand a call to the ffs builtin. The arguments are in ARGLIST.
3197 Return 0 if a normal call should be emitted rather than expanding the
3198 function in-line. If convenient, the result should be placed in TARGET.
3199 SUBTARGET may be used as the target for computing one of EXP's operands. */
3200 static rtx
3201 expand_builtin_ffs (arglist, target, subtarget)
3202 tree arglist;
3203 rtx target, subtarget;
3205 rtx op0;
3206 if (arglist == 0
3207 /* Arg could be non-integer if user redeclared this fcn wrong. */
3208 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
3209 return 0;
3211 /* Compute the argument. */
3212 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
3213 /* Compute ffs, into TARGET if possible.
3214 Set TARGET to wherever the result comes back. */
3215 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
3216 ffs_optab, op0, target, 1);
3217 if (target == 0)
3218 abort ();
3219 return target;
3222 /* If the string passed to fputs is a constant and is one character
3223 long, we attempt to transform this call into __builtin_fputc(). */
3224 static rtx
3225 expand_builtin_fputs (arglist, ignore)
3226 tree arglist;
3227 int ignore;
3229 tree call_expr, len, fn, fn_fputc = built_in_decls[BUILT_IN_FPUTC],
3230 fn_fwrite = built_in_decls[BUILT_IN_FWRITE];
3232 /* If the return value is used, or the replacement _DECL isn't
3233 initialized, don't do the transformation. */
3234 if (!ignore || !fn_fputc || !fn_fwrite)
3235 return 0;
3237 /* Verify the arguments in the original call. */
3238 if (arglist == 0
3239 || (TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
3240 || TREE_CHAIN (arglist) == 0
3241 || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
3242 != POINTER_TYPE)
3243 || current_function_check_memory_usage)
3244 return 0;
3246 /* Get the length of the string passed to fputs. If the length
3247 can't be determined, punt. */
3248 if (!(len = c_strlen (TREE_VALUE (arglist)))
3249 || TREE_CODE (len) != INTEGER_CST)
3250 return 0;
3252 switch (compare_tree_int (len, 1))
3254 case -1: /* length is 0, delete the call entirely . */
3256 /* Evaluate and ignore the argument in case it has
3257 side-effects. */
3258 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
3259 VOIDmode, EXPAND_NORMAL);
3260 return const0_rtx;
3262 case 0: /* length is 1, call fputc. */
3264 const char *p = c_getstr (TREE_VALUE (arglist));
3266 if (p != NULL)
3268 /* New argument list transforming fputs(string, stream) to
3269 fputc(string[0], stream). */
3270 arglist =
3271 build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3272 arglist =
3273 tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
3274 fn = fn_fputc;
3275 break;
3278 /* FALLTHROUGH */
3279 case 1: /* length is greater than 1, call fwrite. */
3281 tree string_arg = TREE_VALUE (arglist);
3283 /* New argument list transforming fputs(string, stream) to
3284 fwrite(string, 1, len, stream). */
3285 arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3286 arglist = tree_cons (NULL_TREE, len, arglist);
3287 arglist = tree_cons (NULL_TREE, integer_one_node, arglist);
3288 arglist = tree_cons (NULL_TREE, string_arg, arglist);
3289 fn = fn_fwrite;
3290 break;
3292 default:
3293 abort();
3296 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
3297 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
3298 call_expr, arglist, NULL_TREE);
3299 TREE_SIDE_EFFECTS (call_expr) = 1;
3300 return expand_expr (call_expr, (ignore ? const0_rtx : NULL_RTX),
3301 VOIDmode, EXPAND_NORMAL);
3304 /* Expand a call to __builtin_expect. We return our argument and
3305 emit a NOTE_INSN_EXPECTED_VALUE note. */
3307 static rtx
3308 expand_builtin_expect (arglist, target)
3309 tree arglist;
3310 rtx target;
3312 tree exp, c;
3313 rtx note, rtx_c;
3315 if (arglist == NULL_TREE
3316 || TREE_CHAIN (arglist) == NULL_TREE)
3317 return const0_rtx;
3318 exp = TREE_VALUE (arglist);
3319 c = TREE_VALUE (TREE_CHAIN (arglist));
3321 if (TREE_CODE (c) != INTEGER_CST)
3323 error ("second arg to `__builtin_expect' must be a constant");
3324 c = integer_zero_node;
3327 target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
3329 /* Don't bother with expected value notes for integral constants. */
3330 if (GET_CODE (target) != CONST_INT)
3332 /* We do need to force this into a register so that we can be
3333 moderately sure to be able to correctly interpret the branch
3334 condition later. */
3335 target = force_reg (GET_MODE (target), target);
3337 rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
3339 note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
3340 NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
3343 return target;
3346 /* Expand an expression EXP that calls a built-in function,
3347 with result going to TARGET if that's convenient
3348 (and in mode MODE if that's convenient).
3349 SUBTARGET may be used as the target for computing one of EXP's operands.
3350 IGNORE is nonzero if the value is to be ignored. */
3353 expand_builtin (exp, target, subtarget, mode, ignore)
3354 tree exp;
3355 rtx target;
3356 rtx subtarget;
3357 enum machine_mode mode;
3358 int ignore;
3360 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3361 tree arglist = TREE_OPERAND (exp, 1);
3362 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
3364 #ifdef MD_EXPAND_BUILTIN
3365 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
3366 return MD_EXPAND_BUILTIN (exp, target, subtarget, mode, ignore);
3367 #endif
3369 /* When not optimizing, generate calls to library functions for a certain
3370 set of builtins. */
3371 if (! optimize && ! CALLED_AS_BUILT_IN (fndecl)
3372 && (fcode == BUILT_IN_SIN || fcode == BUILT_IN_COS
3373 || fcode == BUILT_IN_FSQRT || fcode == BUILT_IN_MEMSET
3374 || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
3375 || fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO
3376 || fcode == BUILT_IN_INDEX || fcode == BUILT_IN_RINDEX
3377 || fcode == BUILT_IN_STRCHR || fcode == BUILT_IN_STRRCHR
3378 || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
3379 || fcode == BUILT_IN_STRNCPY || fcode == BUILT_IN_STRNCMP
3380 || fcode == BUILT_IN_STRSTR || fcode == BUILT_IN_STRPBRK
3381 || fcode == BUILT_IN_STRCAT || fcode == BUILT_IN_STRNCAT
3382 || fcode == BUILT_IN_STRSPN || fcode == BUILT_IN_STRCSPN
3383 || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS
3384 || fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS
3385 || fcode == BUILT_IN_PRINTF || fcode == BUILT_IN_FPUTC
3386 || fcode == BUILT_IN_FPUTS || fcode == BUILT_IN_FWRITE))
3387 return expand_call (exp, target, ignore);
3389 switch (fcode)
3391 case BUILT_IN_ABS:
3392 case BUILT_IN_LABS:
3393 case BUILT_IN_LLABS:
3394 case BUILT_IN_IMAXABS:
3395 case BUILT_IN_FABS:
3396 /* build_function_call changes these into ABS_EXPR. */
3397 abort ();
3399 case BUILT_IN_SIN:
3400 case BUILT_IN_COS:
3401 /* Treat these like sqrt, but only if the user asks for them. */
3402 if (! flag_fast_math)
3403 break;
3404 case BUILT_IN_FSQRT:
3405 target = expand_builtin_mathfn (exp, target, subtarget);
3406 if (target)
3407 return target;
3408 break;
3410 case BUILT_IN_FMOD:
3411 break;
3413 case BUILT_IN_APPLY_ARGS:
3414 return expand_builtin_apply_args ();
3416 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
3417 FUNCTION with a copy of the parameters described by
3418 ARGUMENTS, and ARGSIZE. It returns a block of memory
3419 allocated on the stack into which is stored all the registers
3420 that might possibly be used for returning the result of a
3421 function. ARGUMENTS is the value returned by
3422 __builtin_apply_args. ARGSIZE is the number of bytes of
3423 arguments that must be copied. ??? How should this value be
3424 computed? We'll also need a safe worst case value for varargs
3425 functions. */
3426 case BUILT_IN_APPLY:
3427 if (arglist == 0
3428 /* Arg could be non-pointer if user redeclared this fcn wrong. */
3429 || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
3430 || TREE_CHAIN (arglist) == 0
3431 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
3432 || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
3433 || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
3434 return const0_rtx;
3435 else
3437 int i;
3438 tree t;
3439 rtx ops[3];
3441 for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
3442 ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
3444 return expand_builtin_apply (ops[0], ops[1], ops[2]);
3447 /* __builtin_return (RESULT) causes the function to return the
3448 value described by RESULT. RESULT is address of the block of
3449 memory returned by __builtin_apply. */
3450 case BUILT_IN_RETURN:
3451 if (arglist
3452 /* Arg could be non-pointer if user redeclared this fcn wrong. */
3453 && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
3454 expand_builtin_return (expand_expr (TREE_VALUE (arglist),
3455 NULL_RTX, VOIDmode, 0));
3456 return const0_rtx;
3458 case BUILT_IN_SAVEREGS:
3459 return expand_builtin_saveregs ();
3461 case BUILT_IN_ARGS_INFO:
3462 return expand_builtin_args_info (exp);
3464 /* Return the address of the first anonymous stack arg. */
3465 case BUILT_IN_NEXT_ARG:
3466 return expand_builtin_next_arg (arglist);
3468 case BUILT_IN_CLASSIFY_TYPE:
3469 return expand_builtin_classify_type (arglist);
3471 case BUILT_IN_CONSTANT_P:
3472 return expand_builtin_constant_p (exp);
3474 case BUILT_IN_FRAME_ADDRESS:
3475 case BUILT_IN_RETURN_ADDRESS:
3476 return expand_builtin_frame_address (exp);
3478 /* Returns the address of the area where the structure is returned.
3479 0 otherwise. */
3480 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
3481 if (arglist != 0
3482 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
3483 || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
3484 return const0_rtx;
3485 else
3486 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
3488 case BUILT_IN_ALLOCA:
3489 target = expand_builtin_alloca (arglist, target);
3490 if (target)
3491 return target;
3492 break;
3494 case BUILT_IN_FFS:
3495 target = expand_builtin_ffs (arglist, target, subtarget);
3496 if (target)
3497 return target;
3498 break;
3500 case BUILT_IN_STRLEN:
3501 target = expand_builtin_strlen (exp, target);
3502 if (target)
3503 return target;
3504 break;
3506 case BUILT_IN_STRCPY:
3507 target = expand_builtin_strcpy (exp);
3508 if (target)
3509 return target;
3510 break;
3512 case BUILT_IN_STRNCPY:
3513 target = expand_builtin_strncpy (arglist, target, mode);
3514 if (target)
3515 return target;
3516 break;
3518 case BUILT_IN_STRCAT:
3519 target = expand_builtin_strcat (arglist, target, mode);
3520 if (target)
3521 return target;
3522 break;
3524 case BUILT_IN_STRNCAT:
3525 target = expand_builtin_strncat (arglist, target, mode);
3526 if (target)
3527 return target;
3528 break;
3530 case BUILT_IN_STRSPN:
3531 target = expand_builtin_strspn (arglist, target, mode);
3532 if (target)
3533 return target;
3534 break;
3536 case BUILT_IN_STRCSPN:
3537 target = expand_builtin_strcspn (arglist, target, mode);
3538 if (target)
3539 return target;
3540 break;
3542 case BUILT_IN_STRSTR:
3543 target = expand_builtin_strstr (arglist, target, mode);
3544 if (target)
3545 return target;
3546 break;
3548 case BUILT_IN_STRPBRK:
3549 target = expand_builtin_strpbrk (arglist, target, mode);
3550 if (target)
3551 return target;
3552 break;
3554 case BUILT_IN_INDEX:
3555 case BUILT_IN_STRCHR:
3556 target = expand_builtin_strchr (arglist, target, mode);
3557 if (target)
3558 return target;
3559 break;
3561 case BUILT_IN_RINDEX:
3562 case BUILT_IN_STRRCHR:
3563 target = expand_builtin_strrchr (arglist, target, mode);
3564 if (target)
3565 return target;
3566 break;
3568 case BUILT_IN_MEMCPY:
3569 target = expand_builtin_memcpy (arglist);
3570 if (target)
3571 return target;
3572 break;
3574 case BUILT_IN_MEMSET:
3575 target = expand_builtin_memset (exp);
3576 if (target)
3577 return target;
3578 break;
3580 case BUILT_IN_BZERO:
3581 target = expand_builtin_bzero (exp);
3582 if (target)
3583 return target;
3584 break;
3586 case BUILT_IN_STRCMP:
3587 target = expand_builtin_strcmp (exp, target, mode);
3588 if (target)
3589 return target;
3590 break;
3592 case BUILT_IN_STRNCMP:
3593 target = expand_builtin_strncmp (exp, target, mode);
3594 if (target)
3595 return target;
3596 break;
3598 /* These comparison functions need an instruction that returns an actual
3599 index. An ordinary compare that just sets the condition codes
3600 is not enough. */
3601 #ifdef HAVE_cmpstrsi
3602 case BUILT_IN_BCMP:
3603 case BUILT_IN_MEMCMP:
3604 target = expand_builtin_memcmp (exp, arglist, target);
3605 if (target)
3606 return target;
3607 break;
3608 #else
3609 case BUILT_IN_BCMP:
3610 case BUILT_IN_MEMCMP:
3611 break;
3612 #endif
3614 case BUILT_IN_SETJMP:
3615 target = expand_builtin_setjmp (arglist, target);
3616 if (target)
3617 return target;
3618 break;
3620 /* __builtin_longjmp is passed a pointer to an array of five words.
3621 It's similar to the C library longjmp function but works with
3622 __builtin_setjmp above. */
3623 case BUILT_IN_LONGJMP:
3624 if (arglist == 0 || TREE_CHAIN (arglist) == 0
3625 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
3626 break;
3627 else
3629 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
3630 VOIDmode, 0);
3631 rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
3632 NULL_RTX, VOIDmode, 0);
3634 if (value != const1_rtx)
3636 error ("__builtin_longjmp second argument must be 1");
3637 return const0_rtx;
3640 expand_builtin_longjmp (buf_addr, value);
3641 return const0_rtx;
3644 case BUILT_IN_TRAP:
3645 #ifdef HAVE_trap
3646 if (HAVE_trap)
3647 emit_insn (gen_trap ());
3648 else
3649 #endif
3650 error ("__builtin_trap not supported by this target");
3651 emit_barrier ();
3652 return const0_rtx;
3654 case BUILT_IN_PUTCHAR:
3655 case BUILT_IN_PUTS:
3656 case BUILT_IN_FPUTC:
3657 case BUILT_IN_FWRITE:
3658 break;
3659 case BUILT_IN_FPUTS:
3660 target = expand_builtin_fputs (arglist, ignore);
3661 if (target)
3662 return target;
3663 break;
3665 /* Various hooks for the DWARF 2 __throw routine. */
3666 case BUILT_IN_UNWIND_INIT:
3667 expand_builtin_unwind_init ();
3668 return const0_rtx;
3669 case BUILT_IN_DWARF_CFA:
3670 return virtual_cfa_rtx;
3671 #ifdef DWARF2_UNWIND_INFO
3672 case BUILT_IN_DWARF_FP_REGNUM:
3673 return expand_builtin_dwarf_fp_regnum ();
3674 case BUILT_IN_INIT_DWARF_REG_SIZES:
3675 expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
3676 return const0_rtx;
3677 #endif
3678 case BUILT_IN_FROB_RETURN_ADDR:
3679 return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
3680 case BUILT_IN_EXTRACT_RETURN_ADDR:
3681 return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
3682 case BUILT_IN_EH_RETURN:
3683 expand_builtin_eh_return (TREE_VALUE (arglist),
3684 TREE_VALUE (TREE_CHAIN (arglist)),
3685 TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
3686 return const0_rtx;
3687 case BUILT_IN_VARARGS_START:
3688 return expand_builtin_va_start (0, arglist);
3689 case BUILT_IN_STDARG_START:
3690 return expand_builtin_va_start (1, arglist);
3691 case BUILT_IN_VA_END:
3692 return expand_builtin_va_end (arglist);
3693 case BUILT_IN_VA_COPY:
3694 return expand_builtin_va_copy (arglist);
3695 case BUILT_IN_EXPECT:
3696 return expand_builtin_expect (arglist, target);
3698 default: /* just do library call, if unknown builtin */
3699 error ("built-in function `%s' not currently supported",
3700 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
3703 /* The switch statement above can drop through to cause the function
3704 to be called normally. */
3705 return expand_call (exp, target, ignore);
3708 /* Fold a call to __builtin_constant_p, if we know it will evaluate to a
3709 constant. ARGLIST is the argument list of the call. */
3711 static tree
3712 fold_builtin_constant_p (arglist)
3713 tree arglist;
3715 if (arglist == 0)
3716 return 0;
3718 arglist = TREE_VALUE (arglist);
3720 /* We return 1 for a numeric type that's known to be a constant
3721 value at compile-time or for an aggregate type that's a
3722 literal constant. */
3723 STRIP_NOPS (arglist);
3725 /* If we know this is a constant, emit the constant of one. */
3726 if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
3727 || (TREE_CODE (arglist) == CONSTRUCTOR
3728 && TREE_CONSTANT (arglist))
3729 || (TREE_CODE (arglist) == ADDR_EXPR
3730 && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
3731 return integer_one_node;
3733 /* If we aren't going to be running CSE or this expression
3734 has side effects, show we don't know it to be a constant.
3735 Likewise if it's a pointer or aggregate type since in those
3736 case we only want literals, since those are only optimized
3737 when generating RTL, not later. */
3738 if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected
3739 || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
3740 || POINTER_TYPE_P (TREE_TYPE (arglist)))
3741 return integer_zero_node;
3743 return 0;
3746 /* Used by constant folding to eliminate some builtin calls early. EXP is
3747 the CALL_EXPR of a call to a builtin function. */
3749 tree
3750 fold_builtin (exp)
3751 tree exp;
3753 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3754 tree arglist = TREE_OPERAND (exp, 1);
3755 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
3757 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
3758 return 0;
3760 switch (fcode)
3762 case BUILT_IN_CONSTANT_P:
3763 return fold_builtin_constant_p (arglist);
3765 case BUILT_IN_STRLEN:
3766 if (arglist != 0
3767 /* Arg could be non-pointer if user redeclared this fcn wrong. */
3768 && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE)
3770 tree len = c_strlen (TREE_VALUE (arglist));
3771 if (len != 0)
3772 return len;
3774 break;
3776 default:
3777 break;
3780 return 0;