aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r--gcc/gimple.c461
1 files changed, 244 insertions, 217 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 29eec519b7d..f725a347bac 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -46,6 +46,7 @@ static struct pointer_map_t *type_hash_cache;
/* Global type comparison cache. */
static htab_t gtc_visited;
+static struct obstack gtc_ob;
/* All the tuples have their operand vector (if present) at the very bottom
of the structure. Therefore, the offset required to find the
@@ -3025,8 +3026,8 @@ static hashval_t gimple_type_hash (const void *);
infinite recursion due to self-referential types. */
struct type_pair_d
{
- tree t1;
- tree t2;
+ unsigned int uid1;
+ unsigned int uid2;
int same_p;
};
typedef struct type_pair_d *type_pair_t;
@@ -3037,8 +3038,8 @@ static hashval_t
type_pair_hash (const void *p)
{
const struct type_pair_d *pair = (const struct type_pair_d *) p;
- hashval_t val1 = iterative_hash_hashval_t (htab_hash_pointer (pair->t1), 0);
- hashval_t val2 = iterative_hash_hashval_t (htab_hash_pointer (pair->t2), 0);
+ hashval_t val1 = pair->uid1;
+ hashval_t val2 = pair->uid2;
return (iterative_hash_hashval_t (val2, val1)
^ iterative_hash_hashval_t (val1, val2));
}
@@ -3050,34 +3051,37 @@ type_pair_eq (const void *p1, const void *p2)
{
const struct type_pair_d *pair1 = (const struct type_pair_d *) p1;
const struct type_pair_d *pair2 = (const struct type_pair_d *) p2;
- return ((pair1->t1 == pair2->t1 && pair1->t2 == pair2->t2)
- || (pair1->t1 == pair2->t2 && pair1->t2 == pair2->t1));
+ return ((pair1->uid1 == pair2->uid1 && pair1->uid2 == pair2->uid2)
+ || (pair1->uid1 == pair2->uid2 && pair1->uid2 == pair2->uid1));
}
/* Lookup the pair of types T1 and T2 in *VISITED_P. Insert a new
entry if none existed. */
static type_pair_t
-lookup_type_pair (tree t1, tree t2, htab_t *visited_p)
+lookup_type_pair (tree t1, tree t2, htab_t *visited_p, struct obstack *ob_p)
{
struct type_pair_d pair;
type_pair_t p;
void **slot;
if (*visited_p == NULL)
- *visited_p = htab_create (251, type_pair_hash, type_pair_eq, free);
+ {
+ *visited_p = htab_create (251, type_pair_hash, type_pair_eq, NULL);
+ gcc_obstack_init (ob_p);
+ }
- pair.t1 = t1;
- pair.t2 = t2;
+ pair.uid1 = TYPE_UID (t1);
+ pair.uid2 = TYPE_UID (t2);
slot = htab_find_slot (*visited_p, &pair, INSERT);
if (*slot)
p = *((type_pair_t *) slot);
else
{
- p = XNEW (struct type_pair_d);
- p->t1 = t1;
- p->t2 = t2;
+ p = XOBNEW (ob_p, struct type_pair_d);
+ p->uid1 = TYPE_UID (t1);
+ p->uid2 = TYPE_UID (t2);
p->same_p = -2;
*slot = (void *) p;
}
@@ -3086,62 +3090,38 @@ lookup_type_pair (tree t1, tree t2, htab_t *visited_p)
}
-/* Force merging the type T2 into the type T1. */
-
-void
-gimple_force_type_merge (tree t1, tree t2)
-{
- void **slot;
- type_pair_t p;
-
- /* There's no other way than copying t2 to t1 in this case.
- Yuck. We'll just call this "completing" t1. */
- memcpy (t1, t2, tree_size (t1));
-
- /* Adjust the hash value of T1 if it was computed already. Otherwise
- we would be forced to not hash fields of structs to match the
- hash value of an incomplete struct. */
- if (type_hash_cache
- && (slot = pointer_map_contains (type_hash_cache, t1)) != NULL)
- {
- gimple_type_hash (t2);
- *slot = *pointer_map_contains (type_hash_cache, t2);
- }
-
- /* Adjust cached comparison results for T1 and T2 to make sure
- they now compare compatible. */
- p = lookup_type_pair (t1, t2, &gtc_visited);
- p->same_p = 1;
-}
-
-
-/* Return true if both types have the same name. */
+/* Return true if T1 and T2 have the same name. If FOR_COMPLETION_P is
+ true then if any type has no name return false, otherwise return
+ true if both types have no names. */
static bool
-compare_type_names_p (tree t1, tree t2)
+compare_type_names_p (tree t1, tree t2, bool for_completion_p)
{
tree name1 = TYPE_NAME (t1);
tree name2 = TYPE_NAME (t2);
- /* Consider anonymous types all unique. */
- if (!name1 || !name2)
+ /* Consider anonymous types all unique for completion. */
+ if (for_completion_p
+ && (!name1 || !name2))
return false;
- if (TREE_CODE (name1) == TYPE_DECL)
+ if (name1 && TREE_CODE (name1) == TYPE_DECL)
{
name1 = DECL_NAME (name1);
- if (!name1)
+ if (for_completion_p
+ && !name1)
return false;
}
- gcc_assert (TREE_CODE (name1) == IDENTIFIER_NODE);
+ gcc_assert (!name1 || TREE_CODE (name1) == IDENTIFIER_NODE);
- if (TREE_CODE (name2) == TYPE_DECL)
+ if (name2 && TREE_CODE (name2) == TYPE_DECL)
{
name2 = DECL_NAME (name2);
- if (!name2)
+ if (for_completion_p
+ && !name2)
return false;
}
- gcc_assert (TREE_CODE (name2) == IDENTIFIER_NODE);
+ gcc_assert (!name2 || TREE_CODE (name2) == IDENTIFIER_NODE);
/* Identifiers can be compared with pointer equality rather
than a string comparison. */
@@ -3187,30 +3167,64 @@ compare_field_offset (tree f1, tree f2)
/* Return 1 iff T1 and T2 are structurally identical.
Otherwise, return 0. */
-int
+static int
gimple_types_compatible_p (tree t1, tree t2)
{
type_pair_t p = NULL;
/* Check first for the obvious case of pointer identity. */
if (t1 == t2)
- goto same_types;
+ return 1;
/* Check that we have two types to compare. */
if (t1 == NULL_TREE || t2 == NULL_TREE)
- goto different_types;
+ return 0;
/* Can't be the same type if the types don't have the same code. */
if (TREE_CODE (t1) != TREE_CODE (t2))
- goto different_types;
+ return 0;
+
+ /* Can't be the same type if they have different CV qualifiers. */
+ if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
+ return 0;
/* Void types are always the same. */
if (TREE_CODE (t1) == VOID_TYPE)
- goto same_types;
+ return 1;
- /* Can't be the same type if they have different CV qualifiers. */
- if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
- goto different_types;
+ /* For numerical types do some simple checks before doing three
+ hashtable queries. */
+ if (INTEGRAL_TYPE_P (t1)
+ || SCALAR_FLOAT_TYPE_P (t1)
+ || FIXED_POINT_TYPE_P (t1)
+ || TREE_CODE (t1) == VECTOR_TYPE
+ || TREE_CODE (t1) == COMPLEX_TYPE)
+ {
+ /* Can't be the same type if they have different alignment,
+ sign, precision or mode. */
+ if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
+ || TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
+ || TYPE_MODE (t1) != TYPE_MODE (t2)
+ || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
+ return 0;
+
+ if (TREE_CODE (t1) == INTEGER_TYPE
+ && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2)
+ || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)))
+ return 0;
+
+ /* That's all we need to check for float and fixed-point types. */
+ if (SCALAR_FLOAT_TYPE_P (t1)
+ || FIXED_POINT_TYPE_P (t1))
+ return 1;
+
+ /* Perform cheap tail-recursion for vector and complex types. */
+ if (TREE_CODE (t1) == VECTOR_TYPE
+ || TREE_CODE (t1) == COMPLEX_TYPE)
+ return gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2));
+
+ /* For integral types fall thru to more complex checks. */
+ }
/* If the hash values of t1 and t2 are different the types can't
possibly be the same. This helps keeping the type-pair hashtable
@@ -3220,7 +3234,7 @@ gimple_types_compatible_p (tree t1, tree t2)
/* If we've visited this type pair before (in the case of aggregates
with self-referential types), and we made a decision, return it. */
- p = lookup_type_pair (t1, t2, &gtc_visited);
+ p = lookup_type_pair (t1, t2, &gtc_visited, &gtc_ob);
if (p->same_p == 0 || p->same_p == 1)
{
/* We have already decided whether T1 and T2 are the
@@ -3243,71 +3257,6 @@ gimple_types_compatible_p (tree t1, tree t2)
if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
goto different_types;
- /* For numerical types, the bounds must coincide. */
- if (INTEGRAL_TYPE_P (t1)
- || SCALAR_FLOAT_TYPE_P (t1)
- || FIXED_POINT_TYPE_P (t1))
- {
- /* Can't be the same type if they have different size, alignment,
- sign, precision or mode. Note that from now on, comparisons
- between *_CST nodes must be done using tree_int_cst_equal because
- we cannot assume that constants from T1 and T2 will be shared
- since T1 and T2 are distinct pointers. */
- if (!tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
- || !tree_int_cst_equal (TYPE_SIZE_UNIT (t1), TYPE_SIZE_UNIT (t2))
- || TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
- || TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
- || TYPE_MODE (t1) != TYPE_MODE (t2)
- || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
- goto different_types;
-
- /* For non-enumeral types, check type bounds. FIXME lto, we
- cannot check bounds on enumeral types because different front
- ends will produce different values. In C, enumeral types are
- integers, while in C++ each element will have its own
- symbolic value. We should decide how enums are to be
- represented in GIMPLE and have each front end lower to that. */
- if (TREE_CODE (t1) != ENUMERAL_TYPE)
- {
- tree min1 = TYPE_MIN_VALUE (t1);
- tree max1 = TYPE_MAX_VALUE (t1);
- tree min2 = TYPE_MIN_VALUE (t2);
- tree max2 = TYPE_MAX_VALUE (t2);
- bool min_equal_p = false;
- bool max_equal_p = false;
-
- /* If either type has a minimum value, the other type must
- have the same. */
- if (min1 == NULL_TREE && min2 == NULL_TREE)
- min_equal_p = true;
- else if (min1 && min2 && operand_equal_p (min1, min2, 0))
- min_equal_p = true;
-
- /* Likewise, if either type has a maximum value, the other
- type must have the same. */
- if (max1 == NULL_TREE && max2 == NULL_TREE)
- max_equal_p = true;
- else if (max1 && max2 && operand_equal_p (max1, max2, 0))
- max_equal_p = true;
-
- if (!min_equal_p || !max_equal_p)
- goto different_types;
- }
-
- if (TREE_CODE (t1) == INTEGER_TYPE)
- {
- if (TYPE_IS_SIZETYPE (t1) == TYPE_IS_SIZETYPE (t2)
- && TYPE_STRING_FLAG (t1) == TYPE_STRING_FLAG (t2))
- goto same_types;
- else
- goto different_types;
- }
- else if (TREE_CODE (t1) == BOOLEAN_TYPE)
- goto same_types;
- else if (TREE_CODE (t1) == REAL_TYPE)
- goto same_types;
- }
-
/* Do type-specific comparisons. */
switch (TREE_CODE (t1))
{
@@ -3315,7 +3264,8 @@ gimple_types_compatible_p (tree t1, tree t2)
/* Array types are the same if the element types are the same and
the number of elements are the same. */
if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
- || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
+ || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
+ || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
goto different_types;
else
{
@@ -3395,118 +3345,157 @@ gimple_types_compatible_p (tree t1, tree t2)
case POINTER_TYPE:
case REFERENCE_TYPE:
- {
- /* If the two pointers have different ref-all attributes,
- they can't be the same type. */
- if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
- goto different_types;
-
- /* If one pointer points to an incomplete type variant of
- the other pointed-to type they are the same. */
- if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))
- && (!COMPLETE_TYPE_P (TREE_TYPE (t1))
- || !COMPLETE_TYPE_P (TREE_TYPE (t2)))
- && compare_type_names_p (TREE_TYPE (t1), TREE_TYPE (t2)))
- {
- /* If t2 is complete we want to choose it instead of t1. */
- if (COMPLETE_TYPE_P (TREE_TYPE (t2)))
- gimple_force_type_merge (TREE_TYPE (t1), TREE_TYPE (t2));
- goto same_types;
- }
+ {
+ /* If the two pointers have different ref-all attributes,
+ they can't be the same type. */
+ if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
+ goto different_types;
- /* Otherwise, pointer and reference types are the same if the
- pointed-to types are the same. */
- if (gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+ /* If one pointer points to an incomplete type variant of
+ the other pointed-to type they are the same. */
+ if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1))
+ && (!COMPLETE_TYPE_P (TREE_TYPE (t1))
+ || !COMPLETE_TYPE_P (TREE_TYPE (t2)))
+ && compare_type_names_p (TREE_TYPE (t1), TREE_TYPE (t2), true))
+ {
+ /* Replace the pointed-to incomplete type with the
+ complete one. */
+ if (COMPLETE_TYPE_P (TREE_TYPE (t2)))
+ TREE_TYPE (t1) = TREE_TYPE (t2);
+ else
+ TREE_TYPE (t2) = TREE_TYPE (t1);
goto same_types;
-
+ }
+
+ /* Otherwise, pointer and reference types are the same if the
+ pointed-to types are the same. */
+ if (gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+ goto same_types;
+
+ goto different_types;
+ }
+
+ case INTEGER_TYPE:
+ case BOOLEAN_TYPE:
+ {
+ tree min1 = TYPE_MIN_VALUE (t1);
+ tree max1 = TYPE_MAX_VALUE (t1);
+ tree min2 = TYPE_MIN_VALUE (t2);
+ tree max2 = TYPE_MAX_VALUE (t2);
+ bool min_equal_p = false;
+ bool max_equal_p = false;
+
+ /* If either type has a minimum value, the other type must
+ have the same. */
+ if (min1 == NULL_TREE && min2 == NULL_TREE)
+ min_equal_p = true;
+ else if (min1 && min2 && operand_equal_p (min1, min2, 0))
+ min_equal_p = true;
+
+ /* Likewise, if either type has a maximum value, the other
+ type must have the same. */
+ if (max1 == NULL_TREE && max2 == NULL_TREE)
+ max_equal_p = true;
+ else if (max1 && max2 && operand_equal_p (max1, max2, 0))
+ max_equal_p = true;
+
+ if (!min_equal_p || !max_equal_p)
goto different_types;
- }
- case ENUMERAL_TYPE:
- {
- /* For enumeral types, all the values must be the same. */
- tree v1, v2;
+ goto same_types;
+ }
- if (TYPE_VALUES (t1) == TYPE_VALUES (t2))
- goto same_types;
+ case ENUMERAL_TYPE:
+ {
+ /* FIXME lto, we cannot check bounds on enumeral types because
+ different front ends will produce different values.
+ In C, enumeral types are integers, while in C++ each element
+ will have its own symbolic value. We should decide how enums
+ are to be represented in GIMPLE and have each front end lower
+ to that. */
+ tree v1, v2;
+
+ /* For enumeral types, all the values must be the same. */
+ if (TYPE_VALUES (t1) == TYPE_VALUES (t2))
+ goto same_types;
- for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
- v1 && v2;
- v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2))
- {
- tree c1 = TREE_VALUE (v1);
- tree c2 = TREE_VALUE (v2);
+ for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
+ v1 && v2;
+ v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2))
+ {
+ tree c1 = TREE_VALUE (v1);
+ tree c2 = TREE_VALUE (v2);
- if (TREE_CODE (c1) == CONST_DECL)
- c1 = DECL_INITIAL (c1);
+ if (TREE_CODE (c1) == CONST_DECL)
+ c1 = DECL_INITIAL (c1);
- if (TREE_CODE (c2) == CONST_DECL)
- c2 = DECL_INITIAL (c2);
+ if (TREE_CODE (c2) == CONST_DECL)
+ c2 = DECL_INITIAL (c2);
- if (tree_int_cst_equal (c1, c2) != 1)
- goto different_types;
- }
+ if (tree_int_cst_equal (c1, c2) != 1)
+ goto different_types;
+ }
- /* If one enumeration has more values than the other, they
- are not the same. */
- if (v1 || v2)
- goto different_types;
+ /* If one enumeration has more values than the other, they
+ are not the same. */
+ if (v1 || v2)
+ goto different_types;
- goto same_types;
- }
+ goto same_types;
+ }
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
- {
- /* For aggregate types, all the fields must be the same. */
- tree f1, f2;
+ {
+ tree f1, f2;
- /* Compare every field. */
- for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
- f1 && f2;
- f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
- {
- /* The fields must have the same name, offset and type. */
- if (DECL_NAME (f1) != DECL_NAME (f2)
- || !compare_field_offset (f1, f2)
- || !gimple_types_compatible_p (TREE_TYPE (f1),
- TREE_TYPE (f2)))
- goto different_types;
- }
+ /* If one type requires structural equality checks and the
+ other doesn't, do not merge the types. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (t1)
+ != TYPE_STRUCTURAL_EQUALITY_P (t2))
+ goto different_types;
- /* If one aggregate has more fields than the other, they
- are not the same. */
- if (f1 || f2)
- goto different_types;
+ /* The struct tags shall compare equal. */
+ if (!compare_type_names_p (TYPE_MAIN_VARIANT (t1),
+ TYPE_MAIN_VARIANT (t2), false))
+ goto different_types;
- goto same_types;
- }
+ /* For aggregate types, all the fields must be the same. */
+ for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
+ f1 && f2;
+ f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
+ {
+ /* The fields must have the same name, offset and type. */
+ if (DECL_NAME (f1) != DECL_NAME (f2)
+ || DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
+ || !compare_field_offset (f1, f2)
+ || !gimple_types_compatible_p (TREE_TYPE (f1),
+ TREE_TYPE (f2)))
+ goto different_types;
+ }
- case VECTOR_TYPE:
- if (TYPE_VECTOR_SUBPARTS (t1) != TYPE_VECTOR_SUBPARTS (t2))
- goto different_types;
+ /* If one aggregate has more fields than the other, they
+ are not the same. */
+ if (f1 || f2)
+ goto different_types;
- /* Fallthru */
- case COMPLEX_TYPE:
- if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
- goto different_types;
- goto same_types;
+ goto same_types;
+ }
default:
- goto different_types;
+ gcc_unreachable ();
}
/* Common exit path for types that are not compatible. */
different_types:
- if (p)
- p->same_p = 0;
+ p->same_p = 0;
return 0;
/* Common exit path for types that are compatible. */
same_types:
- if (p)
- p->same_p = 1;
+ p->same_p = 1;
return 1;
}
@@ -3578,12 +3567,11 @@ visit (tree t, struct sccs *state, hashval_t v,
return v;
}
-/* Hash the name of TYPE with the previous hash value V and return it. */
+/* Hash NAME with the previous hash value V and return it. */
static hashval_t
-iterative_hash_type_name (tree type, hashval_t v)
+iterative_hash_name (tree name, hashval_t v)
{
- tree name = TYPE_NAME (TYPE_MAIN_VARIANT (type));
if (!name)
return v;
if (TREE_CODE (name) == TYPE_DECL)
@@ -3655,17 +3643,35 @@ iterative_hash_gimple_type (tree type, hashval_t val,
avoid hash differences for complete vs. incomplete types. */
if (POINTER_TYPE_P (type))
{
- if (AGGREGATE_TYPE_P (TREE_TYPE (type)))
+ if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
{
v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
- v = iterative_hash_type_name (type, v);
+ v = iterative_hash_name
+ (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
}
else
v = visit (TREE_TYPE (type), state, v,
sccstack, sccstate, sccstate_obstack);
}
- /* Recurse for aggregates with a single element. */
+ /* For integer types hash the types min/max values and the string flag. */
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ {
+ v = iterative_hash_expr (TYPE_MIN_VALUE (type), v);
+ v = iterative_hash_expr (TYPE_MAX_VALUE (type), v);
+ v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
+ }
+
+ /* For array types hash their domain and the string flag. */
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type))
+ {
+ v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
+ v = visit (TYPE_DOMAIN (type), state, v,
+ sccstack, sccstate, sccstate_obstack);
+ }
+
+ /* Recurse for aggregates with a single element type. */
if (TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == COMPLEX_TYPE
|| TREE_CODE (type) == VECTOR_TYPE)
@@ -3703,10 +3709,11 @@ iterative_hash_gimple_type (tree type, hashval_t val,
unsigned nf;
tree f;
- v = iterative_hash_type_name (type, v);
+ v = iterative_hash_name (TYPE_NAME (TYPE_MAIN_VARIANT (type)), v);
for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
{
+ v = iterative_hash_name (DECL_NAME (f), v);
v = visit (TREE_TYPE (f), state, v,
sccstack, sccstate, sccstate_obstack);
nf++;
@@ -3802,6 +3809,12 @@ gimple_register_type (tree t)
gcc_assert (TYPE_P (t));
+ /* Always register the main variant first. This is important so we
+ pick up the non-typedef variants as canonical, otherwise we'll end
+ up taking typedef ids for structure tags during comparison. */
+ if (TYPE_MAIN_VARIANT (t) != t)
+ gimple_register_type (TYPE_MAIN_VARIANT (t));
+
if (gimple_types == NULL)
gimple_types = htab_create (16381, gimple_type_hash, gimple_type_eq, 0);
@@ -3917,6 +3930,7 @@ free_gimple_type_tables (void)
if (gtc_visited)
{
htab_delete (gtc_visited);
+ obstack_free (&gtc_ob, NULL);
gtc_visited = NULL;
}
}
@@ -4106,6 +4120,7 @@ gimple_signed_type (tree type)
alias_set_type
gimple_get_alias_set (tree t)
{
+ static bool recursing_p;
tree u;
/* Permit type-punning when accessing a union, provided the access
@@ -4147,6 +4162,12 @@ gimple_get_alias_set (tree t)
{
tree t1;
+ /* ??? We can end up creating cycles with TYPE_MAIN_VARIANT
+ and TYPE_CANONICAL. Avoid recursing endlessly between
+ this langhook and get_alias_set. */
+ if (recursing_p)
+ return -1;
+
/* Unfortunately, there is no canonical form of a pointer type.
In particular, if we have `typedef int I', then `int *', and
`I *' are different types. So, we have to pick a canonical
@@ -4171,7 +4192,13 @@ gimple_get_alias_set (tree t)
C++ committee. */
t1 = build_type_no_quals (t);
if (t1 != t)
- return get_alias_set (t1);
+ {
+ alias_set_type set;
+ recursing_p = true;
+ set = get_alias_set (t1);
+ recursing_p = false;
+ return set;
+ }
}
return -1;