mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 17:23:06 +00:00
libdrgn: deduplicate all types with no members/parameters/enumerators
Even if a compound, function, or enumerated type is complete, we can still deduplicate it as long as it doesn't have members, parameters, or enumerators. Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
parent
1631c11f37
commit
c7af566c6e
@ -100,18 +100,14 @@ struct drgn_program {
|
||||
/** Cache of deduplicated types. */
|
||||
struct drgn_dedupe_type_set dedupe_types;
|
||||
/**
|
||||
* List of created types that cannot be deduplicated.
|
||||
* List of created types that are not deduplicated: types with non-empty
|
||||
* lists of members, parameters, or enumerators.
|
||||
*
|
||||
* Complete structure, union, and class types, as well as function
|
||||
* types, refer to lazily-evaluated types, so they cannot be easily
|
||||
* deduplicated.
|
||||
* Members and parameters contain lazily-evaluated types, so they
|
||||
* cannot be easily deduplicated.
|
||||
*
|
||||
* Complete enumerated types could be deduplicated, but it's probably
|
||||
* not worth the effort of hashing and comparing long lists of
|
||||
* enumerators.
|
||||
*
|
||||
* All other types, including incomplete structure, union, class, and
|
||||
* enumerated types, are deduplicated.
|
||||
* Enumerators could be deduplicated, but it's probably not worth the
|
||||
* effort to hash and compare them.
|
||||
*/
|
||||
struct drgn_typep_vector created_types;
|
||||
/** Cache for @ref drgn_program_find_member(). */
|
||||
|
@ -234,14 +234,8 @@ drgn_type_dedupe_hash_pair(struct drgn_type * const *entry)
|
||||
{
|
||||
struct drgn_type *type = *entry;
|
||||
size_t hash = hash_combine(drgn_type_kind(type),
|
||||
(uintptr_t)drgn_type_language(type));
|
||||
/*
|
||||
* We don't dedupe complete compound or enumerated types, and typedefs
|
||||
* inherit is_complete from the aliased type, so is_complete can only
|
||||
* differ for otherwise equal array types. We implicitly include that in
|
||||
* the hash with the is_complete check below, so we don't need to hash
|
||||
* it explicitly.
|
||||
*/
|
||||
drgn_type_is_complete(type));
|
||||
hash = hash_combine(hash, (uintptr_t)drgn_type_language(type));
|
||||
if (drgn_type_has_name(type))
|
||||
hash = hash_combine(hash, hash_c_string(drgn_type_name(type)));
|
||||
if (drgn_type_has_size(type))
|
||||
@ -257,8 +251,10 @@ drgn_type_dedupe_hash_pair(struct drgn_type * const *entry)
|
||||
hash = hash_combine(hash, (uintptr_t)qualified_type.type);
|
||||
hash = hash_combine(hash, qualified_type.qualifiers);
|
||||
}
|
||||
if (drgn_type_has_length(type) && drgn_type_is_complete(type))
|
||||
if (drgn_type_has_length(type))
|
||||
hash = hash_combine(hash, drgn_type_length(type));
|
||||
if (drgn_type_has_is_variadic(type))
|
||||
hash = hash_combine(hash, drgn_type_is_variadic(type));
|
||||
return hash_pair_from_avalanching_hash(hash);
|
||||
}
|
||||
|
||||
@ -269,8 +265,8 @@ static bool drgn_type_dedupe_eq(struct drgn_type * const *entry_a,
|
||||
struct drgn_type *b = *entry_b;
|
||||
|
||||
if (drgn_type_kind(a) != drgn_type_kind(b) ||
|
||||
drgn_type_language(a) != drgn_type_language(b) ||
|
||||
drgn_type_is_complete(a) != drgn_type_is_complete(b))
|
||||
drgn_type_is_complete(a) != drgn_type_is_complete(b) ||
|
||||
drgn_type_language(a) != drgn_type_language(b))
|
||||
return false;
|
||||
if (drgn_type_has_name(a) &&
|
||||
strcmp(drgn_type_name(a), drgn_type_name(b)) != 0)
|
||||
@ -296,13 +292,15 @@ static bool drgn_type_dedupe_eq(struct drgn_type * const *entry_a,
|
||||
if (drgn_type_has_length(a) &&
|
||||
drgn_type_length(a) != drgn_type_length(b))
|
||||
return false;
|
||||
if (drgn_type_has_is_variadic(a) &&
|
||||
drgn_type_is_variadic(a) != drgn_type_is_variadic(b))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't deduplicate complete compound types, complete enumerated types, or
|
||||
* function types, so the hash and comparison functions ignore members,
|
||||
* enumerators, parameters, and is_variadic.
|
||||
* We don't deduplicate types with members, parameters, or enumerators, so the
|
||||
* hash and comparison functions ignore those.
|
||||
*/
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dedupe_type_set, drgn_type_dedupe_hash_pair,
|
||||
drgn_type_dedupe_eq)
|
||||
@ -503,6 +501,22 @@ drgn_compound_type_create(struct drgn_compound_type_builder *builder,
|
||||
const struct drgn_language *lang,
|
||||
struct drgn_type **ret)
|
||||
{
|
||||
if (!builder->members.size) {
|
||||
struct drgn_type key = {
|
||||
{
|
||||
.kind = builder->kind,
|
||||
.is_complete = true,
|
||||
.primitive = DRGN_NOT_PRIMITIVE_TYPE,
|
||||
.tag = tag,
|
||||
.size = size,
|
||||
.program = builder->prog,
|
||||
.language =
|
||||
lang ? lang : drgn_program_language(builder->prog),
|
||||
}
|
||||
};
|
||||
return find_or_create_type(&key, ret);
|
||||
}
|
||||
|
||||
struct drgn_type *type = malloc(sizeof(*type));
|
||||
if (!type)
|
||||
return &drgn_enomem;
|
||||
@ -604,6 +618,22 @@ struct drgn_error *drgn_enum_type_create(struct drgn_enum_type_builder *builder,
|
||||
"compatible type of enum type must be integer type");
|
||||
}
|
||||
|
||||
if (!builder->enumerators.size) {
|
||||
struct drgn_type key = {
|
||||
{
|
||||
.kind = DRGN_TYPE_ENUM,
|
||||
.is_complete = true,
|
||||
.primitive = DRGN_NOT_PRIMITIVE_TYPE,
|
||||
.tag = tag,
|
||||
.type = compatible_type,
|
||||
.program = builder->prog,
|
||||
.language =
|
||||
lang ? lang : drgn_program_language(builder->prog),
|
||||
}
|
||||
};
|
||||
return find_or_create_type(&key, ret);
|
||||
}
|
||||
|
||||
struct drgn_type *type = malloc(sizeof(*type));
|
||||
if (!type)
|
||||
return &drgn_enomem;
|
||||
@ -804,6 +834,23 @@ drgn_function_type_create(struct drgn_function_type_builder *builder,
|
||||
"type is from different program");
|
||||
}
|
||||
|
||||
if (!builder->parameters.size) {
|
||||
struct drgn_type key = {
|
||||
{
|
||||
.kind = DRGN_TYPE_FUNCTION,
|
||||
.is_complete = true,
|
||||
.primitive = DRGN_NOT_PRIMITIVE_TYPE,
|
||||
.type = return_type.type,
|
||||
.qualifiers = return_type.qualifiers,
|
||||
.is_variadic = is_variadic,
|
||||
.program = builder->prog,
|
||||
.language =
|
||||
lang ? lang : drgn_program_language(builder->prog),
|
||||
}
|
||||
};
|
||||
return find_or_create_type(&key, ret);
|
||||
}
|
||||
|
||||
struct drgn_type *type = malloc(sizeof(*type));
|
||||
if (!type)
|
||||
return &drgn_enomem;
|
||||
|
Loading…
Reference in New Issue
Block a user