Commit 3c2a7a6a by Richard Henderson Committed by Richard Henderson

tree-inline.c (remap_type): New.

        * tree-inline.c (remap_type): New.
        (remap_decl): Use it.  Remap DECL_SIZE*.
        (copy_body_r): Use it.
        (walk_tree): Walk TREE_TYPE too.
        (copy_tree_r): Don't walk subtrees of types.
        * tree.c (variably_modified_type_p): Restructure.  Consider integer
        types with non-const bounds variably modified.

From-SVN: r72114
parent a2b172fb
2003-10-05 Richard Henderson <rth@redhat.com>
* tree-inline.c (remap_type): New.
(remap_decl): Use it. Remap DECL_SIZE*.
(copy_body_r): Use it.
(walk_tree): Walk TREE_TYPE too.
(copy_tree_r): Don't walk subtrees of types.
* tree.c (variably_modified_type_p): Restructure. Consider integer
types with non-const bounds variably modified.
2003-10-05 Kazu Hirata <kazu@cs.umass.edu> 2003-10-05 Kazu Hirata <kazu@cs.umass.edu>
* doc/invoke.texi: Fix typos. * doc/invoke.texi: Fix typos.
......
...@@ -121,6 +121,7 @@ static void expand_calls_inline (tree *, inline_data *); ...@@ -121,6 +121,7 @@ static void expand_calls_inline (tree *, inline_data *);
static bool inlinable_function_p (tree); static bool inlinable_function_p (tree);
static int limits_allow_inlining (tree, inline_data *); static int limits_allow_inlining (tree, inline_data *);
static tree remap_decl (tree, inline_data *); static tree remap_decl (tree, inline_data *);
static tree remap_type (tree, inline_data *);
#ifndef INLINER_FOR_JAVA #ifndef INLINER_FOR_JAVA
static tree initialize_inlined_parameters (inline_data *, tree, tree); static tree initialize_inlined_parameters (inline_data *, tree, tree);
static void remap_block (tree, tree, inline_data *); static void remap_block (tree, tree, inline_data *);
...@@ -146,6 +147,7 @@ remap_decl (tree decl, inline_data *id) ...@@ -146,6 +147,7 @@ remap_decl (tree decl, inline_data *id)
/* See if we have remapped this declaration. */ /* See if we have remapped this declaration. */
n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl); n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
/* If we didn't already have an equivalent for this declaration, /* If we didn't already have an equivalent for this declaration,
create one now. */ create one now. */
if (!n) if (!n)
...@@ -153,29 +155,26 @@ remap_decl (tree decl, inline_data *id) ...@@ -153,29 +155,26 @@ remap_decl (tree decl, inline_data *id)
tree t; tree t;
/* Make a copy of the variable or label. */ /* Make a copy of the variable or label. */
t = copy_decl_for_inlining (decl, fn, t = copy_decl_for_inlining (decl, fn, VARRAY_TREE (id->fns, 0));
VARRAY_TREE (id->fns, 0));
/* Remap types, if necessary. */
/* The decl T could be a dynamic array or other variable size type, TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
in which case some fields need to be remapped because they may if (TREE_CODE (t) == TYPE_DECL)
contain SAVE_EXPRs. */ DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id);
if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE else if (TREE_CODE (t) == PARM_DECL)
&& TYPE_DOMAIN (TREE_TYPE (t))) DECL_ARG_TYPE_AS_WRITTEN (t)
{ = remap_type (DECL_ARG_TYPE_AS_WRITTEN (t), id);
TREE_TYPE (t) = copy_node (TREE_TYPE (t));
TYPE_DOMAIN (TREE_TYPE (t)) /* Remap sizes as necessary. */
= copy_node (TYPE_DOMAIN (TREE_TYPE (t))); walk_tree (&DECL_SIZE (t), copy_body_r, id, NULL);
walk_tree (&TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (t))), walk_tree (&DECL_SIZE_UNIT (t), copy_body_r, id, NULL);
copy_body_r, id, NULL);
}
#ifndef INLINER_FOR_JAVA #ifndef INLINER_FOR_JAVA
if (! DECL_NAME (t) && TREE_TYPE (t) if (! DECL_NAME (t) && TREE_TYPE (t)
&& (*lang_hooks.tree_inlining.anon_aggr_type_p) (TREE_TYPE (t))) && (*lang_hooks.tree_inlining.anon_aggr_type_p) (TREE_TYPE (t)))
{ {
/* For a VAR_DECL of anonymous type, we must also copy the /* For a VAR_DECL of anonymous type, we must also copy the
member VAR_DECLS here and rechain the member VAR_DECLS here and rechain the DECL_ANON_UNION_ELEMS. */
DECL_ANON_UNION_ELEMS. */
tree members = NULL; tree members = NULL;
tree src; tree src;
...@@ -202,6 +201,111 @@ remap_decl (tree decl, inline_data *id) ...@@ -202,6 +201,111 @@ remap_decl (tree decl, inline_data *id)
return (tree) n->value; return (tree) n->value;
} }
static tree
remap_type (tree type, inline_data *id)
{
splay_tree_node node;
tree new, t;
if (type == NULL)
return type;
/* See if we have remapped this type. */
node = splay_tree_lookup (id->decl_map, (splay_tree_key) type);
if (node)
return (tree) node->value;
/* The type only needs remapping if it's variably modified. */
if (! variably_modified_type_p (type))
{
splay_tree_insert (id->decl_map, (splay_tree_key) type,
(splay_tree_value) type);
return type;
}
/* We do need a copy. build and register it now. */
new = copy_node (type);
splay_tree_insert (id->decl_map, (splay_tree_key) type,
(splay_tree_value) new);
/* This is a new type, not a copy of an old type. Need to reassociate
variants. We can handle everything except the main variant lazily. */
t = TYPE_MAIN_VARIANT (type);
if (type != t)
{
t = remap_type (t, id);
TYPE_MAIN_VARIANT (new) = t;
TYPE_NEXT_VARIANT (new) = TYPE_MAIN_VARIANT (t);
TYPE_NEXT_VARIANT (t) = new;
}
else
{
TYPE_MAIN_VARIANT (new) = new;
TYPE_NEXT_VARIANT (new) = NULL;
}
/* Lazily create pointer and reference types. */
TYPE_POINTER_TO (new) = NULL;
TYPE_REFERENCE_TO (new) = NULL;
switch (TREE_CODE (new))
{
case INTEGER_TYPE:
case REAL_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
case CHAR_TYPE:
t = TYPE_MIN_VALUE (new);
if (t && TREE_CODE (t) != INTEGER_CST)
walk_tree (&TYPE_MIN_VALUE (new), copy_body_r, id, NULL);
t = TYPE_MAX_VALUE (new);
if (t && TREE_CODE (t) != INTEGER_CST)
walk_tree (&TYPE_MAX_VALUE (new), copy_body_r, id, NULL);
return new;
case POINTER_TYPE:
TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id);
if (TYPE_MODE (new) == ptr_mode)
TYPE_POINTER_TO (t) = new;
return new;
case REFERENCE_TYPE:
TREE_TYPE (new) = t = remap_type (TREE_TYPE (new), id);
if (TYPE_MODE (new) == ptr_mode)
TYPE_REFERENCE_TO (t) = new;
return new;
case METHOD_TYPE:
case FUNCTION_TYPE:
TREE_TYPE (new) = remap_type (TREE_TYPE (new), id);
walk_tree (&TYPE_ARG_TYPES (new), copy_body_r, id, NULL);
return new;
case ARRAY_TYPE:
TREE_TYPE (new) = remap_type (TREE_TYPE (new), id);
TYPE_DOMAIN (new) = remap_type (TYPE_DOMAIN (new), id);
break;
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
walk_tree (&TYPE_FIELDS (new), copy_body_r, id, NULL);
break;
case FILE_TYPE:
case SET_TYPE:
case OFFSET_TYPE:
default:
/* Shouldn't have been thought variable sized. */
abort ();
}
walk_tree (&TYPE_SIZE (new), copy_body_r, id, NULL);
walk_tree (&TYPE_SIZE_UNIT (new), copy_body_r, id, NULL);
return new;
}
#ifndef INLINER_FOR_JAVA #ifndef INLINER_FOR_JAVA
/* Copy the SCOPE_STMT_BLOCK associated with SCOPE_STMT to contain /* Copy the SCOPE_STMT_BLOCK associated with SCOPE_STMT to contain
remapped versions of the variables therein. And hook the new block remapped versions of the variables therein. And hook the new block
...@@ -525,6 +629,10 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data) ...@@ -525,6 +629,10 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
TREE_OPERAND (*tp, 0) = (tree) n->value; TREE_OPERAND (*tp, 0) = (tree) n->value;
} }
#endif /* INLINER_FOR_JAVA */ #endif /* INLINER_FOR_JAVA */
/* Types may need remapping as well. */
else if (TYPE_P (*tp))
*tp = remap_type (*tp, id);
/* Otherwise, just copy the node. Note that copy_tree_r already /* Otherwise, just copy the node. Note that copy_tree_r already
knows not to copy VAR_DECLs, etc., so this is safe. */ knows not to copy VAR_DECLs, etc., so this is safe. */
else else
...@@ -576,6 +684,8 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data) ...@@ -576,6 +684,8 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
copy_tree_r (tp, walk_subtrees, NULL); copy_tree_r (tp, walk_subtrees, NULL);
TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id);
/* The copied TARGET_EXPR has never been expanded, even if the /* The copied TARGET_EXPR has never been expanded, even if the
original node was expanded already. */ original node was expanded already. */
if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3)) if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3))
...@@ -1787,6 +1897,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_) ...@@ -1787,6 +1897,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
WALK_SUBTREE (DECL_INITIAL (DECL_STMT_DECL (*tp))); WALK_SUBTREE (DECL_INITIAL (DECL_STMT_DECL (*tp)));
WALK_SUBTREE (DECL_SIZE (DECL_STMT_DECL (*tp))); WALK_SUBTREE (DECL_SIZE (DECL_STMT_DECL (*tp)));
WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp))); WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp)));
WALK_SUBTREE (TREE_TYPE (*tp));
} }
/* This can be tail-recursion optimized if we write it this way. */ /* This can be tail-recursion optimized if we write it this way. */
...@@ -1968,8 +2079,7 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) ...@@ -1968,8 +2079,7 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
TREE_CHAIN (*tp) = chain; TREE_CHAIN (*tp) = chain;
#endif /* INLINER_FOR_JAVA */ #endif /* INLINER_FOR_JAVA */
} }
else if (TREE_CODE_CLASS (code) == 't' && !variably_modified_type_p (*tp)) else if (TREE_CODE_CLASS (code) == 't')
/* Types only need to be copied if they are variably modified. */
*walk_subtrees = 0; *walk_subtrees = 0;
return NULL_TREE; return NULL_TREE;
......
...@@ -4273,6 +4273,8 @@ int_fits_type_p (tree c, tree type) ...@@ -4273,6 +4273,8 @@ int_fits_type_p (tree c, tree type)
bool bool
variably_modified_type_p (tree type) variably_modified_type_p (tree type)
{ {
tree t;
if (type == error_mark_node) if (type == error_mark_node)
return false; return false;
...@@ -4281,39 +4283,50 @@ variably_modified_type_p (tree type) ...@@ -4281,39 +4283,50 @@ variably_modified_type_p (tree type)
We do not yet have a representation of the C99 '[*]' syntax. We do not yet have a representation of the C99 '[*]' syntax.
When a representation is chosen, this function should be modified When a representation is chosen, this function should be modified
to test for that case as well. */ to test for that case as well. */
if (TYPE_SIZE (type) t = TYPE_SIZE (type);
&& TYPE_SIZE (type) != error_mark_node if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
&& TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
return true; return true;
/* If TYPE is a pointer or reference, it is variably modified if switch (TREE_CODE (type))
the type pointed to is variably modified. */ {
if ((TREE_CODE (type) == POINTER_TYPE case POINTER_TYPE:
|| TREE_CODE (type) == REFERENCE_TYPE) case REFERENCE_TYPE:
&& variably_modified_type_p (TREE_TYPE (type))) case ARRAY_TYPE:
return true; /* If TYPE is a pointer or reference, it is variably modified if
the type pointed to is variably modified. Similarly for arrays;
note that VLAs are handled by the TYPE_SIZE check above. */
return variably_modified_type_p (TREE_TYPE (type));
/* If TYPE is an array, it is variably modified if the array case FUNCTION_TYPE:
elements are. (Note that the VLA case has already been checked case METHOD_TYPE:
above.) */ /* If TYPE is a function type, it is variably modified if any of the
if (TREE_CODE (type) == ARRAY_TYPE parameters or the return type are variably modified. */
&& variably_modified_type_p (TREE_TYPE (type))) {
return true; tree parm;
/* If TYPE is a function type, it is variably modified if any of the if (variably_modified_type_p (TREE_TYPE (type)))
parameters or the return type are variably modified. */ return true;
if (TREE_CODE (type) == FUNCTION_TYPE for (parm = TYPE_ARG_TYPES (type);
|| TREE_CODE (type) == METHOD_TYPE) parm && parm != void_list_node;
{ parm = TREE_CHAIN (parm))
tree parm; if (variably_modified_type_p (TREE_VALUE (parm)))
return true;
}
break;
if (variably_modified_type_p (TREE_TYPE (type))) case INTEGER_TYPE:
/* Scalar types are variably modified if their end points
aren't constant. */
t = TYPE_MIN_VALUE (type);
if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
return true; return true;
for (parm = TYPE_ARG_TYPES (type); t = TYPE_MAX_VALUE (type);
parm && parm != void_list_node; if (t && t != error_mark_node && TREE_CODE (t) != INTEGER_CST)
parm = TREE_CHAIN (parm)) return true;
if (variably_modified_type_p (TREE_VALUE (parm))) return false;
return true;
default:
break;
} }
/* The current language may have other cases to check, but in general, /* The current language may have other cases to check, but in general,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment