[CLASSES]: Reduce the space needed to represent a DW_TAG_typedef

By having its own class, struct typedef_tag.

As it, as structs, unions and enums have a common part, the node and visited
fields, required when emitting its definitions there is an opportunity for
consolidation, that will be explored when adding the specific classes for
DW_TAG_enumeration & DW_TAG_union.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2007-01-06 15:17:58 -02:00
parent 276ba078f2
commit 6165ac5ba6
8 changed files with 100 additions and 21 deletions

View File

@ -285,6 +285,20 @@ static struct base_type *base_type__new(Dwarf_Die *die)
return self;
}
static struct typedef_tag *typedef_tag__new(Dwarf_Die *die)
{
struct typedef_tag *self = malloc(sizeof(*self));
if (self != NULL) {
tag__init(&self->tag, die);
INIT_LIST_HEAD(&self->node);
self->name = strings__add(attr_string(die, DW_AT_name));
self->visited = 0;
}
return self;
}
static size_t enumeration__snprintf(const struct class *self,
char *bf, size_t len,
const char *suffix, uint8_t ntabs)
@ -573,6 +587,30 @@ static void cus__add_definition(struct cus *self, struct class *class)
list_add_tail(&class->node, self->definitions);
}
struct typedef_tag *cus__find_typedef_definition(const struct cus *self,
const char *name)
{
struct typedef_tag *pos;
if (name == NULL)
return NULL;
list_for_each_entry(pos, self->typedef_definitions, node)
if (pos->name != NULL && strcmp(pos->name, name) == 0)
return pos;
return NULL;
}
static void cus__add_typedef_definition(struct cus *self,
struct typedef_tag *def)
{
def->visited = 1;
if (!list_empty(&def->node))
list_del(&def->node);
list_add_tail(&def->node, self->definitions);
}
static void cus__add_fwd_decl(struct cus *self, struct class *class)
{
class->fwd_decl_emitted = 1;
@ -709,6 +747,8 @@ const char *tag__name(const struct tag *self, const struct cu *cu,
strncpy(bf, "void", len);
else if (self->tag == DW_TAG_base_type)
strncpy(bf, tag__base_type(self)->name, len);
else if (self->tag == DW_TAG_typedef)
strncpy(bf, tag__typedef_tag(self)->name, len);
else if (self->tag == DW_TAG_pointer_type) {
if (self->type == 0) /* No type == void */
strncpy(bf, "void *", len);
@ -1828,6 +1868,20 @@ static void cu__create_new_base_type(Dwarf_Die *die, struct cu *cu)
cu__add_tag(cu, &base->tag);
}
static void cu__create_new_typedef(Dwarf_Die *die, struct cu *cu)
{
struct typedef_tag *tdef = typedef_tag__new(die);
if (tdef == NULL)
oom("typedef_tag__new");
if (dwarf_haschildren(die))
fprintf(stderr, "%s: DW_TAG_typedef WITH children!\n",
__FUNCTION__);
cu__add_tag(cu, &tdef->tag);
}
static void cu__create_new_array(Dwarf_Die *die, struct cu *cu)
{
Dwarf_Die child;
@ -2132,9 +2186,11 @@ static void cu__process_unit(Dwarf_Die *die, struct cu *cu)
case DW_TAG_enumeration_type:
cu__create_new_enumeration(die, cu);
break;
case DW_TAG_typedef:
cu__create_new_typedef(die, cu);
break;
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_typedef:
cu__create_new_class(die, cu);
break;
default:
@ -2261,6 +2317,7 @@ out:
}
struct cus *cus__new(struct list_head *definitions,
struct list_head *typedef_definitions,
struct list_head *fwd_decls)
{
struct cus *self = malloc(sizeof(*self));
@ -2268,8 +2325,11 @@ struct cus *cus__new(struct list_head *definitions,
if (self != NULL) {
INIT_LIST_HEAD(&self->cus);
INIT_LIST_HEAD(&self->priv_definitions);
INIT_LIST_HEAD(&self->priv_typedef_definitions);
INIT_LIST_HEAD(&self->priv_fwd_decls);
self->definitions = definitions ?: &self->priv_definitions;
self->typedef_definitions = typedef_definitions ?:
&self->priv_typedef_definitions;
self->fwd_decls = fwd_decls ?: &self->priv_fwd_decls;
}
@ -2279,25 +2339,25 @@ struct cus *cus__new(struct list_head *definitions,
static int cus__emit_typedef_definitions(struct cus *self, struct cu *cu,
struct tag *tdef)
{
struct class *class = tag__class(tdef);
struct typedef_tag *def = tag__typedef_tag(tdef);
struct tag *type, *ptr_type;
int is_pointer = 0;
char bf[512];
/* Have we already emitted this in this CU? */
if (class->visited)
if (def->visited)
return 0;
/* Ok, lets look at the previous CUs: */
if (cus__find_definition(self, class->name) != NULL) {
if (cus__find_typedef_definition(self, def->name) != NULL) {
/*
* Yes, so lets mark it visited on this CU too,
* to speed up the lookup.
*/
class->visited = 1;
def->visited = 1;
return 0;
}
type = cu__find_tag_by_id(cu, class->tag.type);
type = cu__find_tag_by_id(cu, tdef->type);
if (type->tag == DW_TAG_typedef)
cus__emit_typedef_definitions(self, cu, type);
@ -2313,7 +2373,7 @@ static int cus__emit_typedef_definitions(struct cus *self, struct cu *cu,
case DW_TAG_subroutine_type:
cus__emit_ftype_definitions(self, cu, tag__ftype(type));
ftype__snprintf(tag__ftype(type), cu, bf, sizeof(bf),
class->name, 0, is_pointer, 0);
def->name, 0, is_pointer, 0);
fputs("typedef ", stdout);
printf("%s;\n", bf);
goto out;
@ -2322,17 +2382,17 @@ static int cus__emit_typedef_definitions(struct cus *self, struct cu *cu,
if (ctype->name == NULL)
cus__emit_struct_definitions(self, cu, ctype,
"typedef", class->name);
"typedef", def->name);
else
printf("typedef struct %s %s;\n",
ctype->name, class->name);
ctype->name, def->name);
}
goto out;
}
printf("typedef %s %s;\n", tag__name(type, cu, bf, sizeof(bf)),
class->name);
def->name);
out:
cus__add_definition(self, class);
cus__add_typedef_definition(self, def);
return 1;
}

View File

@ -19,8 +19,10 @@
struct cus {
struct list_head cus;
struct list_head priv_definitions;
struct list_head priv_typedef_definitions;
struct list_head priv_fwd_decls;
struct list_head *definitions;
struct list_head *typedef_definitions;
struct list_head *fwd_decls;
};
@ -84,6 +86,18 @@ static inline struct base_type *tag__base_type(const struct tag *self)
return (struct base_type *)self;
}
struct typedef_tag {
struct tag tag;
struct list_head node; /* In cus->definitions */
const char *name;
uint8_t visited; /* Just one bit is needed */
};
static inline struct typedef_tag *tag__typedef_tag(const struct tag *self)
{
return (struct typedef_tag *)self;
}
struct array_type {
struct tag tag;
const char *name;
@ -212,6 +226,7 @@ extern void function__print(const struct function *self, const struct cu *cu,
const int show_inline_expansions);
extern struct cus *cus__new(struct list_head *definitions,
struct list_head *typedef_definitions,
struct list_head *fwd_decls);
extern int cus__load(struct cus *self, const char *filename);
extern int cus__load_dir(struct cus *self, const char *dirname,

View File

@ -472,7 +472,7 @@ static int show_function_diffs_iterator(struct tag *tag, struct cu *cu,
}
static int show_structure_diffs_iterator(struct tag *tag, struct cu *cu,
void *new_cu)
void *cookie)
{
struct class *class;
@ -587,8 +587,8 @@ int main(int argc, char *argv[])
show_terse_type_changes == 0)
show_function_diffs = show_struct_diffs = 1;
old_cus = cus__new(NULL, NULL);
new_cus = cus__new(NULL, NULL);
old_cus = cus__new(NULL, NULL, NULL);
new_cus = cus__new(NULL, NULL, NULL);
if (old_cus == NULL || new_cus == NULL) {
fputs("codiff: insufficient memory\n", stderr);
return EXIT_FAILURE;
@ -609,7 +609,7 @@ int main(int argc, char *argv[])
cus__for_each_cu(old_cus, cu_diff_iterator, new_cus, NULL);
cus__for_each_cu(new_cus, cu_find_new_tags_iterator, old_cus, NULL);
cus__for_each_cu(old_cus, cu_show_diffs_iterator, NULL, NULL);
cus__for_each_cu(new_cus, cu_show_diffs_iterator, NULL, NULL);
cus__for_each_cu(new_cus, cu_show_diffs_iterator, (void *)1, NULL);
if (total_cus_changed > 1) {
if (show_function_diffs)

View File

@ -19,6 +19,7 @@ static struct cus *cus;
static struct cus *kprobes_cus;
static LIST_HEAD(cus__definitions);
static LIST_HEAD(cus__typedef_definitions);
static LIST_HEAD(cus__fwd_decls);
static void method__add(struct cu *cu, struct function *function)
@ -332,7 +333,8 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
cus = cus__new(&cus__definitions, &cus__fwd_decls);
cus = cus__new(&cus__definitions, &cus__typedef_definitions,
&cus__fwd_decls);
if (cus == NULL) {
out_enomem:
fputs("ctracer: insufficient memory\n", stderr);
@ -340,7 +342,9 @@ out_enomem:
}
if (kprobes_filename != NULL) {
kprobes_cus = cus__new(&cus__definitions, &cus__fwd_decls);
kprobes_cus = cus__new(&cus__definitions,
&cus__typedef_definitions,
&cus__fwd_decls);
if (kprobes_cus == NULL)
goto out_enomem;
if (cus__load(kprobes_cus, kprobes_filename) != 0) {

View File

@ -52,7 +52,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
cus = cus__new(NULL, NULL);
cus = cus__new(NULL, NULL, NULL);
if (cus == NULL) {
fputs("dtagnames: insufficient memory\n", stderr);
return EXIT_FAILURE;

View File

@ -334,7 +334,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
cus = cus__new(NULL, NULL);
cus = cus__new(NULL, NULL, NULL);
if (cus == NULL) {
fputs("pahole: insufficient memory\n", stderr);
return EXIT_FAILURE;

View File

@ -378,7 +378,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
cus = cus__new(NULL, NULL);
cus = cus__new(NULL, NULL, NULL);
if (cus == NULL) {
fputs("pfunct: insufficient memory\n", stderr);
return EXIT_FAILURE;

View File

@ -171,7 +171,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
cus = cus__new(NULL, NULL);
cus = cus__new(NULL, NULL, NULL);
if (cus == NULL) {
fputs("prefcnt: insufficient memory\n", stderr);
return EXIT_FAILURE;