Avoid scheduling builtin setjmp receivers
[official-gcc.git] / gcc / builtins.c
blob3dedc5b336aa7361cb62d5040271c11a27e5f4fb
1 /* Expand builtin functions.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001 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 "toplev.h"
41 #include "tm_p.h"
43 #define CALLED_AS_BUILT_IN(NODE) \
44 (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
46 /* Register mappings for target machines without register windows. */
47 #ifndef INCOMING_REGNO
48 #define INCOMING_REGNO(OUT) (OUT)
49 #endif
50 #ifndef OUTGOING_REGNO
51 #define OUTGOING_REGNO(IN) (IN)
52 #endif
54 #ifndef PAD_VARARGS_DOWN
55 #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
56 #endif
58 /* Define the names of the builtin function types and codes. */
59 const char *const built_in_class_names[4]
60 = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
62 #define DEF_BUILTIN(x) STRINGIFY(x),
63 const char *const built_in_names[(int) END_BUILTINS] =
65 #include "builtins.def"
67 #undef DEF_BUILTIN
69 /* Setup an array of _DECL trees, make sure each element is
70 initialized to NULL_TREE. */
71 #define DEF_BUILTIN(x) NULL_TREE,
72 tree built_in_decls[(int) END_BUILTINS] =
74 #include "builtins.def"
76 #undef DEF_BUILTIN
78 tree (*lang_type_promotes_to) PARAMS ((tree));
80 static int get_pointer_alignment PARAMS ((tree, unsigned));
81 static tree c_strlen PARAMS ((tree));
82 static const char *c_getstr PARAMS ((tree));
83 static rtx c_readstr PARAMS ((const char *,
84 enum machine_mode));
85 static int target_char_cast PARAMS ((tree, char *));
86 static rtx get_memory_rtx PARAMS ((tree));
87 static int apply_args_size PARAMS ((void));
88 static int apply_result_size PARAMS ((void));
89 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
90 static rtx result_vector PARAMS ((int, rtx));
91 #endif
92 static rtx expand_builtin_setjmp PARAMS ((tree, rtx));
93 static rtx expand_builtin_apply_args PARAMS ((void));
94 static rtx expand_builtin_apply_args_1 PARAMS ((void));
95 static rtx expand_builtin_apply PARAMS ((rtx, rtx, rtx));
96 static void expand_builtin_return PARAMS ((rtx));
97 static rtx expand_builtin_classify_type PARAMS ((tree));
98 static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx));
99 static rtx expand_builtin_constant_p PARAMS ((tree));
100 static rtx expand_builtin_args_info PARAMS ((tree));
101 static rtx expand_builtin_next_arg PARAMS ((tree));
102 static rtx expand_builtin_va_start PARAMS ((int, tree));
103 static rtx expand_builtin_va_end PARAMS ((tree));
104 static rtx expand_builtin_va_copy PARAMS ((tree));
105 #ifdef HAVE_cmpstrsi
106 static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx));
107 #endif
108 static rtx expand_builtin_strcmp PARAMS ((tree, rtx,
109 enum machine_mode));
110 static rtx expand_builtin_strncmp PARAMS ((tree, rtx,
111 enum machine_mode));
112 static rtx builtin_memcpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
113 enum machine_mode));
114 static rtx expand_builtin_strcat PARAMS ((tree, rtx,
115 enum machine_mode));
116 static rtx expand_builtin_strncat PARAMS ((tree, rtx,
117 enum machine_mode));
118 static rtx expand_builtin_strspn PARAMS ((tree, rtx,
119 enum machine_mode));
120 static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
121 enum machine_mode));
122 static rtx expand_builtin_memcpy PARAMS ((tree));
123 static rtx expand_builtin_strcpy PARAMS ((tree));
124 static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
125 enum machine_mode));
126 static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
127 enum machine_mode));
128 static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT,
129 enum machine_mode));
130 static rtx expand_builtin_memset PARAMS ((tree));
131 static rtx expand_builtin_bzero PARAMS ((tree));
132 static rtx expand_builtin_strlen PARAMS ((tree, rtx));
133 static rtx expand_builtin_strstr PARAMS ((tree, rtx,
134 enum machine_mode));
135 static rtx expand_builtin_strpbrk PARAMS ((tree, rtx,
136 enum machine_mode));
137 static rtx expand_builtin_strchr PARAMS ((tree, rtx,
138 enum machine_mode));
139 static rtx expand_builtin_strrchr PARAMS ((tree, rtx,
140 enum machine_mode));
141 static rtx expand_builtin_alloca PARAMS ((tree, rtx));
142 static rtx expand_builtin_ffs PARAMS ((tree, rtx, rtx));
143 static rtx expand_builtin_frame_address PARAMS ((tree));
144 static rtx expand_builtin_fputs PARAMS ((tree, int));
145 static tree stabilize_va_list PARAMS ((tree, int));
146 static rtx expand_builtin_expect PARAMS ((tree, rtx));
147 static tree fold_builtin_constant_p PARAMS ((tree));
148 static tree build_function_call_expr PARAMS ((tree, tree));
149 static int validate_arglist PARAMS ((tree, ...));
151 /* Return the alignment in bits of EXP, a pointer valued expression.
152 But don't return more than MAX_ALIGN no matter what.
153 The alignment returned is, by default, the alignment of the thing that
154 EXP points to (if it is not a POINTER_TYPE, 0 is returned).
156 Otherwise, look at the expression to see if we can do better, i.e., if the
157 expression is actually pointing at an object whose alignment is tighter. */
159 static int
160 get_pointer_alignment (exp, max_align)
161 tree exp;
162 unsigned max_align;
164 unsigned align, inner;
166 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
167 return 0;
169 align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
170 align = MIN (align, max_align);
172 while (1)
174 switch (TREE_CODE (exp))
176 case NOP_EXPR:
177 case CONVERT_EXPR:
178 case NON_LVALUE_EXPR:
179 exp = TREE_OPERAND (exp, 0);
180 if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
181 return align;
183 inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
184 align = MIN (inner, max_align);
185 break;
187 case PLUS_EXPR:
188 /* If sum of pointer + int, restrict our maximum alignment to that
189 imposed by the integer. If not, we can't do any better than
190 ALIGN. */
191 if (! host_integerp (TREE_OPERAND (exp, 1), 1))
192 return align;
194 while (((tree_low_cst (TREE_OPERAND (exp, 1), 1) * BITS_PER_UNIT)
195 & (max_align - 1))
196 != 0)
197 max_align >>= 1;
199 exp = TREE_OPERAND (exp, 0);
200 break;
202 case ADDR_EXPR:
203 /* See what we are pointing at and look at its alignment. */
204 exp = TREE_OPERAND (exp, 0);
205 if (TREE_CODE (exp) == FUNCTION_DECL)
206 align = FUNCTION_BOUNDARY;
207 else if (DECL_P (exp))
208 align = DECL_ALIGN (exp);
209 #ifdef CONSTANT_ALIGNMENT
210 else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
211 align = CONSTANT_ALIGNMENT (exp, align);
212 #endif
213 return MIN (align, max_align);
215 default:
216 return align;
221 /* Compute the length of a C string. TREE_STRING_LENGTH is not the right
222 way, because it could contain a zero byte in the middle.
223 TREE_STRING_LENGTH is the size of the character array, not the string.
225 The value returned is of type `ssizetype'.
227 Unfortunately, string_constant can't access the values of const char
228 arrays with initializers, so neither can we do so here. */
230 static tree
231 c_strlen (src)
232 tree src;
234 tree offset_node;
235 int offset, max;
236 const char *ptr;
238 src = string_constant (src, &offset_node);
239 if (src == 0)
240 return 0;
242 max = TREE_STRING_LENGTH (src) - 1;
243 ptr = TREE_STRING_POINTER (src);
245 if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
247 /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
248 compute the offset to the following null if we don't know where to
249 start searching for it. */
250 int i;
252 for (i = 0; i < max; i++)
253 if (ptr[i] == 0)
254 return 0;
256 /* We don't know the starting offset, but we do know that the string
257 has no internal zero bytes. We can assume that the offset falls
258 within the bounds of the string; otherwise, the programmer deserves
259 what he gets. Subtract the offset from the length of the string,
260 and return that. This would perhaps not be valid if we were dealing
261 with named arrays in addition to literal string constants. */
263 return size_diffop (size_int (max), offset_node);
266 /* We have a known offset into the string. Start searching there for
267 a null character. */
268 if (offset_node == 0)
269 offset = 0;
270 else
272 /* Did we get a long long offset? If so, punt. */
273 if (TREE_INT_CST_HIGH (offset_node) != 0)
274 return 0;
275 offset = TREE_INT_CST_LOW (offset_node);
278 /* If the offset is known to be out of bounds, warn, and call strlen at
279 runtime. */
280 if (offset < 0 || offset > max)
282 warning ("offset outside bounds of constant string");
283 return 0;
286 /* Use strlen to search for the first zero byte. Since any strings
287 constructed with build_string will have nulls appended, we win even
288 if we get handed something like (char[4])"abcd".
290 Since OFFSET is our starting index into the string, no further
291 calculation is needed. */
292 return ssize_int (strlen (ptr + offset));
295 /* Return a char pointer for a C string if it is a string constant
296 or sum of string constant and integer constant. */
298 static const char *
299 c_getstr (src)
300 tree src;
302 tree offset_node;
303 int offset, max;
304 const char *ptr;
306 src = string_constant (src, &offset_node);
307 if (src == 0)
308 return 0;
310 max = TREE_STRING_LENGTH (src) - 1;
311 ptr = TREE_STRING_POINTER (src);
313 if (!offset_node)
314 offset = 0;
315 else if (TREE_CODE (offset_node) != INTEGER_CST)
316 return 0;
317 else
319 /* Did we get a long long offset? If so, punt. */
320 if (TREE_INT_CST_HIGH (offset_node) != 0)
321 return 0;
322 offset = TREE_INT_CST_LOW (offset_node);
323 if (offset < 0 || offset > max)
324 return 0;
327 return ptr + offset;
330 /* Return a CONST_INT or CONST_DOUBLE corresponding to target
331 reading GET_MODE_BITSIZE (MODE) bits from string constant
332 STR. */
334 static rtx
335 c_readstr (str, mode)
336 const char *str;
337 enum machine_mode mode;
339 HOST_WIDE_INT c[2];
340 HOST_WIDE_INT ch;
341 unsigned int i, j;
343 if (GET_MODE_CLASS (mode) != MODE_INT)
344 abort ();
345 c[0] = 0;
346 c[1] = 0;
347 ch = 1;
348 for (i = 0; i < GET_MODE_SIZE (mode); i++)
350 j = i;
351 if (WORDS_BIG_ENDIAN)
352 j = GET_MODE_SIZE (mode) - i - 1;
353 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
354 && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
355 j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
356 j *= BITS_PER_UNIT;
357 if (j > 2 * HOST_BITS_PER_WIDE_INT)
358 abort ();
359 if (ch)
360 ch = (unsigned char) str[i];
361 c[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
363 return immed_double_const (c[0], c[1], mode);
366 /* Cast a target constant CST to target CHAR and if that value fits into
367 host char type, return zero and put that value into variable pointed by
368 P. */
370 static int
371 target_char_cast (cst, p)
372 tree cst;
373 char *p;
375 unsigned HOST_WIDE_INT val, hostval;
377 if (TREE_CODE (cst) != INTEGER_CST
378 || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
379 return 1;
381 val = TREE_INT_CST_LOW (cst);
382 if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
383 val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
385 hostval = val;
386 if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
387 hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
389 if (val != hostval)
390 return 1;
392 *p = hostval;
393 return 0;
396 /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
397 times to get the address of either a higher stack frame, or a return
398 address located within it (depending on FNDECL_CODE). */
401 expand_builtin_return_addr (fndecl_code, count, tem)
402 enum built_in_function fndecl_code;
403 int count;
404 rtx tem;
406 int i;
408 /* Some machines need special handling before we can access
409 arbitrary frames. For example, on the sparc, we must first flush
410 all register windows to the stack. */
411 #ifdef SETUP_FRAME_ADDRESSES
412 if (count > 0)
413 SETUP_FRAME_ADDRESSES ();
414 #endif
416 /* On the sparc, the return address is not in the frame, it is in a
417 register. There is no way to access it off of the current frame
418 pointer, but it can be accessed off the previous frame pointer by
419 reading the value from the register window save area. */
420 #ifdef RETURN_ADDR_IN_PREVIOUS_FRAME
421 if (fndecl_code == BUILT_IN_RETURN_ADDRESS)
422 count--;
423 #endif
425 /* Scan back COUNT frames to the specified frame. */
426 for (i = 0; i < count; i++)
428 /* Assume the dynamic chain pointer is in the word that the
429 frame address points to, unless otherwise specified. */
430 #ifdef DYNAMIC_CHAIN_ADDRESS
431 tem = DYNAMIC_CHAIN_ADDRESS (tem);
432 #endif
433 tem = memory_address (Pmode, tem);
434 tem = gen_rtx_MEM (Pmode, tem);
435 MEM_ALIAS_SET (tem) = get_frame_alias_set ();
436 tem = copy_to_reg (tem);
439 /* For __builtin_frame_address, return what we've got. */
440 if (fndecl_code == BUILT_IN_FRAME_ADDRESS)
441 return tem;
443 /* For __builtin_return_address, Get the return address from that
444 frame. */
445 #ifdef RETURN_ADDR_RTX
446 tem = RETURN_ADDR_RTX (count, tem);
447 #else
448 tem = memory_address (Pmode,
449 plus_constant (tem, GET_MODE_SIZE (Pmode)));
450 tem = gen_rtx_MEM (Pmode, tem);
451 MEM_ALIAS_SET (tem) = get_frame_alias_set ();
452 #endif
453 return tem;
456 /* Alias set used for setjmp buffer. */
457 static HOST_WIDE_INT setjmp_alias_set = -1;
459 /* Construct the leading half of a __builtin_setjmp call. Control will
460 return to RECEIVER_LABEL. This is used directly by sjlj exception
461 handling code. */
463 void
464 expand_builtin_setjmp_setup (buf_addr, receiver_label)
465 rtx buf_addr;
466 rtx receiver_label;
468 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
469 rtx stack_save;
470 rtx mem;
472 if (setjmp_alias_set == -1)
473 setjmp_alias_set = new_alias_set ();
475 #ifdef POINTERS_EXTEND_UNSIGNED
476 buf_addr = convert_memory_address (Pmode, buf_addr);
477 #endif
479 buf_addr = force_reg (Pmode, force_operand (buf_addr, NULL_RTX));
481 emit_queue ();
483 /* We store the frame pointer and the address of receiver_label in
484 the buffer and use the rest of it for the stack save area, which
485 is machine-dependent. */
487 #ifndef BUILTIN_SETJMP_FRAME_VALUE
488 #define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
489 #endif
491 mem = gen_rtx_MEM (Pmode, buf_addr);
492 MEM_ALIAS_SET (mem) = setjmp_alias_set;
493 emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
495 mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
496 MEM_ALIAS_SET (mem) = setjmp_alias_set;
498 emit_move_insn (validize_mem (mem),
499 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
501 stack_save = gen_rtx_MEM (sa_mode,
502 plus_constant (buf_addr,
503 2 * GET_MODE_SIZE (Pmode)));
504 MEM_ALIAS_SET (stack_save) = setjmp_alias_set;
505 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
507 /* If there is further processing to do, do it. */
508 #ifdef HAVE_builtin_setjmp_setup
509 if (HAVE_builtin_setjmp_setup)
510 emit_insn (gen_builtin_setjmp_setup (buf_addr));
511 #endif
513 /* Tell optimize_save_area_alloca that extra work is going to
514 need to go on during alloca. */
515 current_function_calls_setjmp = 1;
517 /* Set this so all the registers get saved in our frame; we need to be
518 able to copy the saved values for any registers from frames we unwind. */
519 current_function_has_nonlocal_label = 1;
522 /* Construct the trailing part of a __builtin_setjmp call.
523 This is used directly by sjlj exception handling code. */
525 void
526 expand_builtin_setjmp_receiver (receiver_label)
527 rtx receiver_label ATTRIBUTE_UNUSED;
529 /* Clobber the FP when we get here, so we have to make sure it's
530 marked as used by this function. */
531 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
533 /* Mark the static chain as clobbered here so life information
534 doesn't get messed up for it. */
535 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx));
537 /* Now put in the code to restore the frame pointer, and argument
538 pointer, if needed. The code below is from expand_end_bindings
539 in stmt.c; see detailed documentation there. */
540 #ifdef HAVE_nonlocal_goto
541 if (! HAVE_nonlocal_goto)
542 #endif
543 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
545 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
546 if (fixed_regs[ARG_POINTER_REGNUM])
548 #ifdef ELIMINABLE_REGS
549 size_t i;
550 static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
552 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
553 if (elim_regs[i].from == ARG_POINTER_REGNUM
554 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
555 break;
557 if (i == ARRAY_SIZE (elim_regs))
558 #endif
560 /* Now restore our arg pointer from the address at which it
561 was saved in our stack frame.
562 If there hasn't be space allocated for it yet, make
563 some now. */
564 if (arg_pointer_save_area == 0)
565 arg_pointer_save_area
566 = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
567 emit_move_insn (virtual_incoming_args_rtx,
568 copy_to_reg (arg_pointer_save_area));
571 #endif
573 #ifdef HAVE_builtin_setjmp_receiver
574 if (HAVE_builtin_setjmp_receiver)
575 emit_insn (gen_builtin_setjmp_receiver (receiver_label));
576 else
577 #endif
578 #ifdef HAVE_nonlocal_goto_receiver
579 if (HAVE_nonlocal_goto_receiver)
580 emit_insn (gen_nonlocal_goto_receiver ());
581 else
582 #endif
583 { /* Nothing */ }
585 /* @@@ This is a kludge. Not all machine descriptions define a blockage
586 insn, but we must not allow the code we just generated to be reordered
587 by scheduling. Specifically, the update of the frame pointer must
588 happen immediately, not later. So emit an ASM_INPUT to act as blockage
589 insn. */
590 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
593 /* __builtin_setjmp is passed a pointer to an array of five words (not
594 all will be used on all machines). It operates similarly to the C
595 library function of the same name, but is more efficient. Much of
596 the code below (and for longjmp) is copied from the handling of
597 non-local gotos.
599 NOTE: This is intended for use by GNAT and the exception handling
600 scheme in the compiler and will only work in the method used by
601 them. */
603 static rtx
604 expand_builtin_setjmp (arglist, target)
605 tree arglist;
606 rtx target;
608 rtx buf_addr, next_lab, cont_lab;
610 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
611 return NULL_RTX;
613 if (target == 0 || GET_CODE (target) != REG
614 || REGNO (target) < FIRST_PSEUDO_REGISTER)
615 target = gen_reg_rtx (TYPE_MODE (integer_type_node));
617 buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
619 next_lab = gen_label_rtx ();
620 cont_lab = gen_label_rtx ();
622 expand_builtin_setjmp_setup (buf_addr, next_lab);
624 /* Set TARGET to zero and branch to the continue label. */
625 emit_move_insn (target, const0_rtx);
626 emit_jump_insn (gen_jump (cont_lab));
627 emit_barrier ();
628 emit_label (next_lab);
630 expand_builtin_setjmp_receiver (next_lab);
632 /* Set TARGET to one. */
633 emit_move_insn (target, const1_rtx);
634 emit_label (cont_lab);
636 /* Tell flow about the strange goings on. Putting `next_lab' on
637 `nonlocal_goto_handler_labels' to indicates that function
638 calls may traverse the arc back to this label. */
640 current_function_has_nonlocal_label = 1;
641 nonlocal_goto_handler_labels
642 = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
644 return target;
647 /* __builtin_longjmp is passed a pointer to an array of five words (not
648 all will be used on all machines). It operates similarly to the C
649 library function of the same name, but is more efficient. Much of
650 the code below is copied from the handling of non-local gotos.
652 NOTE: This is intended for use by GNAT and the exception handling
653 scheme in the compiler and will only work in the method used by
654 them. */
656 void
657 expand_builtin_longjmp (buf_addr, value)
658 rtx buf_addr, value;
660 rtx fp, lab, stack, insn;
661 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
663 if (setjmp_alias_set == -1)
664 setjmp_alias_set = new_alias_set ();
666 #ifdef POINTERS_EXTEND_UNSIGNED
667 buf_addr = convert_memory_address (Pmode, buf_addr);
668 #endif
669 buf_addr = force_reg (Pmode, buf_addr);
671 /* We used to store value in static_chain_rtx, but that fails if pointers
672 are smaller than integers. We instead require that the user must pass
673 a second argument of 1, because that is what builtin_setjmp will
674 return. This also makes EH slightly more efficient, since we are no
675 longer copying around a value that we don't care about. */
676 if (value != const1_rtx)
677 abort ();
679 current_function_calls_longjmp = 1;
681 #ifdef HAVE_builtin_longjmp
682 if (HAVE_builtin_longjmp)
683 emit_insn (gen_builtin_longjmp (buf_addr));
684 else
685 #endif
687 fp = gen_rtx_MEM (Pmode, buf_addr);
688 lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr,
689 GET_MODE_SIZE (Pmode)));
691 stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
692 2 * GET_MODE_SIZE (Pmode)));
693 MEM_ALIAS_SET (fp) = MEM_ALIAS_SET (lab) = MEM_ALIAS_SET (stack)
694 = setjmp_alias_set;
696 /* Pick up FP, label, and SP from the block and jump. This code is
697 from expand_goto in stmt.c; see there for detailed comments. */
698 #if HAVE_nonlocal_goto
699 if (HAVE_nonlocal_goto)
700 /* We have to pass a value to the nonlocal_goto pattern that will
701 get copied into the static_chain pointer, but it does not matter
702 what that value is, because builtin_setjmp does not use it. */
703 emit_insn (gen_nonlocal_goto (value, fp, stack, lab));
704 else
705 #endif
707 lab = copy_to_reg (lab);
709 emit_move_insn (hard_frame_pointer_rtx, fp);
710 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
712 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
713 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
714 emit_indirect_jump (lab);
718 /* Search backwards and mark the jump insn as a non-local goto.
719 Note that this precludes the use of __builtin_longjmp to a
720 __builtin_setjmp target in the same function. However, we've
721 already cautioned the user that these functions are for
722 internal exception handling use only. */
723 for (insn = get_last_insn ();
724 GET_CODE (insn) != JUMP_INSN;
725 insn = PREV_INSN (insn))
726 continue;
727 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
728 REG_NOTES (insn));
731 /* Get a MEM rtx for expression EXP which is the address of an operand
732 to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */
734 static rtx
735 get_memory_rtx (exp)
736 tree exp;
738 rtx mem = gen_rtx_MEM (BLKmode,
739 memory_address (BLKmode,
740 expand_expr (exp, NULL_RTX,
741 ptr_mode, EXPAND_SUM)));
743 /* Get an expression we can use to find the attributes to assign to MEM.
744 If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
745 we can. First remove any nops. */
746 while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
747 || TREE_CODE (exp) == NON_LVALUE_EXPR)
748 && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
749 exp = TREE_OPERAND (exp, 0);
751 if (TREE_CODE (exp) == ADDR_EXPR)
752 exp = TREE_OPERAND (exp, 0);
753 else if (POINTER_TYPE_P (TREE_TYPE (exp)))
754 exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
755 else
756 return mem;
758 set_mem_attributes (mem, exp, 0);
760 /* memcpy, memset and other builtin stringops can alias with anything. */
761 MEM_ALIAS_SET (mem) = 0;
762 return mem;
765 /* Built-in functions to perform an untyped call and return. */
767 /* For each register that may be used for calling a function, this
768 gives a mode used to copy the register's value. VOIDmode indicates
769 the register is not used for calling a function. If the machine
770 has register windows, this gives only the outbound registers.
771 INCOMING_REGNO gives the corresponding inbound register. */
772 static enum machine_mode apply_args_mode[FIRST_PSEUDO_REGISTER];
774 /* For each register that may be used for returning values, this gives
775 a mode used to copy the register's value. VOIDmode indicates the
776 register is not used for returning values. If the machine has
777 register windows, this gives only the outbound registers.
778 INCOMING_REGNO gives the corresponding inbound register. */
779 static enum machine_mode apply_result_mode[FIRST_PSEUDO_REGISTER];
781 /* For each register that may be used for calling a function, this
782 gives the offset of that register into the block returned by
783 __builtin_apply_args. 0 indicates that the register is not
784 used for calling a function. */
785 static int apply_args_reg_offset[FIRST_PSEUDO_REGISTER];
787 /* Return the offset of register REGNO into the block returned by
788 __builtin_apply_args. This is not declared static, since it is
789 needed in objc-act.c. */
791 int
792 apply_args_register_offset (regno)
793 int regno;
795 apply_args_size ();
797 /* Arguments are always put in outgoing registers (in the argument
798 block) if such make sense. */
799 #ifdef OUTGOING_REGNO
800 regno = OUTGOING_REGNO(regno);
801 #endif
802 return apply_args_reg_offset[regno];
805 /* Return the size required for the block returned by __builtin_apply_args,
806 and initialize apply_args_mode. */
808 static int
809 apply_args_size ()
811 static int size = -1;
812 int align, regno;
813 enum machine_mode mode;
815 /* The values computed by this function never change. */
816 if (size < 0)
818 /* The first value is the incoming arg-pointer. */
819 size = GET_MODE_SIZE (Pmode);
821 /* The second value is the structure value address unless this is
822 passed as an "invisible" first argument. */
823 if (struct_value_rtx)
824 size += GET_MODE_SIZE (Pmode);
826 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
827 if (FUNCTION_ARG_REGNO_P (regno))
829 /* Search for the proper mode for copying this register's
830 value. I'm not sure this is right, but it works so far. */
831 enum machine_mode best_mode = VOIDmode;
833 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
834 mode != VOIDmode;
835 mode = GET_MODE_WIDER_MODE (mode))
836 if (HARD_REGNO_MODE_OK (regno, mode)
837 && HARD_REGNO_NREGS (regno, mode) == 1)
838 best_mode = mode;
840 if (best_mode == VOIDmode)
841 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
842 mode != VOIDmode;
843 mode = GET_MODE_WIDER_MODE (mode))
844 if (HARD_REGNO_MODE_OK (regno, mode)
845 && (mov_optab->handlers[(int) mode].insn_code
846 != CODE_FOR_nothing))
847 best_mode = mode;
849 mode = best_mode;
850 if (mode == VOIDmode)
851 abort ();
853 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
854 if (size % align != 0)
855 size = CEIL (size, align) * align;
856 apply_args_reg_offset[regno] = size;
857 size += GET_MODE_SIZE (mode);
858 apply_args_mode[regno] = mode;
860 else
862 apply_args_mode[regno] = VOIDmode;
863 apply_args_reg_offset[regno] = 0;
866 return size;
869 /* Return the size required for the block returned by __builtin_apply,
870 and initialize apply_result_mode. */
872 static int
873 apply_result_size ()
875 static int size = -1;
876 int align, regno;
877 enum machine_mode mode;
879 /* The values computed by this function never change. */
880 if (size < 0)
882 size = 0;
884 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
885 if (FUNCTION_VALUE_REGNO_P (regno))
887 /* Search for the proper mode for copying this register's
888 value. I'm not sure this is right, but it works so far. */
889 enum machine_mode best_mode = VOIDmode;
891 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
892 mode != TImode;
893 mode = GET_MODE_WIDER_MODE (mode))
894 if (HARD_REGNO_MODE_OK (regno, mode))
895 best_mode = mode;
897 if (best_mode == VOIDmode)
898 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
899 mode != VOIDmode;
900 mode = GET_MODE_WIDER_MODE (mode))
901 if (HARD_REGNO_MODE_OK (regno, mode)
902 && (mov_optab->handlers[(int) mode].insn_code
903 != CODE_FOR_nothing))
904 best_mode = mode;
906 mode = best_mode;
907 if (mode == VOIDmode)
908 abort ();
910 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
911 if (size % align != 0)
912 size = CEIL (size, align) * align;
913 size += GET_MODE_SIZE (mode);
914 apply_result_mode[regno] = mode;
916 else
917 apply_result_mode[regno] = VOIDmode;
919 /* Allow targets that use untyped_call and untyped_return to override
920 the size so that machine-specific information can be stored here. */
921 #ifdef APPLY_RESULT_SIZE
922 size = APPLY_RESULT_SIZE;
923 #endif
925 return size;
928 #if defined (HAVE_untyped_call) || defined (HAVE_untyped_return)
929 /* Create a vector describing the result block RESULT. If SAVEP is true,
930 the result block is used to save the values; otherwise it is used to
931 restore the values. */
933 static rtx
934 result_vector (savep, result)
935 int savep;
936 rtx result;
938 int regno, size, align, nelts;
939 enum machine_mode mode;
940 rtx reg, mem;
941 rtx *savevec = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
943 size = nelts = 0;
944 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
945 if ((mode = apply_result_mode[regno]) != VOIDmode)
947 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
948 if (size % align != 0)
949 size = CEIL (size, align) * align;
950 reg = gen_rtx_REG (mode, savep ? regno : INCOMING_REGNO (regno));
951 mem = change_address (result, mode,
952 plus_constant (XEXP (result, 0), size));
953 savevec[nelts++] = (savep
954 ? gen_rtx_SET (VOIDmode, mem, reg)
955 : gen_rtx_SET (VOIDmode, reg, mem));
956 size += GET_MODE_SIZE (mode);
958 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelts, savevec));
960 #endif /* HAVE_untyped_call or HAVE_untyped_return */
962 /* Save the state required to perform an untyped call with the same
963 arguments as were passed to the current function. */
965 static rtx
966 expand_builtin_apply_args_1 ()
968 rtx registers;
969 int size, align, regno;
970 enum machine_mode mode;
972 /* Create a block where the arg-pointer, structure value address,
973 and argument registers can be saved. */
974 registers = assign_stack_local (BLKmode, apply_args_size (), -1);
976 /* Walk past the arg-pointer and structure value address. */
977 size = GET_MODE_SIZE (Pmode);
978 if (struct_value_rtx)
979 size += GET_MODE_SIZE (Pmode);
981 /* Save each register used in calling a function to the block. */
982 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
983 if ((mode = apply_args_mode[regno]) != VOIDmode)
985 rtx tem;
987 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
988 if (size % align != 0)
989 size = CEIL (size, align) * align;
991 tem = gen_rtx_REG (mode, INCOMING_REGNO (regno));
993 emit_move_insn (change_address (registers, mode,
994 plus_constant (XEXP (registers, 0),
995 size)),
996 tem);
997 size += GET_MODE_SIZE (mode);
1000 /* Save the arg pointer to the block. */
1001 emit_move_insn (change_address (registers, Pmode, XEXP (registers, 0)),
1002 copy_to_reg (virtual_incoming_args_rtx));
1003 size = GET_MODE_SIZE (Pmode);
1005 /* Save the structure value address unless this is passed as an
1006 "invisible" first argument. */
1007 if (struct_value_incoming_rtx)
1009 emit_move_insn (change_address (registers, Pmode,
1010 plus_constant (XEXP (registers, 0),
1011 size)),
1012 copy_to_reg (struct_value_incoming_rtx));
1013 size += GET_MODE_SIZE (Pmode);
1016 /* Return the address of the block. */
1017 return copy_addr_to_reg (XEXP (registers, 0));
1020 /* __builtin_apply_args returns block of memory allocated on
1021 the stack into which is stored the arg pointer, structure
1022 value address, static chain, and all the registers that might
1023 possibly be used in performing a function call. The code is
1024 moved to the start of the function so the incoming values are
1025 saved. */
1026 static rtx
1027 expand_builtin_apply_args ()
1029 /* Don't do __builtin_apply_args more than once in a function.
1030 Save the result of the first call and reuse it. */
1031 if (apply_args_value != 0)
1032 return apply_args_value;
1034 /* When this function is called, it means that registers must be
1035 saved on entry to this function. So we migrate the
1036 call to the first insn of this function. */
1037 rtx temp;
1038 rtx seq;
1040 start_sequence ();
1041 temp = expand_builtin_apply_args_1 ();
1042 seq = get_insns ();
1043 end_sequence ();
1045 apply_args_value = temp;
1047 /* Put the sequence after the NOTE that starts the function.
1048 If this is inside a SEQUENCE, make the outer-level insn
1049 chain current, so the code is placed at the start of the
1050 function. */
1051 push_topmost_sequence ();
1052 emit_insns_before (seq, NEXT_INSN (get_insns ()));
1053 pop_topmost_sequence ();
1054 return temp;
1058 /* Perform an untyped call and save the state required to perform an
1059 untyped return of whatever value was returned by the given function. */
1061 static rtx
1062 expand_builtin_apply (function, arguments, argsize)
1063 rtx function, arguments, argsize;
1065 int size, align, regno;
1066 enum machine_mode mode;
1067 rtx incoming_args, result, reg, dest, call_insn;
1068 rtx old_stack_level = 0;
1069 rtx call_fusage = 0;
1071 /* Create a block where the return registers can be saved. */
1072 result = assign_stack_local (BLKmode, apply_result_size (), -1);
1074 /* Fetch the arg pointer from the ARGUMENTS block. */
1075 incoming_args = gen_reg_rtx (Pmode);
1076 emit_move_insn (incoming_args,
1077 gen_rtx_MEM (Pmode, arguments));
1078 #ifndef STACK_GROWS_DOWNWARD
1079 incoming_args = expand_binop (Pmode, sub_optab, incoming_args, argsize,
1080 incoming_args, 0, OPTAB_LIB_WIDEN);
1081 #endif
1083 /* Perform postincrements before actually calling the function. */
1084 emit_queue ();
1086 /* Push a new argument block and copy the arguments. Do not allow
1087 the (potential) memcpy call below to interfere with our stack
1088 manipulations. */
1089 do_pending_stack_adjust ();
1090 NO_DEFER_POP;
1092 /* Save the stack with nonlocal if available */
1093 #ifdef HAVE_save_stack_nonlocal
1094 if (HAVE_save_stack_nonlocal)
1095 emit_stack_save (SAVE_NONLOCAL, &old_stack_level, NULL_RTX);
1096 else
1097 #endif
1098 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
1100 /* Push a block of memory onto the stack to store the memory arguments.
1101 Save the address in a register, and copy the memory arguments. ??? I
1102 haven't figured out how the calling convention macros effect this,
1103 but it's likely that the source and/or destination addresses in
1104 the block copy will need updating in machine specific ways. */
1105 dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
1106 emit_block_move (gen_rtx_MEM (BLKmode, dest),
1107 gen_rtx_MEM (BLKmode, incoming_args),
1108 argsize, PARM_BOUNDARY);
1110 /* Refer to the argument block. */
1111 apply_args_size ();
1112 arguments = gen_rtx_MEM (BLKmode, arguments);
1114 /* Walk past the arg-pointer and structure value address. */
1115 size = GET_MODE_SIZE (Pmode);
1116 if (struct_value_rtx)
1117 size += GET_MODE_SIZE (Pmode);
1119 /* Restore each of the registers previously saved. Make USE insns
1120 for each of these registers for use in making the call. */
1121 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1122 if ((mode = apply_args_mode[regno]) != VOIDmode)
1124 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1125 if (size % align != 0)
1126 size = CEIL (size, align) * align;
1127 reg = gen_rtx_REG (mode, regno);
1128 emit_move_insn (reg,
1129 change_address (arguments, mode,
1130 plus_constant (XEXP (arguments, 0),
1131 size)));
1133 use_reg (&call_fusage, reg);
1134 size += GET_MODE_SIZE (mode);
1137 /* Restore the structure value address unless this is passed as an
1138 "invisible" first argument. */
1139 size = GET_MODE_SIZE (Pmode);
1140 if (struct_value_rtx)
1142 rtx value = gen_reg_rtx (Pmode);
1143 emit_move_insn (value,
1144 change_address (arguments, Pmode,
1145 plus_constant (XEXP (arguments, 0),
1146 size)));
1147 emit_move_insn (struct_value_rtx, value);
1148 if (GET_CODE (struct_value_rtx) == REG)
1149 use_reg (&call_fusage, struct_value_rtx);
1150 size += GET_MODE_SIZE (Pmode);
1153 /* All arguments and registers used for the call are set up by now! */
1154 function = prepare_call_address (function, NULL_TREE, &call_fusage, 0);
1156 /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
1157 and we don't want to load it into a register as an optimization,
1158 because prepare_call_address already did it if it should be done. */
1159 if (GET_CODE (function) != SYMBOL_REF)
1160 function = memory_address (FUNCTION_MODE, function);
1162 /* Generate the actual call instruction and save the return value. */
1163 #ifdef HAVE_untyped_call
1164 if (HAVE_untyped_call)
1165 emit_call_insn (gen_untyped_call (gen_rtx_MEM (FUNCTION_MODE, function),
1166 result, result_vector (1, result)));
1167 else
1168 #endif
1169 #ifdef HAVE_call_value
1170 if (HAVE_call_value)
1172 rtx valreg = 0;
1174 /* Locate the unique return register. It is not possible to
1175 express a call that sets more than one return register using
1176 call_value; use untyped_call for that. In fact, untyped_call
1177 only needs to save the return registers in the given block. */
1178 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1179 if ((mode = apply_result_mode[regno]) != VOIDmode)
1181 if (valreg)
1182 abort (); /* HAVE_untyped_call required. */
1183 valreg = gen_rtx_REG (mode, regno);
1186 emit_call_insn (GEN_CALL_VALUE (valreg,
1187 gen_rtx_MEM (FUNCTION_MODE, function),
1188 const0_rtx, NULL_RTX, const0_rtx));
1190 emit_move_insn (change_address (result, GET_MODE (valreg),
1191 XEXP (result, 0)),
1192 valreg);
1194 else
1195 #endif
1196 abort ();
1198 /* Find the CALL insn we just emitted. */
1199 for (call_insn = get_last_insn ();
1200 call_insn && GET_CODE (call_insn) != CALL_INSN;
1201 call_insn = PREV_INSN (call_insn))
1204 if (! call_insn)
1205 abort ();
1207 /* Put the register usage information on the CALL. If there is already
1208 some usage information, put ours at the end. */
1209 if (CALL_INSN_FUNCTION_USAGE (call_insn))
1211 rtx link;
1213 for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
1214 link = XEXP (link, 1))
1217 XEXP (link, 1) = call_fusage;
1219 else
1220 CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
1222 /* Restore the stack. */
1223 #ifdef HAVE_save_stack_nonlocal
1224 if (HAVE_save_stack_nonlocal)
1225 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1226 else
1227 #endif
1228 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1230 OK_DEFER_POP;
1232 /* Return the address of the result block. */
1233 return copy_addr_to_reg (XEXP (result, 0));
1236 /* Perform an untyped return. */
1238 static void
1239 expand_builtin_return (result)
1240 rtx result;
1242 int size, align, regno;
1243 enum machine_mode mode;
1244 rtx reg;
1245 rtx call_fusage = 0;
1247 apply_result_size ();
1248 result = gen_rtx_MEM (BLKmode, result);
1250 #ifdef HAVE_untyped_return
1251 if (HAVE_untyped_return)
1253 emit_jump_insn (gen_untyped_return (result, result_vector (0, result)));
1254 emit_barrier ();
1255 return;
1257 #endif
1259 /* Restore the return value and note that each value is used. */
1260 size = 0;
1261 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1262 if ((mode = apply_result_mode[regno]) != VOIDmode)
1264 align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
1265 if (size % align != 0)
1266 size = CEIL (size, align) * align;
1267 reg = gen_rtx_REG (mode, INCOMING_REGNO (regno));
1268 emit_move_insn (reg,
1269 change_address (result, mode,
1270 plus_constant (XEXP (result, 0),
1271 size)));
1273 push_to_sequence (call_fusage);
1274 emit_insn (gen_rtx_USE (VOIDmode, reg));
1275 call_fusage = get_insns ();
1276 end_sequence ();
1277 size += GET_MODE_SIZE (mode);
1280 /* Put the USE insns before the return. */
1281 emit_insns (call_fusage);
1283 /* Return whatever values was restored by jumping directly to the end
1284 of the function. */
1285 expand_null_return ();
1288 /* Expand a call to __builtin_classify_type with arguments found in
1289 ARGLIST. */
1290 static rtx
1291 expand_builtin_classify_type (arglist)
1292 tree arglist;
1294 if (arglist != 0)
1296 tree type = TREE_TYPE (TREE_VALUE (arglist));
1297 enum tree_code code = TREE_CODE (type);
1298 if (code == VOID_TYPE)
1299 return GEN_INT (void_type_class);
1300 if (code == INTEGER_TYPE)
1301 return GEN_INT (integer_type_class);
1302 if (code == CHAR_TYPE)
1303 return GEN_INT (char_type_class);
1304 if (code == ENUMERAL_TYPE)
1305 return GEN_INT (enumeral_type_class);
1306 if (code == BOOLEAN_TYPE)
1307 return GEN_INT (boolean_type_class);
1308 if (code == POINTER_TYPE)
1309 return GEN_INT (pointer_type_class);
1310 if (code == REFERENCE_TYPE)
1311 return GEN_INT (reference_type_class);
1312 if (code == OFFSET_TYPE)
1313 return GEN_INT (offset_type_class);
1314 if (code == REAL_TYPE)
1315 return GEN_INT (real_type_class);
1316 if (code == COMPLEX_TYPE)
1317 return GEN_INT (complex_type_class);
1318 if (code == FUNCTION_TYPE)
1319 return GEN_INT (function_type_class);
1320 if (code == METHOD_TYPE)
1321 return GEN_INT (method_type_class);
1322 if (code == RECORD_TYPE)
1323 return GEN_INT (record_type_class);
1324 if (code == UNION_TYPE || code == QUAL_UNION_TYPE)
1325 return GEN_INT (union_type_class);
1326 if (code == ARRAY_TYPE)
1328 if (TYPE_STRING_FLAG (type))
1329 return GEN_INT (string_type_class);
1330 else
1331 return GEN_INT (array_type_class);
1333 if (code == SET_TYPE)
1334 return GEN_INT (set_type_class);
1335 if (code == FILE_TYPE)
1336 return GEN_INT (file_type_class);
1337 if (code == LANG_TYPE)
1338 return GEN_INT (lang_type_class);
1340 return GEN_INT (no_type_class);
1343 /* Expand expression EXP, which is a call to __builtin_constant_p. */
1344 static rtx
1345 expand_builtin_constant_p (exp)
1346 tree exp;
1348 tree arglist = TREE_OPERAND (exp, 1);
1349 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1350 rtx tmp;
1352 if (arglist == 0)
1353 return const0_rtx;
1354 arglist = TREE_VALUE (arglist);
1356 /* We have taken care of the easy cases during constant folding. This
1357 case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE get a
1358 chance to see if it can deduce whether ARGLIST is constant. */
1360 tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
1361 tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
1362 return tmp;
1365 /* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
1366 Return 0 if a normal call should be emitted rather than expanding the
1367 function in-line. EXP is the expression that is a call to the builtin
1368 function; if convenient, the result should be placed in TARGET.
1369 SUBTARGET may be used as the target for computing one of EXP's operands. */
1370 static rtx
1371 expand_builtin_mathfn (exp, target, subtarget)
1372 tree exp;
1373 rtx target, subtarget;
1375 optab builtin_optab;
1376 rtx op0, insns;
1377 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
1378 tree arglist = TREE_OPERAND (exp, 1);
1380 if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
1381 return 0;
1383 /* Stabilize and compute the argument. */
1384 if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
1385 && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
1387 exp = copy_node (exp);
1388 TREE_OPERAND (exp, 1) = arglist;
1389 /* Wrap the computation of the argument in a SAVE_EXPR. That
1390 way, if we need to expand the argument again (as in the
1391 flag_errno_math case below where we cannot directly set
1392 errno), we will not perform side-effects more than once.
1393 Note that here we're mutating the original EXP as well as the
1394 copy; that's the right thing to do in case the original EXP
1395 is expanded later. */
1396 TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
1397 arglist = copy_node (arglist);
1399 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
1401 /* Make a suitable register to place result in. */
1402 target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
1404 emit_queue ();
1405 start_sequence ();
1407 switch (DECL_FUNCTION_CODE (fndecl))
1409 case BUILT_IN_SIN:
1410 builtin_optab = sin_optab; break;
1411 case BUILT_IN_COS:
1412 builtin_optab = cos_optab; break;
1413 case BUILT_IN_FSQRT:
1414 builtin_optab = sqrt_optab; break;
1415 default:
1416 abort ();
1419 /* Compute into TARGET.
1420 Set TARGET to wherever the result comes back. */
1421 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
1422 builtin_optab, op0, target, 0);
1424 /* If we were unable to expand via the builtin, stop the
1425 sequence (without outputting the insns) and return 0, causing
1426 a call to the library function. */
1427 if (target == 0)
1429 end_sequence ();
1430 return 0;
1433 /* Check the results by default. But if flag_fast_math is turned on,
1434 then assume sqrt will always be called with valid arguments. */
1436 if (flag_errno_math && ! flag_fast_math)
1438 rtx lab1;
1440 /* Don't define the builtin FP instructions
1441 if your machine is not IEEE. */
1442 if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
1443 abort ();
1445 lab1 = gen_label_rtx ();
1447 /* Test the result; if it is NaN, set errno=EDOM because
1448 the argument was not in the domain. */
1449 emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
1450 0, 0, lab1);
1452 #ifdef TARGET_EDOM
1454 #ifdef GEN_ERRNO_RTX
1455 rtx errno_rtx = GEN_ERRNO_RTX;
1456 #else
1457 rtx errno_rtx
1458 = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
1459 #endif
1461 emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
1463 #else
1464 /* We can't set errno=EDOM directly; let the library call do it.
1465 Pop the arguments right away in case the call gets deleted. */
1466 NO_DEFER_POP;
1467 expand_call (exp, target, 0);
1468 OK_DEFER_POP;
1469 #endif
1471 emit_label (lab1);
1474 /* Output the entire sequence. */
1475 insns = get_insns ();
1476 end_sequence ();
1477 emit_insns (insns);
1479 return target;
1482 /* Expand expression EXP which is a call to the strlen builtin. Return 0
1483 if we failed the caller should emit a normal call, otherwise
1484 try to get the result in TARGET, if convenient. */
1486 static rtx
1487 expand_builtin_strlen (exp, target)
1488 tree exp;
1489 rtx target;
1491 tree arglist = TREE_OPERAND (exp, 1);
1492 enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1494 if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
1495 return 0;
1496 else
1498 rtx pat;
1499 tree src = TREE_VALUE (arglist);
1501 int align
1502 = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
1504 rtx result, src_reg, char_rtx, before_strlen;
1505 enum machine_mode insn_mode = value_mode, char_mode;
1506 enum insn_code icode = CODE_FOR_nothing;
1508 /* If SRC is not a pointer type, don't do this operation inline. */
1509 if (align == 0)
1510 return 0;
1512 /* Bail out if we can't compute strlen in the right mode. */
1513 while (insn_mode != VOIDmode)
1515 icode = strlen_optab->handlers[(int) insn_mode].insn_code;
1516 if (icode != CODE_FOR_nothing)
1517 break;
1519 insn_mode = GET_MODE_WIDER_MODE (insn_mode);
1521 if (insn_mode == VOIDmode)
1522 return 0;
1524 /* Make a place to write the result of the instruction. */
1525 result = target;
1526 if (! (result != 0
1527 && GET_CODE (result) == REG
1528 && GET_MODE (result) == insn_mode
1529 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
1530 result = gen_reg_rtx (insn_mode);
1532 /* Make a place to hold the source address. We will not expand
1533 the actual source until we are sure that the expansion will
1534 not fail -- there are trees that cannot be expanded twice. */
1535 src_reg = gen_reg_rtx (Pmode);
1537 /* Mark the beginning of the strlen sequence so we can emit the
1538 source operand later. */
1539 before_strlen = get_last_insn();
1541 /* Check the string is readable and has an end. */
1542 if (current_function_check_memory_usage)
1543 emit_library_call (chkr_check_str_libfunc, LCT_CONST_MAKE_BLOCK,
1544 VOIDmode, 2, src_reg, Pmode,
1545 GEN_INT (MEMORY_USE_RO),
1546 TYPE_MODE (integer_type_node));
1548 char_rtx = const0_rtx;
1549 char_mode = insn_data[(int) icode].operand[2].mode;
1550 if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
1551 char_mode))
1552 char_rtx = copy_to_mode_reg (char_mode, char_rtx);
1554 pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
1555 char_rtx, GEN_INT (align));
1556 if (! pat)
1557 return 0;
1558 emit_insn (pat);
1560 /* Now that we are assured of success, expand the source. */
1561 start_sequence ();
1562 pat = memory_address (BLKmode,
1563 expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
1564 if (pat != src_reg)
1565 emit_move_insn (src_reg, pat);
1566 pat = gen_sequence ();
1567 end_sequence ();
1569 if (before_strlen)
1570 emit_insn_after (pat, before_strlen);
1571 else
1572 emit_insn_before (pat, get_insns ());
1574 /* Return the value in the proper mode for this function. */
1575 if (GET_MODE (result) == value_mode)
1576 target = result;
1577 else if (target != 0)
1578 convert_move (target, result, 0);
1579 else
1580 target = convert_to_mode (value_mode, result, 0);
1582 return target;
1586 /* Expand a call to the strstr builtin. Return 0 if we failed the
1587 caller should emit a normal call, otherwise try to get the result
1588 in TARGET, if convenient (and in mode MODE if that's convenient). */
1590 static rtx
1591 expand_builtin_strstr (arglist, target, mode)
1592 tree arglist;
1593 rtx target;
1594 enum machine_mode mode;
1596 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
1597 || current_function_check_memory_usage)
1598 return 0;
1599 else
1601 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1602 tree fn;
1603 const char *p1, *p2;
1605 p2 = c_getstr (s2);
1606 if (p2 == NULL)
1607 return 0;
1609 p1 = c_getstr (s1);
1610 if (p1 != NULL)
1612 const char *r = strstr (p1, p2);
1614 if (r == NULL)
1615 return const0_rtx;
1617 /* Return an offset into the constant string argument. */
1618 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1619 s1, ssize_int (r - p1))),
1620 target, mode, EXPAND_NORMAL);
1623 if (p2[0] == '\0')
1624 return expand_expr (s1, target, mode, EXPAND_NORMAL);
1626 if (p2[1] != '\0')
1627 return 0;
1629 fn = built_in_decls[BUILT_IN_STRCHR];
1630 if (!fn)
1631 return 0;
1633 /* New argument list transforming strstr(s1, s2) to
1634 strchr(s1, s2[0]). */
1635 arglist =
1636 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
1637 arglist = tree_cons (NULL_TREE, s1, arglist);
1638 return expand_expr (build_function_call_expr (fn, arglist),
1639 target, mode, EXPAND_NORMAL);
1643 /* Expand a call to the strchr builtin. Return 0 if we failed the
1644 caller should emit a normal call, otherwise try to get the result
1645 in TARGET, if convenient (and in mode MODE if that's convenient). */
1647 static rtx
1648 expand_builtin_strchr (arglist, target, mode)
1649 tree arglist;
1650 rtx target;
1651 enum machine_mode mode;
1653 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
1654 || current_function_check_memory_usage)
1655 return 0;
1656 else
1658 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1659 const char *p1;
1661 if (TREE_CODE (s2) != INTEGER_CST)
1662 return 0;
1664 p1 = c_getstr (s1);
1665 if (p1 != NULL)
1667 char c;
1668 const char *r;
1670 if (target_char_cast (s2, &c))
1671 return 0;
1673 r = strchr (p1, c);
1675 if (r == NULL)
1676 return const0_rtx;
1678 /* Return an offset into the constant string argument. */
1679 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1680 s1, ssize_int (r - p1))),
1681 target, mode, EXPAND_NORMAL);
1684 /* FIXME: Should use here strchrM optab so that ports can optimize
1685 this. */
1686 return 0;
1690 /* Expand a call to the strrchr builtin. Return 0 if we failed the
1691 caller should emit a normal call, otherwise try to get the result
1692 in TARGET, if convenient (and in mode MODE if that's convenient). */
1694 static rtx
1695 expand_builtin_strrchr (arglist, target, mode)
1696 tree arglist;
1697 rtx target;
1698 enum machine_mode mode;
1700 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
1701 || current_function_check_memory_usage)
1702 return 0;
1703 else
1705 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1706 tree fn;
1707 const char *p1;
1709 if (TREE_CODE (s2) != INTEGER_CST)
1710 return 0;
1712 p1 = c_getstr (s1);
1713 if (p1 != NULL)
1715 char c;
1716 const char *r;
1718 if (target_char_cast (s2, &c))
1719 return 0;
1721 r = strrchr (p1, c);
1723 if (r == NULL)
1724 return const0_rtx;
1726 /* Return an offset into the constant string argument. */
1727 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1728 s1, ssize_int (r - p1))),
1729 target, mode, EXPAND_NORMAL);
1732 if (! integer_zerop (s2))
1733 return 0;
1735 fn = built_in_decls[BUILT_IN_STRCHR];
1736 if (!fn)
1737 return 0;
1739 /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
1740 return expand_expr (build_function_call_expr (fn, arglist),
1741 target, mode, EXPAND_NORMAL);
1745 /* Expand a call to the strpbrk builtin. Return 0 if we failed the
1746 caller should emit a normal call, otherwise try to get the result
1747 in TARGET, if convenient (and in mode MODE if that's convenient). */
1749 static rtx
1750 expand_builtin_strpbrk (arglist, target, mode)
1751 tree arglist;
1752 rtx target;
1753 enum machine_mode mode;
1755 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
1756 || current_function_check_memory_usage)
1757 return 0;
1758 else
1760 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
1761 tree fn;
1762 const char *p1, *p2;
1764 p2 = c_getstr (s2);
1765 if (p2 == NULL)
1766 return 0;
1768 p1 = c_getstr (s1);
1769 if (p1 != NULL)
1771 const char *r = strpbrk (p1, p2);
1773 if (r == NULL)
1774 return const0_rtx;
1776 /* Return an offset into the constant string argument. */
1777 return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
1778 s1, ssize_int (r - p1))),
1779 target, mode, EXPAND_NORMAL);
1782 if (p2[0] == '\0')
1784 /* strpbrk(x, "") == NULL.
1785 Evaluate and ignore the arguments in case they had
1786 side-effects. */
1787 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
1788 return const0_rtx;
1791 if (p2[1] != '\0')
1792 return 0; /* Really call strpbrk. */
1794 fn = built_in_decls[BUILT_IN_STRCHR];
1795 if (!fn)
1796 return 0;
1798 /* New argument list transforming strpbrk(s1, s2) to
1799 strchr(s1, s2[0]). */
1800 arglist =
1801 build_tree_list (NULL_TREE, build_int_2 (p2[0], 0));
1802 arglist = tree_cons (NULL_TREE, s1, arglist);
1803 return expand_expr (build_function_call_expr (fn, arglist),
1804 target, mode, EXPAND_NORMAL);
1808 /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
1809 bytes from constant string DATA + OFFSET and return it as target
1810 constant. */
1812 static rtx
1813 builtin_memcpy_read_str (data, offset, mode)
1814 PTR data;
1815 HOST_WIDE_INT offset;
1816 enum machine_mode mode;
1818 const char *str = (const char *) data;
1820 if (offset + GET_MODE_SIZE (mode) > strlen (str) + 1)
1821 abort (); /* Attempt to read past the end of constant string. */
1823 return c_readstr (str + offset, mode);
1826 /* Expand a call to the memcpy builtin, with arguments in ARGLIST. */
1827 static rtx
1828 expand_builtin_memcpy (arglist)
1829 tree arglist;
1831 if (!validate_arglist (arglist,
1832 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
1833 return 0;
1834 else
1836 tree dest = TREE_VALUE (arglist);
1837 tree src = TREE_VALUE (TREE_CHAIN (arglist));
1838 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1839 const char *src_str;
1841 int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
1842 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
1843 rtx dest_mem, src_mem, dest_addr, len_rtx;
1845 /* If either SRC or DEST is not a pointer type, don't do
1846 this operation in-line. */
1847 if (src_align == 0 || dest_align == 0)
1848 return 0;
1850 dest_mem = get_memory_rtx (dest);
1851 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
1852 src_str = c_getstr (src);
1854 /* If SRC is a string constant and block move would be done
1855 by pieces, we can avoid loading the string from memory
1856 and only stored the computed constants. */
1857 if (src_str
1858 && !current_function_check_memory_usage
1859 && GET_CODE (len_rtx) == CONST_INT
1860 && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
1861 && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
1862 (PTR) src_str, dest_align))
1864 store_by_pieces (dest_mem, INTVAL (len_rtx),
1865 builtin_memcpy_read_str,
1866 (PTR) src_str, dest_align);
1867 return force_operand (XEXP (dest_mem, 0), NULL_RTX);
1870 src_mem = get_memory_rtx (src);
1872 /* Just copy the rights of SRC to the rights of DEST. */
1873 if (current_function_check_memory_usage)
1874 emit_library_call (chkr_copy_bitmap_libfunc, LCT_CONST_MAKE_BLOCK,
1875 VOIDmode, 3, XEXP (dest_mem, 0), Pmode,
1876 XEXP (src_mem, 0), Pmode,
1877 len_rtx, TYPE_MODE (sizetype));
1879 /* Copy word part most expediently. */
1880 dest_addr
1881 = emit_block_move (dest_mem, src_mem, len_rtx,
1882 MIN (src_align, dest_align));
1884 if (dest_addr == 0)
1885 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
1887 return dest_addr;
1891 /* Expand expression EXP, which is a call to the strcpy builtin. Return 0
1892 if we failed the caller should emit a normal call. */
1894 static rtx
1895 expand_builtin_strcpy (exp)
1896 tree exp;
1898 tree arglist = TREE_OPERAND (exp, 1);
1899 rtx result;
1901 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
1902 return 0;
1903 else
1905 tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
1907 if (len == 0)
1908 return 0;
1910 len = size_binop (PLUS_EXPR, len, ssize_int (1));
1911 chainon (arglist, build_tree_list (NULL_TREE, len));
1914 result = expand_builtin_memcpy (arglist);
1916 if (! result)
1917 TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
1918 return result;
1921 /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
1922 bytes from constant string DATA + OFFSET and return it as target
1923 constant. */
1925 static rtx
1926 builtin_strncpy_read_str (data, offset, mode)
1927 PTR data;
1928 HOST_WIDE_INT offset;
1929 enum machine_mode mode;
1931 const char *str = (const char *) data;
1933 if ((unsigned HOST_WIDE_INT) offset > strlen (str))
1934 return const0_rtx;
1936 return c_readstr (str + offset, mode);
1939 /* Expand expression EXP, which is a call to the strncpy builtin. Return 0
1940 if we failed the caller should emit a normal call. */
1942 static rtx
1943 expand_builtin_strncpy (arglist, target, mode)
1944 tree arglist;
1945 rtx target;
1946 enum machine_mode mode;
1948 if (!validate_arglist (arglist,
1949 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
1950 return 0;
1951 else
1953 tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
1954 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
1956 /* We must be passed a constant len parameter. */
1957 if (TREE_CODE (len) != INTEGER_CST)
1958 return 0;
1960 /* If the len parameter is zero, return the dst parameter. */
1961 if (compare_tree_int (len, 0) == 0)
1963 /* Evaluate and ignore the src argument in case it has
1964 side-effects. */
1965 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
1966 VOIDmode, EXPAND_NORMAL);
1967 /* Return the dst parameter. */
1968 return expand_expr (TREE_VALUE (arglist), target, mode,
1969 EXPAND_NORMAL);
1972 /* Now, we must be passed a constant src ptr parameter. */
1973 if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
1974 return 0;
1976 slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
1978 /* We're required to pad with trailing zeros if the requested
1979 len is greater than strlen(s2)+1. In that case try to
1980 use store_by_pieces, if it fails, punt. */
1981 if (tree_int_cst_lt (slen, len))
1983 tree dest = TREE_VALUE (arglist);
1984 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
1985 const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
1986 rtx dest_mem;
1988 if (!p || !dest_align || TREE_INT_CST_HIGH (len)
1989 || !can_store_by_pieces (TREE_INT_CST_LOW (len),
1990 builtin_strncpy_read_str,
1991 (PTR) p, dest_align))
1992 return 0;
1994 dest_mem = get_memory_rtx (dest);
1995 store_by_pieces (dest_mem, TREE_INT_CST_LOW (len),
1996 builtin_strncpy_read_str,
1997 (PTR) p, dest_align);
1998 return force_operand (XEXP (dest_mem, 0), NULL_RTX);
2001 /* OK transform into builtin memcpy. */
2002 return expand_builtin_memcpy (arglist);
2006 /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
2007 bytes from constant string DATA + OFFSET and return it as target
2008 constant. */
2010 static rtx
2011 builtin_memset_read_str (data, offset, mode)
2012 PTR data;
2013 HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
2014 enum machine_mode mode;
2016 const char *c = (const char *) data;
2017 char *p = alloca (GET_MODE_SIZE (mode));
2019 memset (p, *c, GET_MODE_SIZE (mode));
2021 return c_readstr (p, mode);
2024 /* Expand expression EXP, which is a call to the memset builtin. Return 0
2025 if we failed the caller should emit a normal call. */
2027 static rtx
2028 expand_builtin_memset (exp)
2029 tree exp;
2031 tree arglist = TREE_OPERAND (exp, 1);
2033 if (!validate_arglist (arglist,
2034 POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
2035 return 0;
2036 else
2038 tree dest = TREE_VALUE (arglist);
2039 tree val = TREE_VALUE (TREE_CHAIN (arglist));
2040 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2041 char c;
2043 int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
2044 rtx dest_mem, dest_addr, len_rtx;
2046 /* If DEST is not a pointer type, don't do this
2047 operation in-line. */
2048 if (dest_align == 0)
2049 return 0;
2051 if (TREE_CODE (val) != INTEGER_CST)
2052 return 0;
2054 if (target_char_cast (val, &c))
2055 return 0;
2057 if (c)
2059 if (TREE_CODE (len) != INTEGER_CST || TREE_INT_CST_HIGH (len))
2060 return 0;
2061 if (current_function_check_memory_usage
2062 || !can_store_by_pieces (TREE_INT_CST_LOW (len),
2063 builtin_memset_read_str,
2064 (PTR) &c, dest_align))
2065 return 0;
2067 dest_mem = get_memory_rtx (dest);
2068 store_by_pieces (dest_mem, TREE_INT_CST_LOW (len),
2069 builtin_memset_read_str,
2070 (PTR) &c, dest_align);
2071 return force_operand (XEXP (dest_mem, 0), NULL_RTX);
2074 len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2076 dest_mem = get_memory_rtx (dest);
2078 /* Just check DST is writable and mark it as readable. */
2079 if (current_function_check_memory_usage)
2080 emit_library_call (chkr_check_addr_libfunc, LCT_CONST_MAKE_BLOCK,
2081 VOIDmode, 3, XEXP (dest_mem, 0), Pmode,
2082 len_rtx, TYPE_MODE (sizetype),
2083 GEN_INT (MEMORY_USE_WO),
2084 TYPE_MODE (integer_type_node));
2087 dest_addr = clear_storage (dest_mem, len_rtx, dest_align);
2089 if (dest_addr == 0)
2090 dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
2092 return dest_addr;
2096 /* Expand expression EXP, which is a call to the bzero builtin. Return 0
2097 if we failed the caller should emit a normal call. */
2098 static rtx
2099 expand_builtin_bzero (exp)
2100 tree exp;
2102 tree arglist = TREE_OPERAND (exp, 1);
2103 tree dest, size, newarglist;
2104 rtx result;
2106 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2107 return NULL_RTX;
2109 dest = TREE_VALUE (arglist);
2110 size = TREE_VALUE (TREE_CHAIN (arglist));
2112 /* New argument list transforming bzero(ptr x, int y) to
2113 memset(ptr x, int 0, size_t y). */
2115 newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
2116 newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
2117 newarglist = tree_cons (NULL_TREE, dest, newarglist);
2119 TREE_OPERAND (exp, 1) = newarglist;
2120 result = expand_builtin_memset(exp);
2122 /* Always restore the original arguments. */
2123 TREE_OPERAND (exp, 1) = arglist;
2125 return result;
2128 #ifdef HAVE_cmpstrsi
2129 /* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
2130 ARGLIST is the argument list for this call. Return 0 if we failed and the
2131 caller should emit a normal call, otherwise try to get the result in
2132 TARGET, if convenient. */
2133 static rtx
2134 expand_builtin_memcmp (exp, arglist, target)
2135 tree exp;
2136 tree arglist;
2137 rtx target;
2139 /* If we need to check memory accesses, call the library function. */
2140 if (current_function_check_memory_usage)
2141 return 0;
2143 if (!validate_arglist (arglist,
2144 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2145 return 0;
2148 enum machine_mode mode;
2149 tree arg1 = TREE_VALUE (arglist);
2150 tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2151 tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2152 rtx arg1_rtx, arg2_rtx, arg3_rtx;
2153 rtx result;
2154 rtx insn;
2156 int arg1_align
2157 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2158 int arg2_align
2159 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2160 enum machine_mode insn_mode
2161 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
2163 /* If we don't have POINTER_TYPE, call the function. */
2164 if (arg1_align == 0 || arg2_align == 0)
2165 return 0;
2167 /* Make a place to write the result of the instruction. */
2168 result = target;
2169 if (! (result != 0
2170 && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
2171 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2172 result = gen_reg_rtx (insn_mode);
2174 arg1_rtx = get_memory_rtx (arg1);
2175 arg2_rtx = get_memory_rtx (arg2);
2176 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2177 if (!HAVE_cmpstrsi)
2178 insn = NULL_RTX;
2179 else
2180 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
2181 GEN_INT (MIN (arg1_align, arg2_align)));
2183 if (insn)
2184 emit_insn (insn);
2185 else
2186 emit_library_call_value (memcmp_libfunc, result, LCT_PURE_MAKE_BLOCK,
2187 TYPE_MODE (integer_type_node), 3,
2188 XEXP (arg1_rtx, 0), Pmode,
2189 XEXP (arg2_rtx, 0), Pmode,
2190 convert_to_mode (TYPE_MODE (sizetype), arg3_rtx,
2191 TREE_UNSIGNED (sizetype)),
2192 TYPE_MODE (sizetype));
2194 /* Return the value in the proper mode for this function. */
2195 mode = TYPE_MODE (TREE_TYPE (exp));
2196 if (GET_MODE (result) == mode)
2197 return result;
2198 else if (target != 0)
2200 convert_move (target, result, 0);
2201 return target;
2203 else
2204 return convert_to_mode (mode, result, 0);
2207 #endif
2209 /* Expand expression EXP, which is a call to the strcmp builtin. Return 0
2210 if we failed the caller should emit a normal call, otherwise try to get
2211 the result in TARGET, if convenient. */
2213 static rtx
2214 expand_builtin_strcmp (exp, target, mode)
2215 tree exp;
2216 rtx target;
2217 enum machine_mode mode;
2219 tree arglist = TREE_OPERAND (exp, 1);
2220 tree arg1, arg2;
2221 const char *p1, *p2;
2223 /* If we need to check memory accesses, call the library function. */
2224 if (current_function_check_memory_usage)
2225 return 0;
2227 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2228 return 0;
2230 arg1 = TREE_VALUE (arglist);
2231 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2233 p1 = c_getstr (arg1);
2234 p2 = c_getstr (arg2);
2236 if (p1 && p2)
2238 const int i = strcmp (p1, p2);
2239 return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
2242 /* If either arg is "", return an expression corresponding to
2243 (*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
2244 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2246 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2247 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2248 tree ind1 =
2249 fold (build1 (CONVERT_EXPR, integer_type_node,
2250 build1 (INDIRECT_REF, cst_uchar_node,
2251 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2252 tree ind2 =
2253 fold (build1 (CONVERT_EXPR, integer_type_node,
2254 build1 (INDIRECT_REF, cst_uchar_node,
2255 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2256 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2257 return expand_expr (result, target, mode, EXPAND_NORMAL);
2260 #ifdef HAVE_cmpstrsi
2261 if (! HAVE_cmpstrsi)
2262 return 0;
2265 tree len = c_strlen (arg1);
2266 tree len2 = c_strlen (arg2);
2267 rtx result;
2269 if (len)
2270 len = size_binop (PLUS_EXPR, ssize_int (1), len);
2272 if (len2)
2273 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
2275 /* If we don't have a constant length for the first, use the length
2276 of the second, if we know it. We don't require a constant for
2277 this case; some cost analysis could be done if both are available
2278 but neither is constant. For now, assume they're equally cheap
2279 unless one has side effects.
2281 If both strings have constant lengths, use the smaller. This
2282 could arise if optimization results in strcpy being called with
2283 two fixed strings, or if the code was machine-generated. We should
2284 add some code to the `memcmp' handler below to deal with such
2285 situations, someday. */
2287 if (!len || TREE_CODE (len) != INTEGER_CST)
2289 if (len2 && !TREE_SIDE_EFFECTS (len2))
2290 len = len2;
2291 else if (len == 0)
2292 return 0;
2294 else if (len2 && TREE_CODE (len2) == INTEGER_CST
2295 && tree_int_cst_lt (len2, len))
2296 len = len2;
2298 /* If both arguments have side effects, we cannot optimize. */
2299 if (TREE_SIDE_EFFECTS (len))
2300 return 0;
2302 chainon (arglist, build_tree_list (NULL_TREE, len));
2303 result = expand_builtin_memcmp (exp, arglist, target);
2304 if (! result)
2305 TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
2307 return result;
2309 #else
2310 return 0;
2311 #endif
2314 /* Expand expression EXP, which is a call to the strncmp builtin. Return 0
2315 if we failed the caller should emit a normal call, otherwise try to get
2316 the result in TARGET, if convenient. */
2317 static rtx
2318 expand_builtin_strncmp (exp, target, mode)
2319 tree exp;
2320 rtx target;
2321 enum machine_mode mode;
2323 tree arglist = TREE_OPERAND (exp, 1);
2324 tree arg1, arg2, arg3;
2325 const char *p1, *p2;
2327 /* If we need to check memory accesses, call the library function. */
2328 if (current_function_check_memory_usage)
2329 return 0;
2331 if (!validate_arglist (arglist,
2332 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2333 return 0;
2335 arg1 = TREE_VALUE (arglist);
2336 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2337 arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2339 /* If the len parameter is zero, return zero. */
2340 if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0)
2342 /* Evaluate and ignore arg1 and arg2 in case they have
2343 side-effects. */
2344 expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2345 expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2346 return const0_rtx;
2349 p1 = c_getstr (arg1);
2350 p2 = c_getstr (arg2);
2352 /* If all arguments are constant, evaluate at compile-time. */
2353 if (host_integerp (arg3, 1) && p1 && p2)
2355 const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
2356 return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
2359 /* If len == 1 or (either string parameter is "" and (len >= 1)),
2360 return (*(const u_char*)arg1 - *(const u_char*)arg2). */
2361 if (host_integerp (arg3, 1)
2362 && (tree_low_cst (arg3, 1) == 1
2363 || (tree_low_cst (arg3, 1) > 1
2364 && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0')))))
2366 tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
2367 tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
2368 tree ind1 =
2369 fold (build1 (CONVERT_EXPR, integer_type_node,
2370 build1 (INDIRECT_REF, cst_uchar_node,
2371 build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
2372 tree ind2 =
2373 fold (build1 (CONVERT_EXPR, integer_type_node,
2374 build1 (INDIRECT_REF, cst_uchar_node,
2375 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2376 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2377 return expand_expr (result, target, mode, EXPAND_NORMAL);
2380 #ifdef HAVE_cmpstrsi
2381 /* If c_strlen can determine an expression for one of the string
2382 lengths, and it doesn't have side effects, then call
2383 expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3). */
2384 if (HAVE_cmpstrsi)
2386 tree newarglist, len = 0;
2388 /* Perhaps one of the strings is really constant, if so prefer
2389 that constant length over the other string's length. */
2390 if (p1)
2391 len = c_strlen (arg1);
2392 else if (p2)
2393 len = c_strlen (arg2);
2395 /* If we still don't have a len, try either string arg as long
2396 as they don't have side effects. */
2397 if (!len && !TREE_SIDE_EFFECTS (arg1))
2398 len = c_strlen (arg1);
2399 if (!len && !TREE_SIDE_EFFECTS (arg2))
2400 len = c_strlen (arg2);
2401 /* If we still don't have a length, punt. */
2402 if (!len)
2403 return 0;
2405 /* Add one to the string length. */
2406 len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
2408 /* The actual new length parameter is MIN(len,arg3). */
2409 len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
2411 newarglist = build_tree_list (NULL_TREE, len);
2412 newarglist = tree_cons (NULL_TREE, arg2, newarglist);
2413 newarglist = tree_cons (NULL_TREE, arg1, newarglist);
2414 return expand_builtin_memcmp (exp, newarglist, target);
2416 #endif
2418 return 0;
2421 /* Expand expression EXP, which is a call to the strcat builtin.
2422 Return 0 if we failed the caller should emit a normal call,
2423 otherwise try to get the result in TARGET, if convenient. */
2424 static rtx
2425 expand_builtin_strcat (arglist, target, mode)
2426 tree arglist;
2427 rtx target;
2428 enum machine_mode mode;
2430 /* If we need to check memory accesses, call the library function. */
2431 if (current_function_check_memory_usage)
2432 return 0;
2434 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2435 return 0;
2436 else
2438 tree dst = TREE_VALUE (arglist),
2439 src = TREE_VALUE (TREE_CHAIN (arglist));
2440 const char *p = c_getstr (src);
2442 /* If the string length is zero, return the dst parameter. */
2443 if (p && *p == '\0')
2444 return expand_expr (dst, target, mode, EXPAND_NORMAL);
2446 return 0;
2450 /* Expand expression EXP, which is a call to the strncat builtin.
2451 Return 0 if we failed the caller should emit a normal call,
2452 otherwise try to get the result in TARGET, if convenient. */
2453 static rtx
2454 expand_builtin_strncat (arglist, target, mode)
2455 tree arglist;
2456 rtx target;
2457 enum machine_mode mode;
2459 /* If we need to check memory accesses, call the library function. */
2460 if (current_function_check_memory_usage)
2461 return 0;
2463 if (!validate_arglist (arglist,
2464 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2465 return 0;
2466 else
2468 tree dst = TREE_VALUE (arglist),
2469 src = TREE_VALUE (TREE_CHAIN (arglist)),
2470 len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
2471 const char *p = c_getstr (src);
2473 /* If the requested length is zero, or the src parameter string
2474 length is zero, return the dst parameter. */
2475 if ((TREE_CODE (len) == INTEGER_CST && compare_tree_int (len, 0) == 0)
2476 || (p && *p == '\0'))
2478 /* Evaluate and ignore the src and len parameters in case
2479 they have side-effects. */
2480 expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
2481 expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
2482 return expand_expr (dst, target, mode, EXPAND_NORMAL);
2485 /* If the requested len is greater than or equal to the string
2486 length, call strcat. */
2487 if (TREE_CODE (len) == INTEGER_CST && p
2488 && compare_tree_int (len, strlen (p)) >= 0)
2490 tree newarglist =
2491 tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src)),
2492 fn = built_in_decls[BUILT_IN_STRCAT];
2494 /* If the replacement _DECL isn't initialized, don't do the
2495 transformation. */
2496 if (!fn)
2497 return 0;
2499 return expand_expr (build_function_call_expr (fn, newarglist),
2500 target, mode, EXPAND_NORMAL);
2502 return 0;
2506 /* Expand expression EXP, which is a call to the strspn builtin.
2507 Return 0 if we failed the caller should emit a normal call,
2508 otherwise try to get the result in TARGET, if convenient. */
2509 static rtx
2510 expand_builtin_strspn (arglist, target, mode)
2511 tree arglist;
2512 rtx target;
2513 enum machine_mode mode;
2515 /* If we need to check memory accesses, call the library function. */
2516 if (current_function_check_memory_usage)
2517 return 0;
2519 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2520 return 0;
2521 else
2523 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2524 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2526 /* If both arguments are constants, evaluate at compile-time. */
2527 if (p1 && p2)
2529 const size_t r = strspn (p1, p2);
2530 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2533 /* If either argument is "", return 0. */
2534 if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
2536 /* Evaluate and ignore both arguments in case either one has
2537 side-effects. */
2538 expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
2539 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2540 return const0_rtx;
2542 return 0;
2546 /* Expand expression EXP, which is a call to the strcspn builtin.
2547 Return 0 if we failed the caller should emit a normal call,
2548 otherwise try to get the result in TARGET, if convenient. */
2549 static rtx
2550 expand_builtin_strcspn (arglist, target, mode)
2551 tree arglist;
2552 rtx target;
2553 enum machine_mode mode;
2555 /* If we need to check memory accesses, call the library function. */
2556 if (current_function_check_memory_usage)
2557 return 0;
2559 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2560 return 0;
2561 else
2563 tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
2564 const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
2566 /* If both arguments are constants, evaluate at compile-time. */
2567 if (p1 && p2)
2569 const size_t r = strcspn (p1, p2);
2570 return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
2573 /* If the first argument is "", return 0. */
2574 if (p1 && *p1 == '\0')
2576 /* Evaluate and ignore argument s2 in case it has
2577 side-effects. */
2578 expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
2579 return const0_rtx;
2582 /* If the second argument is "", return __builtin_strlen(s1). */
2583 if (p2 && *p2 == '\0')
2585 tree newarglist = build_tree_list (NULL_TREE, s1),
2586 fn = built_in_decls[BUILT_IN_STRLEN];
2588 /* If the replacement _DECL isn't initialized, don't do the
2589 transformation. */
2590 if (!fn)
2591 return 0;
2593 return expand_expr (build_function_call_expr (fn, newarglist),
2594 target, mode, EXPAND_NORMAL);
2596 return 0;
2600 /* Expand a call to __builtin_saveregs, generating the result in TARGET,
2601 if that's convenient. */
2604 expand_builtin_saveregs ()
2606 rtx val, seq;
2608 /* Don't do __builtin_saveregs more than once in a function.
2609 Save the result of the first call and reuse it. */
2610 if (saveregs_value != 0)
2611 return saveregs_value;
2613 /* When this function is called, it means that registers must be
2614 saved on entry to this function. So we migrate the call to the
2615 first insn of this function. */
2617 start_sequence ();
2619 #ifdef EXPAND_BUILTIN_SAVEREGS
2620 /* Do whatever the machine needs done in this case. */
2621 val = EXPAND_BUILTIN_SAVEREGS ();
2622 #else
2623 /* ??? We used to try and build up a call to the out of line function,
2624 guessing about what registers needed saving etc. This became much
2625 harder with __builtin_va_start, since we don't have a tree for a
2626 call to __builtin_saveregs to fall back on. There was exactly one
2627 port (i860) that used this code, and I'm unconvinced it could actually
2628 handle the general case. So we no longer try to handle anything
2629 weird and make the backend absorb the evil. */
2631 error ("__builtin_saveregs not supported by this target");
2632 val = const0_rtx;
2633 #endif
2635 seq = get_insns ();
2636 end_sequence ();
2638 saveregs_value = val;
2640 /* Put the sequence after the NOTE that starts the function. If this
2641 is inside a SEQUENCE, make the outer-level insn chain current, so
2642 the code is placed at the start of the function. */
2643 push_topmost_sequence ();
2644 emit_insns_after (seq, get_insns ());
2645 pop_topmost_sequence ();
2647 return val;
2650 /* __builtin_args_info (N) returns word N of the arg space info
2651 for the current function. The number and meanings of words
2652 is controlled by the definition of CUMULATIVE_ARGS. */
2654 static rtx
2655 expand_builtin_args_info (exp)
2656 tree exp;
2658 tree arglist = TREE_OPERAND (exp, 1);
2659 int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
2660 int *word_ptr = (int *) &current_function_args_info;
2661 #if 0
2662 /* These are used by the code below that is if 0'ed away */
2663 int i;
2664 tree type, elts, result;
2665 #endif
2667 if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
2668 abort ();
2670 if (arglist != 0)
2672 tree arg = TREE_VALUE (arglist);
2673 if (TREE_CODE (arg) != INTEGER_CST)
2674 error ("argument of `__builtin_args_info' must be constant");
2675 else
2677 int wordnum = TREE_INT_CST_LOW (arg);
2679 if (wordnum < 0 || wordnum >= nwords || TREE_INT_CST_HIGH (arg))
2680 error ("argument of `__builtin_args_info' out of range");
2681 else
2682 return GEN_INT (word_ptr[wordnum]);
2685 else
2686 error ("missing argument in `__builtin_args_info'");
2688 return const0_rtx;
2690 #if 0
2691 for (i = 0; i < nwords; i++)
2692 elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
2694 type = build_array_type (integer_type_node,
2695 build_index_type (build_int_2 (nwords, 0)));
2696 result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
2697 TREE_CONSTANT (result) = 1;
2698 TREE_STATIC (result) = 1;
2699 result = build1 (INDIRECT_REF, build_pointer_type (type), result);
2700 TREE_CONSTANT (result) = 1;
2701 return expand_expr (result, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD);
2702 #endif
2705 /* Expand ARGLIST, from a call to __builtin_next_arg. */
2706 static rtx
2707 expand_builtin_next_arg (arglist)
2708 tree arglist;
2710 tree fntype = TREE_TYPE (current_function_decl);
2712 if ((TYPE_ARG_TYPES (fntype) == 0
2713 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2714 == void_type_node))
2715 && ! current_function_varargs)
2717 error ("`va_start' used in function with fixed args");
2718 return const0_rtx;
2721 if (arglist)
2723 tree last_parm = tree_last (DECL_ARGUMENTS (current_function_decl));
2724 tree arg = TREE_VALUE (arglist);
2726 /* Strip off all nops for the sake of the comparison. This
2727 is not quite the same as STRIP_NOPS. It does more.
2728 We must also strip off INDIRECT_EXPR for C++ reference
2729 parameters. */
2730 while (TREE_CODE (arg) == NOP_EXPR
2731 || TREE_CODE (arg) == CONVERT_EXPR
2732 || TREE_CODE (arg) == NON_LVALUE_EXPR
2733 || TREE_CODE (arg) == INDIRECT_REF)
2734 arg = TREE_OPERAND (arg, 0);
2735 if (arg != last_parm)
2736 warning ("second parameter of `va_start' not last named argument");
2738 else if (! current_function_varargs)
2739 /* Evidently an out of date version of <stdarg.h>; can't validate
2740 va_start's second argument, but can still work as intended. */
2741 warning ("`__builtin_next_arg' called without an argument");
2743 return expand_binop (Pmode, add_optab,
2744 current_function_internal_arg_pointer,
2745 current_function_arg_offset_rtx,
2746 NULL_RTX, 0, OPTAB_LIB_WIDEN);
2749 /* Make it easier for the backends by protecting the valist argument
2750 from multiple evaluations. */
2752 static tree
2753 stabilize_va_list (valist, needs_lvalue)
2754 tree valist;
2755 int needs_lvalue;
2757 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
2759 if (TREE_SIDE_EFFECTS (valist))
2760 valist = save_expr (valist);
2762 /* For this case, the backends will be expecting a pointer to
2763 TREE_TYPE (va_list_type_node), but it's possible we've
2764 actually been given an array (an actual va_list_type_node).
2765 So fix it. */
2766 if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
2768 tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node));
2769 tree p2 = build_pointer_type (va_list_type_node);
2771 valist = build1 (ADDR_EXPR, p2, valist);
2772 valist = fold (build1 (NOP_EXPR, p1, valist));
2775 else
2777 tree pt;
2779 if (! needs_lvalue)
2781 if (! TREE_SIDE_EFFECTS (valist))
2782 return valist;
2784 pt = build_pointer_type (va_list_type_node);
2785 valist = fold (build1 (ADDR_EXPR, pt, valist));
2786 TREE_SIDE_EFFECTS (valist) = 1;
2789 if (TREE_SIDE_EFFECTS (valist))
2790 valist = save_expr (valist);
2791 valist = fold (build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)),
2792 valist));
2795 return valist;
2798 /* The "standard" implementation of va_start: just assign `nextarg' to
2799 the variable. */
2800 void
2801 std_expand_builtin_va_start (stdarg_p, valist, nextarg)
2802 int stdarg_p;
2803 tree valist;
2804 rtx nextarg;
2806 tree t;
2808 if (! stdarg_p)
2810 /* The dummy named parameter is declared as a 'word' sized
2811 object, but if a 'word' is smaller than an 'int', it would
2812 have been promoted to int when it was added to the arglist. */
2813 int align = PARM_BOUNDARY / BITS_PER_UNIT;
2814 int size = MAX (UNITS_PER_WORD,
2815 GET_MODE_SIZE (TYPE_MODE (integer_type_node)));
2816 int offset = ((size + align - 1) / align) * align;
2817 nextarg = plus_constant (nextarg, -offset);
2820 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2821 make_tree (ptr_type_node, nextarg));
2822 TREE_SIDE_EFFECTS (t) = 1;
2824 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2827 /* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
2828 __builtin_varargs_va_start, depending on STDARG_P. */
2829 static rtx
2830 expand_builtin_va_start (stdarg_p, arglist)
2831 int stdarg_p;
2832 tree arglist;
2834 rtx nextarg;
2835 tree chain = arglist, valist;
2837 if (stdarg_p)
2838 nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
2839 else
2840 nextarg = expand_builtin_next_arg (NULL_TREE);
2842 if (TREE_CHAIN (chain))
2843 error ("too many arguments to function `va_start'");
2845 valist = stabilize_va_list (TREE_VALUE (arglist), 1);
2847 #ifdef EXPAND_BUILTIN_VA_START
2848 EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
2849 #else
2850 std_expand_builtin_va_start (stdarg_p, valist, nextarg);
2851 #endif
2853 return const0_rtx;
2856 /* The "standard" implementation of va_arg: read the value from the
2857 current (padded) address and increment by the (padded) size. */
2860 std_expand_builtin_va_arg (valist, type)
2861 tree valist, type;
2863 tree addr_tree, t;
2864 HOST_WIDE_INT align;
2865 HOST_WIDE_INT rounded_size;
2866 rtx addr;
2868 /* Compute the rounded size of the type. */
2869 align = PARM_BOUNDARY / BITS_PER_UNIT;
2870 rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
2872 /* Get AP. */
2873 addr_tree = valist;
2874 if (PAD_VARARGS_DOWN)
2876 /* Small args are padded downward. */
2878 HOST_WIDE_INT adj;
2879 adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT;
2880 if (rounded_size > align)
2881 adj = rounded_size;
2883 addr_tree = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
2884 build_int_2 (rounded_size - adj, 0));
2887 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
2888 addr = copy_to_reg (addr);
2890 /* Compute new value for AP. */
2891 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
2892 build (PLUS_EXPR, TREE_TYPE (valist), valist,
2893 build_int_2 (rounded_size, 0)));
2894 TREE_SIDE_EFFECTS (t) = 1;
2895 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2897 return addr;
2900 /* Expand __builtin_va_arg, which is not really a builtin function, but
2901 a very special sort of operator. */
2904 expand_builtin_va_arg (valist, type)
2905 tree valist, type;
2907 rtx addr, result;
2908 tree promoted_type, want_va_type, have_va_type;
2910 /* Verify that valist is of the proper type. */
2912 want_va_type = va_list_type_node;
2913 have_va_type = TREE_TYPE (valist);
2914 if (TREE_CODE (want_va_type) == ARRAY_TYPE)
2916 /* If va_list is an array type, the argument may have decayed
2917 to a pointer type, e.g. by being passed to another function.
2918 In that case, unwrap both types so that we can compare the
2919 underlying records. */
2920 if (TREE_CODE (have_va_type) == ARRAY_TYPE
2921 || TREE_CODE (have_va_type) == POINTER_TYPE)
2923 want_va_type = TREE_TYPE (want_va_type);
2924 have_va_type = TREE_TYPE (have_va_type);
2927 if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type))
2929 error ("first argument to `va_arg' not of type `va_list'");
2930 addr = const0_rtx;
2933 /* Generate a diagnostic for requesting data of a type that cannot
2934 be passed through `...' due to type promotion at the call site. */
2935 else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
2937 const char *name = "<anonymous type>", *pname = 0;
2938 static int gave_help;
2940 if (TYPE_NAME (type))
2942 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
2943 name = IDENTIFIER_POINTER (TYPE_NAME (type));
2944 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
2945 && DECL_NAME (TYPE_NAME (type)))
2946 name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
2948 if (TYPE_NAME (promoted_type))
2950 if (TREE_CODE (TYPE_NAME (promoted_type)) == IDENTIFIER_NODE)
2951 pname = IDENTIFIER_POINTER (TYPE_NAME (promoted_type));
2952 else if (TREE_CODE (TYPE_NAME (promoted_type)) == TYPE_DECL
2953 && DECL_NAME (TYPE_NAME (promoted_type)))
2954 pname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (promoted_type)));
2957 error ("`%s' is promoted to `%s' when passed through `...'", name, pname);
2958 if (! gave_help)
2960 gave_help = 1;
2961 error ("(so you should pass `%s' not `%s' to `va_arg')", pname, name);
2964 addr = const0_rtx;
2966 else
2968 /* Make it easier for the backends by protecting the valist argument
2969 from multiple evaluations. */
2970 valist = stabilize_va_list (valist, 0);
2972 #ifdef EXPAND_BUILTIN_VA_ARG
2973 addr = EXPAND_BUILTIN_VA_ARG (valist, type);
2974 #else
2975 addr = std_expand_builtin_va_arg (valist, type);
2976 #endif
2979 result = gen_rtx_MEM (TYPE_MODE (type), addr);
2980 MEM_ALIAS_SET (result) = get_varargs_alias_set ();
2982 return result;
2985 /* Expand ARGLIST, from a call to __builtin_va_end. */
2987 static rtx
2988 expand_builtin_va_end (arglist)
2989 tree arglist;
2991 tree valist = TREE_VALUE (arglist);
2993 #ifdef EXPAND_BUILTIN_VA_END
2994 valist = stabilize_va_list (valist, 0);
2995 EXPAND_BUILTIN_VA_END(arglist);
2996 #else
2997 /* Evaluate for side effects, if needed. I hate macros that don't
2998 do that. */
2999 if (TREE_SIDE_EFFECTS (valist))
3000 expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
3001 #endif
3003 return const0_rtx;
3006 /* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a
3007 builtin rather than just as an assignment in stdarg.h because of the
3008 nastiness of array-type va_list types. */
3010 static rtx
3011 expand_builtin_va_copy (arglist)
3012 tree arglist;
3014 tree dst, src, t;
3016 dst = TREE_VALUE (arglist);
3017 src = TREE_VALUE (TREE_CHAIN (arglist));
3019 dst = stabilize_va_list (dst, 1);
3020 src = stabilize_va_list (src, 0);
3022 if (TREE_CODE (va_list_type_node) != ARRAY_TYPE)
3024 t = build (MODIFY_EXPR, va_list_type_node, dst, src);
3025 TREE_SIDE_EFFECTS (t) = 1;
3026 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
3028 else
3030 rtx dstb, srcb, size;
3032 /* Evaluate to pointers. */
3033 dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL);
3034 srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL);
3035 size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX,
3036 VOIDmode, EXPAND_NORMAL);
3038 /* "Dereference" to BLKmode memories. */
3039 dstb = gen_rtx_MEM (BLKmode, dstb);
3040 MEM_ALIAS_SET (dstb) = get_alias_set (TREE_TYPE (TREE_TYPE (dst)));
3041 srcb = gen_rtx_MEM (BLKmode, srcb);
3042 MEM_ALIAS_SET (srcb) = get_alias_set (TREE_TYPE (TREE_TYPE (src)));
3044 /* Copy. */
3045 emit_block_move (dstb, srcb, size, TYPE_ALIGN (va_list_type_node));
3048 return const0_rtx;
3051 /* Expand a call to one of the builtin functions __builtin_frame_address or
3052 __builtin_return_address. */
3053 static rtx
3054 expand_builtin_frame_address (exp)
3055 tree exp;
3057 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3058 tree arglist = TREE_OPERAND (exp, 1);
3060 /* The argument must be a nonnegative integer constant.
3061 It counts the number of frames to scan up the stack.
3062 The value is the return address saved in that frame. */
3063 if (arglist == 0)
3064 /* Warning about missing arg was already issued. */
3065 return const0_rtx;
3066 else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST
3067 || tree_int_cst_sgn (TREE_VALUE (arglist)) < 0)
3069 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3070 error ("invalid arg to `__builtin_frame_address'");
3071 else
3072 error ("invalid arg to `__builtin_return_address'");
3073 return const0_rtx;
3075 else
3077 rtx tem = expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
3078 TREE_INT_CST_LOW (TREE_VALUE (arglist)),
3079 hard_frame_pointer_rtx);
3081 /* Some ports cannot access arbitrary stack frames. */
3082 if (tem == NULL)
3084 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3085 warning ("unsupported arg to `__builtin_frame_address'");
3086 else
3087 warning ("unsupported arg to `__builtin_return_address'");
3088 return const0_rtx;
3091 /* For __builtin_frame_address, return what we've got. */
3092 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
3093 return tem;
3095 if (GET_CODE (tem) != REG
3096 && ! CONSTANT_P (tem))
3097 tem = copy_to_mode_reg (Pmode, tem);
3098 return tem;
3102 /* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if
3103 we failed and the caller should emit a normal call, otherwise try to get
3104 the result in TARGET, if convenient. */
3106 static rtx
3107 expand_builtin_alloca (arglist, target)
3108 tree arglist;
3109 rtx target;
3111 rtx op0;
3112 rtx result;
3114 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3115 return 0;
3117 /* Compute the argument. */
3118 op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
3120 /* Allocate the desired space. */
3121 result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
3123 #ifdef POINTERS_EXTEND_UNSIGNED
3124 result = convert_memory_address (ptr_mode, result);
3125 #endif
3127 return result;
3130 /* Expand a call to the ffs builtin. The arguments are in ARGLIST.
3131 Return 0 if a normal call should be emitted rather than expanding the
3132 function in-line. If convenient, the result should be placed in TARGET.
3133 SUBTARGET may be used as the target for computing one of EXP's operands. */
3135 static rtx
3136 expand_builtin_ffs (arglist, target, subtarget)
3137 tree arglist;
3138 rtx target, subtarget;
3140 rtx op0;
3141 if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
3142 return 0;
3144 /* Compute the argument. */
3145 op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
3146 /* Compute ffs, into TARGET if possible.
3147 Set TARGET to wherever the result comes back. */
3148 target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
3149 ffs_optab, op0, target, 1);
3150 if (target == 0)
3151 abort ();
3152 return target;
3155 /* If the string passed to fputs is a constant and is one character
3156 long, we attempt to transform this call into __builtin_fputc(). */
3158 static rtx
3159 expand_builtin_fputs (arglist, ignore)
3160 tree arglist;
3161 int ignore;
3163 tree len, fn, fn_fputc = built_in_decls[BUILT_IN_FPUTC],
3164 fn_fwrite = built_in_decls[BUILT_IN_FWRITE];
3166 /* If the return value is used, or the replacement _DECL isn't
3167 initialized, don't do the transformation. */
3168 if (!ignore || !fn_fputc || !fn_fwrite)
3169 return 0;
3171 /* Verify the arguments in the original call. */
3172 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)
3173 || current_function_check_memory_usage)
3174 return 0;
3176 /* Get the length of the string passed to fputs. If the length
3177 can't be determined, punt. */
3178 if (!(len = c_strlen (TREE_VALUE (arglist)))
3179 || TREE_CODE (len) != INTEGER_CST)
3180 return 0;
3182 switch (compare_tree_int (len, 1))
3184 case -1: /* length is 0, delete the call entirely . */
3186 /* Evaluate and ignore the argument in case it has
3187 side-effects. */
3188 expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
3189 VOIDmode, EXPAND_NORMAL);
3190 return const0_rtx;
3192 case 0: /* length is 1, call fputc. */
3194 const char *p = c_getstr (TREE_VALUE (arglist));
3196 if (p != NULL)
3198 /* New argument list transforming fputs(string, stream) to
3199 fputc(string[0], stream). */
3200 arglist =
3201 build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3202 arglist =
3203 tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
3204 fn = fn_fputc;
3205 break;
3208 /* FALLTHROUGH */
3209 case 1: /* length is greater than 1, call fwrite. */
3211 tree string_arg = TREE_VALUE (arglist);
3213 /* New argument list transforming fputs(string, stream) to
3214 fwrite(string, 1, len, stream). */
3215 arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
3216 arglist = tree_cons (NULL_TREE, len, arglist);
3217 arglist = tree_cons (NULL_TREE, size_one_node, arglist);
3218 arglist = tree_cons (NULL_TREE, string_arg, arglist);
3219 fn = fn_fwrite;
3220 break;
3222 default:
3223 abort();
3226 return expand_expr (build_function_call_expr (fn, arglist),
3227 (ignore ? const0_rtx : NULL_RTX),
3228 VOIDmode, EXPAND_NORMAL);
3231 /* Expand a call to __builtin_expect. We return our argument and
3232 emit a NOTE_INSN_EXPECTED_VALUE note. */
3234 static rtx
3235 expand_builtin_expect (arglist, target)
3236 tree arglist;
3237 rtx target;
3239 tree exp, c;
3240 rtx note, rtx_c;
3242 if (arglist == NULL_TREE
3243 || TREE_CHAIN (arglist) == NULL_TREE)
3244 return const0_rtx;
3245 exp = TREE_VALUE (arglist);
3246 c = TREE_VALUE (TREE_CHAIN (arglist));
3248 if (TREE_CODE (c) != INTEGER_CST)
3250 error ("second arg to `__builtin_expect' must be a constant");
3251 c = integer_zero_node;
3254 target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
3256 /* Don't bother with expected value notes for integral constants. */
3257 if (GET_CODE (target) != CONST_INT)
3259 /* We do need to force this into a register so that we can be
3260 moderately sure to be able to correctly interpret the branch
3261 condition later. */
3262 target = force_reg (GET_MODE (target), target);
3264 rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
3266 note = emit_note (NULL, NOTE_INSN_EXPECTED_VALUE);
3267 NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
3270 return target;
3273 /* Expand an expression EXP that calls a built-in function,
3274 with result going to TARGET if that's convenient
3275 (and in mode MODE if that's convenient).
3276 SUBTARGET may be used as the target for computing one of EXP's operands.
3277 IGNORE is nonzero if the value is to be ignored. */
3280 expand_builtin (exp, target, subtarget, mode, ignore)
3281 tree exp;
3282 rtx target;
3283 rtx subtarget;
3284 enum machine_mode mode;
3285 int ignore;
3287 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3288 tree arglist = TREE_OPERAND (exp, 1);
3289 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
3291 #ifdef MD_EXPAND_BUILTIN
3292 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
3293 return MD_EXPAND_BUILTIN (exp, target, subtarget, mode, ignore);
3294 #endif
3296 /* When not optimizing, generate calls to library functions for a certain
3297 set of builtins. */
3298 if (! optimize && ! CALLED_AS_BUILT_IN (fndecl)
3299 && (fcode == BUILT_IN_SIN || fcode == BUILT_IN_COS
3300 || fcode == BUILT_IN_FSQRT || fcode == BUILT_IN_MEMSET
3301 || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
3302 || fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO
3303 || fcode == BUILT_IN_INDEX || fcode == BUILT_IN_RINDEX
3304 || fcode == BUILT_IN_STRCHR || fcode == BUILT_IN_STRRCHR
3305 || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
3306 || fcode == BUILT_IN_STRNCPY || fcode == BUILT_IN_STRNCMP
3307 || fcode == BUILT_IN_STRSTR || fcode == BUILT_IN_STRPBRK
3308 || fcode == BUILT_IN_STRCAT || fcode == BUILT_IN_STRNCAT
3309 || fcode == BUILT_IN_STRSPN || fcode == BUILT_IN_STRCSPN
3310 || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS
3311 || fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS
3312 || fcode == BUILT_IN_PRINTF || fcode == BUILT_IN_FPUTC
3313 || fcode == BUILT_IN_FPUTS || fcode == BUILT_IN_FWRITE))
3314 return expand_call (exp, target, ignore);
3316 switch (fcode)
3318 case BUILT_IN_ABS:
3319 case BUILT_IN_FABS:
3320 /* build_function_call changes these into ABS_EXPR. */
3321 abort ();
3323 case BUILT_IN_CONJ:
3324 case BUILT_IN_CREAL:
3325 case BUILT_IN_CIMAG:
3326 /* expand_tree_builtin changes these into CONJ_EXPR, REALPART_EXPR
3327 and IMAGPART_EXPR. */
3328 abort ();
3330 case BUILT_IN_SIN:
3331 case BUILT_IN_COS:
3332 /* Treat these like sqrt, but only if the user asks for them. */
3333 if (! flag_fast_math)
3334 break;
3335 case BUILT_IN_FSQRT:
3336 target = expand_builtin_mathfn (exp, target, subtarget);
3337 if (target)
3338 return target;
3339 break;
3341 case BUILT_IN_FMOD:
3342 break;
3344 case BUILT_IN_APPLY_ARGS:
3345 return expand_builtin_apply_args ();
3347 /* __builtin_apply (FUNCTION, ARGUMENTS, ARGSIZE) invokes
3348 FUNCTION with a copy of the parameters described by
3349 ARGUMENTS, and ARGSIZE. It returns a block of memory
3350 allocated on the stack into which is stored all the registers
3351 that might possibly be used for returning the result of a
3352 function. ARGUMENTS is the value returned by
3353 __builtin_apply_args. ARGSIZE is the number of bytes of
3354 arguments that must be copied. ??? How should this value be
3355 computed? We'll also need a safe worst case value for varargs
3356 functions. */
3357 case BUILT_IN_APPLY:
3358 if (!validate_arglist (arglist, POINTER_TYPE,
3359 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)
3360 && !validate_arglist (arglist, REFERENCE_TYPE,
3361 POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3362 return const0_rtx;
3363 else
3365 int i;
3366 tree t;
3367 rtx ops[3];
3369 for (t = arglist, i = 0; t; t = TREE_CHAIN (t), i++)
3370 ops[i] = expand_expr (TREE_VALUE (t), NULL_RTX, VOIDmode, 0);
3372 return expand_builtin_apply (ops[0], ops[1], ops[2]);
3375 /* __builtin_return (RESULT) causes the function to return the
3376 value described by RESULT. RESULT is address of the block of
3377 memory returned by __builtin_apply. */
3378 case BUILT_IN_RETURN:
3379 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
3380 expand_builtin_return (expand_expr (TREE_VALUE (arglist),
3381 NULL_RTX, VOIDmode, 0));
3382 return const0_rtx;
3384 case BUILT_IN_SAVEREGS:
3385 return expand_builtin_saveregs ();
3387 case BUILT_IN_ARGS_INFO:
3388 return expand_builtin_args_info (exp);
3390 /* Return the address of the first anonymous stack arg. */
3391 case BUILT_IN_NEXT_ARG:
3392 return expand_builtin_next_arg (arglist);
3394 case BUILT_IN_CLASSIFY_TYPE:
3395 return expand_builtin_classify_type (arglist);
3397 case BUILT_IN_CONSTANT_P:
3398 return expand_builtin_constant_p (exp);
3400 case BUILT_IN_FRAME_ADDRESS:
3401 case BUILT_IN_RETURN_ADDRESS:
3402 return expand_builtin_frame_address (exp);
3404 /* Returns the address of the area where the structure is returned.
3405 0 otherwise. */
3406 case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
3407 if (arglist != 0
3408 || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
3409 || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
3410 return const0_rtx;
3411 else
3412 return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
3414 case BUILT_IN_ALLOCA:
3415 target = expand_builtin_alloca (arglist, target);
3416 if (target)
3417 return target;
3418 break;
3420 case BUILT_IN_FFS:
3421 target = expand_builtin_ffs (arglist, target, subtarget);
3422 if (target)
3423 return target;
3424 break;
3426 case BUILT_IN_STRLEN:
3427 target = expand_builtin_strlen (exp, target);
3428 if (target)
3429 return target;
3430 break;
3432 case BUILT_IN_STRCPY:
3433 target = expand_builtin_strcpy (exp);
3434 if (target)
3435 return target;
3436 break;
3438 case BUILT_IN_STRNCPY:
3439 target = expand_builtin_strncpy (arglist, target, mode);
3440 if (target)
3441 return target;
3442 break;
3444 case BUILT_IN_STRCAT:
3445 target = expand_builtin_strcat (arglist, target, mode);
3446 if (target)
3447 return target;
3448 break;
3450 case BUILT_IN_STRNCAT:
3451 target = expand_builtin_strncat (arglist, target, mode);
3452 if (target)
3453 return target;
3454 break;
3456 case BUILT_IN_STRSPN:
3457 target = expand_builtin_strspn (arglist, target, mode);
3458 if (target)
3459 return target;
3460 break;
3462 case BUILT_IN_STRCSPN:
3463 target = expand_builtin_strcspn (arglist, target, mode);
3464 if (target)
3465 return target;
3466 break;
3468 case BUILT_IN_STRSTR:
3469 target = expand_builtin_strstr (arglist, target, mode);
3470 if (target)
3471 return target;
3472 break;
3474 case BUILT_IN_STRPBRK:
3475 target = expand_builtin_strpbrk (arglist, target, mode);
3476 if (target)
3477 return target;
3478 break;
3480 case BUILT_IN_INDEX:
3481 case BUILT_IN_STRCHR:
3482 target = expand_builtin_strchr (arglist, target, mode);
3483 if (target)
3484 return target;
3485 break;
3487 case BUILT_IN_RINDEX:
3488 case BUILT_IN_STRRCHR:
3489 target = expand_builtin_strrchr (arglist, target, mode);
3490 if (target)
3491 return target;
3492 break;
3494 case BUILT_IN_MEMCPY:
3495 target = expand_builtin_memcpy (arglist);
3496 if (target)
3497 return target;
3498 break;
3500 case BUILT_IN_MEMSET:
3501 target = expand_builtin_memset (exp);
3502 if (target)
3503 return target;
3504 break;
3506 case BUILT_IN_BZERO:
3507 target = expand_builtin_bzero (exp);
3508 if (target)
3509 return target;
3510 break;
3512 case BUILT_IN_STRCMP:
3513 target = expand_builtin_strcmp (exp, target, mode);
3514 if (target)
3515 return target;
3516 break;
3518 case BUILT_IN_STRNCMP:
3519 target = expand_builtin_strncmp (exp, target, mode);
3520 if (target)
3521 return target;
3522 break;
3524 /* These comparison functions need an instruction that returns an actual
3525 index. An ordinary compare that just sets the condition codes
3526 is not enough. */
3527 #ifdef HAVE_cmpstrsi
3528 case BUILT_IN_BCMP:
3529 case BUILT_IN_MEMCMP:
3530 target = expand_builtin_memcmp (exp, arglist, target);
3531 if (target)
3532 return target;
3533 break;
3534 #else
3535 case BUILT_IN_BCMP:
3536 case BUILT_IN_MEMCMP:
3537 break;
3538 #endif
3540 case BUILT_IN_SETJMP:
3541 target = expand_builtin_setjmp (arglist, target);
3542 if (target)
3543 return target;
3544 break;
3546 /* __builtin_longjmp is passed a pointer to an array of five words.
3547 It's similar to the C library longjmp function but works with
3548 __builtin_setjmp above. */
3549 case BUILT_IN_LONGJMP:
3550 if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
3551 break;
3552 else
3554 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
3555 VOIDmode, 0);
3556 rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
3557 NULL_RTX, VOIDmode, 0);
3559 if (value != const1_rtx)
3561 error ("__builtin_longjmp second argument must be 1");
3562 return const0_rtx;
3565 expand_builtin_longjmp (buf_addr, value);
3566 return const0_rtx;
3569 case BUILT_IN_TRAP:
3570 #ifdef HAVE_trap
3571 if (HAVE_trap)
3572 emit_insn (gen_trap ());
3573 else
3574 #endif
3575 error ("__builtin_trap not supported by this target");
3576 emit_barrier ();
3577 return const0_rtx;
3579 case BUILT_IN_PUTCHAR:
3580 case BUILT_IN_PUTS:
3581 case BUILT_IN_FPUTC:
3582 case BUILT_IN_FWRITE:
3583 break;
3584 case BUILT_IN_FPUTS:
3585 target = expand_builtin_fputs (arglist, ignore);
3586 if (target)
3587 return target;
3588 break;
3590 /* Various hooks for the DWARF 2 __throw routine. */
3591 case BUILT_IN_UNWIND_INIT:
3592 expand_builtin_unwind_init ();
3593 return const0_rtx;
3594 case BUILT_IN_DWARF_CFA:
3595 return virtual_cfa_rtx;
3596 #ifdef DWARF2_UNWIND_INFO
3597 case BUILT_IN_DWARF_FP_REGNUM:
3598 return expand_builtin_dwarf_fp_regnum ();
3599 case BUILT_IN_INIT_DWARF_REG_SIZES:
3600 expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
3601 return const0_rtx;
3602 #endif
3603 case BUILT_IN_FROB_RETURN_ADDR:
3604 return expand_builtin_frob_return_addr (TREE_VALUE (arglist));
3605 case BUILT_IN_EXTRACT_RETURN_ADDR:
3606 return expand_builtin_extract_return_addr (TREE_VALUE (arglist));
3607 case BUILT_IN_EH_RETURN:
3608 expand_builtin_eh_return (TREE_VALUE (arglist),
3609 TREE_VALUE (TREE_CHAIN (arglist)),
3610 TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))));
3611 return const0_rtx;
3612 case BUILT_IN_VARARGS_START:
3613 return expand_builtin_va_start (0, arglist);
3614 case BUILT_IN_STDARG_START:
3615 return expand_builtin_va_start (1, arglist);
3616 case BUILT_IN_VA_END:
3617 return expand_builtin_va_end (arglist);
3618 case BUILT_IN_VA_COPY:
3619 return expand_builtin_va_copy (arglist);
3620 case BUILT_IN_EXPECT:
3621 return expand_builtin_expect (arglist, target);
3623 default: /* just do library call, if unknown builtin */
3624 error ("built-in function `%s' not currently supported",
3625 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
3628 /* The switch statement above can drop through to cause the function
3629 to be called normally. */
3630 return expand_call (exp, target, ignore);
3633 /* Fold a call to __builtin_constant_p, if we know it will evaluate to a
3634 constant. ARGLIST is the argument list of the call. */
3636 static tree
3637 fold_builtin_constant_p (arglist)
3638 tree arglist;
3640 if (arglist == 0)
3641 return 0;
3643 arglist = TREE_VALUE (arglist);
3645 /* We return 1 for a numeric type that's known to be a constant
3646 value at compile-time or for an aggregate type that's a
3647 literal constant. */
3648 STRIP_NOPS (arglist);
3650 /* If we know this is a constant, emit the constant of one. */
3651 if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c'
3652 || (TREE_CODE (arglist) == CONSTRUCTOR
3653 && TREE_CONSTANT (arglist))
3654 || (TREE_CODE (arglist) == ADDR_EXPR
3655 && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST))
3656 return integer_one_node;
3658 /* If we aren't going to be running CSE or this expression
3659 has side effects, show we don't know it to be a constant.
3660 Likewise if it's a pointer or aggregate type since in those
3661 case we only want literals, since those are only optimized
3662 when generating RTL, not later. */
3663 if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected
3664 || AGGREGATE_TYPE_P (TREE_TYPE (arglist))
3665 || POINTER_TYPE_P (TREE_TYPE (arglist)))
3666 return integer_zero_node;
3668 return 0;
3671 /* Used by constant folding to eliminate some builtin calls early. EXP is
3672 the CALL_EXPR of a call to a builtin function. */
3674 tree
3675 fold_builtin (exp)
3676 tree exp;
3678 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3679 tree arglist = TREE_OPERAND (exp, 1);
3680 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
3682 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
3683 return 0;
3685 switch (fcode)
3687 case BUILT_IN_CONSTANT_P:
3688 return fold_builtin_constant_p (arglist);
3690 case BUILT_IN_STRLEN:
3691 if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
3693 tree len = c_strlen (TREE_VALUE (arglist));
3694 if (len != 0)
3695 return len;
3697 break;
3699 default:
3700 break;
3703 return 0;
3706 static tree
3707 build_function_call_expr (fn, arglist)
3708 tree fn, arglist;
3710 tree call_expr;
3712 call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
3713 call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
3714 call_expr, arglist);
3715 TREE_SIDE_EFFECTS (call_expr) = 1;
3716 return fold (call_expr);
3719 /* This function validates the types of a function call argument list
3720 represented as a tree chain of parameters against a specified list
3721 of tree_codes. If the last specifier is a 0, that represents an
3722 ellipses, otherwise the last specifier must be a VOID_TYPE. */
3723 static int
3724 validate_arglist VPARAMS ((tree arglist, ...))
3726 #ifndef ANSI_PROTOTYPES
3727 tree arglist;
3728 #endif
3729 enum tree_code code;
3730 va_list ap;
3732 VA_START (ap, arglist);
3734 #ifndef ANSI_PROTOTYPES
3735 arglist = va_arg (ap, tree);
3736 #endif
3738 do {
3739 code = va_arg (ap, enum tree_code);
3740 switch (code)
3742 case 0:
3743 /* This signifies an ellipses, any further arguments are all ok. */
3744 va_end (ap);
3745 return 1;
3746 case VOID_TYPE:
3747 /* This signifies an endlink, if no arguments remain, return
3748 true, otherwise return false. */
3749 va_end (ap);
3750 return arglist == 0;
3751 default:
3752 /* If no parameters remain or the parameter's code does not
3753 match the specified code, return false. Otherwise continue
3754 checking any remaining arguments. */
3755 if (arglist == 0 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
3757 va_end (ap);
3758 return 0;
3760 break;
3762 arglist = TREE_CHAIN (arglist);
3763 } while (1);