X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fbuiltins.c;h=5b476ca8fec6f7d5087af7dd33e064dbecca904a;hb=07e3a3d29f34767991ff4decd0061e049b8faaa5;hp=dc2297e99a6e78794a9fd7bbdd49fb5ab17184a2;hpb=8ff6a5cde05b81806baee38dafe2401696d768ca;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/builtins.c b/gcc/builtins.c index dc2297e99a6..5b476ca8fec 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -107,12 +107,12 @@ 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); -static rtx expand_builtin_strcat (tree, rtx, enum machine_mode); +static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode); static rtx expand_builtin_strncat (tree, rtx, enum machine_mode); 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, int); +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_strcpy (tree, rtx, enum machine_mode); @@ -162,7 +162,7 @@ static tree fold_builtin_ceil (tree); static tree fold_builtin_round (tree); static tree fold_builtin_bitop (tree); static tree fold_builtin_memcpy (tree); -static tree fold_builtin_mempcpy (tree); +static tree fold_builtin_mempcpy (tree, tree, int); static tree fold_builtin_memmove (tree, tree); static tree fold_builtin_strchr (tree); static tree fold_builtin_memcmp (tree); @@ -452,7 +452,7 @@ builtin_save_expr (tree exp) times to get the address of either a higher stack frame, or a return address located within it (depending on FNDECL_CODE). */ -rtx +static rtx expand_builtin_return_addr (enum built_in_function fndecl_code, int count, rtx tem) { @@ -688,7 +688,7 @@ expand_builtin_setjmp (tree arglist, rtx target) scheme in the compiler and will only work in the method used by them. */ -void +static void expand_builtin_longjmp (rtx buf_addr, rtx value) { rtx fp, lab, stack, insn, last; @@ -922,28 +922,29 @@ expand_builtin_prefetch (tree arglist) /* Argument 1 (read/write flag) must be a compile-time constant int. */ if (TREE_CODE (arg1) != INTEGER_CST) { - error ("second arg to %<__builtin_prefetch%> must be a constant"); + error ("second argument to %<__builtin_prefetch%> must be a constant"); arg1 = integer_zero_node; } op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); /* Argument 1 must be either zero or one. */ if (INTVAL (op1) != 0 && INTVAL (op1) != 1) { - warning ("invalid second arg to __builtin_prefetch; using zero"); + warning ("invalid second argument to %<__builtin_prefetch%>;" + " using zero"); op1 = const0_rtx; } /* Argument 2 (locality) must be a compile-time constant int. */ if (TREE_CODE (arg2) != INTEGER_CST) { - error ("third arg to %<__builtin_prefetch%> must be a constant"); + error ("third argument to %<__builtin_prefetch%> must be a constant"); arg2 = integer_zero_node; } op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0); /* Argument 2 must be 0, 1, 2, or 3. */ if (INTVAL (op2) < 0 || INTVAL (op2) > 3) { - warning ("invalid third arg to __builtin_prefetch; using zero"); + warning ("invalid third argument to %<__builtin_prefetch%>; using zero"); op2 = const0_rtx; } @@ -2621,7 +2622,7 @@ expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode) stpcpy. */ static rtx -expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode, +expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode, int endp) { if (!validate_arglist (arglist, @@ -2648,48 +2649,20 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode, 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 DEST is not a pointer type, call the normal function. */ - if (dest_align == 0) + if (result) + return expand_expr (result, target, mode, EXPAND_NORMAL); + + /* If either SRC or DEST is not a pointer type, don't do this + operation in-line. */ + if (dest_align == 0 || src_align == 0) return 0; - /* If SRC and DEST are the same (and not volatile), do nothing. */ - if (operand_equal_p (src, dest, 0)) - { - tree expr; - - if (endp == 0) - { - /* Evaluate and ignore LEN in case it has side-effects. */ - expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL); - return expand_expr (dest, target, mode, EXPAND_NORMAL); - } - - if (endp == 2) - len = fold (build2 (MINUS_EXPR, TREE_TYPE (len), len, - integer_one_node)); - len = fold_convert (TREE_TYPE (dest), len); - expr = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len)); - return expand_expr (expr, target, mode, EXPAND_NORMAL); - } - /* If LEN is not constant, call the normal function. */ if (! host_integerp (len, 1)) return 0; - /* If the LEN parameter is zero, return DEST. */ - if (tree_low_cst (len, 1) == 0) - { - /* Evaluate and ignore SRC in case it has side-effects. */ - expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL); - return expand_expr (dest, target, mode, EXPAND_NORMAL); - } - - /* If either SRC is not a pointer type, don't do this - operation in-line. */ - if (src_align == 0) - return 0; - len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0); src_str = c_getstr (src); @@ -2753,7 +2726,7 @@ expand_builtin_memmove (tree arglist, tree type, rtx target, tree result = fold_builtin_memmove (arglist, type); if (result) - expand_expr (result, target, mode, EXPAND_NORMAL); + return expand_expr (result, target, mode, EXPAND_NORMAL); /* If DEST is not a pointer type, call the normal function. */ if (dest_align == 0) @@ -2779,7 +2752,7 @@ expand_builtin_memmove (tree arglist, tree type, rtx target, it is ok to use memcpy as well. */ if (integer_onep (len)) { - rtx ret = expand_builtin_mempcpy (arglist, target, mode, + rtx ret = expand_builtin_mempcpy (arglist, type, target, mode, /*endp=*/0); if (ret) return ret; @@ -2950,7 +2923,8 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode) 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, target, mode, /*endp=*/2); + ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp), + target, mode, /*endp=*/2); if (ret) return ret; @@ -3590,7 +3564,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode) otherwise try to get the result in TARGET, if convenient. */ static rtx -expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode) +expand_builtin_strcat (tree arglist, tree type, rtx target, enum machine_mode mode) { if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) return 0; @@ -3640,7 +3614,7 @@ expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode) pass in a target of zero, it should never actually be used. If this was successful return the original dst, not the result of mempcpy. */ - if (expand_builtin_mempcpy (arglist, /*target=*/0, mode, /*endp=*/0)) + if (expand_builtin_mempcpy (arglist, type, /*target=*/0, mode, /*endp=*/0)) return expand_expr (dst, target, mode, EXPAND_NORMAL); else return 0; @@ -3888,6 +3862,11 @@ expand_builtin_va_start (tree arglist) chain = TREE_CHAIN (arglist); + if (!chain) + { + error ("too few arguments to function %"); + return const0_rtx; + } if (TREE_CHAIN (chain)) error ("too many arguments to function %"); @@ -4180,9 +4159,9 @@ expand_builtin_frame_address (tree fndecl, tree arglist) else if (! host_integerp (TREE_VALUE (arglist), 1)) { if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) - error ("invalid arg to %<__builtin_frame_address%>"); + error ("invalid argument to %<__builtin_frame_address%>"); else - error ("invalid arg to %<__builtin_return_address%>"); + error ("invalid argument to %<__builtin_return_address%>"); return const0_rtx; } else @@ -4196,9 +4175,9 @@ expand_builtin_frame_address (tree fndecl, tree arglist) if (tem == NULL) { if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS) - warning ("unsupported arg to %<__builtin_frame_address%>"); + warning ("unsupported argument to %<__builtin_frame_address%>"); else - warning ("unsupported arg to %<__builtin_return_address%>"); + warning ("unsupported argument to %<__builtin_return_address%>"); return const0_rtx; } @@ -4301,7 +4280,7 @@ expand_builtin_expect (tree arglist, rtx target) if (TREE_CODE (c) != INTEGER_CST) { - error ("second arg to %<__builtin_expect%> must be a constant"); + error ("second argument to %<__builtin_expect%> must be a constant"); c = integer_zero_node; } @@ -4442,7 +4421,7 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label) return ret; } -void +static void expand_builtin_trap (void) { #ifdef HAVE_trap @@ -5383,7 +5362,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_STRCAT: - target = expand_builtin_strcat (arglist, target, mode); + target = expand_builtin_strcat (arglist, TREE_TYPE (exp), target, mode); if (target) return target; break; @@ -5439,7 +5418,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; case BUILT_IN_MEMPCPY: - target = expand_builtin_mempcpy (arglist, target, mode, /*endp=*/ 1); + target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1); if (target) return target; break; @@ -5508,7 +5487,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, if (value != const1_rtx) { - error ("__builtin_longjmp second argument must be 1"); + error ("%<__builtin_longjmp%> second argument must be 1"); return const0_rtx; } @@ -5852,8 +5831,15 @@ fold_builtin_inf (tree type, int warn) { REAL_VALUE_TYPE real; + /* __builtin_inff is intended to be usable to define INFINITY on all + targets. If an infinity is not available, INFINITY expands "to a + positive constant of type float that overflows at translation + time", footnote "In this case, using INFINITY will violate the + constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4). + Thus we pedwarn to ensure this constraint violation is + diagnosed. */ if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn) - warning ("target format does not support infinity"); + pedwarn ("target format does not support infinity"); real_inf (&real); return build_real (type, real); @@ -6971,31 +6957,34 @@ fold_builtin_memcpy (tree exp) NULL_TREE if no simplification can be made. */ static tree -fold_builtin_mempcpy (tree exp) +fold_builtin_mempcpy (tree arglist, tree type, int endp) { - tree arglist = TREE_OPERAND (exp, 1); - tree dest, src, len; - - if (!validate_arglist (arglist, - POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; + if (validate_arglist (arglist, + POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) + { + tree dest = TREE_VALUE (arglist); + tree src = TREE_VALUE (TREE_CHAIN (arglist)); + tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); - len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + /* If the LEN parameter is zero, return DEST. */ + if (integer_zerop (len)) + return omit_one_operand (type, dest, src); - /* If the LEN parameter is zero, return DEST. */ - if (integer_zerop (len)) - return omit_one_operand (TREE_TYPE (exp), dest, src); + /* If SRC and DEST are the same (and not volatile), return DEST+LEN. */ + if (operand_equal_p (src, dest, 0)) + { + if (endp == 0) + return omit_one_operand (type, dest, len); - /* If SRC and DEST are the same (and not volatile), return DEST+LEN. */ - if (operand_equal_p (src, dest, 0)) - { - tree temp = fold_convert (TREE_TYPE (dest), len); - temp = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp)); - return fold_convert (TREE_TYPE (exp), temp); + if (endp == 2) + len = fold (build2 (MINUS_EXPR, TREE_TYPE (len), len, + ssize_int (1))); + + len = fold_convert (TREE_TYPE (dest), len); + len = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len)); + return fold_convert (type, len); + } } - return 0; } @@ -7614,13 +7603,12 @@ fold_builtin_unordered_cmp (tree exp, tree type = TREE_TYPE (TREE_TYPE (fndecl)); enum tree_code code; tree arg0, arg1; + tree type0, type1; + enum tree_code code0, code1; + tree cmp_type = NULL_TREE; if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) { - enum tree_code code0, code1; - tree type0, type1; - tree cmp_type = 0; - /* Check that we have exactly two arguments. */ if (arglist == 0 || TREE_CHAIN (arglist) == 0) { @@ -7634,39 +7622,34 @@ fold_builtin_unordered_cmp (tree exp, IDENTIFIER_POINTER (DECL_NAME (fndecl))); return error_mark_node; } - - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); - - type0 = TREE_TYPE (arg0); - type1 = TREE_TYPE (arg1); - - code0 = TREE_CODE (type0); - code1 = TREE_CODE (type1); - - if (code0 == REAL_TYPE && code1 == REAL_TYPE) - /* Choose the wider of two real types. */ - cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1) - ? type0 : type1; - else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE) - cmp_type = type0; - else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE) - cmp_type = type1; - else - { - error ("non-floating-point argument to function %qs", - IDENTIFIER_POINTER (DECL_NAME (fndecl))); - return error_mark_node; - } - - arg0 = fold_convert (cmp_type, arg0); - arg1 = fold_convert (cmp_type, arg1); } + + arg0 = TREE_VALUE (arglist); + arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + + type0 = TREE_TYPE (arg0); + type1 = TREE_TYPE (arg1); + + code0 = TREE_CODE (type0); + code1 = TREE_CODE (type1); + + if (code0 == REAL_TYPE && code1 == REAL_TYPE) + /* Choose the wider of two real types. */ + cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1) + ? type0 : type1; + else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE) + cmp_type = type0; + else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE) + cmp_type = type1; else { - arg0 = TREE_VALUE (arglist); - arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + error ("non-floating-point argument to function %qs", + IDENTIFIER_POINTER (DECL_NAME (fndecl))); + return error_mark_node; } + + arg0 = fold_convert (cmp_type, arg0); + arg1 = fold_convert (cmp_type, arg1); if (unordered_code == UNORDERED_EXPR) { @@ -7964,7 +7947,7 @@ fold_builtin_1 (tree exp, bool ignore) return fold_builtin_memcpy (exp); case BUILT_IN_MEMPCPY: - return fold_builtin_mempcpy (exp); + return fold_builtin_mempcpy (arglist, type, /*endp=*/1); case BUILT_IN_MEMMOVE: return fold_builtin_memmove (arglist, type);