X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fbuiltins.c;h=cdc5cebcbc6dea3bcc5c076ebbde0bd488fb803b;hb=576aff9d272cd8ebec2b93b10dcf5eae125e9667;hp=f39a073951b634096f3a550992d775ea6cb57a62;hpb=a601d32a513ad5e895c7a332bc836e3398966b3b;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/builtins.c b/gcc/builtins.c index f39a073951b..cdc5cebcbc6 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -111,15 +111,15 @@ 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); -static rtx expand_builtin_bcopy (tree, tree); +static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree); +static rtx expand_builtin_bcopy (tree); static rtx expand_builtin_strcpy (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 (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); @@ -351,7 +351,7 @@ c_strlen (tree src, int only_value) runtime. */ if (offset < 0 || offset > max) { - warning ("offset outside bounds of constant string"); + warning (0, "offset outside bounds of constant string"); return 0; } @@ -945,7 +945,7 @@ expand_builtin_prefetch (tree arglist) /* Argument 1 must be either zero or one. */ if (INTVAL (op1) != 0 && INTVAL (op1) != 1) { - warning ("invalid second argument to %<__builtin_prefetch%>;" + warning (0, "invalid second argument to %<__builtin_prefetch%>;" " using zero"); op1 = const0_rtx; } @@ -960,7 +960,7 @@ expand_builtin_prefetch (tree arglist) /* Argument 2 must be 0, 1, 2, or 3. */ if (INTVAL (op2) < 0 || INTVAL (op2) > 3) { - warning ("invalid third argument to %<__builtin_prefetch%>; using zero"); + warning (0, "invalid third argument to %<__builtin_prefetch%>; using zero"); op2 = const0_rtx; } @@ -2808,7 +2808,8 @@ expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode) /* Copy word part most expediently. */ dest_addr = emit_block_move (dest_mem, src_mem, len_rtx, - BLOCK_OP_NORMAL); + CALL_EXPR_TAILCALL (exp) + ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL); if (dest_addr == 0) { @@ -2915,7 +2916,7 @@ expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode m static rtx expand_builtin_memmove (tree arglist, tree type, rtx target, - enum machine_mode mode) + enum machine_mode mode, tree orig_exp) { if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) @@ -2947,11 +2948,13 @@ expand_builtin_memmove (tree arglist, tree type, rtx target, normal memcpy. */ if (readonly_data_expr (src)) { - tree const fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; + 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); + 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, @@ -2973,8 +2976,10 @@ expand_builtin_memmove (tree arglist, tree type, rtx target, if we failed the caller should emit a normal call. */ static rtx -expand_builtin_bcopy (tree arglist, tree type) +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, @@ -2994,7 +2999,7 @@ expand_builtin_bcopy (tree arglist, tree type) newarglist = tree_cons (NULL_TREE, src, newarglist); newarglist = tree_cons (NULL_TREE, dest, newarglist); - return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode); + return expand_builtin_memmove (newarglist, type, const0_rtx, VOIDmode, exp); } #ifndef HAVE_movstr @@ -3288,7 +3293,8 @@ builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED, convenient). */ static rtx -expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode) +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)) @@ -3374,7 +3380,9 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode) dest_mem = get_memory_rtx (dest); set_mem_align (dest_mem, dest_align); - dest_addr = clear_storage (dest_mem, len_rtx); + dest_addr = clear_storage (dest_mem, len_rtx, + CALL_EXPR_TAILCALL (orig_exp) + ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL); if (dest_addr == 0) { @@ -3390,8 +3398,9 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode) if we failed the caller should emit a normal call. */ static rtx -expand_builtin_bzero (tree arglist) +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)) @@ -3409,7 +3418,7 @@ expand_builtin_bzero (tree arglist) newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist); newarglist = tree_cons (NULL_TREE, dest, newarglist); - return expand_builtin_memset (newarglist, const0_rtx, VOIDmode); + return expand_builtin_memset (newarglist, const0_rtx, VOIDmode, exp); } /* Expand expression EXP, which is a call to the memcmp built-in function. @@ -3548,7 +3557,7 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) tree len, len1, len2; rtx arg1_rtx, arg2_rtx, arg3_rtx; rtx result, insn; - tree fndecl; + tree fndecl, fn; int arg1_align = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; @@ -3632,8 +3641,10 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode) arglist = build_tree_list (NULL_TREE, arg2); arglist = tree_cons (NULL_TREE, arg1, arglist); fndecl = get_callee_fndecl (exp); - exp = build_function_call_expr (fndecl, arglist); - return expand_call (exp, target, target == const0_rtx); + 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); } #endif return 0; @@ -3670,7 +3681,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) tree len, len1, len2; rtx arg1_rtx, arg2_rtx, arg3_rtx; rtx result, insn; - tree fndecl; + tree fndecl, fn; int arg1_align = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; @@ -3760,8 +3771,10 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) arglist = tree_cons (NULL_TREE, arg2, arglist); arglist = tree_cons (NULL_TREE, arg1, arglist); fndecl = get_callee_fndecl (exp); - exp = build_function_call_expr (fndecl, arglist); - return expand_call (exp, target, target == const0_rtx); + 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); } #endif return 0; @@ -3810,7 +3823,8 @@ expand_builtin_strcat (tree arglist, tree type, rtx target, enum machine_mode mo fold (build_function_call_expr (strlen_fn, build_tree_list (NULL_TREE, dst))); - /* Create (dst + strlen (dst)). */ + /* Create (dst + (cast) strlen (dst)). */ + newdst = fold_convert (TREE_TYPE (dst), newdst); newdst = fold (build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst)); /* Prepend the new dst argument. */ @@ -4219,12 +4233,12 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p) /* Unfortunately, this is merely undefined, rather than a constraint violation, so we cannot make this an error. If this call is never executed, the program is still strictly conforming. */ - warning ("%qT is promoted to %qT when passed through %<...%>", + warning (0, "%qT is promoted to %qT when passed through %<...%>", type, promoted_type); if (! gave_help) { gave_help = true; - warning ("(so you should pass %qT not %qT to %)", + warning (0, "(so you should pass %qT not %qT to %)", promoted_type, type); } @@ -4261,7 +4275,8 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p) gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue); if (!targetm.gimplify_va_arg_expr) - /* Once most targets are converted this should abort. */ + /* FIXME:Once most targets are converted we should merely + assert this is non-null. */ return GS_ALL_DONE; *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p); @@ -4363,9 +4378,9 @@ expand_builtin_frame_address (tree fndecl, tree arglist) if (tem == NULL) { if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) - warning ("unsupported argument to %<__builtin_frame_address%>"); + warning (0, "unsupported argument to %<__builtin_frame_address%>"); else - warning ("unsupported argument to %<__builtin_return_address%>"); + warning (0, "unsupported argument to %<__builtin_return_address%>"); return const0_rtx; } @@ -4691,15 +4706,16 @@ build_string_literal (int len, const char *str) return t; } -/* Expand a call to printf or printf_unlocked with argument list ARGLIST. +/* Expand EXP, a call to printf or printf_unlocked. Return 0 if a normal call should be emitted rather than transforming the function inline. If convenient, the result should be placed in TARGET with mode MODE. UNLOCKED indicates this is a printf_unlocked call. */ static rtx -expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode, +expand_builtin_printf (tree exp, rtx target, enum machine_mode mode, bool unlocked) { + tree arglist = TREE_OPERAND (exp, 1); tree fn_putchar = unlocked ? implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTCHAR]; @@ -4790,19 +4806,22 @@ expand_builtin_printf (tree arglist, rtx target, enum machine_mode mode, if (!fn) return 0; - return expand_expr (build_function_call_expr (fn, arglist), - target, mode, EXPAND_NORMAL); + 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 fprintf or fprintf_unlocked with argument list ARGLIST. +/* Expand EXP, a call to fprintf or fprintf_unlocked. Return 0 if a normal call should be emitted rather than transforming the function inline. If convenient, the result should be placed in TARGET with mode MODE. UNLOCKED indicates this is a fprintf_unlocked call. */ static rtx -expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode, +expand_builtin_fprintf (tree exp, rtx target, enum machine_mode mode, bool unlocked) { + tree arglist = TREE_OPERAND (exp, 1); tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTC]; tree fn_fputs = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED] @@ -4884,8 +4903,10 @@ expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode mode, if (!fn) return 0; - return expand_expr (build_function_call_expr (fn, arglist), - target, mode, EXPAND_NORMAL); + 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 @@ -5848,25 +5869,26 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_MEMMOVE: - target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target, mode); + target = expand_builtin_memmove (arglist, TREE_TYPE (exp), target, + mode, exp); if (target) return target; break; case BUILT_IN_BCOPY: - target = expand_builtin_bcopy (arglist, TREE_TYPE (exp)); + target = expand_builtin_bcopy (exp); if (target) return target; break; case BUILT_IN_MEMSET: - target = expand_builtin_memset (arglist, target, mode); + target = expand_builtin_memset (arglist, target, mode, exp); if (target) return target; break; case BUILT_IN_BZERO: - target = expand_builtin_bzero (arglist); + target = expand_builtin_bzero (exp); if (target) return target; break; @@ -5943,13 +5965,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, return const0_rtx; case BUILT_IN_PRINTF: - target = expand_builtin_printf (arglist, target, mode, false); + target = expand_builtin_printf (exp, target, mode, false); if (target) return target; break; case BUILT_IN_PRINTF_UNLOCKED: - target = expand_builtin_printf (arglist, target, mode, true); + target = expand_builtin_printf (exp, target, mode, true); if (target) return target; break; @@ -5966,13 +5988,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_FPRINTF: - target = expand_builtin_fprintf (arglist, target, mode, false); + target = expand_builtin_fprintf (exp, target, mode, false); if (target) return target; break; case BUILT_IN_FPRINTF_UNLOCKED: - target = expand_builtin_fprintf (arglist, target, mode, true); + target = expand_builtin_fprintf (exp, target, mode, true); if (target) return target; break; @@ -6316,10 +6338,17 @@ fold_builtin_constant_p (tree arglist) /* If we know this is a constant, emit the constant of one. */ if (CONSTANT_CLASS_P (arglist) || (TREE_CODE (arglist) == CONSTRUCTOR - && TREE_CONSTANT (arglist)) - || (TREE_CODE (arglist) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST)) + && TREE_CONSTANT (arglist))) return integer_one_node; + if (TREE_CODE (arglist) == ADDR_EXPR) + { + tree op = TREE_OPERAND (arglist, 0); + if (TREE_CODE (op) == STRING_CST + || (TREE_CODE (op) == ARRAY_REF + && integer_zerop (TREE_OPERAND (op, 1)) + && TREE_CODE (TREE_OPERAND (op, 0)) == STRING_CST)) + return integer_one_node; + } /* If this expression has side effects, show we don't know it to be a constant. Likewise if it's a pointer or aggregate type since in @@ -9484,7 +9513,7 @@ fold_builtin_next_arg (tree arglist) { /* Evidently an out of date version of ; can't validate va_start's second argument, but can still work as intended. */ - warning ("%<__builtin_next_arg%> called without an argument"); + warning (0, "%<__builtin_next_arg%> called without an argument"); return true; } /* We use __builtin_va_start (ap, 0, 0) or __builtin_next_arg (0, 0) @@ -9519,7 +9548,7 @@ fold_builtin_next_arg (tree arglist) argument. We just warn and set the arg to be the last argument so that we will get wrong-code because of it. */ - warning ("second parameter of % not last named argument"); + warning (0, "second parameter of % not last named argument"); } /* We want to verify the second parameter just once before the tree optimizers are run and then avoid keeping it in the tree,