summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/ada/ChangeLog4
-rw-r--r--gcc/ada/trans.c10
-rw-r--r--gcc/function.c3
-rw-r--r--gcc/gimplify.c57
-rw-r--r--gcc/stor-layout.c18
-rw-r--r--gcc/tree.h5
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,5 +1,21 @@
2004-12-22 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * 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 <rth@redhat.com>
+
+ * 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 <kenner@vlsi1.ultra.nyu.edu>
+
* tree-sra.c (type_can_be_decomposed_p): Reject variable sized types.
2004-12-22 Mark Mitchell <mark@codesourcery.com>
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 <kenner@vlsi1.ultra.nyu.edu>
+
+ * trans.c (mark_visited): Set TYPE_SIZES_GIMPLIFIED.
+
2004-12-19 Richard Henderson <rth@redhat.com>
* 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)