From ad50bc8d803c56fc9ec9a81b70877e74d61c7c14 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 22 Dec 2004 10:51:24 -0800 Subject: [PATCH] [multiple changes] 2004-12-22 Richard Kenner * trans.c (mark_visited): Set TYPE_SIZES_GIMPLIFIED. 2004-12-22 Richard Kenner * tree.h (TYPE_SIZES_GIMPLIFIED): New. * function.c (gimplify_parm_type): Don't gimplify type if already done. * gimplify.c (gimplify_decl_expr): Likewise. (gimplify_type_sizes): Set TYPE_SIZES_GIMPLIFIED. Examine nested array types. 2004-12-22 Richard Henderson * gimplify.c (eval_save_expr): Remove. (gimplify_one_sizepos): Unshare expr before gimplifying. * stor-layout.c (variable_size): Revert 2004-12-19 change. (layout_decl): Revert 2004-12-18 change. (layout_type): Revert 2004-12-21 change. From-SVN: r92495 --- gcc/ChangeLog | 16 +++++++++++++ gcc/ada/ChangeLog | 4 ++++ gcc/ada/trans.c | 10 ++++++--- gcc/function.c | 3 ++- gcc/gimplify.c | 57 +++++++++++++++++++++++++++++++---------------- gcc/stor-layout.c | 18 +++++---------- gcc/tree.h | 5 +++++ 7 files changed, 77 insertions(+), 36 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9d04f8bdf3b..b2e063b8370 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2004-12-22 Richard Kenner + + * tree.h (TYPE_SIZES_GIMPLIFIED): New. + * function.c (gimplify_parm_type): Don't gimplify type if already done. + * gimplify.c (gimplify_decl_expr): Likewise. + (gimplify_type_sizes): Set TYPE_SIZES_GIMPLIFIED. Examine nested + array types. + +2004-12-22 Richard Henderson + + * gimplify.c (eval_save_expr): Remove. + (gimplify_one_sizepos): Unshare expr before gimplifying. + * stor-layout.c (variable_size): Revert 2004-12-19 change. + (layout_decl): Revert 2004-12-18 change. + (layout_type): Revert 2004-12-21 change. + 2004-12-22 Richard Kenner * tree-sra.c (type_can_be_decomposed_p): Reject variable sized types. diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 1676f35bb87..479443a6fb9 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2004-12-22 Richard Kenner + + * trans.c (mark_visited): Set TYPE_SIZES_GIMPLIFIED. + 2004-12-19 Richard Henderson * trans.c (gigi): Update gimplify_body call. diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c index e3d5f47e023..0db17093811 100644 --- a/gcc/ada/trans.c +++ b/gcc/ada/trans.c @@ -4283,9 +4283,10 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity) } } -/* Utility function to mark nodes with TREE_VISITED. Called from walk_tree. - We use this to indicate all variable sizes and positions in global types - may not be shared by any subprogram. */ +/* Utility function to mark nodes with TREE_VISITED and types as having their + sized gimplified. Called from walk_tree. We use this to indicate all + variable sizes and positions in global types may not be shared by any + subprogram. */ static tree mark_visited (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) @@ -4298,6 +4299,9 @@ mark_visited (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) else if (!TYPE_IS_DUMMY_P (*tp)) TREE_VISITED (*tp) = 1; + if (TYPE_P (*tp)) + TYPE_SIZES_GIMPLIFIED (*tp) = 1; + return NULL_TREE; } diff --git a/gcc/function.c b/gcc/function.c index a7dc2236bf6..4f1af4f331d 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3172,7 +3172,8 @@ gimplify_parm_type (tree *tp, int *walk_subtrees, void *data) { if (POINTER_TYPE_P (t)) *walk_subtrees = 1; - else if (TYPE_SIZE (t) && !TREE_CONSTANT (TYPE_SIZE (t))) + else if (TYPE_SIZE (t) && !TREE_CONSTANT (TYPE_SIZE (t)) + && !TYPE_SIZES_GIMPLIFIED (t)) { gimplify_type_sizes (t, (tree *) data); *walk_subtrees = 1; diff --git a/gcc/gimplify.c b/gcc/gimplify.c index c92d9a5e4bc..2434a815c7c 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -996,7 +996,12 @@ gimplify_decl_expr (tree *stmt_p) of the emitted code: see mx_register_decls(). */ tree t, args, addr, ptr_type; - gimplify_type_sizes (TREE_TYPE (decl), stmt_p); + /* ??? We really shouldn't need to gimplify the type of the variable + since it already should have been done. But leave this here + for now to avoid disrupting too many things at once. */ + if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl))) + gimplify_type_sizes (TREE_TYPE (decl), stmt_p); + gimplify_one_sizepos (&DECL_SIZE (decl), stmt_p); gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), stmt_p); @@ -4180,7 +4185,17 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, void gimplify_type_sizes (tree type, tree *list_p) { - tree field; + tree field, t; + + /* Note that we do not check for TYPE_SIZES_GIMPLIFIED already set because + that's not supposed to happen on types where gimplifcation does anything. + We should assert that it isn't set, but we can indeed be called multiple + times on pointers. Unfortunately, this includes fat pointers which we + can't easily test for. We could pass TYPE down to gimplify_one_sizepos + and test there, but it doesn't seem worth it. */ + + /* We first do the main variant, then copy into any other variants. */ + type = TYPE_MAIN_VARIANT (type); switch (TREE_CODE (type)) { @@ -4194,11 +4209,22 @@ gimplify_type_sizes (tree type, tree *list_p) case REAL_TYPE: gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p); gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p); + + for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) + { + TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type); + TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type); + TYPE_SIZES_GIMPLIFIED (t) = 1; + } break; case ARRAY_TYPE: - /* These anonymous types don't have declarations, so handle them here. */ - gimplify_type_sizes (TYPE_DOMAIN (type), list_p); + /* These types may not have declarations, so handle them here. */ + if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (type))) + gimplify_type_sizes (TREE_TYPE (type), list_p); + + if (!TYPE_SIZES_GIMPLIFIED (TYPE_DOMAIN (type))) + gimplify_type_sizes (TYPE_DOMAIN (type), list_p); break; case RECORD_TYPE: @@ -4215,23 +4241,15 @@ gimplify_type_sizes (tree type, tree *list_p) gimplify_one_sizepos (&TYPE_SIZE (type), list_p); gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p); -} -/* A subroutine of gimplify_one_sizepos, called via walk_tree. Evaluate - the expression if it's a SAVE_EXPR and add it to the statement list - in DATA. */ - -static tree -eval_save_expr (tree *tp, int *walk_subtrees, void *data) -{ - if (TREE_CODE (*tp) == SAVE_EXPR) + for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) { - *walk_subtrees = 0; - gimplify_and_add (*tp, (tree *) data); + TYPE_SIZE (t) = TYPE_SIZE (type); + TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type); + TYPE_SIZES_GIMPLIFIED (t) = 1; } - else if (TYPE_P (*tp) || DECL_P (*tp)) - *walk_subtrees = 0; - return NULL; + + TYPE_SIZES_GIMPLIFIED (type) = 1; } /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P, @@ -4251,7 +4269,8 @@ gimplify_one_sizepos (tree *expr_p, tree *stmt_p) || CONTAINS_PLACEHOLDER_P (*expr_p)) return; - walk_tree (expr_p, eval_save_expr, stmt_p, NULL); + *expr_p = unshare_expr (*expr_p); + gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue); } #ifdef ENABLE_CHECKING diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 13fdb3cf14c..ac7fb744f66 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -125,19 +125,11 @@ variable_size (tree size) just return SIZE unchanged. Likewise for self-referential sizes and constant sizes. */ if (TREE_CONSTANT (size) - || TREE_CODE (size) == SAVE_EXPR || lang_hooks.decls.global_bindings_p () < 0 || CONTAINS_PLACEHOLDER_P (size)) return size; - /* Force creation of a SAVE_EXPR. This solves (1) code duplication - problems between parent and nested functions that occasionally can't - be cleaned up because of portions of the expression escaping the - parent function via the FRAME object, and (2) tree sharing problems - between the type system and the gimple code, which can leak SSA_NAME - objects into e.g. TYPE_SIZE, which cause heartburn when emitting - debug information. */ - size = build1 (SAVE_EXPR, TREE_TYPE (size), size); + size = save_expr (size); /* If an array with a variable number of elements is declared, and the elements require destruction, we will emit a cleanup for the @@ -333,8 +325,8 @@ layout_decl (tree decl, unsigned int known_align) if (DECL_SIZE (decl) == 0) { - DECL_SIZE (decl) = unshare_expr (TYPE_SIZE (type)); - DECL_SIZE_UNIT (decl) = unshare_expr (TYPE_SIZE_UNIT (type)); + DECL_SIZE (decl) = TYPE_SIZE (type); + DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type); } else if (DECL_SIZE_UNIT (decl) == 0) DECL_SIZE_UNIT (decl) @@ -1644,8 +1636,8 @@ layout_type (tree type) if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index) && TYPE_SIZE (element)) { - tree ub = unshare_expr (TYPE_MAX_VALUE (index)); - tree lb = unshare_expr (TYPE_MIN_VALUE (index)); + tree ub = TYPE_MAX_VALUE (index); + tree lb = TYPE_MIN_VALUE (index); tree length; tree element_size; diff --git a/gcc/tree.h b/gcc/tree.h index f70683ccd54..76424a5c6b9 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -368,6 +368,8 @@ struct tree_common GTY(()) all expressions all decls all constants + TYPE_SIZES_GIMPLIFIED + ..._TYPE unsigned_flag: @@ -934,6 +936,9 @@ extern void tree_operand_check_failed (int, enum tree_code, also appear in an expression or decl where the value is constant. */ #define TREE_CONSTANT(NODE) (NON_TYPE_CHECK (NODE)->common.constant_flag) +/* Nonzero if NODE, a type, has had its sizes gimplified. */ +#define TYPE_SIZES_GIMPLIFIED(NODE) (TYPE_CHECK (NODE)->common.constant_flag) + /* In a decl (most significantly a FIELD_DECL), means an unsigned field. */ #define DECL_UNSIGNED(NODE) (DECL_CHECK (NODE)->common.unsigned_flag)