libdrgn: look up primitive types on demand

Instead of caching all primitive types ahead of time, look them up on
demand. This is preparation for making the type index API more flexible.
This commit is contained in:
Omar Sandoval 2019-04-22 12:30:15 -07:00
parent 932b7857b5
commit 06960f591c
5 changed files with 241 additions and 183 deletions

View File

@ -1290,6 +1290,11 @@ drgn_dwarf_type_index_find(struct drgn_type_index *tindex,
uint64_t tag; uint64_t tag;
switch (kind) { switch (kind) {
case DRGN_TYPE_INT:
case DRGN_TYPE_BOOL:
case DRGN_TYPE_FLOAT:
tag = DW_TAG_base_type;
break;
case DRGN_TYPE_STRUCT: case DRGN_TYPE_STRUCT:
tag = DW_TAG_structure_type; tag = DW_TAG_structure_type;
break; break;
@ -1310,62 +1315,21 @@ drgn_dwarf_type_index_find(struct drgn_type_index *tindex,
drgn_dwarf_index_iterator_init(&it, dtindex->dindex, name, name_len, drgn_dwarf_index_iterator_init(&it, dtindex->dindex, name, name_len,
&tag, 1); &tag, 1);
while (!(err = drgn_dwarf_index_iterator_next(&it, &die))) { while (!(err = drgn_dwarf_index_iterator_next(&it, &die))) {
if (die_matches_filename(&die, filename)) if (die_matches_filename(&die, filename)) {
return drgn_type_from_dwarf(dtindex, &die, ret); err = drgn_type_from_dwarf(dtindex, &die, ret);
} if (err)
if (err && err->code != DRGN_ERROR_STOP) return err;
return err; /*
return drgn_type_index_not_found_error(kind, name, name_len, filename); * For DW_TAG_base_type, we need to check that the type
} * we found was the right kind.
*/
static struct drgn_error * if (drgn_type_kind(ret->type) == kind)
drgn_dwarf_type_index_iterate_primitive_types(struct drgn_dwarf_type_index *dtindex, return NULL;
struct drgn_dwarf_index_iterator *it)
{
struct drgn_error *err;
Dwarf_Die die;
struct drgn_qualified_type qualified_type;
enum drgn_primitive_type primitive;
while (!(err = drgn_dwarf_index_iterator_next(it, &die))) {
err = drgn_type_from_dwarf(dtindex, &die, &qualified_type);
if (err)
return err;
primitive = drgn_type_primitive(qualified_type.type);
if (primitive != DRGN_NOT_PRIMITIVE_TYPE) {
dtindex->tindex.primitive_types[primitive] =
qualified_type.type;
} }
} }
if (err && err->code != DRGN_ERROR_STOP) if (err && err->code != DRGN_ERROR_STOP)
return err; return err;
return NULL; return drgn_type_index_not_found_error(kind, name, name_len, filename);
}
static struct drgn_error *
drgn_dwarf_type_index_find_primitive_types(struct drgn_dwarf_type_index *dtindex)
{
struct drgn_error *err;
uint64_t tag;
struct drgn_dwarf_index_iterator it;
tag = DW_TAG_base_type;
drgn_dwarf_index_iterator_init(&it, dtindex->dindex, NULL, 0, &tag, 1);
err = drgn_dwarf_type_index_iterate_primitive_types(dtindex, &it);
if (err)
return err;
tag = DW_TAG_typedef;
drgn_dwarf_index_iterator_init(&it, dtindex->dindex, "size_t",
strlen("size_t"), &tag, 1);
err = drgn_dwarf_type_index_iterate_primitive_types(dtindex, &it);
if (err)
return err;
drgn_dwarf_index_iterator_init(&it, dtindex->dindex, "ptrdiff_t",
strlen("ptrdiff_t"), &tag, 1);
return drgn_dwarf_type_index_iterate_primitive_types(dtindex, &it);
} }
static void drgn_dwarf_type_index_destroy(struct drgn_type_index *tindex) static void drgn_dwarf_type_index_destroy(struct drgn_type_index *tindex)
@ -1396,7 +1360,6 @@ struct drgn_error *
drgn_dwarf_type_index_create(struct drgn_dwarf_index *dindex, drgn_dwarf_type_index_create(struct drgn_dwarf_index *dindex,
struct drgn_dwarf_type_index **ret) struct drgn_dwarf_type_index **ret)
{ {
struct drgn_error *err;
struct drgn_dwarf_type_index *dtindex; struct drgn_dwarf_type_index *dtindex;
dtindex = malloc(sizeof(*dtindex)); dtindex = malloc(sizeof(*dtindex));
@ -1411,12 +1374,6 @@ drgn_dwarf_type_index_create(struct drgn_dwarf_index *dindex,
dtindex->dindex = dindex; dtindex->dindex = dindex;
dtindex->depth = 0; dtindex->depth = 0;
err = drgn_dwarf_type_index_find_primitive_types(dtindex);
if (err) {
drgn_type_index_destroy(&dtindex->tindex);
return err;
}
*ret = dtindex; *ret = dtindex;
return NULL; return NULL;
} }

View File

@ -1899,12 +1899,20 @@ c_parse_specifier_qualifier_list(struct drgn_type_index *tindex,
} else if (identifier) { } else if (identifier) {
if (strncmp(identifier, "size_t", if (strncmp(identifier, "size_t",
strlen("size_t")) == 0) { strlen("size_t")) == 0) {
ret->type = tindex->primitive_types[DRGN_C_TYPE_SIZE_T]; err = drgn_type_index_find_primitive(tindex,
DRGN_C_TYPE_SIZE_T,
&ret->type);
if (err)
return err;
ret->qualifiers = 0; ret->qualifiers = 0;
goto out; goto out;
} else if (strncmp(identifier, "ptrdiff_t", } else if (strncmp(identifier, "ptrdiff_t",
strlen("ptrdiff_t")) == 0) { strlen("ptrdiff_t")) == 0) {
ret->type = tindex->primitive_types[DRGN_C_TYPE_PTRDIFF_T]; err = drgn_type_index_find_primitive(tindex,
DRGN_C_TYPE_PTRDIFF_T,
&ret->type);
if (err)
return err;
ret->qualifiers = 0; ret->qualifiers = 0;
goto out; goto out;
} else { } else {
@ -1921,7 +1929,11 @@ c_parse_specifier_qualifier_list(struct drgn_type_index *tindex,
if (err) if (err)
return err; return err;
} else { } else {
ret->type = tindex->primitive_types[specifier_kind[specifier]]; err = drgn_type_index_find_primitive(tindex,
specifier_kind[specifier],
&ret->type);
if (err)
return err;
ret->qualifiers = 0; ret->qualifiers = 0;
} }
out: out:
@ -2372,48 +2384,70 @@ out:
static struct drgn_error *c_integer_literal(struct drgn_object *res, static struct drgn_error *c_integer_literal(struct drgn_object *res,
uint64_t uvalue) uint64_t uvalue)
{ {
struct drgn_type **types = res->prog->tindex->primitive_types; static const enum drgn_primitive_type types[] = {
struct drgn_qualified_type qualified_type; DRGN_C_TYPE_INT,
DRGN_C_TYPE_LONG,
DRGN_C_TYPE_LONG_LONG,
DRGN_C_TYPE_UNSIGNED_LONG_LONG,
};
struct drgn_error *err;
unsigned int bits; unsigned int bits;
struct drgn_qualified_type qualified_type;
size_t i;
_Static_assert(sizeof(unsigned long long) == 8, _Static_assert(sizeof(unsigned long long) == 8,
"unsigned long long is not 64 bits"); "unsigned long long is not 64 bits");
bits = uvalue ? 64 - __builtin_clzll(uvalue) : 0; bits = uvalue ? 64 - __builtin_clzll(uvalue) : 0;
qualified_type.qualifiers = 0; qualified_type.qualifiers = 0;
if (bits < 8 * drgn_type_size(types[DRGN_C_TYPE_INT])) { for (i = 0; i < ARRAY_SIZE(types); i++) {
qualified_type.type = types[DRGN_C_TYPE_INT]; err = drgn_type_index_find_primitive(res->prog->tindex,
} else if (bits < 8 * drgn_type_size(types[DRGN_C_TYPE_LONG])) { types[i],
qualified_type.type = types[DRGN_C_TYPE_LONG]; &qualified_type.type);
} else if (bits < 8 * drgn_type_size(types[DRGN_C_TYPE_LONG_LONG])) { if (err)
qualified_type.type = types[DRGN_C_TYPE_LONG_LONG]; return err;
} else if (bits <=
8 * drgn_type_size(types[DRGN_C_TYPE_UNSIGNED_LONG_LONG])) { if (drgn_type_is_signed(qualified_type.type) &&
qualified_type.type = types[DRGN_C_TYPE_UNSIGNED_LONG_LONG]; bits < 8 * drgn_type_size(qualified_type.type)) {
return drgn_object_set_unsigned(res, qualified_type, uvalue, 0); return drgn_object_set_signed(res,
} else { qualified_type,
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, uvalue, 0);
"integer literal is too large"); } else if (!drgn_type_is_signed(qualified_type.type) &&
bits <= 8 * drgn_type_size(qualified_type.type)) {
return drgn_object_set_unsigned(res, qualified_type,
uvalue, 0);
}
} }
return drgn_object_set_signed(res, qualified_type, uvalue, 0); return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
"integer literal is too large");
} }
static struct drgn_error *c_bool_literal(struct drgn_object *res, bool bvalue) static struct drgn_error *c_bool_literal(struct drgn_object *res, bool bvalue)
{ {
struct drgn_qualified_type qualified_type = { struct drgn_error *err;
res->prog->tindex->primitive_types[DRGN_C_TYPE_INT], struct drgn_qualified_type qualified_type;
};
err = drgn_type_index_find_primitive(res->prog->tindex,
DRGN_C_TYPE_INT,
&qualified_type.type);
if (err)
return err;
qualified_type.qualifiers = 0;
return drgn_object_set_signed(res, qualified_type, bvalue, 0); return drgn_object_set_signed(res, qualified_type, bvalue, 0);
} }
static struct drgn_error *c_float_literal(struct drgn_object *res, static struct drgn_error *c_float_literal(struct drgn_object *res,
double fvalue) double fvalue)
{ {
struct drgn_qualified_type qualified_type = { struct drgn_error *err;
res->prog->tindex->primitive_types[DRGN_C_TYPE_DOUBLE], struct drgn_qualified_type qualified_type;
};
err = drgn_type_index_find_primitive(res->prog->tindex,
DRGN_C_TYPE_DOUBLE,
&qualified_type.type);
if (err)
return err;
qualified_type.qualifiers = 0;
return drgn_object_set_float(res, qualified_type, fvalue); return drgn_object_set_float(res, qualified_type, fvalue);
} }
@ -2468,7 +2502,9 @@ static bool c_can_represent_all_values(struct drgn_type *type1,
static struct drgn_error *c_integer_promotions(struct drgn_type_index *tindex, static struct drgn_error *c_integer_promotions(struct drgn_type_index *tindex,
struct drgn_object_type *type) struct drgn_object_type *type)
{ {
struct drgn_error *err;
enum drgn_primitive_type primitive; enum drgn_primitive_type primitive;
struct drgn_type *int_type;
switch (drgn_type_kind(type->underlying_type)) { switch (drgn_type_kind(type->underlying_type)) {
case DRGN_TYPE_ENUM: case DRGN_TYPE_ENUM:
@ -2511,18 +2547,29 @@ static struct drgn_error *c_integer_promotions(struct drgn_type_index *tindex,
* promotes it to the full width, but GCC does not. We implement the GCC * promotes it to the full width, but GCC does not. We implement the GCC
* behavior of preserving the width. * behavior of preserving the width.
*/ */
if (primitive == DRGN_NOT_PRIMITIVE_TYPE || type->bit_field_size) { if (primitive >= ARRAY_SIZE(c_integer_conversion_rank) ||
if (c_can_represent_all_values(tindex->primitive_types[DRGN_C_TYPE_INT], type->bit_field_size) {
0, type->underlying_type, err = drgn_type_index_find_primitive(tindex, DRGN_C_TYPE_INT,
&int_type);
if (err)
return err;
if (c_can_represent_all_values(int_type, 0,
type->underlying_type,
type->bit_field_size)) { type->bit_field_size)) {
type->type = type->underlying_type = type->type = type->underlying_type = int_type;
tindex->primitive_types[DRGN_C_TYPE_INT];
type->bit_field_size = 0; type->bit_field_size = 0;
} else if (c_can_represent_all_values(tindex->primitive_types[DRGN_C_TYPE_UNSIGNED_INT], return NULL;
0, type->underlying_type, }
type->bit_field_size)) {
type->type = type->underlying_type = err = drgn_type_index_find_primitive(tindex,
tindex->primitive_types[DRGN_C_TYPE_UNSIGNED_INT]; DRGN_C_TYPE_UNSIGNED_INT,
&int_type);
if (err)
return err;
if (c_can_represent_all_values(int_type, 0,
type->underlying_type,
type->bit_field_size)) {
type->type = type->underlying_type = int_type;
type->bit_field_size = 0; type->bit_field_size = 0;
} }
return NULL; return NULL;
@ -2538,15 +2585,50 @@ static struct drgn_error *c_integer_promotions(struct drgn_type_index *tindex,
* If int can represent all values of the original type, then the result * If int can represent all values of the original type, then the result
* is int. Otherwise, the result is unsigned int. * is int. Otherwise, the result is unsigned int.
*/ */
if (c_can_represent_all_values(tindex->primitive_types[DRGN_C_TYPE_INT], err = drgn_type_index_find_primitive(tindex, DRGN_C_TYPE_INT,
0, type->underlying_type, 0)) &int_type);
type->type = tindex->primitive_types[DRGN_C_TYPE_INT]; if (err)
else return err;
type->type = tindex->primitive_types[DRGN_C_TYPE_UNSIGNED_INT]; if (c_can_represent_all_values(int_type, 0, type->underlying_type, 0)) {
type->type = int_type;
} else {
err = drgn_type_index_find_primitive(tindex,
DRGN_C_TYPE_UNSIGNED_INT,
&type->type);
if (err)
return err;
}
type->underlying_type = type->type; type->underlying_type = type->type;
return NULL; return NULL;
} }
static struct drgn_error *
c_corresponding_unsigned_type(struct drgn_type_index *tindex,
enum drgn_primitive_type type,
struct drgn_type **ret)
{
switch (type) {
/*
* char, signed char, and short are promoted to int, so we don't need to
* handle them here.
*/
case DRGN_C_TYPE_INT:
return drgn_type_index_find_primitive(tindex,
DRGN_C_TYPE_UNSIGNED_INT,
ret);
case DRGN_C_TYPE_LONG:
return drgn_type_index_find_primitive(tindex,
DRGN_C_TYPE_UNSIGNED_LONG,
ret);
case DRGN_C_TYPE_LONG_LONG:
return drgn_type_index_find_primitive(tindex,
DRGN_C_TYPE_UNSIGNED_LONG_LONG,
ret);
default:
DRGN_UNREACHABLE();
}
}
static struct drgn_error *c_common_real_type(struct drgn_type_index *tindex, static struct drgn_error *c_common_real_type(struct drgn_type_index *tindex,
struct drgn_object_type *type1, struct drgn_object_type *type1,
struct drgn_object_type *type2, struct drgn_object_type *type2,
@ -2720,14 +2802,11 @@ static struct drgn_error *c_common_real_type(struct drgn_type_index *tindex,
* rank, then it must have greater size and thus be able to represent * rank, then it must have greater size and thus be able to represent
* all values of the unsigned integer type. * all values of the unsigned integer type.
*/ */
if (is_signed1) { err = c_corresponding_unsigned_type(tindex,
assert(primitive1 != DRGN_NOT_PRIMITIVE_TYPE); is_signed1 ? primitive1 : primitive2,
ret->type = tindex->primitive_types[primitive1 + 1]; &ret->type);
} else { if (err)
assert(is_signed2); return err;
assert(primitive2 != DRGN_NOT_PRIMITIVE_TYPE);
ret->type = tindex->primitive_types[primitive2 + 1];
}
ret->underlying_type = ret->type; ret->underlying_type = ret->type;
ret->bit_field_size = 0; ret->bit_field_size = 0;
return NULL; return NULL;
@ -2943,13 +3022,14 @@ static struct drgn_error *c_op_sub(struct drgn_object *res,
return err; return err;
if (lhs_pointer && rhs_pointer) { if (lhs_pointer && rhs_pointer) {
struct drgn_type *ptrdiff_type = struct drgn_object_type type = {};
lhs->prog->tindex->primitive_types[DRGN_C_TYPE_PTRDIFF_T];
struct drgn_object_type type = {
.type = ptrdiff_type,
.underlying_type = ptrdiff_type,
};
err = drgn_type_index_find_primitive(lhs->prog->tindex,
DRGN_C_TYPE_PTRDIFF_T,
&type.type);
if (err)
return err;
type.underlying_type = drgn_underlying_type(type.type);
if (!c_pointers_similar(&lhs_type, &rhs_type, lhs_size, if (!c_pointers_similar(&lhs_type, &rhs_type, lhs_size,
rhs_size)) rhs_size))
goto type_error; goto type_error;

View File

@ -158,7 +158,6 @@ drgn_mock_type_index_create(uint8_t word_size, bool little_endian,
struct drgn_mock_type_index **ret) struct drgn_mock_type_index **ret)
{ {
struct drgn_mock_type_index *mtindex; struct drgn_mock_type_index *mtindex;
size_t i;
if (word_size != 4 && word_size != 8) { if (word_size != 4 && word_size != 8) {
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
@ -174,15 +173,6 @@ drgn_mock_type_index_create(uint8_t word_size, bool little_endian,
mtindex->types = types; mtindex->types = types;
mtindex->num_types = num_types; mtindex->num_types = num_types;
for (i = 0; i < mtindex->num_types; i++) {
struct drgn_type *type = mtindex->types[i].type;
enum drgn_primitive_type primitive;
primitive = drgn_type_primitive(type);
if (primitive != DRGN_NOT_PRIMITIVE_TYPE)
mtindex->tindex.primitive_types[primitive] = type;
}
*ret = mtindex; *ret = mtindex;
return NULL; return NULL;
} }

View File

@ -72,6 +72,48 @@ static bool drgn_array_type_eq(struct drgn_type * const *ap,
DEFINE_HASH_SET_FUNCTIONS(drgn_array_type_set, struct drgn_type *, DEFINE_HASH_SET_FUNCTIONS(drgn_array_type_set, struct drgn_type *,
drgn_array_type_hash, drgn_array_type_eq) drgn_array_type_hash, drgn_array_type_eq)
void drgn_type_index_init(struct drgn_type_index *tindex,
const struct drgn_type_index_ops *ops,
uint8_t word_size, bool little_endian)
{
memset(tindex, 0, sizeof(*tindex));
tindex->ops = ops;
drgn_pointer_type_set_init(&tindex->pointer_types);
drgn_array_type_set_init(&tindex->array_types);
tindex->word_size = word_size;
tindex->little_endian = little_endian;
}
static void free_pointer_types(struct drgn_type_index *tindex)
{
struct drgn_pointer_type_set_pos pos;
pos = drgn_pointer_type_set_first_pos(&tindex->pointer_types);
while (pos.item) {
free(*pos.item);
drgn_pointer_type_set_next_pos(&pos);
}
drgn_pointer_type_set_deinit(&tindex->pointer_types);
}
static void free_array_types(struct drgn_type_index *tindex)
{
struct drgn_array_type_set_pos pos;
pos = drgn_array_type_set_first_pos(&tindex->array_types);
while (pos.item) {
free(*pos.item);
drgn_array_type_set_next_pos(&pos);
}
drgn_array_type_set_deinit(&tindex->array_types);
}
void drgn_type_index_deinit(struct drgn_type_index *tindex)
{
free_array_types(tindex);
free_pointer_types(tindex);
}
/* Default long, unsigned long, size_t, and ptrdiff_t are 64 bits. */ /* Default long, unsigned long, size_t, and ptrdiff_t are 64 bits. */
static struct drgn_type default_primitive_types[DRGN_PRIMITIVE_TYPE_NUM]; static struct drgn_type default_primitive_types[DRGN_PRIMITIVE_TYPE_NUM];
/* 32-bit version of long, unsigned long, size_t, and ptrdiff_t. */ /* 32-bit version of long, unsigned long, size_t, and ptrdiff_t. */
@ -167,69 +209,56 @@ static void default_primitive_types_init(void)
DRGN_C_TYPE_PTRDIFF_T); DRGN_C_TYPE_PTRDIFF_T);
} }
void drgn_type_index_init(struct drgn_type_index *tindex, struct drgn_error *
const struct drgn_type_index_ops *ops, drgn_type_index_find_primitive(struct drgn_type_index *tindex,
uint8_t word_size, bool little_endian) enum drgn_primitive_type type,
struct drgn_type **ret)
{ {
struct drgn_error *err;
struct drgn_qualified_type qualified_type;
enum drgn_type_kind kind;
const char * const *spellings;
size_t i; size_t i;
memset(tindex, 0, sizeof(*tindex)); if (tindex->primitive_types[type]) {
tindex->ops = ops; *ret = tindex->primitive_types[type];
drgn_pointer_type_set_init(&tindex->pointer_types); return NULL;
drgn_array_type_set_init(&tindex->array_types); }
tindex->word_size = word_size;
tindex->little_endian = little_endian;
for (i = 0; i < ARRAY_SIZE(tindex->primitive_types); i++) { kind = drgn_primitive_type_kind[type];
if (drgn_primitive_type_kind[i] == DRGN_TYPE_VOID) { if (kind == DRGN_TYPE_VOID) {
tindex->primitive_types[i] = &drgn_void_type; *ret = &drgn_void_type;
} else if (word_size == 4 && i == DRGN_C_TYPE_LONG) { goto out;
tindex->primitive_types[i] = }
&default_primitive_types_32bit[0];
} else if (word_size == 4 && i == DRGN_C_TYPE_UNSIGNED_LONG) { spellings = drgn_primitive_type_spellings[type];
tindex->primitive_types[i] = for (i = 0; spellings[i]; i++) {
&default_primitive_types_32bit[1]; err = drgn_type_index_find_internal(tindex, kind, spellings[i],
} else if (word_size == 4 && i == DRGN_C_TYPE_SIZE_T) { strlen(spellings[i]), NULL,
tindex->primitive_types[i] = &qualified_type);
&default_primitive_types_32bit[2]; if (err && err->code == DRGN_ERROR_LOOKUP) {
} else if (word_size == 4 && i == DRGN_C_TYPE_PTRDIFF_T) { drgn_error_destroy(err);
tindex->primitive_types[i] = } else if (err) {
&default_primitive_types_32bit[3]; return err;
} else { } else if (drgn_type_primitive(qualified_type.type) == type) {
tindex->primitive_types[i] = *ret = qualified_type.type;
&default_primitive_types[i]; goto out;
} }
} }
}
static void free_pointer_types(struct drgn_type_index *tindex) if (tindex->word_size == 4 && type == DRGN_C_TYPE_LONG)
{ *ret = &default_primitive_types_32bit[0];
struct drgn_pointer_type_set_pos pos; else if (tindex->word_size == 4 && type == DRGN_C_TYPE_UNSIGNED_LONG)
*ret = &default_primitive_types_32bit[1];
pos = drgn_pointer_type_set_first_pos(&tindex->pointer_types); else if (tindex->word_size == 4 && type == DRGN_C_TYPE_SIZE_T)
while (pos.item) { *ret = &default_primitive_types_32bit[2];
free(*pos.item); else if (tindex->word_size == 4 && type == DRGN_C_TYPE_PTRDIFF_T)
drgn_pointer_type_set_next_pos(&pos); *ret = &default_primitive_types_32bit[3];
} else
drgn_pointer_type_set_deinit(&tindex->pointer_types); *ret = &default_primitive_types[type];
} out:
tindex->primitive_types[type] = *ret;
static void free_array_types(struct drgn_type_index *tindex) return NULL;
{
struct drgn_array_type_set_pos pos;
pos = drgn_array_type_set_first_pos(&tindex->array_types);
while (pos.item) {
free(*pos.item);
drgn_array_type_set_next_pos(&pos);
}
drgn_array_type_set_deinit(&tindex->array_types);
}
void drgn_type_index_deinit(struct drgn_type_index *tindex)
{
free_array_types(tindex);
free_pointer_types(tindex);
} }
struct drgn_error * struct drgn_error *

View File

@ -82,10 +82,7 @@ struct drgn_type_index {
/** /**
* Initialize the common part of a @ref drgn_type_index. * Initialize the common part of a @ref drgn_type_index.
* *
* This should only be called by type index implementations. It initializes @ref * This should only be called by type index implementations.
* drgn_type_index::primitive_types to a default set of types based on @p
* word_size. The implementation should override the C types with the
* definitions that it finds.
* *
* @param[in] tindex Type index to initialize. * @param[in] tindex Type index to initialize.
* @param[in] ops Operation dispatch table. * @param[in] ops Operation dispatch table.
@ -117,6 +114,11 @@ static inline void drgn_type_index_destroy(struct drgn_type_index *tindex)
tindex->ops->destroy(tindex); tindex->ops->destroy(tindex);
} }
struct drgn_error *
drgn_type_index_find_primitive(struct drgn_type_index *tindex,
enum drgn_primitive_type type,
struct drgn_type **ret);
/** /**
* Find a type in a @ref drgn_type_index. * Find a type in a @ref drgn_type_index.
* *