From: Richard Henderson Date: Sat, 10 Jul 2004 01:52:53 +0000 (-0700) Subject: builtins.c (std_gimplify_va_arg_expr): Deny ARGS_GROW_DOWNWARD. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e4d3eef11d6ed460db6aa66fea489bd3e0c9f577;p=gcc.git builtins.c (std_gimplify_va_arg_expr): Deny ARGS_GROW_DOWNWARD. * builtins.c (std_gimplify_va_arg_expr): Deny ARGS_GROW_DOWNWARD. Always align upward to arg boundary. Use size_in_bytes/round_up. Maintain type-correctness of constants. * stor-layout.c (round_up, round_down): Special-case powers of 2. From-SVN: r84430 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a7d6eaab1c6..d99487d7213 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2004-07-09 Richard Henderson + + * builtins.c (std_gimplify_va_arg_expr): Deny ARGS_GROW_DOWNWARD. + Always align upward to arg boundary. Use size_in_bytes/round_up. + Maintain type-correctness of constants. + * stor-layout.c (round_up, round_down): Special-case powers of 2. + 2004-07-09 David S. Miller * config/sparc/sparc.c (*_costs): Scale instruction costs diff --git a/gcc/builtins.c b/gcc/builtins.c index a17a337ec01..dd39967de6a 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -4473,72 +4473,61 @@ expand_builtin_va_arg (tree valist, tree type) tree std_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p) { - tree addr, t, type_size = NULL; - tree align, alignm1, malign; - tree rounded_size; - tree valist_tmp; - HOST_WIDE_INT boundary; + tree addr, t, type_size, rounded_size, valist_tmp; + unsigned int align, boundary; + +#ifdef ARGS_GROW_DOWNWARD + /* All of the alignment and movement below is for args-grow-up machines. + As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all + implement their own specialized gimplify_va_arg_expr routines. */ + abort (); +#endif /* Compute the rounded size of the type. */ - align = size_int (PARM_BOUNDARY / BITS_PER_UNIT); - alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1); - malign = size_int (-(PARM_BOUNDARY / BITS_PER_UNIT)); + align = PARM_BOUNDARY / BITS_PER_UNIT; boundary = FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), type); + /* Hoist the valist value into a temporary for the moment. */ valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL); /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually requires greater alignment, we must perform dynamic alignment. */ - if (boundary > PARM_BOUNDARY) { - if (!PAD_VARARGS_DOWN) - { - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, - build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, - build_int_2 (boundary / BITS_PER_UNIT - 1, 0))); - gimplify_and_add (t, pre_p); - } + unsigned byte_bound = boundary / BITS_PER_UNIT; + + t = fold_convert (TREE_TYPE (valist), size_int (byte_bound - 1)); t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, - build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, - build_int_2 (~(boundary / BITS_PER_UNIT - 1), -1))); + build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t)); + gimplify_and_add (t, pre_p); + + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, + build2 (BIT_AND_EXPR, TREE_TYPE (valist), valist_tmp, t)); gimplify_and_add (t, pre_p); - } - if (type == error_mark_node - || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL - || TREE_OVERFLOW (type_size)) - rounded_size = size_zero_node; - else - { - rounded_size = fold (build2 (PLUS_EXPR, sizetype, type_size, alignm1)); - rounded_size = fold (build2 (BIT_AND_EXPR, sizetype, - rounded_size, malign)); } + type_size = size_in_bytes (type); + rounded_size = round_up (type_size, align); + /* Reduce rounded_size so it's sharable with the postqueue. */ gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue); /* Get AP. */ addr = valist_tmp; - if (PAD_VARARGS_DOWN && ! integer_zerop (rounded_size)) + if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size)) { /* Small args are padded downward. */ - addr = fold (build2 (PLUS_EXPR, TREE_TYPE (addr), addr, - fold (build3 (COND_EXPR, sizetype, - fold (build2 (GT_EXPR, sizetype, - rounded_size, - align)), - size_zero_node, - fold (build2 (MINUS_EXPR, - sizetype, - rounded_size, - type_size)))))); + t = fold (build2 (GT_EXPR, sizetype, rounded_size, size_int (align))); + t = fold (build3 (COND_EXPR, sizetype, t, size_zero_node, + size_binop (MINUS_EXPR, rounded_size, type_size))); + t = fold_convert (TREE_TYPE (addr), t); + addr = build2 (PLUS_EXPR, TREE_TYPE (addr), addr, t); } /* Compute new value for AP. */ - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, - fold (build2 (PLUS_EXPR, TREE_TYPE (valist), - valist_tmp, rounded_size))); + t = fold_convert (TREE_TYPE (valist), rounded_size); + t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist_tmp, t); + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); gimplify_and_add (t, pre_p); addr = fold_convert (build_pointer_type (type), addr); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index cf97159b5c5..689768536af 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -274,9 +274,24 @@ get_mode_alignment (enum machine_mode mode) tree round_up (tree value, int divisor) { - tree arg = size_int_type (divisor, TREE_TYPE (value)); + tree t; + + /* If divisor is a power of two, simplify this to bit manipulation. */ + if (divisor == (divisor & -divisor)) + { + t = size_int_type (divisor - 1, TREE_TYPE (value)); + value = size_binop (PLUS_EXPR, value, t); + t = size_int_type (-divisor, TREE_TYPE (value)); + value = size_binop (BIT_AND_EXPR, value, t); + } + else + { + t = size_int_type (divisor, TREE_TYPE (value)); + value = size_binop (CEIL_DIV_EXPR, value, t); + value = size_binop (MULT_EXPR, value, t); + } - return size_binop (MULT_EXPR, size_binop (CEIL_DIV_EXPR, value, arg), arg); + return value; } /* Likewise, but round down. */ @@ -284,9 +299,22 @@ round_up (tree value, int divisor) tree round_down (tree value, int divisor) { - tree arg = size_int_type (divisor, TREE_TYPE (value)); + tree t; + + /* If divisor is a power of two, simplify this to bit manipulation. */ + if (divisor == (divisor & -divisor)) + { + t = size_int_type (-divisor, TREE_TYPE (value)); + value = size_binop (BIT_AND_EXPR, value, t); + } + else + { + t = size_int_type (divisor, TREE_TYPE (value)); + value = size_binop (FLOOR_DIV_EXPR, value, t); + value = size_binop (MULT_EXPR, value, t); + } - return size_binop (MULT_EXPR, size_binop (FLOOR_DIV_EXPR, value, arg), arg); + return value; } /* Subroutine of layout_decl: Force alignment required for the data type.