This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
| Other format: | [Raw text] | |
2006-06-30 Sandra Loosemore <sandra@codesourcery.com> * gcc/tree.c (init_call_expr_arg_iterator): Define. (first_call_expr_arg): Define. (next_call_expr_arg): Define. (more_call_expr_args_p): Define. (call_expr_nargs): Define. (call_expr_arg): Define. * gcc/tree.h (CALL_EXPR_FN, CALL_EXPR_STATIC_CHAIN, CALL_EXPR_ARGS): Define. (CALL_EXPR_ARG0, CALL_EXPR_ARG1, CALL_EXPR_ARG2): Define. (call_expr_arg_iterator): Declare. (init_call_expr_arg_iterator): Declare. (first_call_expr_arg): Declare. (next_call_expr_arg): Declare. (more_call_expr_args_p): Declare. (call_expr_nargs): Declare. (call_expr_arg): Declare. (fold_call_expr): Declare new function replacing fold_builtin. (fold_builtin_next_arg): Add bool argument. (fold_build_call_expr): Declare. (build_call_expr): Declare. * gcc/builtins.c (expand_builtin_setjmp): Change interfaces to all the expand_builtin_foo functions pass the whole CALL_EXPR instead of just its arglist, while the fold_builtin_foo functions get the individual arguments instead. Use the new argument accessors. Update all callers. (expand_builtin_nonlocal_goto): Likewise. (expand_builtin_prefetch): Likewise. (expand_builtin_classify_type): Likewise. (expand_errno_check): Likewise. (expand_builtin_mathfn): Likewise. (expand_builtin_mathfn_2): Likewise. (expand_builtin_mathfn_3): Likewise. (expand_builtin_sincos): Likewise. (expand_builtin_int_roundingfn): Likewise. (expand_builtin_pow): Likewise. (expand_builtin_powi): Likewise. (expand_builtin_strstr): Likewise. (expand_builtin_strchr): Likewise. (expand_builtin_strrchr): Likewise. (expand_builtin_strpbrk): Likewise. (expand_builtin_memcpy): Likewise. (expand_builtin_mempcpy): Likewise. (expand_builtin_memmove): Likewise, plus split off new helper function expand_builtin_memmove_args. (expand_builtin_bcopy): Likewise. (expand_builtin_strcpy): Likewise, plus split off new helper function expand_builtin_strcpy_args. (expand_builtin_stpcpy): Likewise. (expand_builtin_strncpy): Likewise. (expand_builtin_memset): Likewise, plus split off new helper function expand_builtin_memset_args. (expand_builtin_bzero): Likewise. (expand_builtin_memcmp): Likewise. (expand_builtin_strcmp): Likewise. (expand_builtin_strncmp): Likewise. (expand_builtin_strcat): Likewise. (expand_builtin_strncat): Likewise. (expand_builtin_strspn): Likewise. (expand_builtin_strcspn): Likewise. (expand_builtin_args_info): Likewise. (expand_builtin_va_start): Likewise. (expand_builtin_va_end): Likewise. (expand_builtin_va_copy): Likewise. (expand_builtin_frame_address): Likewise. (expand_builtin_alloca): Likewise. (expand_builtin_unop): Likewise. (expand_builtin_fputs): Likewise. (expand_builtin_expect): Likewise. (expand_builtin_expect_jump): Likewise. (expand_builtin_fabs): Likewise. (expand_builtin_copysign): Likewise. (expand_builtin_printf): Likewise. (expand_builtin_fprintf): Likewise. (expand_builtin_sprintf): Likewise. (expand_builtin_init_trampoline): Likewise. (expand_builtin_adjust_trampoline): Likewise. (expand_builtin_signbit): Likewise. (expand_builtin_fork_or_exec): Likewise. (expand_builtin_sync_operation): Likewise. (expand_builtin_compare_and_swap): Likewise. (expand_builtin_lock_test_and_set): Likewise. (expand_builtin_lock_release): Likewise. (expand_builtin): Likewise. (builtin_mathfn_code): Likewise. (fold_builtin_constant_p): Likewise. (fold_builtin_expect): Likewise. (fold_builtin_classify_type): Likewise. (fold_builtin_strlen): Likewise. (fold_builtin_nan): Likewise. (fold_trunc_transparent_mathfn): Likewise. (fold_fixed_mathfn): Likewise. (fold_builtin_cabs): Likewise. (fold_builtin_sqrt): Likewise. (fold_builtin_cbrt): Likewise. (fold_builtin_sin): Likewise. (fold_builtin_cos): Likewise. (fold_builtin_tan): Likewise. (fold_builtin_atan): Likewise. (fold_builtin_trunc): Likewise. (fold_builtin_floor): Likewise. (fold_builtin_ceil): Likewise. (fold_builtin_round): Likewise. (fold_builtin_int_roundingfn): Likewise. (fold_builtin_bitop): Likewise. (fold_builtin_logarithm): Likewise. (fold_builtin_pow): Likewise. (fold_builtin_powi): Likewise. (fold_builtin_exponent): Likewise. (fold_builtin_memcpy): Likewise. (fold_builtin_mempcpy): Likewise. (fold_builtin_memmove): Likewise. (fold_builtin_strcpy): Likewise. (fold_builtin_strncpy): Likewise. (fold_builtin_memcmp): Likewise. (fold_builtin_strcmp): Likewise. (fold_builtin_strncmp): Likewise. (fold_builtin_signbit): Likewise. (fold_builtin_copysign): Likewise. (fold_builtin_isascii): Likewise. (fold_builtin_toascii): Likewise. (fold_builtin_isdigit): Likewise. (fold_builtin_fabs): Likewise. (fold_builtin_abs): Likewise. (fold_builtin_classify): Likewise. (fold_builtin_unordered_cmp): Likewise. (fold_builtin_1): Likewise. Split into new functions fold_builtin_n, fold_builtin_0, fold_builtin_1, fold_builtin_2, fold_builtin_3, fold_builtin_4, and fold_builtin_varargs, to dispatch based on the number of arguments. (fold_call_expr): New function replacing fold_builtin. (fold_build_call_expr): New function. (build_call_expr): New function. (rewrite_call_expr): New function. (validate_arg): New function. (validate_arglist): Rewrite to use new interfaces, as above. (fold_builtin_strstr): Likewise. (fold_builtin_strchr): Likewise. (fold_builtin_strrchr): Likewise. (fold_builtin_strpbrk): Likewise. (fold_builtin_strcat): Likewise. (fold_builtin_strncat): Likewise. (fold_builtin_strspn): Likewise. (fold_builtin_strcspn): Likewise. (fold_builtin_fputs): Likewise. (fold_builtin_next_arg): Likewise. Also fix destructive modification of argument list, which seems like a Bad Idea. (fold_builtin_sprintf): Likewise. (expand_builtin_object_size): Likewise. (expand_builtin_memory_chk): Likewise. (maybe_emit_chk_warning): Likewise. (maybe_emit_sprintf_chk_warning): Likewise. (fold_builtin_object_size): Likewise. (fold_builtin_memory_chk): Likewise. (fold_builtin_stxcpy_chk): Likewise. (fold_builtin_strncpy_chk): Likewise. (fold_builtin_strcat_chk): Likewise. (fold_builtin_strncat_chk): Likewise. (fold_builtin_sprintf_chk): Likewise. (fold_builtin_snprintf_chk): Likewise. (fold_builtin_printf): Likewise. (fold_builtin_fprintf): Likewise. * gcc/fold-const.c (fold_ternary): Remove call to fold_builtin.... (fold): ...and replace it with a call to fold_call_expr here. (fold_build3_stat): Use fold_build_call_expr to fold and construct CALL_EXPRs. * gcc/tree-ssa-ccp.c (ccp_fold): Use new arglist primitives and update calls to the various fold_builtin_foo functions to reflect their new interfaces. (ccp_fold_builtin): Likewise. * gcc/gimplify.c (gimplify_call_expr): Likewise. * gcc/except.c (expand_builtin_eh_return_data_regno): Change arguments to match other expand_builtin_foo functions. * gcc/tree-object-size.c (compute_object_sizes): Replace call to fold_builtin with fold_call_expr.
Index: gcc/tree.c
===================================================================
*** gcc/tree.c (revision 115087)
--- gcc/tree.c (working copy)
*************** stdarg_p (tree fntype)
*** 7603,7606 ****
--- 7603,7680 ----
!= void_type_node));
}
+ /* Initialize the abstract argument list iterator object ITER with the argument
+ list from CALL_EXPR node EXP. */
+
+ void
+ init_call_expr_arg_iterator (tree exp, call_expr_arg_iterator *iter)
+ {
+ iter->tail = CALL_EXPR_ARGS (exp);
+ }
+
+ /* Initialize the abstract argument list iterator object ITER, then advance
+ past and return the first argument. Useful in for expressions, e.g.
+ for (arg = first_call_expr_arg (exp, &iter); arg;
+ arg = next_call_expr_arg (&iter)) */
+
+ tree
+ first_call_expr_arg (tree exp, call_expr_arg_iterator *iter)
+ {
+ init_call_expr_arg_iterator (exp, iter);
+ return next_call_expr_arg (iter);
+ }
+
+ /* Return the next argument from abstract argument list iterator object ITER,
+ and advance its state. Returns NULL_TREE if there are no more arguments. */
+
+ tree
+ next_call_expr_arg (call_expr_arg_iterator *iter)
+ {
+ tree result;
+ if (iter->tail == NULL_TREE)
+ return NULL_TREE;
+ result = TREE_VALUE (iter->tail);
+ iter->tail = TREE_CHAIN (iter->tail);
+ return result;
+ }
+
+ /* Test whether there are more arguments in abstract argument list iterator
+ ITER, without changing its state. */
+
+ bool
+ more_call_expr_args_p (const call_expr_arg_iterator *iter)
+ {
+ return (iter->tail != NULL_TREE);
+ }
+
+ /* Count the number of arguments passed in CALL_EXPR node EXP. */
+ int
+ call_expr_nargs (tree exp)
+ {
+ call_expr_arg_iterator iter;
+ int i = 0;
+ tree arg;
+ for (arg = first_call_expr_arg (exp, &iter); arg;
+ arg = next_call_expr_arg (&iter))
+ i++;
+ return i;
+ }
+
+ /* Return the Nth (zero-based) argument from CALL_EXPR node EXP. Returns
+ NULL if there aren't that many arguments. */
+
+ tree
+ call_expr_arg (tree exp, int n)
+ {
+ call_expr_arg_iterator iter;
+ tree t = NULL;
+ int i;
+ for (i = 0, t = first_call_expr_arg (exp, &iter);
+ (i < n) && t;
+ i++, t = next_call_expr_arg (&iter))
+ ;
+ return t;
+ }
+
+
#include "gt-tree.h"
Index: gcc/tree.h
===================================================================
*** gcc/tree.h (revision 115087)
--- gcc/tree.h (working copy)
*************** struct tree_constructor GTY(())
*** 1533,1538 ****
--- 1533,1553 ----
#define ASSERT_EXPR_VAR(NODE) TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 0)
#define ASSERT_EXPR_COND(NODE) TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 1)
+ /* CALL_EXPR accessors. */
+ #define CALL_EXPR_FN(NODE) TREE_OPERAND_CHECK_CODE ((NODE), CALL_EXPR, 0)
+ #define CALL_EXPR_STATIC_CHAIN(NODE) TREE_OPERAND_CHECK_CODE ((NODE), CALL_EXPR, 2)
+ #define CALL_EXPR_ARGS(NODE) TREE_OPERAND_CHECK_CODE ((NODE), CALL_EXPR, 1)
+ #define CALL_EXPR_ARG0(NODE) TREE_VALUE (CALL_EXPR_ARGS (NODE))
+ #define CALL_EXPR_ARG1(NODE) TREE_VALUE (TREE_CHAIN (CALL_EXPR_ARGS (NODE)))
+ #define CALL_EXPR_ARG2(NODE) TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CALL_EXPR_ARGS (NODE))))
+
+
+ typedef struct call_expr_arg_iterator_d GTY (())
+ {
+ tree tail;
+ } call_expr_arg_iterator;
+
+
/* OpenMP directive and clause accessors. */
#define OMP_BODY(NODE) \
*************** extern tree lower_bound_in_type (tree, t
*** 4135,4140 ****
--- 4150,4162 ----
extern int operand_equal_for_phi_arg_p (tree, tree);
extern bool empty_body_p (tree);
extern bool stdarg_p (tree);
+ extern void init_call_expr_arg_iterator (tree, call_expr_arg_iterator *);
+ extern tree first_call_expr_arg (tree, call_expr_arg_iterator *);
+ extern tree next_call_expr_arg (call_expr_arg_iterator *);
+ extern bool more_call_expr_args_p (const call_expr_arg_iterator *);
+ extern int call_expr_nargs (tree);
+ extern tree call_expr_arg (tree, int);
+
/* In stmt.c */
*************** extern enum tree_code invert_tree_compar
*** 4241,4259 ****
extern bool tree_expr_nonzero_p (tree);
/* In builtins.c */
! extern tree fold_builtin (tree, tree, bool);
! extern tree fold_builtin_fputs (tree, bool, bool, tree);
! extern tree fold_builtin_strcpy (tree, tree, tree);
! extern tree fold_builtin_strncpy (tree, tree, tree);
! extern tree fold_builtin_memory_chk (tree, tree, tree, bool,
enum built_in_function);
! extern tree fold_builtin_stxcpy_chk (tree, tree, tree, bool,
enum built_in_function);
! extern tree fold_builtin_strncpy_chk (tree, tree);
extern tree fold_builtin_snprintf_chk (tree, tree, enum built_in_function);
! extern bool fold_builtin_next_arg (tree);
extern enum built_in_function builtin_mathfn_code (tree);
extern tree build_function_call_expr (tree, tree);
extern tree mathfn_built_in (tree, enum built_in_function fn);
extern tree strip_float_extensions (tree);
extern tree c_strlen (tree, int);
--- 4263,4283 ----
extern bool tree_expr_nonzero_p (tree);
/* In builtins.c */
! extern tree fold_call_expr (tree, bool);
! extern tree fold_builtin_fputs (tree, tree, bool, bool, tree);
! extern tree fold_builtin_strcpy (tree, tree, tree, tree);
! extern tree fold_builtin_strncpy (tree, tree, tree, tree, tree);
! extern tree fold_builtin_memory_chk (tree, tree, tree, tree, tree, tree, bool,
enum built_in_function);
! extern tree fold_builtin_stxcpy_chk (tree, tree, tree, tree, tree, bool,
enum built_in_function);
! extern tree fold_builtin_strncpy_chk (tree, tree, tree, tree, tree);
extern tree fold_builtin_snprintf_chk (tree, tree, enum built_in_function);
! extern bool fold_builtin_next_arg (tree, bool);
extern enum built_in_function builtin_mathfn_code (tree);
extern tree build_function_call_expr (tree, tree);
+ extern tree fold_build_call_expr (tree, tree, tree, tree);
+ extern tree build_call_expr (tree, int, ...);
extern tree mathfn_built_in (tree, enum built_in_function fn);
extern tree strip_float_extensions (tree);
extern tree c_strlen (tree, int);
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c (revision 115087)
--- gcc/builtins.c (working copy)
*************** static rtx expand_builtin_next_arg (void
*** 101,107 ****
static rtx expand_builtin_va_start (tree);
static rtx expand_builtin_va_end (tree);
static rtx expand_builtin_va_copy (tree);
! static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
--- 101,107 ----
static rtx expand_builtin_va_start (tree);
static rtx expand_builtin_va_end (tree);
static rtx expand_builtin_va_copy (tree);
! static rtx expand_builtin_memcmp (tree, rtx, enum machine_mode);
static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
*************** static rtx expand_builtin_strncat (tree,
*** 110,131 ****
static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
! static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
! static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
static rtx expand_builtin_bcopy (tree);
static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
! static rtx expand_builtin_memset (tree, rtx, enum machine_mode, tree);
static rtx expand_builtin_bzero (tree);
static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strstr (tree, tree, rtx, enum machine_mode);
! static rtx expand_builtin_strpbrk (tree, tree, rtx, enum machine_mode);
! static rtx expand_builtin_strchr (tree, tree, rtx, enum machine_mode);
! static rtx expand_builtin_strrchr (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_alloca (tree, rtx);
static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
static rtx expand_builtin_frame_address (tree, tree);
--- 110,135 ----
static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
! static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode);
! static rtx expand_builtin_mempcpy_args (tree, tree, tree, tree, rtx, enum machine_mode, int);
! static rtx expand_builtin_memmove (tree, rtx, enum machine_mode);
! static rtx expand_builtin_memmove_args (tree, tree, tree, tree, rtx, enum machine_mode, tree);
static rtx expand_builtin_bcopy (tree);
static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
+ static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
static rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, enum machine_mode);
! static rtx expand_builtin_memset (tree, rtx, enum machine_mode);
! static rtx expand_builtin_memset_args (tree, tree, tree, rtx, enum machine_mode, tree);
static rtx expand_builtin_bzero (tree);
static rtx expand_builtin_strlen (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strstr (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strpbrk (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strchr (tree, rtx, enum machine_mode);
! static rtx expand_builtin_strrchr (tree, rtx, enum machine_mode);
static rtx expand_builtin_alloca (tree, rtx);
static rtx expand_builtin_unop (enum machine_mode, tree, rtx, rtx, optab);
static rtx expand_builtin_frame_address (tree, tree);
*************** static rtx expand_builtin_sprintf (tree,
*** 136,145 ****
--- 140,152 ----
static tree stabilize_va_list (tree, int);
static rtx expand_builtin_expect (tree, rtx);
static tree fold_builtin_constant_p (tree);
+ static tree fold_builtin_expect (tree);
static tree fold_builtin_classify_type (tree);
static tree fold_builtin_strlen (tree);
static tree fold_builtin_inf (tree, int);
static tree fold_builtin_nan (tree, tree, int);
+ static tree rewrite_call_expr (tree, int, tree, int, ...);
+ static int validate_arg (tree, enum tree_code code);
static int validate_arglist (tree, ...);
static bool integer_valued_real_p (tree);
static tree fold_trunc_transparent_mathfn (tree, tree);
*************** static rtx expand_builtin_signbit (tree,
*** 149,156 ****
static tree fold_builtin_cabs (tree, tree);
static tree fold_builtin_sqrt (tree, tree);
static tree fold_builtin_cbrt (tree, tree);
! static tree fold_builtin_pow (tree, tree, tree);
! static tree fold_builtin_powi (tree, tree, tree);
static tree fold_builtin_sin (tree);
static tree fold_builtin_cos (tree, tree, tree);
static tree fold_builtin_tan (tree);
--- 156,163 ----
static tree fold_builtin_cabs (tree, tree);
static tree fold_builtin_sqrt (tree, tree);
static tree fold_builtin_cbrt (tree, tree);
! static tree fold_builtin_pow (tree, tree, tree, tree);
! static tree fold_builtin_powi (tree, tree, tree, tree);
static tree fold_builtin_sin (tree);
static tree fold_builtin_cos (tree, tree, tree);
static tree fold_builtin_tan (tree);
*************** static tree fold_builtin_ceil (tree, tre
*** 161,204 ****
static tree fold_builtin_round (tree, tree);
static tree fold_builtin_int_roundingfn (tree, tree);
static tree fold_builtin_bitop (tree, tree);
! static tree fold_builtin_memcpy (tree, tree);
! static tree fold_builtin_mempcpy (tree, tree, int);
! static tree fold_builtin_memmove (tree, tree);
! static tree fold_builtin_strchr (tree, tree);
! static tree fold_builtin_memcmp (tree);
! static tree fold_builtin_strcmp (tree);
! static tree fold_builtin_strncmp (tree);
static tree fold_builtin_signbit (tree, tree);
! static tree fold_builtin_copysign (tree, tree, tree);
static tree fold_builtin_isascii (tree);
static tree fold_builtin_toascii (tree);
static tree fold_builtin_isdigit (tree);
static tree fold_builtin_fabs (tree, tree);
static tree fold_builtin_abs (tree, tree);
! static tree fold_builtin_unordered_cmp (tree, tree, enum tree_code,
enum tree_code);
static tree fold_builtin_1 (tree, tree, bool);
!
! static tree fold_builtin_strpbrk (tree, tree);
! static tree fold_builtin_strstr (tree, tree);
! static tree fold_builtin_strrchr (tree, tree);
! static tree fold_builtin_strcat (tree);
! static tree fold_builtin_strncat (tree);
! static tree fold_builtin_strspn (tree);
! static tree fold_builtin_strcspn (tree);
! static tree fold_builtin_sprintf (tree, int);
static rtx expand_builtin_object_size (tree);
static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
enum built_in_function);
static void maybe_emit_chk_warning (tree, enum built_in_function);
static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
! static tree fold_builtin_object_size (tree);
! static tree fold_builtin_strcat_chk (tree, tree);
! static tree fold_builtin_strncat_chk (tree, tree);
static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
! static tree fold_builtin_printf (tree, tree, bool, enum built_in_function);
! static tree fold_builtin_fprintf (tree, tree, bool, enum built_in_function);
static bool init_target_chars (void);
static unsigned HOST_WIDE_INT target_newline;
--- 168,219 ----
static tree fold_builtin_round (tree, tree);
static tree fold_builtin_int_roundingfn (tree, tree);
static tree fold_builtin_bitop (tree, tree);
! static tree fold_builtin_memcpy (tree, tree, tree, tree);
! static tree fold_builtin_mempcpy (tree, tree, tree, tree, int);
! static tree fold_builtin_memmove (tree, tree, tree, tree);
! static tree fold_builtin_strchr (tree, tree, tree);
! static tree fold_builtin_memcmp (tree, tree, tree);
! static tree fold_builtin_strcmp (tree, tree);
! static tree fold_builtin_strncmp (tree, tree, tree);
static tree fold_builtin_signbit (tree, tree);
! static tree fold_builtin_copysign (tree, tree, tree, tree);
static tree fold_builtin_isascii (tree);
static tree fold_builtin_toascii (tree);
static tree fold_builtin_isdigit (tree);
static tree fold_builtin_fabs (tree, tree);
static tree fold_builtin_abs (tree, tree);
! static tree fold_builtin_unordered_cmp (tree, tree, tree, enum tree_code,
enum tree_code);
+ static tree fold_builtin_n (tree, tree *, int, bool);
+ static tree fold_builtin_0 (tree, bool);
static tree fold_builtin_1 (tree, tree, bool);
! static tree fold_builtin_2 (tree, tree, tree, bool);
! static tree fold_builtin_3 (tree, tree, tree, tree, bool);
! static tree fold_builtin_4 (tree, tree, tree, tree, tree, bool);
! static tree fold_builtin_varargs (tree, tree, bool);
!
! static tree fold_builtin_strpbrk (tree, tree, tree);
! static tree fold_builtin_strstr (tree, tree, tree);
! static tree fold_builtin_strrchr (tree, tree, tree);
! static tree fold_builtin_strcat (tree, tree);
! static tree fold_builtin_strncat (tree, tree, tree);
! static tree fold_builtin_strspn (tree, tree);
! static tree fold_builtin_strcspn (tree, tree);
! static tree fold_builtin_sprintf (tree, tree, tree, int);
static rtx expand_builtin_object_size (tree);
static rtx expand_builtin_memory_chk (tree, rtx, enum machine_mode,
enum built_in_function);
static void maybe_emit_chk_warning (tree, enum built_in_function);
static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function);
! static tree fold_builtin_object_size (tree, tree);
! static tree fold_builtin_strcat_chk (tree, tree, tree, tree);
! static tree fold_builtin_strncat_chk (tree, tree, tree, tree, tree);
static tree fold_builtin_sprintf_chk (tree, enum built_in_function);
! static tree fold_builtin_printf (tree, tree, tree, bool,
! enum built_in_function);
! static tree fold_builtin_fprintf (tree, tree, tree, tree, bool,
! enum built_in_function);
static bool init_target_chars (void);
static unsigned HOST_WIDE_INT target_newline;
*************** expand_builtin_setjmp_receiver (rtx rece
*** 703,720 ****
them. */
static rtx
! expand_builtin_setjmp (tree arglist, rtx target)
{
rtx buf_addr, next_lab, cont_lab;
! if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
if (target == 0 || !REG_P (target)
|| REGNO (target) < FIRST_PSEUDO_REGISTER)
target = gen_reg_rtx (TYPE_MODE (integer_type_node));
! buf_addr = expand_normal (TREE_VALUE (arglist));
next_lab = gen_label_rtx ();
cont_lab = gen_label_rtx ();
--- 718,735 ----
them. */
static rtx
! expand_builtin_setjmp (tree exp, rtx target)
{
rtx buf_addr, next_lab, cont_lab;
! if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
if (target == 0 || !REG_P (target)
|| REGNO (target) < FIRST_PSEUDO_REGISTER)
target = gen_reg_rtx (TYPE_MODE (integer_type_node));
! buf_addr = expand_normal (CALL_EXPR_ARG0 (exp));
next_lab = gen_label_rtx ();
cont_lab = gen_label_rtx ();
*************** expand_builtin_longjmp (rtx buf_addr, rt
*** 844,860 ****
and the address of the save area. */
static rtx
! expand_builtin_nonlocal_goto (tree arglist)
{
tree t_label, t_save_area;
rtx r_label, r_save_area, r_fp, r_sp, insn;
! if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
! t_label = TREE_VALUE (arglist);
! arglist = TREE_CHAIN (arglist);
! t_save_area = TREE_VALUE (arglist);
r_label = expand_normal (t_label);
r_label = convert_memory_address (Pmode, r_label);
--- 859,874 ----
and the address of the save area. */
static rtx
! expand_builtin_nonlocal_goto (tree exp)
{
tree t_label, t_save_area;
rtx r_label, r_save_area, r_fp, r_sp, insn;
! if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
! t_label = CALL_EXPR_ARG0 (exp);
! t_save_area = CALL_EXPR_ARG1 (exp);
r_label = expand_normal (t_label);
r_label = convert_memory_address (Pmode, r_label);
*************** expand_builtin_update_setjmp_buf (rtx bu
*** 954,984 ****
effects. */
static void
! expand_builtin_prefetch (tree arglist)
{
tree arg0, arg1, arg2;
rtx op0, op1, op2;
! if (!validate_arglist (arglist, POINTER_TYPE, 0))
return;
! arg0 = TREE_VALUE (arglist);
/* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
zero (read) and argument 2 (locality) defaults to 3 (high degree of
locality). */
! if (TREE_CHAIN (arglist))
! {
! arg1 = TREE_VALUE (TREE_CHAIN (arglist));
! if (TREE_CHAIN (TREE_CHAIN (arglist)))
! arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
! else
! arg2 = build_int_cst (NULL_TREE, 3);
! }
else
! {
! arg1 = integer_zero_node;
! arg2 = build_int_cst (NULL_TREE, 3);
! }
/* Argument 0 is an address. */
op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
--- 968,995 ----
effects. */
static void
! expand_builtin_prefetch (tree exp)
{
tree arg0, arg1, arg2;
+ int nargs;
rtx op0, op1, op2;
! if (!validate_arglist (exp, POINTER_TYPE, 0))
return;
! arg0 = CALL_EXPR_ARG0 (exp);
/* Arguments 1 and 2 are optional; argument 1 (read/write) defaults to
zero (read) and argument 2 (locality) defaults to 3 (high degree of
locality). */
! nargs = call_expr_nargs (exp);
! if (nargs > 1)
! arg1 = CALL_EXPR_ARG1 (exp);
! else
! arg1 = integer_zero_node;
! if (nargs > 2)
! arg2 = CALL_EXPR_ARG2 (exp);
else
! arg2 = build_int_cst (NULL_TREE, 3);
/* Argument 0 is an address. */
op0 = expand_expr (arg0, NULL_RTX, Pmode, EXPAND_NORMAL);
*************** type_to_class (tree type)
*** 1618,1631 ****
}
}
! /* Expand a call to __builtin_classify_type with arguments found in
! ARGLIST. */
static rtx
! expand_builtin_classify_type (tree arglist)
{
! if (arglist != 0)
! return GEN_INT (type_to_class (TREE_TYPE (TREE_VALUE (arglist))));
return GEN_INT (no_type_class);
}
--- 1629,1641 ----
}
}
! /* Expand a call EXP to __builtin_classify_type. */
static rtx
! expand_builtin_classify_type (tree exp)
{
! if (call_expr_nargs (exp))
! return GEN_INT (type_to_class (TREE_TYPE (CALL_EXPR_ARG0 (exp))));
return GEN_INT (no_type_class);
}
*************** expand_errno_check (tree exp, rtx target
*** 1756,1762 ****
#ifdef TARGET_EDOM
/* If this built-in doesn't throw an exception, set errno directly. */
! if (TREE_NOTHROW (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
{
#ifdef GEN_ERRNO_RTX
rtx errno_rtx = GEN_ERRNO_RTX;
--- 1766,1772 ----
#ifdef TARGET_EDOM
/* If this built-in doesn't throw an exception, set errno directly. */
! if (TREE_NOTHROW (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
{
#ifdef GEN_ERRNO_RTX
rtx errno_rtx = GEN_ERRNO_RTX;
*************** expand_errno_check (tree exp, rtx target
*** 1778,1784 ****
emit_label (lab);
}
-
/* Expand a call to one of the builtin math functions (sqrt, exp, or log).
Return 0 if a normal call should be emitted rather than expanding the
function in-line. EXP is the expression that is a call to the builtin
--- 1788,1793 ----
*************** expand_builtin_mathfn (tree exp, rtx tar
*** 1791,1805 ****
optab builtin_optab;
rtx op0, insns, before_call;
tree fndecl = get_callee_fndecl (exp);
- tree arglist = TREE_OPERAND (exp, 1);
enum machine_mode mode;
bool errno_set = false;
tree arg, narg;
! if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
return 0;
! arg = TREE_VALUE (arglist);
switch (DECL_FUNCTION_CODE (fndecl))
{
--- 1800,1813 ----
optab builtin_optab;
rtx op0, insns, before_call;
tree fndecl = get_callee_fndecl (exp);
enum machine_mode mode;
bool errno_set = false;
tree arg, narg;
! if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
return 0;
! arg = CALL_EXPR_ARG0 (exp);
switch (DECL_FUNCTION_CODE (fndecl))
{
*************** expand_builtin_mathfn (tree exp, rtx tar
*** 1873,1880 ****
if (narg != arg)
{
arg = narg;
! arglist = build_tree_list (NULL_TREE, arg);
! exp = build_function_call_expr (fndecl, arglist);
}
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
--- 1881,1887 ----
if (narg != arg)
{
arg = narg;
! exp = build_call_expr (fndecl, 1, arg);
}
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
*************** expand_builtin_mathfn_2 (tree exp, rtx t
*** 1963,1970 ****
rtx op0, op1, insns;
int op1_type = REAL_TYPE;
tree fndecl = get_callee_fndecl (exp);
! tree arglist = TREE_OPERAND (exp, 1);
! tree arg0, arg1, temp, narg;
enum machine_mode mode;
bool errno_set = true;
bool stable = true;
--- 1970,1976 ----
rtx op0, op1, insns;
int op1_type = REAL_TYPE;
tree fndecl = get_callee_fndecl (exp);
! tree arg0, arg1, narg;
enum machine_mode mode;
bool errno_set = true;
bool stable = true;
*************** expand_builtin_mathfn_2 (tree exp, rtx t
*** 1974,1984 ****
|| (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
op1_type = INTEGER_TYPE;
! if (!validate_arglist (arglist, REAL_TYPE, op1_type, VOID_TYPE))
return 0;
! arg0 = TREE_VALUE (arglist);
! arg1 = TREE_VALUE (TREE_CHAIN (arglist));
switch (DECL_FUNCTION_CODE (fndecl))
{
--- 1980,1990 ----
|| (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LDEXPL))
op1_type = INTEGER_TYPE;
! if (!validate_arglist (exp, REAL_TYPE, op1_type, VOID_TYPE))
return 0;
! arg0 = CALL_EXPR_ARG0 (exp);
! arg1 = CALL_EXPR_ARG1 (exp);
switch (DECL_FUNCTION_CODE (fndecl))
{
*************** expand_builtin_mathfn_2 (tree exp, rtx t
*** 2013,2036 ****
if (narg != arg1)
{
arg1 = narg;
- temp = build_tree_list (NULL_TREE, narg);
stable = false;
}
- else
- temp = TREE_CHAIN (arglist);
-
narg = builtin_save_expr (arg0);
if (narg != arg0)
{
arg0 = narg;
- arglist = tree_cons (NULL_TREE, narg, temp);
stable = false;
}
- else if (! stable)
- arglist = tree_cons (NULL_TREE, arg0, temp);
if (! stable)
! exp = build_function_call_expr (fndecl, arglist);
op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
op1 = expand_normal (arg1);
--- 2019,2035 ----
if (narg != arg1)
{
arg1 = narg;
stable = false;
}
narg = builtin_save_expr (arg0);
if (narg != arg0)
{
arg0 = narg;
stable = false;
}
if (! stable)
! exp = build_call_expr (fndecl, 2, arg0, arg1);
op0 = expand_expr (arg0, subtarget, VOIDmode, EXPAND_NORMAL);
op1 = expand_normal (arg1);
*************** expand_builtin_mathfn_3 (tree exp, rtx t
*** 2075,2088 ****
optab builtin_optab;
rtx op0, insns;
tree fndecl = get_callee_fndecl (exp);
- tree arglist = TREE_OPERAND (exp, 1);
enum machine_mode mode;
tree arg, narg;
! if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
return 0;
! arg = TREE_VALUE (arglist);
switch (DECL_FUNCTION_CODE (fndecl))
{
--- 2074,2086 ----
optab builtin_optab;
rtx op0, insns;
tree fndecl = get_callee_fndecl (exp);
enum machine_mode mode;
tree arg, narg;
! if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
return 0;
! arg = CALL_EXPR_ARG0 (exp);
switch (DECL_FUNCTION_CODE (fndecl))
{
*************** expand_builtin_mathfn_3 (tree exp, rtx t
*** 2122,2129 ****
if (narg != arg)
{
arg = narg;
! arglist = build_tree_list (NULL_TREE, arg);
! exp = build_function_call_expr (fndecl, arglist);
}
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
--- 2120,2126 ----
if (narg != arg)
{
arg = narg;
! exp = build_call_expr (fndecl, 1, arg);
}
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
*************** static rtx
*** 2183,2200 ****
expand_builtin_sincos (tree exp)
{
rtx op0, op1, op2, target1, target2;
- tree arglist = TREE_OPERAND (exp, 1);
enum machine_mode mode;
tree arg, sinp, cosp;
int result;
! if (!validate_arglist (arglist, REAL_TYPE,
POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
! arg = TREE_VALUE (arglist);
! sinp = TREE_VALUE (TREE_CHAIN (arglist));
! cosp = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
/* Make a suitable register to place result in. */
mode = TYPE_MODE (TREE_TYPE (arg));
--- 2180,2196 ----
expand_builtin_sincos (tree exp)
{
rtx op0, op1, op2, target1, target2;
enum machine_mode mode;
tree arg, sinp, cosp;
int result;
! if (!validate_arglist (exp, REAL_TYPE,
POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
! arg = CALL_EXPR_ARG0 (exp);
! sinp = CALL_EXPR_ARG1 (exp);
! cosp = CALL_EXPR_ARG2 (exp);
/* Make a suitable register to place result in. */
mode = TYPE_MODE (TREE_TYPE (arg));
*************** expand_builtin_int_roundingfn (tree exp,
*** 2235,2250 ****
optab builtin_optab;
rtx op0, insns, tmp;
tree fndecl = get_callee_fndecl (exp);
- tree arglist = TREE_OPERAND (exp, 1);
enum built_in_function fallback_fn;
tree fallback_fndecl;
enum machine_mode mode;
tree arg, narg;
! if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
gcc_unreachable ();
! arg = TREE_VALUE (arglist);
switch (DECL_FUNCTION_CODE (fndecl))
{
--- 2231,2245 ----
optab builtin_optab;
rtx op0, insns, tmp;
tree fndecl = get_callee_fndecl (exp);
enum built_in_function fallback_fn;
tree fallback_fndecl;
enum machine_mode mode;
tree arg, narg;
! if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
gcc_unreachable ();
! arg = CALL_EXPR_ARG0 (exp);
switch (DECL_FUNCTION_CODE (fndecl))
{
*************** expand_builtin_int_roundingfn (tree exp,
*** 2279,2286 ****
if (narg != arg)
{
arg = narg;
! arglist = build_tree_list (NULL_TREE, arg);
! exp = build_function_call_expr (fndecl, arglist);
}
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
--- 2274,2280 ----
if (narg != arg)
{
arg = narg;
! exp = build_call_expr (fndecl, 1, arg);
}
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
*************** expand_builtin_int_roundingfn (tree exp,
*** 2310,2316 ****
/* We shouldn't get here on targets without TARGET_C99_FUNCTIONS.
??? Perhaps convert (int)floorf(x) into (int)floor((double)x). */
gcc_assert (fallback_fndecl != NULL_TREE);
! exp = build_function_call_expr (fallback_fndecl, arglist);
tmp = expand_normal (exp);
--- 2304,2310 ----
/* We shouldn't get here on targets without TARGET_C99_FUNCTIONS.
??? Perhaps convert (int)floorf(x) into (int)floor((double)x). */
gcc_assert (fallback_fndecl != NULL_TREE);
! exp = build_call_expr (fallback_fndecl, 1, arg);
tmp = expand_normal (exp);
*************** expand_powi (rtx x, enum machine_mode mo
*** 2535,2548 ****
static rtx
expand_builtin_pow (tree exp, rtx target, rtx subtarget)
{
- tree arglist = TREE_OPERAND (exp, 1);
tree arg0, arg1;
! if (! validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
return 0;
! arg0 = TREE_VALUE (arglist);
! arg1 = TREE_VALUE (TREE_CHAIN (arglist));
if (TREE_CODE (arg1) == REAL_CST
&& ! TREE_CONSTANT_OVERFLOW (arg1))
--- 2529,2541 ----
static rtx
expand_builtin_pow (tree exp, rtx target, rtx subtarget)
{
tree arg0, arg1;
! if (! validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
return 0;
! arg0 = CALL_EXPR_ARG0 (exp);
! arg1 = CALL_EXPR_ARG1 (exp);
if (TREE_CODE (arg1) == REAL_CST
&& ! TREE_CONSTANT_OVERFLOW (arg1))
*************** expand_builtin_pow (tree exp, rtx target
*** 2585,2601 ****
static rtx
expand_builtin_powi (tree exp, rtx target, rtx subtarget)
{
- tree arglist = TREE_OPERAND (exp, 1);
tree arg0, arg1;
rtx op0, op1;
enum machine_mode mode;
enum machine_mode mode2;
! if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
! arg0 = TREE_VALUE (arglist);
! arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mode = TYPE_MODE (TREE_TYPE (exp));
/* Handle constant power. */
--- 2578,2593 ----
static rtx
expand_builtin_powi (tree exp, rtx target, rtx subtarget)
{
tree arg0, arg1;
rtx op0, op1;
enum machine_mode mode;
enum machine_mode mode2;
! if (! validate_arglist (exp, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
! arg0 = CALL_EXPR_ARG0 (exp);
! arg1 = CALL_EXPR_ARG1 (exp);
mode = TYPE_MODE (TREE_TYPE (exp));
/* Handle constant power. */
*************** expand_builtin_powi (tree exp, rtx targe
*** 2646,2660 ****
try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strlen (tree arglist, rtx target,
enum machine_mode target_mode)
{
! if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
rtx pat;
! tree len, src = TREE_VALUE (arglist);
rtx result, src_reg, char_rtx, before_strlen;
enum machine_mode insn_mode = target_mode, char_mode;
enum insn_code icode = CODE_FOR_nothing;
--- 2638,2652 ----
try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strlen (tree exp, rtx target,
enum machine_mode target_mode)
{
! if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
rtx pat;
! tree len, src = CALL_EXPR_ARG0 (exp);
rtx result, src_reg, char_rtx, before_strlen;
enum machine_mode insn_mode = target_mode, char_mode;
enum insn_code icode = CODE_FOR_nothing;
*************** expand_builtin_strlen (tree arglist, rtx
*** 2754,2764 ****
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
! expand_builtin_strstr (tree arglist, tree type, rtx target, enum machine_mode mode)
{
! if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strstr (arglist, type);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
--- 2746,2758 ----
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
! expand_builtin_strstr (tree exp, rtx target, enum machine_mode mode)
{
! if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree type = TREE_TYPE (exp);
! tree result = fold_builtin_strstr (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp), type);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
*************** expand_builtin_strstr (tree arglist, tre
*** 2770,2780 ****
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
! expand_builtin_strchr (tree arglist, tree type, rtx target, enum machine_mode mode)
{
! if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strchr (arglist, type);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
--- 2764,2776 ----
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
! expand_builtin_strchr (tree exp, rtx target, enum machine_mode mode)
{
! if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
! tree type = TREE_TYPE (exp);
! tree result = fold_builtin_strchr (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp), type);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
*************** expand_builtin_strchr (tree arglist, tre
*** 2788,2798 ****
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
! expand_builtin_strrchr (tree arglist, tree type, rtx target, enum machine_mode mode)
{
! if (validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strrchr (arglist, type);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
--- 2784,2796 ----
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
! expand_builtin_strrchr (tree exp, rtx target, enum machine_mode mode)
{
! if (validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
! tree type = TREE_TYPE (exp);
! tree result = fold_builtin_strrchr (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp), type);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
*************** expand_builtin_strrchr (tree arglist, tr
*** 2804,2814 ****
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
! expand_builtin_strpbrk (tree arglist, tree type, rtx target, enum machine_mode mode)
{
! if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strpbrk (arglist, type);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
--- 2802,2814 ----
in TARGET, if convenient (and in mode MODE if that's convenient). */
static rtx
! expand_builtin_strpbrk (tree exp, rtx target, enum machine_mode mode)
{
! if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree type = TREE_TYPE (exp);
! tree result = fold_builtin_strpbrk (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp), type);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
*************** builtin_memcpy_read_str (void *data, HOS
*** 2832,2838 ****
return c_readstr (str + offset, mode);
}
! /* Expand a call to the memcpy builtin, with arguments in ARGLIST.
Return 0 if we failed, the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in
mode MODE if that's convenient). */
--- 2832,2838 ----
return c_readstr (str + offset, mode);
}
! /* Expand a call EXP to the memcpy builtin.
Return 0 if we failed, the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in
mode MODE if that's convenient). */
*************** static rtx
*** 2840,2860 ****
expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
{
tree fndecl = get_callee_fndecl (exp);
! tree arglist = TREE_OPERAND (exp, 1);
! if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree dest = TREE_VALUE (arglist);
! tree src = TREE_VALUE (TREE_CHAIN (arglist));
! tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
const char *src_str;
unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, dest_addr, len_rtx;
! tree result = fold_builtin_memcpy (fndecl, arglist);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
--- 2840,2860 ----
expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
{
tree fndecl = get_callee_fndecl (exp);
! if (!validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree dest = CALL_EXPR_ARG0 (exp);
! tree src = CALL_EXPR_ARG1 (exp);
! tree len = CALL_EXPR_ARG2 (exp);
const char *src_str;
unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, dest_addr, len_rtx;
! tree result = fold_builtin_memcpy (dest, src, len,
! TREE_TYPE (TREE_TYPE (fndecl)));
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
*************** expand_builtin_memcpy (tree exp, rtx tar
*** 2907,2913 ****
}
}
! /* Expand a call to the mempcpy builtin, with arguments in ARGLIST.
Return 0 if we failed; the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in
mode MODE if that's convenient). If ENDP is 0 return the
--- 2907,2913 ----
}
}
! /* Expand a call EXP to the mempcpy builtin.
Return 0 if we failed; the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in
mode MODE if that's convenient). If ENDP is 0 return the
*************** expand_builtin_memcpy (tree exp, rtx tar
*** 2916,2949 ****
stpcpy. */
static rtx
! expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode,
! int endp)
{
! if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
/* If return value is ignored, transform mempcpy into memcpy. */
! else if (target == const0_rtx)
{
tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
! return expand_expr (build_function_call_expr (fn, arglist),
target, mode, EXPAND_NORMAL);
}
else
{
- tree dest = TREE_VALUE (arglist);
- tree src = TREE_VALUE (TREE_CHAIN (arglist));
- tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
const char *src_str;
unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, len_rtx;
! tree result = fold_builtin_mempcpy (arglist, type, endp);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
--- 2916,2960 ----
stpcpy. */
static rtx
! expand_builtin_mempcpy (tree exp, rtx target, enum machine_mode mode)
{
! if (!validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
+ else
+ {
+ tree dest = CALL_EXPR_ARG0 (exp);
+ tree src = CALL_EXPR_ARG1 (exp);
+ tree len = CALL_EXPR_ARG2 (exp);
+ return expand_builtin_mempcpy_args (dest, src, len,
+ TREE_TYPE (exp),
+ target, mode, /*endp=*/ 1);
+ }
+ }
+
+ static rtx
+ expand_builtin_mempcpy_args (tree dest, tree src, tree len, tree type,
+ rtx target, enum machine_mode mode, int endp)
+ {
/* If return value is ignored, transform mempcpy into memcpy. */
! if (target == const0_rtx)
{
tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
! return expand_expr (build_call_expr (fn, 3, dest, src, len),
target, mode, EXPAND_NORMAL);
}
else
{
const char *src_str;
unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, len_rtx;
! tree result = fold_builtin_mempcpy (dest, src, len, type, endp);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
*************** expand_builtin_mempcpy (tree arglist, tr
*** 3002,3062 ****
if we failed; the caller should emit a normal call. */
static rtx
! expand_builtin_memmove (tree arglist, tree type, rtx target,
! enum machine_mode mode, tree orig_exp)
{
! if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree dest = TREE_VALUE (arglist);
! tree src = TREE_VALUE (TREE_CHAIN (arglist));
! tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
! unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
! unsigned int dest_align
! = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
! tree result = fold_builtin_memmove (arglist, type);
! if (result)
! return expand_expr (result, target, mode, EXPAND_NORMAL);
! /* If DEST is not a pointer type, call the normal function. */
! if (dest_align == 0)
! return 0;
! /* If either SRC is not a pointer type, don't do this
! operation in-line. */
! if (src_align == 0)
! return 0;
! /* If src is categorized for a readonly section we can use
! normal memcpy. */
! if (readonly_data_expr (src))
! {
! tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
! if (!fn)
! return 0;
! fn = build_function_call_expr (fn, arglist);
! if (TREE_CODE (fn) == CALL_EXPR)
! CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
! return expand_expr (fn, target, mode, EXPAND_NORMAL);
! }
! /* If length is 1 and we can expand memcpy call inline,
! it is ok to use memcpy as well. */
! if (integer_onep (len))
! {
! rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
! /*endp=*/0);
! if (ret)
! return ret;
! }
! /* Otherwise, call the normal function. */
! return 0;
! }
}
/* Expand expression EXP, which is a call to the bcopy builtin. Return 0
--- 3013,3082 ----
if we failed; the caller should emit a normal call. */
static rtx
! expand_builtin_memmove (tree exp, rtx target, enum machine_mode mode)
{
! if (!validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree dest = CALL_EXPR_ARG0 (exp);
! tree src = CALL_EXPR_ARG1 (exp);
! tree len = CALL_EXPR_ARG2 (exp);
! return expand_builtin_memmove_args (dest, src, len,
! TREE_TYPE (exp), target, mode, exp);
! }
! }
! static rtx
! expand_builtin_memmove_args (tree dest, tree src, tree len,
! tree type, rtx target,
! enum machine_mode mode, tree orig_exp)
! {
! unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
! unsigned int dest_align
! = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
! tree result = fold_builtin_memmove (dest, src, len, type);
! if (result)
! return expand_expr (result, target, mode, EXPAND_NORMAL);
! /* If DEST is not a pointer type, call the normal function. */
! if (dest_align == 0)
! return 0;
! /* If either SRC is not a pointer type, don't do this
! operation in-line. */
! if (src_align == 0)
! return 0;
! /* If src is categorized for a readonly section we can use
! normal memcpy. */
! if (readonly_data_expr (src))
! {
! tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
! if (!fn)
! return 0;
! fn = build_call_expr (fn, 3, dest, src, len);
! if (TREE_CODE (fn) == CALL_EXPR)
! CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
! return expand_expr (fn, target, mode, EXPAND_NORMAL);
! }
! /* If length is 1 and we can expand memcpy call inline,
! it is ok to use memcpy as well. */
! if (integer_onep (len))
! {
! rtx ret = expand_builtin_mempcpy_args (dest, src, len, type,
! target, mode,
! /*endp=*/0);
! if (ret)
! return ret;
! }
!
! /* Otherwise, call the normal function. */
! return 0;
}
/* Expand expression EXP, which is a call to the bcopy builtin. Return 0
*************** expand_builtin_memmove (tree arglist, tr
*** 3065,3092 ****
static rtx
expand_builtin_bcopy (tree exp)
{
- tree arglist = TREE_OPERAND (exp, 1);
tree type = TREE_TYPE (exp);
! tree src, dest, size, newarglist;
! if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return NULL_RTX;
! src = TREE_VALUE (arglist);
! dest = TREE_VALUE (TREE_CHAIN (arglist));
! size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
/* New argument list transforming bcopy(ptr x, ptr y, int z) to
memmove(ptr y, ptr x, size_t z). This is done this way
so that if it isn't expanded inline, we fallback to
calling bcopy instead of memmove. */
! newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
! newarglist = tree_cons (NULL_TREE, src, newarglist);
! newarglist = tree_cons (NULL_TREE, dest, newarglist);
!
! return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode, exp);
}
#ifndef HAVE_movstr
--- 3085,3109 ----
static rtx
expand_builtin_bcopy (tree exp)
{
tree type = TREE_TYPE (exp);
! tree src, dest, size;
! if (!validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return NULL_RTX;
! src = CALL_EXPR_ARG0 (exp);
! dest = CALL_EXPR_ARG1 (exp);
! size = CALL_EXPR_ARG2 (exp);
/* New argument list transforming bcopy(ptr x, ptr y, int z) to
memmove(ptr y, ptr x, size_t z). This is done this way
so that if it isn't expanded inline, we fallback to
calling bcopy instead of memmove. */
! return expand_builtin_memmove_args (dest, src,
! fold_convert (sizetype, size),
! type, const0_rtx, VOIDmode, exp);
}
#ifndef HAVE_movstr
*************** expand_movstr (tree dest, tree src, rtx
*** 3162,3183 ****
convenient). */
static rtx
! expand_builtin_strcpy (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
{
! if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strcpy (fndecl, arglist, 0);
! if (result)
! return expand_expr (result, target, mode, EXPAND_NORMAL);
!
! return expand_movstr (TREE_VALUE (arglist),
! TREE_VALUE (TREE_CHAIN (arglist)),
! target, /*endp=*/0);
}
return 0;
}
! /* Expand a call to the stpcpy builtin, with arguments in ARGLIST.
Return 0 if we failed the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in
mode MODE if that's convenient). */
--- 3179,3206 ----
convenient). */
static rtx
! expand_builtin_strcpy (tree fndecl, tree exp, rtx target, enum machine_mode mode)
{
! if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree dest = CALL_EXPR_ARG0 (exp);
! tree src = CALL_EXPR_ARG1 (exp);
! return expand_builtin_strcpy_args (fndecl, dest, src, target, mode);
}
return 0;
}
! static rtx
! expand_builtin_strcpy_args (tree fndecl, tree dest, tree src,
! rtx target, enum machine_mode mode)
! {
! tree result = fold_builtin_strcpy (fndecl, dest, src, 0);
! if (result)
! return expand_expr (result, target, mode, EXPAND_NORMAL);
! return expand_movstr (dest, src, target, /*endp=*/0);
! }
!
! /* Expand a call EXP to the stpcpy builtin.
Return 0 if we failed the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in
mode MODE if that's convenient). */
*************** expand_builtin_strcpy (tree fndecl, tree
*** 3185,3191 ****
static rtx
expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
{
! tree arglist = TREE_OPERAND (exp, 1);
/* If return value is ignored, transform stpcpy into strcpy. */
if (target == const0_rtx)
{
--- 3208,3220 ----
static rtx
expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
{
! tree dst, src;
! if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
! return 0;
!
! dst = CALL_EXPR_ARG0 (exp);
! src = CALL_EXPR_ARG1 (exp);
!
/* If return value is ignored, transform stpcpy into strcpy. */
if (target == const0_rtx)
{
*************** expand_builtin_stpcpy (tree exp, rtx tar
*** 3193,3227 ****
if (!fn)
return 0;
! return expand_expr (build_function_call_expr (fn, arglist),
target, mode, EXPAND_NORMAL);
}
-
- if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
- return 0;
else
{
! tree dst, src, len, lenp1;
! tree narglist;
rtx ret;
/* Ensure we get an actual string whose length can be evaluated at
compile-time, not an expression containing a string. This is
because the latter will potentially produce pessimized code
when used to produce the return value. */
- src = TREE_VALUE (TREE_CHAIN (arglist));
if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
! return expand_movstr (TREE_VALUE (arglist),
! TREE_VALUE (TREE_CHAIN (arglist)),
! target, /*endp=*/2);
- dst = TREE_VALUE (arglist);
lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
! narglist = build_tree_list (NULL_TREE, lenp1);
! narglist = tree_cons (NULL_TREE, src, narglist);
! narglist = tree_cons (NULL_TREE, dst, narglist);
! ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp),
! target, mode, /*endp=*/2);
if (ret)
return ret;
--- 3222,3245 ----
if (!fn)
return 0;
! return expand_expr (build_call_expr (fn, 2, dst, src),
target, mode, EXPAND_NORMAL);
}
else
{
! tree len, lenp1;
rtx ret;
/* Ensure we get an actual string whose length can be evaluated at
compile-time, not an expression containing a string. This is
because the latter will potentially produce pessimized code
when used to produce the return value. */
if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
! return expand_movstr (dst, src, target, /*endp=*/2);
lenp1 = size_binop (PLUS_EXPR, len, ssize_int (1));
! ret = expand_builtin_mempcpy_args (dst, src, lenp1, TREE_TYPE (exp),
! target, mode, /*endp=*/2);
if (ret)
return ret;
*************** expand_builtin_stpcpy (tree exp, rtx tar
*** 3232,3239 ****
if (GET_CODE (len_rtx) == CONST_INT)
{
! ret = expand_builtin_strcpy (get_callee_fndecl (exp),
! arglist, target, mode);
if (ret)
{
--- 3250,3257 ----
if (GET_CODE (len_rtx) == CONST_INT)
{
! ret = expand_builtin_strcpy_args (get_callee_fndecl (exp),
! dst, src, target, mode);
if (ret)
{
*************** expand_builtin_stpcpy (tree exp, rtx tar
*** 3256,3264 ****
}
}
! return expand_movstr (TREE_VALUE (arglist),
! TREE_VALUE (TREE_CHAIN (arglist)),
! target, /*endp=*/2);
}
}
--- 3274,3280 ----
}
}
! return expand_movstr (dst, src, target, /*endp=*/2);
}
}
*************** static rtx
*** 3285,3297 ****
expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
{
tree fndecl = get_callee_fndecl (exp);
! tree arglist = TREE_OPERAND (exp, 1);
! if (validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
! tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
! tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
! tree result = fold_builtin_strncpy (fndecl, arglist, slen);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
--- 3301,3314 ----
expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
{
tree fndecl = get_callee_fndecl (exp);
! if (validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
! tree dest = CALL_EXPR_ARG0 (exp);
! tree src = CALL_EXPR_ARG1 (exp);
! tree slen = c_strlen (src, 1);
! tree len = CALL_EXPR_ARG2 (exp);
! tree result = fold_builtin_strncpy (fndecl, dest, src, len, slen);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
*************** expand_builtin_strncpy (tree exp, rtx ta
*** 3307,3316 ****
use store_by_pieces, if it fails, punt. */
if (tree_int_cst_lt (slen, len))
{
- tree dest = TREE_VALUE (arglist);
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
! const char *p = c_getstr (TREE_VALUE (TREE_CHAIN (arglist)));
rtx dest_mem;
if (!p || dest_align == 0 || !host_integerp (len, 1)
--- 3324,3332 ----
use store_by_pieces, if it fails, punt. */
if (tree_int_cst_lt (slen, len))
{
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
! const char *p = c_getstr (src);
rtx dest_mem;
if (!p || dest_align == 0 || !host_integerp (len, 1)
*************** builtin_memset_gen_str (void *data, HOST
*** 3379,3501 ****
convenient). */
static rtx
! expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
! tree orig_exp)
{
! if (!validate_arglist (arglist,
POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree dest = TREE_VALUE (arglist);
! tree val = TREE_VALUE (TREE_CHAIN (arglist));
! tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
! tree fndecl, fn;
! enum built_in_function fcode;
! char c;
! unsigned int dest_align;
! rtx dest_mem, dest_addr, len_rtx;
!
! dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
!
! /* If DEST is not a pointer type, don't do this
! operation in-line. */
! if (dest_align == 0)
! return 0;
! /* If the LEN parameter is zero, return DEST. */
! if (integer_zerop (len))
! {
! /* Evaluate and ignore VAL in case it has side-effects. */
! expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
! return expand_expr (dest, target, mode, EXPAND_NORMAL);
! }
! /* Stabilize the arguments in case we fail. */
! dest = builtin_save_expr (dest);
! val = builtin_save_expr (val);
! len = builtin_save_expr (len);
! len_rtx = expand_normal (len);
! dest_mem = get_memory_rtx (dest, len);
! if (TREE_CODE (val) != INTEGER_CST)
{
! rtx val_rtx;
!
! val_rtx = expand_normal (val);
! val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
! val_rtx, 0);
!
! /* Assume that we can memset by pieces if we can store the
! * the coefficients by pieces (in the required modes).
! * We can't pass builtin_memset_gen_str as that emits RTL. */
! c = 1;
! if (host_integerp (len, 1)
! && !(optimize_size && tree_low_cst (len, 1) > 1)
! && can_store_by_pieces (tree_low_cst (len, 1),
! builtin_memset_read_str, &c, dest_align))
! {
! val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
! val_rtx);
! store_by_pieces (dest_mem, tree_low_cst (len, 1),
! builtin_memset_gen_str, val_rtx, dest_align, 0);
! }
! else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
! dest_align))
! goto do_libcall;
!
! dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
! dest_mem = convert_memory_address (ptr_mode, dest_mem);
! return dest_mem;
}
!
! if (target_char_cast (val, &c))
goto do_libcall;
! if (c)
! {
! if (host_integerp (len, 1)
! && !(optimize_size && tree_low_cst (len, 1) > 1)
! && can_store_by_pieces (tree_low_cst (len, 1),
! builtin_memset_read_str, &c, dest_align))
! store_by_pieces (dest_mem, tree_low_cst (len, 1),
! builtin_memset_read_str, &c, dest_align, 0);
! else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
! dest_align))
! goto do_libcall;
!
! dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
! dest_mem = convert_memory_address (ptr_mode, dest_mem);
! return dest_mem;
! }
!
! set_mem_align (dest_mem, dest_align);
! dest_addr = clear_storage (dest_mem, len_rtx,
! CALL_EXPR_TAILCALL (orig_exp)
! ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
! if (dest_addr == 0)
! {
! dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
! dest_addr = convert_memory_address (ptr_mode, dest_addr);
! }
! return dest_addr;
! do_libcall:
! fndecl = get_callee_fndecl (orig_exp);
! fcode = DECL_FUNCTION_CODE (fndecl);
! gcc_assert (fcode == BUILT_IN_MEMSET || fcode == BUILT_IN_BZERO);
! arglist = build_tree_list (NULL_TREE, len);
! if (fcode == BUILT_IN_MEMSET)
! arglist = tree_cons (NULL_TREE, val, arglist);
! arglist = tree_cons (NULL_TREE, dest, arglist);
! fn = build_function_call_expr (fndecl, arglist);
! if (TREE_CODE (fn) == CALL_EXPR)
! CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
! return expand_call (fn, target, target == const0_rtx);
! }
}
/* Expand expression EXP, which is a call to the bzero builtin. Return 0
--- 3395,3522 ----
convenient). */
static rtx
! expand_builtin_memset (tree exp, rtx target, enum machine_mode mode)
{
! if (!validate_arglist (exp,
POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree dest = CALL_EXPR_ARG0 (exp);
! tree val = CALL_EXPR_ARG1 (exp);
! tree len = CALL_EXPR_ARG2 (exp);
! return expand_builtin_memset_args (dest, val, len, target, mode, exp);
! }
! }
! static rtx
! expand_builtin_memset_args (tree dest, tree val, tree len,
! rtx target, enum machine_mode mode, tree orig_exp)
! {
! tree fndecl, fn;
! enum built_in_function fcode;
! char c;
! unsigned int dest_align;
! rtx dest_mem, dest_addr, len_rtx;
! dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
! /* If DEST is not a pointer type, don't do this operation in-line. */
! if (dest_align == 0)
! return 0;
! /* If the LEN parameter is zero, return DEST. */
! if (integer_zerop (len))
! {
! /* Evaluate and ignore VAL in case it has side-effects. */
! expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
! return expand_expr (dest, target, mode, EXPAND_NORMAL);
! }
!
! /* Stabilize the arguments in case we fail. */
! dest = builtin_save_expr (dest);
! val = builtin_save_expr (val);
! len = builtin_save_expr (len);
!
! len_rtx = expand_normal (len);
! dest_mem = get_memory_rtx (dest, len);
!
! if (TREE_CODE (val) != INTEGER_CST)
! {
! rtx val_rtx;
!
! val_rtx = expand_normal (val);
! val_rtx = convert_to_mode (TYPE_MODE (unsigned_char_type_node),
! val_rtx, 0);
!
! /* Assume that we can memset by pieces if we can store the
! * the coefficients by pieces (in the required modes).
! * We can't pass builtin_memset_gen_str as that emits RTL. */
! c = 1;
! if (host_integerp (len, 1)
! && !(optimize_size && tree_low_cst (len, 1) > 1)
! && can_store_by_pieces (tree_low_cst (len, 1),
! builtin_memset_read_str, &c, dest_align))
{
! val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
! val_rtx);
! store_by_pieces (dest_mem, tree_low_cst (len, 1),
! builtin_memset_gen_str, val_rtx, dest_align, 0);
}
! else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
! dest_align))
goto do_libcall;
+
+ dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+ dest_mem = convert_memory_address (ptr_mode, dest_mem);
+ return dest_mem;
+ }
+
+ if (target_char_cast (val, &c))
+ goto do_libcall;
+
+ if (c)
+ {
+ if (host_integerp (len, 1)
+ && !(optimize_size && tree_low_cst (len, 1) > 1)
+ && can_store_by_pieces (tree_low_cst (len, 1),
+ builtin_memset_read_str, &c, dest_align))
+ store_by_pieces (dest_mem, tree_low_cst (len, 1),
+ builtin_memset_read_str, &c, dest_align, 0);
+ else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
+ dest_align))
+ goto do_libcall;
+
+ dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+ dest_mem = convert_memory_address (ptr_mode, dest_mem);
+ return dest_mem;
+ }
! set_mem_align (dest_mem, dest_align);
! dest_addr = clear_storage (dest_mem, len_rtx,
! CALL_EXPR_TAILCALL (orig_exp)
! ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL);
! if (dest_addr == 0)
! {
! dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
! dest_addr = convert_memory_address (ptr_mode, dest_addr);
! }
! return dest_addr;
! do_libcall:
! fndecl = get_callee_fndecl (orig_exp);
! fcode = DECL_FUNCTION_CODE (fndecl);
! if (fcode == BUILT_IN_MEMSET)
! fn = build_call_expr (fndecl, 3, dest, val, len);
! else if (fcode == BUILT_IN_BZERO)
! fn = build_call_expr (fndecl, 2, dest, len);
! else
! gcc_unreachable ();
! if (TREE_CODE (fn) == CALL_EXPR)
! CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (orig_exp);
! return expand_call (fn, target, target == const0_rtx);
}
/* Expand expression EXP, which is a call to the bzero builtin. Return 0
*************** expand_builtin_memset (tree arglist, rtx
*** 3504,3558 ****
static rtx
expand_builtin_bzero (tree exp)
{
! tree arglist = TREE_OPERAND (exp, 1);
! tree dest, size, newarglist;
! if (!validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return NULL_RTX;
! dest = TREE_VALUE (arglist);
! size = TREE_VALUE (TREE_CHAIN (arglist));
/* New argument list transforming bzero(ptr x, int y) to
memset(ptr x, int 0, size_t y). This is done this way
so that if it isn't expanded inline, we fallback to
calling bzero instead of memset. */
! newarglist = build_tree_list (NULL_TREE, fold_convert (sizetype, size));
! newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
! newarglist = tree_cons (NULL_TREE, dest, newarglist);
!
! return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp);
}
/* Expand expression EXP, which is a call to the memcmp built-in function.
! ARGLIST is the argument list for this call. Return 0 if we failed and the
caller should emit a normal call, otherwise try to get the result in
TARGET, if convenient (and in mode MODE, if that's convenient). */
static rtx
! expand_builtin_memcmp (tree exp ATTRIBUTE_UNUSED, tree arglist, rtx target,
! enum machine_mode mode)
{
! if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree result = fold_builtin_memcmp (arglist);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
{
- tree arg1 = TREE_VALUE (arglist);
- tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
- tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result;
rtx insn;
int arg1_align
= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
int arg2_align
--- 3525,3578 ----
static rtx
expand_builtin_bzero (tree exp)
{
! tree dest, size;
! if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return NULL_RTX;
! dest = CALL_EXPR_ARG0 (exp);
! size = CALL_EXPR_ARG1 (exp);
/* New argument list transforming bzero(ptr x, int y) to
memset(ptr x, int 0, size_t y). This is done this way
so that if it isn't expanded inline, we fallback to
calling bzero instead of memset. */
! return expand_builtin_memset_args (dest, integer_zero_node,
! fold_convert (sizetype, size),
! const0_rtx, VOIDmode, exp);
}
/* Expand expression EXP, which is a call to the memcmp built-in function.
! Return 0 if we failed and the
caller should emit a normal call, otherwise try to get the result in
TARGET, if convenient (and in mode MODE, if that's convenient). */
static rtx
! expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode)
{
! if (!validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree result = fold_builtin_memcmp (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp),
! CALL_EXPR_ARG2 (exp));
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
#if defined HAVE_cmpmemsi || defined HAVE_cmpstrnsi
{
rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result;
rtx insn;
+ tree arg1 = CALL_EXPR_ARG0 (exp);
+ tree arg2 = CALL_EXPR_ARG1 (exp);
+ tree len = CALL_EXPR_ARG2 (exp);
+
int arg1_align
= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
int arg2_align
*************** expand_builtin_memcmp (tree exp ATTRIBUT
*** 3642,3654 ****
static rtx
expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
{
! tree arglist = TREE_OPERAND (exp, 1);
!
! if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
! tree result = fold_builtin_strcmp (arglist);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
--- 3662,3673 ----
static rtx
expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
{
! if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
! tree result = fold_builtin_strcmp (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp));
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
*************** expand_builtin_strcmp (tree exp, rtx tar
*** 3661,3668 ****
rtx result, insn = NULL_RTX;
tree fndecl, fn;
! tree arg1 = TREE_VALUE (arglist);
! tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
int arg1_align
= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
int arg2_align
--- 3680,3687 ----
rtx result, insn = NULL_RTX;
tree fndecl, fn;
! tree arg1 = CALL_EXPR_ARG0 (exp);
! tree arg2 = CALL_EXPR_ARG1 (exp);
int arg1_align
= get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
int arg2_align
*************** expand_builtin_strcmp (tree exp, rtx tar
*** 3775,3784 ****
#ifdef HAVE_cmpstrnsi
do_libcall:
#endif
- arglist = build_tree_list (NULL_TREE, arg2);
- arglist = tree_cons (NULL_TREE, arg1, arglist);
fndecl = get_callee_fndecl (exp);
! fn = build_function_call_expr (fndecl, arglist);
if (TREE_CODE (fn) == CALL_EXPR)
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
return expand_call (fn, target, target == const0_rtx);
--- 3794,3801 ----
#ifdef HAVE_cmpstrnsi
do_libcall:
#endif
fndecl = get_callee_fndecl (exp);
! fn = build_call_expr (fndecl, 2, arg1, arg2);
if (TREE_CODE (fn) == CALL_EXPR)
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
return expand_call (fn, target, target == const0_rtx);
*************** expand_builtin_strcmp (tree exp, rtx tar
*** 3794,3807 ****
static rtx
expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
{
! tree arglist = TREE_OPERAND (exp, 1);
!
! if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree result = fold_builtin_strncmp (arglist);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
--- 3811,3824 ----
static rtx
expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
{
! if (!validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
! tree result = fold_builtin_strncmp (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp),
! CALL_EXPR_ARG2 (exp));
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
*************** expand_builtin_strncmp (tree exp, rtx ta
*** 3812,3820 ****
#ifdef HAVE_cmpstrnsi
if (HAVE_cmpstrnsi)
{
! tree arg1 = TREE_VALUE (arglist);
! tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
! tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
tree len, len1, len2;
rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result, insn;
--- 3829,3837 ----
#ifdef HAVE_cmpstrnsi
if (HAVE_cmpstrnsi)
{
! tree arg1 = CALL_EXPR_ARG0 (exp);
! tree arg2 = CALL_EXPR_ARG1 (exp);
! tree arg3 = CALL_EXPR_ARG2 (exp);
tree len, len1, len2;
rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result, insn;
*************** expand_builtin_strncmp (tree exp, rtx ta
*** 3904,3914 ****
/* Expand the library call ourselves using a stabilized argument
list to avoid re-evaluating the function's arguments twice. */
- arglist = build_tree_list (NULL_TREE, len);
- arglist = tree_cons (NULL_TREE, arg2, arglist);
- arglist = tree_cons (NULL_TREE, arg1, arglist);
fndecl = get_callee_fndecl (exp);
! fn = build_function_call_expr (fndecl, arglist);
if (TREE_CODE (fn) == CALL_EXPR)
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
return expand_call (fn, target, target == const0_rtx);
--- 3921,3928 ----
/* Expand the library call ourselves using a stabilized argument
list to avoid re-evaluating the function's arguments twice. */
fndecl = get_callee_fndecl (exp);
! fn = build_call_expr (fndecl, 3, arg1, arg2, len);
if (TREE_CODE (fn) == CALL_EXPR)
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
return expand_call (fn, target, target == const0_rtx);
*************** expand_builtin_strncmp (tree exp, rtx ta
*** 3922,3935 ****
otherwise try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
{
! if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
! tree dst = TREE_VALUE (arglist),
! src = TREE_VALUE (TREE_CHAIN (arglist));
const char *p = c_getstr (src);
/* If the string length is zero, return the dst parameter. */
--- 3936,3949 ----
otherwise try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strcat (tree fndecl, tree exp, rtx target, enum machine_mode mode)
{
! if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
! tree dst = CALL_EXPR_ARG0 (exp),
! src = CALL_EXPR_ARG1 (exp);
const char *p = c_getstr (src);
/* If the string length is zero, return the dst parameter. */
*************** expand_builtin_strcat (tree fndecl, tree
*** 3945,3971 ****
/* Stabilize the argument list. */
newsrc = builtin_save_expr (src);
- if (newsrc != src)
- arglist = build_tree_list (NULL_TREE, newsrc);
- else
- arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe. */
-
dst = builtin_save_expr (dst);
start_sequence ();
/* Create strlen (dst). */
! newdst =
! build_function_call_expr (strlen_fn,
! build_tree_list (NULL_TREE, dst));
/* Create (dst + (cast) strlen (dst)). */
newdst = fold_convert (TREE_TYPE (dst), newdst);
newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
newdst = builtin_save_expr (newdst);
- arglist = tree_cons (NULL_TREE, newdst, arglist);
! if (!expand_builtin_strcpy (fndecl, arglist, target, mode))
{
end_sequence (); /* Stop sequence. */
return 0;
--- 3959,3977 ----
/* Stabilize the argument list. */
newsrc = builtin_save_expr (src);
dst = builtin_save_expr (dst);
start_sequence ();
/* Create strlen (dst). */
! newdst = build_call_expr (strlen_fn, 1, dst);
/* Create (dst + (cast) strlen (dst)). */
newdst = fold_convert (TREE_TYPE (dst), newdst);
newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
newdst = builtin_save_expr (newdst);
! if (!expand_builtin_strcpy_args (fndecl, newdst, newsrc, target, mode))
{
end_sequence (); /* Stop sequence. */
return 0;
*************** expand_builtin_strcat (tree fndecl, tree
*** 3988,3999 ****
otherwise try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strncat (tree arglist, rtx target, enum machine_mode mode)
{
! if (validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strncat (arglist);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
--- 3994,4007 ----
otherwise try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strncat (tree exp, rtx target, enum machine_mode mode)
{
! if (validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strncat (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp),
! CALL_EXPR_ARG2 (exp));
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
*************** expand_builtin_strncat (tree arglist, rt
*** 4005,4015 ****
otherwise try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strspn (tree arglist, rtx target, enum machine_mode mode)
{
! if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strspn (arglist);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
--- 4013,4024 ----
otherwise try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strspn (tree exp, rtx target, enum machine_mode mode)
{
! if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strspn (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp));
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
*************** expand_builtin_strspn (tree arglist, rtx
*** 4021,4031 ****
otherwise try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strcspn (tree arglist, rtx target, enum machine_mode mode)
{
! if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strcspn (arglist);
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
--- 4030,4041 ----
otherwise try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strcspn (tree exp, rtx target, enum machine_mode mode)
{
! if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_strcspn (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp));
if (result)
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
*************** expand_builtin_saveregs (void)
*** 4074,4093 ****
is controlled by the definition of CUMULATIVE_ARGS. */
static rtx
! expand_builtin_args_info (tree arglist)
{
int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
int *word_ptr = (int *) ¤t_function_args_info;
gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
! if (arglist != 0)
{
! if (!host_integerp (TREE_VALUE (arglist), 0))
error ("argument of %<__builtin_args_info%> must be constant");
else
{
! HOST_WIDE_INT wordnum = tree_low_cst (TREE_VALUE (arglist), 0);
if (wordnum < 0 || wordnum >= nwords)
error ("argument of %<__builtin_args_info%> out of range");
--- 4084,4103 ----
is controlled by the definition of CUMULATIVE_ARGS. */
static rtx
! expand_builtin_args_info (tree exp)
{
int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
int *word_ptr = (int *) ¤t_function_args_info;
gcc_assert (sizeof (CUMULATIVE_ARGS) % sizeof (int) == 0);
! if (call_expr_nargs (exp) != 0)
{
! if (!host_integerp (CALL_EXPR_ARG0 (exp), 0))
error ("argument of %<__builtin_args_info%> must be constant");
else
{
! HOST_WIDE_INT wordnum = tree_low_cst (CALL_EXPR_ARG0 (exp), 0);
if (wordnum < 0 || wordnum >= nwords)
error ("argument of %<__builtin_args_info%> out of range");
*************** std_expand_builtin_va_start (tree valist
*** 4180,4206 ****
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
! /* Expand ARGLIST, from a call to __builtin_va_start. */
static rtx
! expand_builtin_va_start (tree arglist)
{
rtx nextarg;
! tree chain, valist;
! chain = TREE_CHAIN (arglist);
!
! if (!chain)
{
error ("too few arguments to function %<va_start%>");
return const0_rtx;
}
! if (fold_builtin_next_arg (chain))
return const0_rtx;
nextarg = expand_builtin_next_arg ();
! valist = stabilize_va_list (TREE_VALUE (arglist), 1);
#ifdef EXPAND_BUILTIN_VA_START
EXPAND_BUILTIN_VA_START (valist, nextarg);
--- 4190,4214 ----
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
! /* Expand EXP, a call to __builtin_va_start. */
static rtx
! expand_builtin_va_start (tree exp)
{
rtx nextarg;
! tree valist;
! if (call_expr_nargs (exp) < 2)
{
error ("too few arguments to function %<va_start%>");
return const0_rtx;
}
! if (fold_builtin_next_arg (exp, true))
return const0_rtx;
nextarg = expand_builtin_next_arg ();
! valist = stabilize_va_list (CALL_EXPR_ARG0 (exp), 1);
#ifdef EXPAND_BUILTIN_VA_START
EXPAND_BUILTIN_VA_START (valist, nextarg);
*************** gimplify_va_arg_expr (tree *expr_p, tree
*** 4382,4389 ****
/* We can, however, treat "undefined" any way we please.
Call abort to encourage the user to fix the program. */
inform ("if this code is reached, the program will abort");
! t = build_function_call_expr (implicit_built_in_decls[BUILT_IN_TRAP],
! NULL);
append_to_statement_list (t, pre_p);
/* This is dead code, but go ahead and finish so that the
--- 4390,4396 ----
/* We can, however, treat "undefined" any way we please.
Call abort to encourage the user to fix the program. */
inform ("if this code is reached, the program will abort");
! t = build_call_expr (implicit_built_in_decls[BUILT_IN_TRAP], 0);
append_to_statement_list (t, pre_p);
/* This is dead code, but go ahead and finish so that the
*************** gimplify_va_arg_expr (tree *expr_p, tree
*** 4421,4432 ****
}
}
! /* Expand ARGLIST, from a call to __builtin_va_end. */
static rtx
! expand_builtin_va_end (tree arglist)
{
! tree valist = TREE_VALUE (arglist);
/* Evaluate for side effects, if needed. I hate macros that don't
do that. */
--- 4428,4439 ----
}
}
! /* Expand EXP, a call to __builtin_va_end. */
static rtx
! expand_builtin_va_end (tree exp)
{
! tree valist = CALL_EXPR_ARG0 (exp);
/* Evaluate for side effects, if needed. I hate macros that don't
do that. */
*************** expand_builtin_va_end (tree arglist)
*** 4436,4452 ****
return const0_rtx;
}
! /* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a
builtin rather than just as an assignment in stdarg.h because of the
nastiness of array-type va_list types. */
static rtx
! expand_builtin_va_copy (tree arglist)
{
tree dst, src, t;
! dst = TREE_VALUE (arglist);
! src = TREE_VALUE (TREE_CHAIN (arglist));
dst = stabilize_va_list (dst, 1);
src = stabilize_va_list (src, 0);
--- 4443,4459 ----
return const0_rtx;
}
! /* Expand EXP, a call to __builtin_va_copy. We do this as a
builtin rather than just as an assignment in stdarg.h because of the
nastiness of array-type va_list types. */
static rtx
! expand_builtin_va_copy (tree exp)
{
tree dst, src, t;
! dst = CALL_EXPR_ARG0 (exp);
! src = CALL_EXPR_ARG1 (exp);
dst = stabilize_va_list (dst, 1);
src = stabilize_va_list (src, 0);
*************** expand_builtin_va_copy (tree arglist)
*** 4489,4503 ****
__builtin_return_address. */
static rtx
! expand_builtin_frame_address (tree fndecl, tree arglist)
{
/* The argument must be a nonnegative integer constant.
It counts the number of frames to scan up the stack.
The value is the return address saved in that frame. */
! if (arglist == 0)
/* Warning about missing arg was already issued. */
return const0_rtx;
! else if (! host_integerp (TREE_VALUE (arglist), 1))
{
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
error ("invalid argument to %<__builtin_frame_address%>");
--- 4496,4510 ----
__builtin_return_address. */
static rtx
! expand_builtin_frame_address (tree fndecl, tree exp)
{
/* The argument must be a nonnegative integer constant.
It counts the number of frames to scan up the stack.
The value is the return address saved in that frame. */
! if (call_expr_nargs (exp) == 0)
/* Warning about missing arg was already issued. */
return const0_rtx;
! else if (! host_integerp (CALL_EXPR_ARG0 (exp), 1))
{
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
error ("invalid argument to %<__builtin_frame_address%>");
*************** expand_builtin_frame_address (tree fndec
*** 4509,4515 ****
{
rtx tem
= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
! tree_low_cst (TREE_VALUE (arglist), 1));
/* Some ports cannot access arbitrary stack frames. */
if (tem == NULL)
--- 4516,4522 ----
{
rtx tem
= expand_builtin_return_addr (DECL_FUNCTION_CODE (fndecl),
! tree_low_cst (CALL_EXPR_ARG0 (exp), 1));
/* Some ports cannot access arbitrary stack frames. */
if (tem == NULL)
*************** expand_builtin_frame_address (tree fndec
*** 4532,4543 ****
}
}
! /* Expand a call to the alloca builtin, with arguments ARGLIST. Return 0 if
we failed and the caller should emit a normal call, otherwise try to get
the result in TARGET, if convenient. */
static rtx
! expand_builtin_alloca (tree arglist, rtx target)
{
rtx op0;
rtx result;
--- 4539,4550 ----
}
}
! /* Expand EXP, a call to the alloca builtin. Return 0 if
we failed and the caller should emit a normal call, otherwise try to get
the result in TARGET, if convenient. */
static rtx
! expand_builtin_alloca (tree exp, rtx target)
{
rtx op0;
rtx result;
*************** expand_builtin_alloca (tree arglist, rtx
*** 4548,4558 ****
if (flag_mudflap)
return 0;
! if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
return 0;
/* Compute the argument. */
! op0 = expand_normal (TREE_VALUE (arglist));
/* Allocate the desired space. */
result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
--- 4555,4565 ----
if (flag_mudflap)
return 0;
! if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
return 0;
/* Compute the argument. */
! op0 = expand_normal (CALL_EXPR_ARG0 (exp));
/* Allocate the desired space. */
result = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
*************** expand_builtin_alloca (tree arglist, rtx
*** 4561,4584 ****
return result;
}
! /* Expand a call to a unary builtin. The arguments are in ARGLIST.
Return 0 if a normal call should be emitted rather than expanding the
function in-line. If convenient, the result should be placed in TARGET.
SUBTARGET may be used as the target for computing one of EXP's operands. */
static rtx
! expand_builtin_unop (enum machine_mode target_mode, tree arglist, rtx target,
rtx subtarget, optab op_optab)
{
rtx op0;
! if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
return 0;
/* Compute the argument. */
! op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
/* Compute op, into TARGET if possible.
Set TARGET to wherever the result comes back. */
! target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
op_optab, op0, target, 1);
gcc_assert (target);
--- 4568,4591 ----
return result;
}
! /* Expand a call to a unary builtin in EXP.
Return 0 if a normal call should be emitted rather than expanding the
function in-line. If convenient, the result should be placed in TARGET.
SUBTARGET may be used as the target for computing one of EXP's operands. */
static rtx
! expand_builtin_unop (enum machine_mode target_mode, tree exp, rtx target,
rtx subtarget, optab op_optab)
{
rtx op0;
! if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE))
return 0;
/* Compute the argument. */
! op0 = expand_expr (CALL_EXPR_ARG0 (exp), subtarget, VOIDmode, 0);
/* Compute op, into TARGET if possible.
Set TARGET to wherever the result comes back. */
! target = expand_unop (TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG0 (exp))),
op_optab, op0, target, 1);
gcc_assert (target);
*************** expand_builtin_unop (enum machine_mode t
*** 4589,4600 ****
long, we attempt to transform this call into __builtin_fputc(). */
static rtx
! expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
{
/* Verify the arguments in the original call. */
! if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_fputs (arglist, (target == const0_rtx),
unlocked, NULL_TREE);
if (result)
return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
--- 4596,4609 ----
long, we attempt to transform this call into __builtin_fputc(). */
static rtx
! expand_builtin_fputs (tree exp, rtx target, bool unlocked)
{
/* Verify the arguments in the original call. */
! if (validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
! tree result = fold_builtin_fputs (CALL_EXPR_ARG0 (exp),
! CALL_EXPR_ARG1 (exp),
! (target == const0_rtx),
unlocked, NULL_TREE);
if (result)
return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
*************** expand_builtin_fputs (tree arglist, rtx
*** 4607,4622 ****
a non-jump context. */
static rtx
! expand_builtin_expect (tree arglist, rtx target)
{
! tree exp, c;
rtx note, rtx_c;
! if (arglist == NULL_TREE
! || TREE_CHAIN (arglist) == NULL_TREE)
return const0_rtx;
! exp = TREE_VALUE (arglist);
! c = TREE_VALUE (TREE_CHAIN (arglist));
if (TREE_CODE (c) != INTEGER_CST)
{
--- 4616,4630 ----
a non-jump context. */
static rtx
! expand_builtin_expect (tree exp, rtx target)
{
! tree arg, c;
rtx note, rtx_c;
! if (call_expr_nargs (exp) < 2)
return const0_rtx;
! arg = CALL_EXPR_ARG0 (exp);
! c = CALL_EXPR_ARG1 (exp);
if (TREE_CODE (c) != INTEGER_CST)
{
*************** expand_builtin_expect (tree arglist, rtx
*** 4624,4630 ****
c = integer_zero_node;
}
! target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
/* Don't bother with expected value notes for integral constants. */
if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
--- 4632,4638 ----
c = integer_zero_node;
}
! target = expand_expr (arg, target, VOIDmode, EXPAND_NORMAL);
/* Don't bother with expected value notes for integral constants. */
if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
*************** expand_builtin_expect (tree arglist, rtx
*** 4653,4661 ****
rtx
expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
{
! tree arglist = TREE_OPERAND (exp, 1);
! tree arg0 = TREE_VALUE (arglist);
! tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
rtx ret = NULL_RTX;
/* Only handle __builtin_expect (test, 0) and
--- 4661,4668 ----
rtx
expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
{
! tree arg0 = CALL_EXPR_ARG0 (exp);
! tree arg1 = CALL_EXPR_ARG1 (exp);
rtx ret = NULL_RTX;
/* Only handle __builtin_expect (test, 0) and
*************** expand_builtin_trap (void)
*** 4773,4818 ****
emit_barrier ();
}
! /* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST.
Return 0 if a normal call should be emitted rather than expanding
the function inline. If convenient, the result should be placed
in TARGET. SUBTARGET may be used as the target for computing
the operand. */
static rtx
! expand_builtin_fabs (tree arglist, rtx target, rtx subtarget)
{
enum machine_mode mode;
tree arg;
rtx op0;
! if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
return 0;
! arg = TREE_VALUE (arglist);
mode = TYPE_MODE (TREE_TYPE (arg));
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
}
! /* Expand a call to copysign, copysignf, or copysignl with arguments ARGLIST.
Return NULL is a normal call should be emitted rather than expanding the
function inline. If convenient, the result should be placed in TARGET.
SUBTARGET may be used as the target for computing the operand. */
static rtx
! expand_builtin_copysign (tree arglist, rtx target, rtx subtarget)
{
rtx op0, op1;
tree arg;
! if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
return 0;
! arg = TREE_VALUE (arglist);
op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
! arg = TREE_VALUE (TREE_CHAIN (arglist));
op1 = expand_normal (arg);
return expand_copysign (op0, op1, target);
--- 4780,4825 ----
emit_barrier ();
}
! /* Expand EXP, a call to fabs, fabsf or fabsl.
Return 0 if a normal call should be emitted rather than expanding
the function inline. If convenient, the result should be placed
in TARGET. SUBTARGET may be used as the target for computing
the operand. */
static rtx
! expand_builtin_fabs (tree exp, rtx target, rtx subtarget)
{
enum machine_mode mode;
tree arg;
rtx op0;
! if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
return 0;
! arg = CALL_EXPR_ARG0 (exp);
mode = TYPE_MODE (TREE_TYPE (arg));
op0 = expand_expr (arg, subtarget, VOIDmode, 0);
return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
}
! /* Expand EXP, a call to copysign, copysignf, or copysignl.
Return NULL is a normal call should be emitted rather than expanding the
function inline. If convenient, the result should be placed in TARGET.
SUBTARGET may be used as the target for computing the operand. */
static rtx
! expand_builtin_copysign (tree exp, rtx target, rtx subtarget)
{
rtx op0, op1;
tree arg;
! if (!validate_arglist (exp, REAL_TYPE, REAL_TYPE, VOID_TYPE))
return 0;
! arg = CALL_EXPR_ARG0 (exp);
op0 = expand_expr (arg, subtarget, VOIDmode, EXPAND_NORMAL);
! arg = CALL_EXPR_ARG1 (exp);
op1 = expand_normal (arg);
return expand_copysign (op0, op1, target);
*************** static rtx
*** 4852,4858 ****
expand_builtin_printf (tree exp, rtx target, enum machine_mode mode,
bool unlocked)
{
- tree arglist = TREE_OPERAND (exp, 1);
/* If we're using an unlocked function, assume the other unlocked
functions exist explicitly. */
tree const fn_putchar = unlocked ? built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED]
--- 4859,4864 ----
*************** expand_builtin_printf (tree exp, rtx tar
*** 4860,4878 ****
tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
: implicit_built_in_decls[BUILT_IN_PUTS];
const char *fmt_str;
! tree fn, fmt, arg;
/* If the return value is used, don't do the transformation. */
if (target != const0_rtx)
return 0;
/* Verify the required arguments in the original call. */
! if (! arglist)
return 0;
! fmt = TREE_VALUE (arglist);
if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
return 0;
- arglist = TREE_CHAIN (arglist);
/* Check whether the format is a literal string constant. */
fmt_str = c_getstr (fmt);
--- 4866,4885 ----
tree const fn_puts = unlocked ? built_in_decls[BUILT_IN_PUTS_UNLOCKED]
: implicit_built_in_decls[BUILT_IN_PUTS];
const char *fmt_str;
! tree fn = 0;
! tree fmt, arg;
! int nargs = call_expr_nargs (exp);
/* If the return value is used, don't do the transformation. */
if (target != const0_rtx)
return 0;
/* Verify the required arguments in the original call. */
! if (nargs == 0)
return 0;
! fmt = CALL_EXPR_ARG0 (exp);
if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
return 0;
/* Check whether the format is a literal string constant. */
fmt_str = c_getstr (fmt);
*************** expand_builtin_printf (tree exp, rtx tar
*** 4885,4904 ****
/* If the format specifier was "%s\n", call __builtin_puts(arg). */
if (strcmp (fmt_str, target_percent_s_newline) == 0)
{
! if (! arglist
! || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
! || TREE_CHAIN (arglist))
return 0;
! fn = fn_puts;
}
/* If the format specifier was "%c", call __builtin_putchar(arg). */
else if (strcmp (fmt_str, target_percent_c) == 0)
{
! if (! arglist
! || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
! || TREE_CHAIN (arglist))
return 0;
! fn = fn_putchar;
}
else
{
--- 4892,4911 ----
/* If the format specifier was "%s\n", call __builtin_puts(arg). */
if (strcmp (fmt_str, target_percent_s_newline) == 0)
{
! if ((nargs != 2)
! || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG1 (exp))))
return 0;
! if (fn_puts)
! fn = build_call_expr (fn_puts, 1, CALL_EXPR_ARG1 (exp));
}
/* If the format specifier was "%c", call __builtin_putchar(arg). */
else if (strcmp (fmt_str, target_percent_c) == 0)
{
! if ((nargs != 2)
! || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG1 (exp))) != INTEGER_TYPE)
return 0;
! if (fn_putchar)
! fn = build_call_expr (fn_putchar, 1, CALL_EXPR_ARG1 (exp));
}
else
{
*************** expand_builtin_printf (tree exp, rtx tar
*** 4906,4912 ****
if (strchr (fmt_str, target_percent))
return 0;
! if (arglist)
return 0;
/* If the format specifier was "", printf does nothing. */
--- 4913,4919 ----
if (strchr (fmt_str, target_percent))
return 0;
! if (nargs > 1)
return 0;
/* If the format specifier was "", printf does nothing. */
*************** expand_builtin_printf (tree exp, rtx tar
*** 4919,4926 ****
convert "c"[0] to an int and pass that to the replacement
function. */
arg = build_int_cst (NULL_TREE, fmt_str[0]);
! arglist = build_tree_list (NULL_TREE, arg);
! fn = fn_putchar;
}
else
{
--- 4926,4933 ----
convert "c"[0] to an int and pass that to the replacement
function. */
arg = build_int_cst (NULL_TREE, fmt_str[0]);
! if (fn_putchar)
! fn = build_call_expr (fn_putchar, 1, arg);
}
else
{
*************** expand_builtin_printf (tree exp, rtx tar
*** 4933,4942 ****
char *newstr = alloca (len);
memcpy (newstr, fmt_str, len - 1);
newstr[len - 1] = 0;
-
arg = build_string_literal (len, newstr);
! arglist = build_tree_list (NULL_TREE, arg);
! fn = fn_puts;
}
else
/* We'd like to arrange to call fputs(string,stdout) here,
--- 4940,4948 ----
char *newstr = alloca (len);
memcpy (newstr, fmt_str, len - 1);
newstr[len - 1] = 0;
arg = build_string_literal (len, newstr);
! if (fn_puts)
! fn = build_call_expr (fn_puts, 1, arg);
}
else
/* We'd like to arrange to call fputs(string,stdout) here,
*************** expand_builtin_printf (tree exp, rtx tar
*** 4947,4953 ****
if (!fn)
return 0;
- fn = build_function_call_expr (fn, arglist);
if (TREE_CODE (fn) == CALL_EXPR)
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
return expand_expr (fn, target, mode, EXPAND_NORMAL);
--- 4953,4958 ----
*************** static rtx
*** 4962,4968 ****
expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode,
bool unlocked)
{
- tree arglist = TREE_OPERAND (exp, 1);
/* If we're using an unlocked function, assume the other unlocked
functions exist explicitly. */
tree const fn_fputc = unlocked ? built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
--- 4967,4972 ----
*************** expand_builtin_fprintf (tree exp, rtx ta
*** 4970,4994 ****
tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
: implicit_built_in_decls[BUILT_IN_FPUTS];
const char *fmt_str;
! tree fn, fmt, fp, arg;
/* If the return value is used, don't do the transformation. */
if (target != const0_rtx)
return 0;
/* Verify the required arguments in the original call. */
! if (! arglist)
return 0;
! fp = TREE_VALUE (arglist);
if (! POINTER_TYPE_P (TREE_TYPE (fp)))
return 0;
! arglist = TREE_CHAIN (arglist);
! if (! arglist)
! return 0;
! fmt = TREE_VALUE (arglist);
if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
return 0;
- arglist = TREE_CHAIN (arglist);
/* Check whether the format is a literal string constant. */
fmt_str = c_getstr (fmt);
--- 4974,4996 ----
tree const fn_fputs = unlocked ? built_in_decls[BUILT_IN_FPUTS_UNLOCKED]
: implicit_built_in_decls[BUILT_IN_FPUTS];
const char *fmt_str;
! tree fn = 0;
! tree fmt, fp, arg;
! int nargs = call_expr_nargs (exp);
/* If the return value is used, don't do the transformation. */
if (target != const0_rtx)
return 0;
/* Verify the required arguments in the original call. */
! if (nargs < 2)
return 0;
! fp = CALL_EXPR_ARG0 (exp);
if (! POINTER_TYPE_P (TREE_TYPE (fp)))
return 0;
! fmt = CALL_EXPR_ARG1 (exp);
if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
return 0;
/* Check whether the format is a literal string constant. */
fmt_str = c_getstr (fmt);
*************** expand_builtin_fprintf (tree exp, rtx ta
*** 5001,5026 ****
/* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
if (strcmp (fmt_str, target_percent_s) == 0)
{
! if (! arglist
! || ! POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (arglist)))
! || TREE_CHAIN (arglist))
return 0;
! arg = TREE_VALUE (arglist);
! arglist = build_tree_list (NULL_TREE, fp);
! arglist = tree_cons (NULL_TREE, arg, arglist);
! fn = fn_fputs;
}
/* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
else if (strcmp (fmt_str, target_percent_c) == 0)
{
! if (! arglist
! || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE
! || TREE_CHAIN (arglist))
return 0;
! arg = TREE_VALUE (arglist);
! arglist = build_tree_list (NULL_TREE, fp);
! arglist = tree_cons (NULL_TREE, arg, arglist);
! fn = fn_fputc;
}
else
{
--- 5003,5024 ----
/* If the format specifier was "%s", call __builtin_fputs(arg,fp). */
if (strcmp (fmt_str, target_percent_s) == 0)
{
! if ((nargs != 3)
! || ! POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG2 (exp))))
return 0;
! arg = CALL_EXPR_ARG2 (exp);
! if (fn_fputs)
! fn = build_call_expr (fn_fputs, 2, arg, fp);
}
/* If the format specifier was "%c", call __builtin_fputc(arg,fp). */
else if (strcmp (fmt_str, target_percent_c) == 0)
{
! if ((nargs != 3)
! || TREE_CODE (TREE_TYPE (CALL_EXPR_ARG2 (exp))) != INTEGER_TYPE)
return 0;
! arg = CALL_EXPR_ARG2 (exp);
! if (fn_fputc)
! fn = build_call_expr (fn_fputc, 2, arg, fp);
}
else
{
*************** expand_builtin_fprintf (tree exp, rtx ta
*** 5028,5034 ****
if (strchr (fmt_str, target_percent))
return 0;
! if (arglist)
return 0;
/* If the format specifier was "", fprintf does nothing. */
--- 5026,5032 ----
if (strchr (fmt_str, target_percent))
return 0;
! if (nargs > 2)
return 0;
/* If the format specifier was "", fprintf does nothing. */
*************** expand_builtin_fprintf (tree exp, rtx ta
*** 5042,5086 ****
/* When "string" doesn't contain %, replace all cases of
fprintf(stream,string) with fputs(string,stream). The fputs
builtin will take care of special cases like length == 1. */
! arglist = build_tree_list (NULL_TREE, fp);
! arglist = tree_cons (NULL_TREE, fmt, arglist);
! fn = fn_fputs;
}
if (!fn)
return 0;
- fn = build_function_call_expr (fn, arglist);
if (TREE_CODE (fn) == CALL_EXPR)
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
return expand_expr (fn, target, mode, EXPAND_NORMAL);
}
! /* Expand a call to sprintf with argument list ARGLIST. Return 0 if
a normal call should be emitted rather than expanding the function
inline. If convenient, the result should be placed in TARGET with
mode MODE. */
static rtx
! expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
{
! tree orig_arglist, dest, fmt;
const char *fmt_str;
!
! orig_arglist = arglist;
/* Verify the required arguments in the original call. */
! if (! arglist)
return 0;
! dest = TREE_VALUE (arglist);
if (! POINTER_TYPE_P (TREE_TYPE (dest)))
return 0;
! arglist = TREE_CHAIN (arglist);
! if (! arglist)
! return 0;
! fmt = TREE_VALUE (arglist);
if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
return 0;
- arglist = TREE_CHAIN (arglist);
/* Check whether the format is a literal string constant. */
fmt_str = c_getstr (fmt);
--- 5040,5077 ----
/* When "string" doesn't contain %, replace all cases of
fprintf(stream,string) with fputs(string,stream). The fputs
builtin will take care of special cases like length == 1. */
! if (fn_fputs)
! fn = build_call_expr (fn_fputs, 2, fmt, fp);
}
if (!fn)
return 0;
if (TREE_CODE (fn) == CALL_EXPR)
CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
return expand_expr (fn, target, mode, EXPAND_NORMAL);
}
! /* Expand a call EXP to sprintf. Return 0 if
a normal call should be emitted rather than expanding the function
inline. If convenient, the result should be placed in TARGET with
mode MODE. */
static rtx
! expand_builtin_sprintf (tree exp, rtx target, enum machine_mode mode)
{
! tree dest, fmt;
const char *fmt_str;
! int nargs = call_expr_nargs (exp);
/* Verify the required arguments in the original call. */
! if (nargs < 2)
return 0;
! dest = CALL_EXPR_ARG0 (exp);
if (! POINTER_TYPE_P (TREE_TYPE (dest)))
return 0;
! fmt = CALL_EXPR_ARG0 (exp);
if (! POINTER_TYPE_P (TREE_TYPE (fmt)))
return 0;
/* Check whether the format is a literal string constant. */
fmt_str = c_getstr (fmt);
*************** expand_builtin_sprintf (tree arglist, rt
*** 5096,5104 ****
tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
tree exp;
! if (arglist || ! fn)
return 0;
! expand_expr (build_function_call_expr (fn, orig_arglist),
const0_rtx, VOIDmode, EXPAND_NORMAL);
if (target == const0_rtx)
return const0_rtx;
--- 5087,5095 ----
tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
tree exp;
! if ((nargs > 2) || ! fn)
return 0;
! expand_expr (build_call_expr (fn, 2, dest, fmt),
const0_rtx, VOIDmode, EXPAND_NORMAL);
if (target == const0_rtx)
return const0_rtx;
*************** expand_builtin_sprintf (tree arglist, rt
*** 5113,5122 ****
if (! fn)
return 0;
!
! if (! arglist || TREE_CHAIN (arglist))
return 0;
! arg = TREE_VALUE (arglist);
if (! POINTER_TYPE_P (TREE_TYPE (arg)))
return 0;
--- 5104,5112 ----
if (! fn)
return 0;
! if (nargs != 3)
return 0;
! arg = CALL_EXPR_ARG2 (exp);
if (! POINTER_TYPE_P (TREE_TYPE (arg)))
return 0;
*************** expand_builtin_sprintf (tree arglist, rt
*** 5129,5137 ****
else
len = NULL_TREE;
! arglist = build_tree_list (NULL_TREE, arg);
! arglist = tree_cons (NULL_TREE, dest, arglist);
! expand_expr (build_function_call_expr (fn, arglist),
const0_rtx, VOIDmode, EXPAND_NORMAL);
if (target == const0_rtx)
--- 5119,5125 ----
else
len = NULL_TREE;
! expand_expr (build_call_expr (fn, 2, dest, arg),
const0_rtx, VOIDmode, EXPAND_NORMAL);
if (target == const0_rtx)
*************** round_trampoline_addr (rtx tramp)
*** 5192,5198 ****
}
static rtx
! expand_builtin_init_trampoline (tree arglist)
{
tree t_tramp, t_func, t_chain;
rtx r_tramp, r_func, r_chain;
--- 5180,5186 ----
}
static rtx
! expand_builtin_init_trampoline (tree exp)
{
tree t_tramp, t_func, t_chain;
rtx r_tramp, r_func, r_chain;
*************** expand_builtin_init_trampoline (tree arg
*** 5200,5214 ****
rtx blktramp;
#endif
! if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE,
POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
! t_tramp = TREE_VALUE (arglist);
! arglist = TREE_CHAIN (arglist);
! t_func = TREE_VALUE (arglist);
! arglist = TREE_CHAIN (arglist);
! t_chain = TREE_VALUE (arglist);
r_tramp = expand_normal (t_tramp);
r_func = expand_normal (t_func);
--- 5188,5200 ----
rtx blktramp;
#endif
! if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE,
POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
! t_tramp = CALL_EXPR_ARG0 (exp);
! t_func = CALL_EXPR_ARG1 (exp);
! t_chain = CALL_EXPR_ARG2 (exp);
r_tramp = expand_normal (t_tramp);
r_func = expand_normal (t_func);
*************** expand_builtin_init_trampoline (tree arg
*** 5229,5242 ****
}
static rtx
! expand_builtin_adjust_trampoline (tree arglist)
{
rtx tramp;
! if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
! tramp = expand_normal (TREE_VALUE (arglist));
tramp = round_trampoline_addr (tramp);
#ifdef TRAMPOLINE_ADJUST_ADDRESS
TRAMPOLINE_ADJUST_ADDRESS (tramp);
--- 5215,5228 ----
}
static rtx
! expand_builtin_adjust_trampoline (tree exp)
{
rtx tramp;
! if (!validate_arglist (exp, POINTER_TYPE, VOID_TYPE))
return NULL_RTX;
! tramp = expand_normal (CALL_EXPR_ARG0 (exp));
tramp = round_trampoline_addr (tramp);
#ifdef TRAMPOLINE_ADJUST_ADDRESS
TRAMPOLINE_ADJUST_ADDRESS (tramp);
*************** expand_builtin_signbit (tree exp, rtx ta
*** 5256,5270 ****
const struct real_format *fmt;
enum machine_mode fmode, imode, rmode;
HOST_WIDE_INT hi, lo;
! tree arg, arglist;
int word, bitpos;
rtx temp;
! arglist = TREE_OPERAND (exp, 1);
! if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
return 0;
! arg = TREE_VALUE (arglist);
fmode = TYPE_MODE (TREE_TYPE (arg));
rmode = TYPE_MODE (TREE_TYPE (exp));
fmt = REAL_MODE_FORMAT (fmode);
--- 5242,5255 ----
const struct real_format *fmt;
enum machine_mode fmode, imode, rmode;
HOST_WIDE_INT hi, lo;
! tree arg;
int word, bitpos;
rtx temp;
! if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE))
return 0;
! arg = CALL_EXPR_ARG0 (exp);
fmode = TYPE_MODE (TREE_TYPE (arg));
rmode = TYPE_MODE (TREE_TYPE (exp));
fmt = REAL_MODE_FORMAT (fmode);
*************** expand_builtin_signbit (tree exp, rtx ta
*** 5347,5358 ****
}
/* Expand fork or exec calls. TARGET is the desired target of the
! call. ARGLIST is the list of arguments of the call. FN is the
identificator of the actual function. IGNORE is nonzero if the
value is to be ignored. */
static rtx
! expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
{
tree id, decl;
tree call;
--- 5332,5343 ----
}
/* Expand fork or exec calls. TARGET is the desired target of the
! call. EXP is the call. FN is the
identificator of the actual function. IGNORE is nonzero if the
value is to be ignored. */
static rtx
! expand_builtin_fork_or_exec (tree fn, tree exp, rtx target, int ignore)
{
tree id, decl;
tree call;
*************** expand_builtin_fork_or_exec (tree fn, tr
*** 5406,5415 ****
TREE_NOTHROW (decl) = 1;
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
DECL_VISIBILITY_SPECIFIED (decl) = 1;
! call = build_function_call_expr (decl, arglist);
!
return expand_call (call, target, ignore);
! }
/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
--- 5391,5400 ----
TREE_NOTHROW (decl) = 1;
DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
DECL_VISIBILITY_SPECIFIED (decl) = 1;
! call = rewrite_call_expr (exp, 0, decl, 0);
return expand_call (call, target, ignore);
! }
!
/* Reconstitute a mode for a __sync intrinsic operation. Since the type of
*************** get_builtin_sync_mem (tree loc, enum mac
*** 5451,5457 ****
}
/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
! ARGLIST is the operands list to the function. CODE is the rtx code
that corresponds to the arithmetic or logical operation from the name;
an exception here is that NOT actually means NAND. TARGET is an optional
place for us to store the results; AFTER is true if this is the
--- 5436,5442 ----
}
/* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
! EXP is the CALL_EXPR. CODE is the rtx code
that corresponds to the arithmetic or logical operation from the name;
an exception here is that NOT actually means NAND. TARGET is an optional
place for us to store the results; AFTER is true if this is the
*************** get_builtin_sync_mem (tree loc, enum mac
*** 5459,5475 ****
the result of the operation at all. */
static rtx
! expand_builtin_sync_operation (enum machine_mode mode, tree arglist,
enum rtx_code code, bool after,
rtx target, bool ignore)
{
rtx val, mem;
/* Expand the operands. */
! mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
! arglist = TREE_CHAIN (arglist);
! val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
if (ignore)
return expand_sync_operation (mem, val, code);
--- 5444,5459 ----
the result of the operation at all. */
static rtx
! expand_builtin_sync_operation (enum machine_mode mode, tree exp,
enum rtx_code code, bool after,
rtx target, bool ignore)
{
rtx val, mem;
/* Expand the operands. */
! mem = get_builtin_sync_mem (CALL_EXPR_ARG0 (exp), mode);
! val = expand_expr (CALL_EXPR_ARG1 (exp), NULL, mode, EXPAND_NORMAL);
if (ignore)
return expand_sync_operation (mem, val, code);
*************** expand_builtin_sync_operation (enum mach
*** 5478,5525 ****
}
/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
! intrinsics. ARGLIST is the operands list to the function. IS_BOOL is
true if this is the boolean form. TARGET is a place for us to store the
results; this is NOT optional if IS_BOOL is true. */
static rtx
! expand_builtin_compare_and_swap (enum machine_mode mode, tree arglist,
bool is_bool, rtx target)
{
rtx old_val, new_val, mem;
/* Expand the operands. */
! mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
!
! arglist = TREE_CHAIN (arglist);
! old_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
!
! arglist = TREE_CHAIN (arglist);
! new_val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
if (is_bool)
return expand_bool_compare_and_swap (mem, old_val, new_val, target);
else
return expand_val_compare_and_swap (mem, old_val, new_val, target);
}
/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
general form is actually an atomic exchange, and some targets only
support a reduced form with the second argument being a constant 1.
! ARGLIST is the operands list to the function; TARGET is an optional
place for us to store the results. */
static rtx
! expand_builtin_lock_test_and_set (enum machine_mode mode, tree arglist,
rtx target)
{
rtx val, mem;
/* Expand the operands. */
! mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
!
! arglist = TREE_CHAIN (arglist);
! val = expand_expr (TREE_VALUE (arglist), NULL, mode, EXPAND_NORMAL);
return expand_sync_lock_test_and_set (mem, val, target);
}
--- 5462,5504 ----
}
/* Expand the __sync_val_compare_and_swap and __sync_bool_compare_and_swap
! intrinsics. EXP is the CALL_EXPR. IS_BOOL is
true if this is the boolean form. TARGET is a place for us to store the
results; this is NOT optional if IS_BOOL is true. */
static rtx
! expand_builtin_compare_and_swap (enum machine_mode mode, tree exp,
bool is_bool, rtx target)
{
rtx old_val, new_val, mem;
/* Expand the operands. */
! mem = get_builtin_sync_mem (CALL_EXPR_ARG0 (exp), mode);
! old_val = expand_expr (CALL_EXPR_ARG1 (exp), NULL, mode, EXPAND_NORMAL);
! new_val = expand_expr (CALL_EXPR_ARG2 (exp), NULL, mode, EXPAND_NORMAL);
if (is_bool)
return expand_bool_compare_and_swap (mem, old_val, new_val, target);
else
return expand_val_compare_and_swap (mem, old_val, new_val, target);
}
+
/* Expand the __sync_lock_test_and_set intrinsic. Note that the most
general form is actually an atomic exchange, and some targets only
support a reduced form with the second argument being a constant 1.
! EXP is the CALL_EXPR; TARGET is an optional
place for us to store the results. */
static rtx
! expand_builtin_lock_test_and_set (enum machine_mode mode, tree exp,
rtx target)
{
rtx val, mem;
/* Expand the operands. */
! mem = get_builtin_sync_mem (CALL_EXPR_ARG0 (exp), mode);
! val = expand_expr (CALL_EXPR_ARG1 (exp), NULL, mode, EXPAND_NORMAL);
return expand_sync_lock_test_and_set (mem, val, target);
}
*************** expand_builtin_synchronize (void)
*** 5547,5564 ****
expand_asm_expr (x);
}
! /* Expand the __sync_lock_release intrinsic. ARGLIST is the operands list
! to the function. */
static void
! expand_builtin_lock_release (enum machine_mode mode, tree arglist)
{
enum insn_code icode;
rtx mem, insn;
rtx val = const0_rtx;
/* Expand the operands. */
! mem = get_builtin_sync_mem (TREE_VALUE (arglist), mode);
/* If there is an explicit operation in the md file, use it. */
icode = sync_lock_release[mode];
--- 5526,5542 ----
expand_asm_expr (x);
}
! /* Expand the __sync_lock_release intrinsic. EXP is the CALL_EXPR. */
static void
! expand_builtin_lock_release (enum machine_mode mode, tree exp)
{
enum insn_code icode;
rtx mem, insn;
rtx val = const0_rtx;
/* Expand the operands. */
! mem = get_builtin_sync_mem (CALL_EXPR_ARG0 (exp), mode);
/* If there is an explicit operation in the md file, use it. */
icode = sync_lock_release[mode];
*************** expand_builtin (tree exp, rtx target, rt
*** 5592,5598 ****
int ignore)
{
tree fndecl = get_callee_fndecl (exp);
- tree arglist = TREE_OPERAND (exp, 1);
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
--- 5570,5575 ----
*************** expand_builtin (tree exp, rtx target, rt
*** 5620,5628 ****
{
bool volatilep = false;
tree arg;
! for (arg = arglist; arg; arg = TREE_CHAIN (arg))
! if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
{
volatilep = true;
break;
--- 5597,5607 ----
{
bool volatilep = false;
tree arg;
+ call_expr_arg_iterator iter;
! for (arg = first_call_expr_arg (exp, &iter); arg;
! arg = next_call_expr_arg (&iter))
! if (TREE_THIS_VOLATILE (arg))
{
volatilep = true;
break;
*************** expand_builtin (tree exp, rtx target, rt
*** 5630,5638 ****
if (! volatilep)
{
! for (arg = arglist; arg; arg = TREE_CHAIN (arg))
! expand_expr (TREE_VALUE (arg), const0_rtx,
! VOIDmode, EXPAND_NORMAL);
return const0_rtx;
}
}
--- 5609,