{
void **slot;
gimple_type_leader_entry *leader;
- tree mv_leader;
/* If we registered this type before return the cached result. */
leader = &gimple_type_leader[TYPE_UID (t) % GIMPLE_TYPE_LEADER_SIZE];
case we do not care for the main variant leader. */
if (!registering_mv
&& TYPE_MAIN_VARIANT (t) != t)
- mv_leader = gimple_register_type_1 (TYPE_MAIN_VARIANT (t), true);
- else
- mv_leader = t;
+ gimple_register_type_1 (TYPE_MAIN_VARIANT (t), true);
+ /* See if we already have an equivalent type registered. */
slot = htab_find_slot (gimple_types, t, INSERT);
if (*slot
&& *(tree *)slot != t)
{
tree new_type = (tree) *((tree *) slot);
-
- /* Do not merge types with different addressability. */
- gcc_assert (TREE_ADDRESSABLE (t) == TREE_ADDRESSABLE (new_type));
-
- /* If t is not its main variant then make t unreachable from its
- main variant list. Otherwise we'd queue up a lot of duplicates
- there. */
- if (t != TYPE_MAIN_VARIANT (t))
- {
- tree tem = TYPE_MAIN_VARIANT (t);
- while (tem && TYPE_NEXT_VARIANT (tem) != t)
- tem = TYPE_NEXT_VARIANT (tem);
- if (tem)
- TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
- TYPE_NEXT_VARIANT (t) = NULL_TREE;
- }
-
- /* If we are a pointer then remove us from the pointer-to or
- reference-to chain. Otherwise we'd queue up a lot of duplicates
- there. */
- if (TREE_CODE (t) == POINTER_TYPE)
- {
- if (TYPE_POINTER_TO (TREE_TYPE (t)) == t)
- TYPE_POINTER_TO (TREE_TYPE (t)) = TYPE_NEXT_PTR_TO (t);
- else
- {
- tree tem = TYPE_POINTER_TO (TREE_TYPE (t));
- while (tem && TYPE_NEXT_PTR_TO (tem) != t)
- tem = TYPE_NEXT_PTR_TO (tem);
- if (tem)
- TYPE_NEXT_PTR_TO (tem) = TYPE_NEXT_PTR_TO (t);
- }
- TYPE_NEXT_PTR_TO (t) = NULL_TREE;
- }
- else if (TREE_CODE (t) == REFERENCE_TYPE)
- {
- if (TYPE_REFERENCE_TO (TREE_TYPE (t)) == t)
- TYPE_REFERENCE_TO (TREE_TYPE (t)) = TYPE_NEXT_REF_TO (t);
- else
- {
- tree tem = TYPE_REFERENCE_TO (TREE_TYPE (t));
- while (tem && TYPE_NEXT_REF_TO (tem) != t)
- tem = TYPE_NEXT_REF_TO (tem);
- if (tem)
- TYPE_NEXT_REF_TO (tem) = TYPE_NEXT_REF_TO (t);
- }
- TYPE_NEXT_REF_TO (t) = NULL_TREE;
- }
-
leader->type = t;
leader->leader = new_type;
- t = new_type;
- }
- else
- {
- leader->type = t;
- leader->leader = t;
- /* We're the type leader. Make our TYPE_MAIN_VARIANT valid. */
- if (TYPE_MAIN_VARIANT (t) != t
- && TYPE_MAIN_VARIANT (t) != mv_leader)
- {
- /* Remove us from our main variant list as we are not the variant
- leader and the variant leader will change. */
- tree tem = TYPE_MAIN_VARIANT (t);
- while (tem && TYPE_NEXT_VARIANT (tem) != t)
- tem = TYPE_NEXT_VARIANT (tem);
- if (tem)
- TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
- TYPE_NEXT_VARIANT (t) = NULL_TREE;
- /* Adjust our main variant. Linking us into its variant list
- will happen at fixup time. */
- TYPE_MAIN_VARIANT (t) = mv_leader;
- }
- *slot = (void *) t;
+ return new_type;
}
+ /* If not, insert it to the cache and the hash. */
+ leader->type = t;
+ leader->leader = t;
+ *slot = (void *) t;
return t;
}
static void
lto_ft_common (tree t)
{
- /* The following re-creates the TYPE_REFERENCE_TO and TYPE_POINTER_TO
- lists. We do not stream TYPE_REFERENCE_TO, TYPE_POINTER_TO or
- TYPE_NEXT_PTR_TO and TYPE_NEXT_REF_TO.
- First remove us from any pointer list we are on. */
- if (TREE_CODE (t) == POINTER_TYPE)
- {
- if (TYPE_POINTER_TO (TREE_TYPE (t)) == t)
- TYPE_POINTER_TO (TREE_TYPE (t)) = TYPE_NEXT_PTR_TO (t);
- else
- {
- tree tem = TYPE_POINTER_TO (TREE_TYPE (t));
- while (tem && TYPE_NEXT_PTR_TO (tem) != t)
- tem = TYPE_NEXT_PTR_TO (tem);
- if (tem)
- TYPE_NEXT_PTR_TO (tem) = TYPE_NEXT_PTR_TO (t);
- }
- TYPE_NEXT_PTR_TO (t) = NULL_TREE;
- }
- else if (TREE_CODE (t) == REFERENCE_TYPE)
- {
- if (TYPE_REFERENCE_TO (TREE_TYPE (t)) == t)
- TYPE_REFERENCE_TO (TREE_TYPE (t)) = TYPE_NEXT_REF_TO (t);
- else
- {
- tree tem = TYPE_REFERENCE_TO (TREE_TYPE (t));
- while (tem && TYPE_NEXT_REF_TO (tem) != t)
- tem = TYPE_NEXT_REF_TO (tem);
- if (tem)
- TYPE_NEXT_REF_TO (tem) = TYPE_NEXT_REF_TO (t);
- }
- TYPE_NEXT_REF_TO (t) = NULL_TREE;
- }
-
/* Fixup our type. */
LTO_FIXUP_TREE (TREE_TYPE (t));
- /* Second put us on the list of pointers of the new pointed-to type
- if we are a main variant. This is done in lto_ft_type after
- fixing up our main variant. */
LTO_FIXUP_TREE (TREE_CHAIN (t));
}
static void
lto_ft_type (tree t)
{
- tree tem, mv;
-
lto_ft_common (t);
LTO_FIXUP_TREE (TYPE_CACHED_VALUES (t));
LTO_FIXUP_TREE (TYPE_SIZE (t));
LTO_FIXUP_TREE (t->type_non_common.binfo);
LTO_FIXUP_TREE (TYPE_CONTEXT (t));
-
- /* Compute the canonical type of t and fix that up. From this point
- there are no longer any types with TYPE_STRUCTURAL_EQUALITY_P
- and its type-based alias problems. */
- if (!TYPE_CANONICAL (t))
- {
- TYPE_CANONICAL (t) = gimple_register_canonical_type (t);
- LTO_FIXUP_TREE (TYPE_CANONICAL (t));
- }
-
- /* The following re-creates proper variant lists while fixing up
- the variant leaders. We do not stream TYPE_NEXT_VARIANT so the
- variant list state before fixup is broken. */
-
- /* Remove us from our main variant list if we are not the variant leader. */
- if (TYPE_MAIN_VARIANT (t) != t)
- {
- tem = TYPE_MAIN_VARIANT (t);
- while (tem && TYPE_NEXT_VARIANT (tem) != t)
- tem = TYPE_NEXT_VARIANT (tem);
- if (tem)
- TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
- TYPE_NEXT_VARIANT (t) = NULL_TREE;
- }
-
- /* Query our new main variant. */
- mv = gimple_register_type (TYPE_MAIN_VARIANT (t));
-
- /* If we were the variant leader and we get replaced ourselves drop
- all variants from our list. */
- if (TYPE_MAIN_VARIANT (t) == t
- && mv != t)
- {
- tem = t;
- while (tem)
- {
- tree tem2 = TYPE_NEXT_VARIANT (tem);
- TYPE_NEXT_VARIANT (tem) = NULL_TREE;
- tem = tem2;
- }
- }
-
- /* Finally adjust our main variant and fix it up. */
- TYPE_MAIN_VARIANT (t) = mv;
- LTO_FIXUP_TREE (TYPE_MAIN_VARIANT (t));
-
- /* As the second step of reconstructing the pointer chains put us
- on the list of pointers of the new pointed-to type
- if we are a main variant. See lto_ft_common for the first step. */
- if (TREE_CODE (t) == POINTER_TYPE
- && TYPE_MAIN_VARIANT (t) == t)
- {
- TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t));
- TYPE_POINTER_TO (TREE_TYPE (t)) = t;
- }
- else if (TREE_CODE (t) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (t) == t)
- {
- TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t));
- TYPE_REFERENCE_TO (TREE_TYPE (t)) = t;
- }
}
/* Fix up fields of a BINFO T. */
/* Go backwards because childs streamed for the first time come
as part of their parents, and hence are created after them. */
+
+ /* First register all types in the cache.
+ This makes sure to have the original structure in the type cycles
+ when registering them and computing hashes. */
for (i = len; i-- > from;)
{
tree t = VEC_index (tree, cache->nodes, i);
- if (!t)
+ if (!t
+ || !TYPE_P (t))
continue;
- /* Now try to find a canonical variant of T itself. */
- if (TYPE_P (t))
- gimple_register_type (t);
+ gimple_register_type (t);
}
- /* Go backwards because childs streamed for the first time come
- as part of their parents, and hence are created after them. */
+ /* Second fixup all trees in the new cache entries. */
for (i = len; i-- > from;)
{
tree t = VEC_index (tree, cache->nodes, i);
/* First fixup the fields of T. */
lto_fixup_types (t);
+ if (!TYPE_P (t))
+ continue;
+
/* Now try to find a canonical variant of T itself. */
- if (TYPE_P (t))
+ t = gimple_register_type (t);
+
+ if (t == oldt)
{
- t = gimple_register_type (t);
- if (t == oldt
- && TYPE_MAIN_VARIANT (t) != t)
+ /* The following re-creates proper variant lists while fixing up
+ the variant leaders. We do not stream TYPE_NEXT_VARIANT so the
+ variant list state before fixup is broken. */
+ tree tem, mv;
+
+ /* Remove us from our main variant list if we are not the
+ variant leader. */
+ if (TYPE_MAIN_VARIANT (t) != t)
{
- /* If this is its own type, link it into the variant chain. */
- TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t));
- TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)) = t;
+ tem = TYPE_MAIN_VARIANT (t);
+ while (tem && TYPE_NEXT_VARIANT (tem) != t)
+ tem = TYPE_NEXT_VARIANT (tem);
+ if (tem)
+ TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
+ TYPE_NEXT_VARIANT (t) = NULL_TREE;
}
- }
- if (t != oldt)
- {
- if (RECORD_OR_UNION_TYPE_P (t))
+
+ /* Query our new main variant. */
+ mv = gimple_register_type (TYPE_MAIN_VARIANT (t));
+
+ /* If we were the variant leader and we get replaced ourselves drop
+ all variants from our list. */
+ if (TYPE_MAIN_VARIANT (t) == t
+ && mv != t)
{
- tree f1, f2;
- if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt))
- for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt);
- f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
- {
- unsigned ix;
- gcc_assert (f1 != f2 && DECL_NAME (f1) == DECL_NAME (f2));
- if (!lto_streamer_cache_lookup (cache, f2, &ix))
- gcc_unreachable ();
- /* If we're going to replace an element which we'd
- still visit in the next iterations, we wouldn't
- handle it, so do it here. We do have to handle it
- even though the field_decl itself will be removed,
- as it could refer to e.g. integer_cst which we
- wouldn't reach via any other way, hence they
- (and their type) would stay uncollected. */
- if (ix < i)
- lto_fixup_types (f2);
- lto_streamer_cache_insert_at (cache, f1, ix);
- }
+ tem = t;
+ while (tem)
+ {
+ tree tem2 = TYPE_NEXT_VARIANT (tem);
+ TYPE_NEXT_VARIANT (tem) = NULL_TREE;
+ tem = tem2;
+ }
+ }
+
+ /* If we are not our own variant leader link us into our new leaders
+ variant list. */
+ if (mv != t)
+ {
+ TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (mv);
+ TYPE_NEXT_VARIANT (mv) = t;
+ }
+
+ /* Finally adjust our main variant and fix it up. */
+ TYPE_MAIN_VARIANT (t) = mv;
+
+ /* The following reconstructs the pointer chains
+ of the new pointed-to type if we are a main variant. We do
+ not stream those so they are broken before fixup. */
+ if (TREE_CODE (t) == POINTER_TYPE
+ && TYPE_MAIN_VARIANT (t) == t)
+ {
+ TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t));
+ TYPE_POINTER_TO (TREE_TYPE (t)) = t;
+ }
+ else if (TREE_CODE (t) == REFERENCE_TYPE
+ && TYPE_MAIN_VARIANT (t) == t)
+ {
+ TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t));
+ TYPE_REFERENCE_TO (TREE_TYPE (t)) = t;
}
+ }
+
+ else if (RECORD_OR_UNION_TYPE_P (t))
+ {
+ tree f1, f2;
+ if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt))
+ for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt);
+ f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
+ {
+ unsigned ix;
+ gcc_assert (f1 != f2 && DECL_NAME (f1) == DECL_NAME (f2));
+ if (!lto_streamer_cache_lookup (cache, f2, &ix))
+ gcc_unreachable ();
+ /* If we're going to replace an element which we'd
+ still visit in the next iterations, we wouldn't
+ handle it, so do it here. We do have to handle it
+ even though the field_decl itself will be removed,
+ as it could refer to e.g. integer_cst which we
+ wouldn't reach via any other way, hence they
+ (and their type) would stay uncollected. */
+ /* ??? We should rather make sure to replace all
+ references to f2 with f1. That means handling
+ COMPONENT_REFs and CONSTRUCTOR elements in
+ lto_fixup_types and special-case the field-decl
+ operand handling. */
+ if (ix < i)
+ lto_fixup_types (f2);
+ lto_streamer_cache_insert_at (cache, f1, ix);
+ }
/* If we found a tree that is equal to oldt replace it in the
cache, so that further users (in the various LTO sections)
lto_streamer_cache_insert_at (cache, t, i);
}
}
+
+ /* Finally compute the canonical type of t. From this point
+ there are no longer any types with TYPE_STRUCTURAL_EQUALITY_P
+ and its type-based alias problems. This step requires the
+ TYPE_POINTER_TO lists being present, so make sure it is done
+ last. */
+ for (i = len; i-- > from;)
+ {
+ tree t = VEC_index (tree, cache->nodes, i);
+ if (!t
+ || !TYPE_P (t))
+ continue;
+
+ if (!TYPE_CANONICAL (t))
+ TYPE_CANONICAL (t) = gimple_register_canonical_type (t);
+ }
}
/* Read all the symbols from buffer DATA, using descriptors in DECL_DATA.