This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH][C/Ada] Streamline range type building and hashing
> Sure. Another approach would be to introduce a build_nonshared_array_type
> function and make that and build_array_type wrap a common worker with
> a flag.
Unsurprisingly we need the same treatment for range types as for array types.
Here's the proposed patch, tested on i586-suse-linux, OK for mainline?
2010-09-17 Eric Botcazou <ebotcazou@adacore.com>
* langhooks.h (struct lang_hooks_for_types): Remove hash_types field.
* langhooks-def.h (LANG_HOOKS_HASH_TYPES): Delete.
(LANG_HOOKS_FOR_TYPES_INITIALIZER): Remove LANG_HOOKS_HASH_TYPES.
* system.h (LANG_HOOKS_HASH_TYPES): Poison.
* tree.c (type_hash_canon): Do not test lang_hooks.types.hash_types.
(build_nonstandard_integer_type): Likewise.
(build_range_type_1): New function, built from...
(build_range_type): ...this. Call build_range_type_1.
(build_nonshared_range_type): New function.
(build_array_type_1): New function, built from...
(build_array_type: ...this. Call build_array_type_1.
(build_nonshared_array_type): New function.
* tree.h (build_nonshared_range_type): Declare.
(build_nonshared_array_type): Likewise.
ada/
* gcc-interface/decl.c (gnat_to_gnu_entity): Replace calls to
build_array_type with calls to build_nonshared_array_type.
(substitute_in_type): Likewise.
* gcc-interface/misc.c (LANG_HOOKS_HASH_TYPES): Delete.
(LANG_HOOKS_TYPE_HASH_EQ): Define.
(gnat_post_options): Add 'static' keyword.
(gnat_type_hash_eq): New static function.
* gcc-interface/utils.c (fntype_same_flags_p): New function.
(create_subprog_type): Call it.
(create_index_type): Call build_nonshared_range_type and tidy up.
(create_range_type): Likewise.
* gcc-interface/gigi.h (fntype_same_flags_p): Declare.
--
Eric Botcazou
Index: tree.c
===================================================================
--- tree.c (revision 164295)
+++ tree.c (working copy)
@@ -6104,9 +6104,6 @@ type_hash_canon (unsigned int hashcode,
being passed. */
gcc_assert (TYPE_MAIN_VARIANT (type) == type);
- if (!lang_hooks.types.hash_types)
- return type;
-
/* See if the type is in the hash table already. If so, return it.
Otherwise, add the type. */
t1 = type_hash_lookup (hashcode, type);
@@ -7074,21 +7071,20 @@ build_nonstandard_integer_type (unsigned
ret = itype;
if (host_integerp (TYPE_MAX_VALUE (itype), 1))
ret = type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype);
- if (precision <= MAX_INT_CACHED_PREC && lang_hooks.types.hash_types)
+ if (precision <= MAX_INT_CACHED_PREC)
nonstandard_integer_type_cache[precision + unsignedp] = ret;
return ret;
}
-/* Create a range of some discrete type TYPE (an INTEGER_TYPE,
- ENUMERAL_TYPE or BOOLEAN_TYPE), with low bound LOWVAL and
- high bound HIGHVAL. */
+/* Create a range of some discrete type TYPE (an INTEGER_TYPE, ENUMERAL_TYPE
+ or BOOLEAN_TYPE) with low bound LOWVAL and high bound HIGHVAL. If SHARED
+ is true, reuse such a type that has already been constructed. */
-tree
-build_range_type (tree type, tree lowval, tree highval)
+static tree
+build_range_type_1 (tree type, tree lowval, tree highval, bool shared)
{
tree itype = make_node (INTEGER_TYPE);
- hashval_t hash;
TREE_TYPE (itype) = type;
@@ -7112,10 +7108,32 @@ build_range_type (tree type, tree lowval
SET_TYPE_STRUCTURAL_EQUALITY (itype);
return itype;
}
- hash = iterative_hash_expr (TYPE_MIN_VALUE (itype), 0);
- hash = iterative_hash_expr (TYPE_MAX_VALUE (itype), hash);
- hash = iterative_hash_hashval_t (TYPE_HASH (type), hash);
- return type_hash_canon (hash, itype);
+
+ if (shared)
+ {
+ hashval_t hash = iterative_hash_expr (TYPE_MIN_VALUE (itype), 0);
+ hash = iterative_hash_expr (TYPE_MAX_VALUE (itype), hash);
+ hash = iterative_hash_hashval_t (TYPE_HASH (type), hash);
+ itype = type_hash_canon (hash, itype);
+ }
+
+ return itype;
+}
+
+/* Wrapper around build_range_type_1 with SHARED set to true. */
+
+tree
+build_range_type (tree type, tree lowval, tree highval)
+{
+ return build_range_type_1 (type, lowval, highval, true);
+}
+
+/* Wrapper around build_range_type_1 with SHARED set to false. */
+
+tree
+build_nonshared_range_type (tree type, tree lowval, tree highval)
+{
+ return build_range_type_1 (type, lowval, highval, false);
}
/* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE.
@@ -7186,13 +7204,12 @@ subrange_type_for_debug_p (const_tree ty
/* Construct, lay out and return the type of arrays of elements with ELT_TYPE
and number of elements specified by the range of values of INDEX_TYPE.
- If such a type has already been constructed, reuse it. */
+ If SHARED is true, reuse such a type that has already been constructed. */
-tree
-build_array_type (tree elt_type, tree index_type)
+static tree
+build_array_type_1 (tree elt_type, tree index_type, bool shared)
{
tree t;
- hashval_t hashcode = 0;
if (TREE_CODE (elt_type) == FUNCTION_TYPE)
{
@@ -7212,10 +7229,13 @@ build_array_type (tree elt_type, tree in
if (TYPE_STRUCTURAL_EQUALITY_P (t))
return t;
- hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
- if (index_type)
- hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
- t = type_hash_canon (hashcode, t);
+ if (shared)
+ {
+ hashval_t hashcode = iterative_hash_object (TYPE_HASH (elt_type), 0);
+ if (index_type)
+ hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
+ t = type_hash_canon (hashcode, t);
+ }
if (TYPE_CANONICAL (t) == t)
{
@@ -7225,13 +7245,31 @@ build_array_type (tree elt_type, tree in
else if (TYPE_CANONICAL (elt_type) != elt_type
|| (index_type && TYPE_CANONICAL (index_type) != index_type))
TYPE_CANONICAL (t)
- = build_array_type (TYPE_CANONICAL (elt_type),
- index_type ? TYPE_CANONICAL (index_type) : NULL);
+ = build_array_type_1 (TYPE_CANONICAL (elt_type),
+ index_type
+ ? TYPE_CANONICAL (index_type) : NULL_TREE,
+ shared);
}
return t;
}
+/* Wrapper around build_array_type_1 with SHARED set to true. */
+
+tree
+build_array_type (tree elt_type, tree index_type)
+{
+ return build_array_type_1 (elt_type, index_type, true);
+}
+
+/* Wrapper around build_array_type_1 with SHARED set to false. */
+
+tree
+build_nonshared_array_type (tree elt_type, tree index_type)
+{
+ return build_array_type_1 (elt_type, index_type, false);
+}
+
/* Recursively examines the array elements of TYPE, until a non-array
element type is found. */
Index: tree.h
===================================================================
--- tree.h (revision 164295)
+++ tree.h (working copy)
@@ -4082,6 +4082,7 @@ extern tree build_opaque_vector_type (tr
extern tree build_type_no_quals (tree);
extern tree build_index_type (tree);
extern tree build_array_type (tree, tree);
+extern tree build_nonshared_array_type (tree, tree);
extern tree build_function_type (tree, tree);
extern tree build_function_type_list (tree, ...);
extern tree build_function_type_skip_args (tree, bitmap);
@@ -5107,6 +5108,7 @@ extern void build_common_tree_nodes_2 (i
extern void build_common_builtin_nodes (void);
extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
extern tree build_range_type (tree, tree, tree);
+extern tree build_nonshared_range_type (tree, tree, tree);
extern bool subrange_type_for_debug_p (const_tree, tree *, tree *);
extern HOST_WIDE_INT int_cst_value (const_tree);
extern HOST_WIDEST_INT widest_int_cst_value (const_tree);
Index: langhooks.h
===================================================================
--- langhooks.h (revision 164295)
+++ langhooks.h (working copy)
@@ -138,11 +138,6 @@ struct lang_hooks_for_types
return values from functions. The argument TYPE is the top of the
chain, and BOTTOM is the new type which we will point to. */
tree (*reconstruct_complex_type) (tree, tree);
-
- /* Nonzero if types that are identical are to be hashed so that only
- one copy is kept. If a language requires unique types for each
- user-specified type, such as Ada, this should be set to TRUE. */
- bool hash_types;
};
/* Language hooks related to decls and the symbol table. */
Index: system.h
===================================================================
--- system.h (revision 164295)
+++ system.h (working copy)
@@ -780,7 +780,7 @@ extern void fancy_abort (const char *, i
LANG_HOOKS_MAYBE_BUILD_CLEANUP LANG_HOOKS_UPDATE_DECL_AFTER_SAVING \
LANG_HOOKS_POPLEVEL LANG_HOOKS_TRUTHVALUE_CONVERSION \
TARGET_PROMOTE_FUNCTION_ARGS TARGET_PROMOTE_FUNCTION_RETURN \
- LANG_HOOKS_MISSING_ARGUMENT
+ LANG_HOOKS_MISSING_ARGUMENT LANG_HOOKS_HASH_TYPES
/* Miscellaneous macros that are no longer used. */
#pragma GCC poison USE_MAPPED_LOCATION
Index: langhooks-def.h
===================================================================
--- langhooks-def.h (revision 164295)
+++ langhooks-def.h (working copy)
@@ -178,7 +178,6 @@ extern tree lhd_make_node (enum tree_cod
#define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL
#define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL
#define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE reconstruct_complex_type
-#define LANG_HOOKS_HASH_TYPES true
#define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
LANG_HOOKS_MAKE_TYPE, \
@@ -195,8 +194,7 @@ extern tree lhd_make_node (enum tree_cod
LANG_HOOKS_TYPE_HASH_EQ, \
LANG_HOOKS_GET_ARRAY_DESCR_INFO, \
LANG_HOOKS_GET_SUBRANGE_BOUNDS, \
- LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
- LANG_HOOKS_HASH_TYPES \
+ LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE \
}
/* Declaration hooks. */
Index: ada/gcc-interface/utils.c
===================================================================
--- ada/gcc-interface/utils.c (revision 167894)
+++ ada/gcc-interface/utils.c (working copy)
@@ -1106,10 +1106,8 @@ create_subprog_type (tree return_type, t
/* TYPE may have been shared since GCC hashes types. If it has a different
CICO_LIST, make a copy. Likewise for the various flags. */
- if (TYPE_CI_CO_LIST (type) != cico_list
- || TYPE_RETURN_UNCONSTRAINED_P (type) != return_unconstrained_p
- || TYPE_RETURN_BY_DIRECT_REF_P (type) != return_by_direct_ref_p
- || TREE_ADDRESSABLE (type) != return_by_invisi_ref_p)
+ if (!fntype_same_flags_p (type, cico_list, return_unconstrained_p,
+ return_by_direct_ref_p, return_by_invisi_ref_p))
{
type = copy_type (type);
TYPE_CI_CO_LIST (type) = cico_list;
@@ -1165,17 +1163,9 @@ tree
create_index_type (tree min, tree max, tree index, Node_Id gnat_node)
{
/* First build a type for the desired range. */
- tree type = build_range_type (sizetype, min, max);
-
- /* If this type has the TYPE_INDEX_TYPE we want, return it. */
- if (TYPE_INDEX_TYPE (type) == index)
- return type;
-
- /* Otherwise, if TYPE_INDEX_TYPE is set, make a copy. Note that we have
- no way of sharing these types, but that's only a small hole. */
- if (TYPE_INDEX_TYPE (type))
- type = copy_type (type);
+ tree type = build_nonshared_range_type (sizetype, min, max);
+ /* Then set the index type. */
SET_TYPE_INDEX_TYPE (type, index);
create_type_decl (NULL_TREE, type, NULL, true, false, gnat_node);
@@ -1194,26 +1184,12 @@ create_range_type (tree type, tree min,
type = sizetype;
/* First build a type with the base range. */
- range_type
- = build_range_type (type, TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type));
-
- min = convert (type, min);
- max = convert (type, max);
-
- /* If this type has the TYPE_RM_{MIN,MAX}_VALUE we want, return it. */
- if (TYPE_RM_MIN_VALUE (range_type)
- && TYPE_RM_MAX_VALUE (range_type)
- && operand_equal_p (TYPE_RM_MIN_VALUE (range_type), min, 0)
- && operand_equal_p (TYPE_RM_MAX_VALUE (range_type), max, 0))
- return range_type;
-
- /* Otherwise, if TYPE_RM_{MIN,MAX}_VALUE is set, make a copy. */
- if (TYPE_RM_MIN_VALUE (range_type) || TYPE_RM_MAX_VALUE (range_type))
- range_type = copy_type (range_type);
+ range_type = build_nonshared_range_type (type, TYPE_MIN_VALUE (type),
+ TYPE_MAX_VALUE (type));
/* Then set the actual range. */
- SET_TYPE_RM_MIN_VALUE (range_type, min);
- SET_TYPE_RM_MAX_VALUE (range_type, max);
+ SET_TYPE_RM_MIN_VALUE (range_type, convert (type, min));
+ SET_TYPE_RM_MAX_VALUE (range_type, convert (type, max));
return range_type;
}
@@ -2123,6 +2099,18 @@ gnat_types_compatible_p (tree t1, tree t
return 0;
}
+
+/* Return true if T, a FUNCTION_TYPE, has the specified list of flags. */
+
+bool
+fntype_same_flags_p (const_tree t, tree cico_list, bool return_unconstrained_p,
+ bool return_by_direct_ref_p, bool return_by_invisi_ref_p)
+{
+ return TYPE_CI_CO_LIST (t) == cico_list
+ && TYPE_RETURN_UNCONSTRAINED_P (t) == return_unconstrained_p
+ && TYPE_RETURN_BY_DIRECT_REF_P (t) == return_by_direct_ref_p
+ && TREE_ADDRESSABLE (t) == return_by_invisi_ref_p;
+}
/* EXP is an expression for the size of an object. If this size contains
discriminant references, replace them with the maximum (if MAX_P) or
Index: ada/gcc-interface/decl.c
===================================================================
--- ada/gcc-interface/decl.c (revision 167848)
+++ ada/gcc-interface/decl.c (working copy)
@@ -2070,7 +2070,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
/* Now build the array type. */
for (index = ndim - 1; index >= 0; index--)
{
- tem = build_array_type (tem, gnu_index_types[index]);
+ tem = build_nonshared_array_type (tem, gnu_index_types[index]);
TYPE_MULTI_ARRAY_P (tem) = (index > 0);
if (array_type_has_nonaliased_component (tem, gnat_entity))
TYPE_NONALIASED_COMPONENT (tem) = 1;
@@ -2403,7 +2403,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
/* Now build the array type. */
for (index = ndim - 1; index >= 0; index --)
{
- gnu_type = build_array_type (gnu_type, gnu_index_types[index]);
+ gnu_type = build_nonshared_array_type (gnu_type,
+ gnu_index_types[index]);
TYPE_MULTI_ARRAY_P (gnu_type) = (index > 0);
if (array_type_has_nonaliased_component (gnu_type, gnat_entity))
TYPE_NONALIASED_COMPONENT (gnu_type) = 1;
@@ -2649,8 +2650,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
gnat_entity);
gnu_type
- = build_array_type (gnat_to_gnu_type (Component_Type (gnat_entity)),
- gnu_index_type);
+ = build_nonshared_array_type (gnat_to_gnu_type
+ (Component_Type (gnat_entity)),
+ gnu_index_type);
if (array_type_has_nonaliased_component (gnu_type, gnat_entity))
TYPE_NONALIASED_COMPONENT (gnu_type) = 1;
relate_alias_sets (gnu_type, gnu_string_type, ALIAS_SET_COPY);
@@ -8610,7 +8612,7 @@ substitute_in_type (tree t, tree f, tree
if (component == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))
return t;
- nt = build_array_type (component, domain);
+ nt = build_nonshared_array_type (component, domain);
TYPE_ALIGN (nt) = TYPE_ALIGN (t);
TYPE_USER_ALIGN (nt) = TYPE_USER_ALIGN (t);
SET_TYPE_MODE (nt, TYPE_MODE (t));
Index: ada/gcc-interface/gigi.h
===================================================================
--- ada/gcc-interface/gigi.h (revision 167824)
+++ ada/gcc-interface/gigi.h (working copy)
@@ -447,6 +447,9 @@ extern tree gnat_signed_type (tree type_
transparently converted to each other. */
extern int gnat_types_compatible_p (tree t1, tree t2);
+/* Return true if T, a FUNCTION_TYPE, has the specified list of flags. */
+extern bool fntype_same_flags_p (const_tree, tree, bool, bool, bool);
+
/* Create an expression whose value is that of EXPR,
converted to type TYPE. The TREE_TYPE of the value
is always TYPE. This function implements all reasonable
Index: ada/gcc-interface/misc.c
===================================================================
--- ada/gcc-interface/misc.c (revision 167824)
+++ ada/gcc-interface/misc.c (working copy)
@@ -72,6 +72,7 @@ static void gnat_print_decl (FILE *, tr
static void gnat_print_type (FILE *, tree, int);
static const char *gnat_printable_name (tree, int);
static const char *gnat_dwarf_name (tree, int);
+static bool gnat_type_hash_eq (const_tree, const_tree);
static tree gnat_return_tree (tree);
static void gnat_parse_file (int);
static void internal_error_function (diagnostic_context *,
@@ -98,8 +99,8 @@ static tree gnat_eh_personality (void);
#define LANG_HOOKS_POST_OPTIONS gnat_post_options
#undef LANG_HOOKS_PARSE_FILE
#define LANG_HOOKS_PARSE_FILE gnat_parse_file
-#undef LANG_HOOKS_HASH_TYPES
-#define LANG_HOOKS_HASH_TYPES false
+#undef LANG_HOOKS_TYPE_HASH_EQ
+#define LANG_HOOKS_TYPE_HASH_EQ gnat_type_hash_eq
#undef LANG_HOOKS_GETDECLS
#define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
#undef LANG_HOOKS_PUSHDECL
@@ -304,7 +305,7 @@ gnat_init_options (unsigned int decoded_
/* Post-switch processing. */
-bool
+static bool
gnat_post_options (const char **pfilename ATTRIBUTE_UNUSED)
{
/* Excess precision other than "fast" requires front-end
@@ -598,6 +599,20 @@ gnat_dwarf_name (tree decl, int verbosit
return (const char *) IDENTIFIER_POINTER (DECL_NAME (decl));
}
+/* Return true if types T1 and T2 are identical for type hashing purposes.
+ Called only after doing all language independent checks. At present,
+ this function is only called when both types are FUNCTION_TYPE. */
+
+static bool
+gnat_type_hash_eq (const_tree t1, const_tree t2)
+{
+ gcc_assert (TREE_CODE (t1) == FUNCTION_TYPE);
+ return fntype_same_flags_p (t1, TYPE_CI_CO_LIST (t2),
+ TYPE_RETURN_UNCONSTRAINED_P (t2),
+ TYPE_RETURN_BY_DIRECT_REF_P (t2),
+ TREE_ADDRESSABLE (t2));
+}
+
/* Do nothing (return the tree node passed). */
static tree