[CLASSES]: Use just one tags list in struct lexblock
To preserve ordering, even with DW_tag_label tags not being kept in order by gcc its better to have just one list, uses less space and keeps what is in the dwarf sections. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This commit is contained in:
parent
5b17097b2e
commit
214a115dc6
128
classes.c
128
classes.c
|
@ -353,7 +353,6 @@ static void cu__add_function(struct cu *self, struct function *function)
|
||||||
|
|
||||||
static void cu__add_variable(struct cu *self, struct variable *variable)
|
static void cu__add_variable(struct cu *self, struct variable *variable)
|
||||||
{
|
{
|
||||||
variable->cu = self;
|
|
||||||
list_add_tail(&variable->cu_node, &self->variables);
|
list_add_tail(&variable->cu_node, &self->variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,24 +608,24 @@ const char *tag__name(const struct tag *self, const struct cu *cu,
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *variable__type_name(const struct variable *self,
|
const char *variable__type_name(const struct variable *self,
|
||||||
|
const struct cu *cu,
|
||||||
char *bf, size_t len)
|
char *bf, size_t len)
|
||||||
{
|
{
|
||||||
if (self->tag.type != 0) {
|
if (self->tag.type != 0) {
|
||||||
struct tag *tag = cu__find_tag_by_id(self->cu, self->tag.type);
|
struct tag *tag = cu__find_tag_by_id(cu, self->tag.type);
|
||||||
return tag__name(tag, self->cu, bf, len);
|
return tag__name(tag, cu, bf, len);
|
||||||
} else if (self->abstract_origin != 0) {
|
} else if (self->abstract_origin != 0) {
|
||||||
struct variable *var;
|
struct variable *var;
|
||||||
|
|
||||||
var = cu__find_variable_by_id(self->cu,
|
var = cu__find_variable_by_id(cu, self->abstract_origin);
|
||||||
self->abstract_origin);
|
|
||||||
if (var != NULL)
|
if (var != NULL)
|
||||||
return variable__type_name(var, bf, len);
|
return variable__type_name(var, cu, bf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *variable__name(const struct variable *self)
|
const char *variable__name(const struct variable *self, const struct cu *cu)
|
||||||
{
|
{
|
||||||
if (self->name == NULL) {
|
if (self->name == NULL) {
|
||||||
if (self->abstract_origin == 0)
|
if (self->abstract_origin == 0)
|
||||||
|
@ -634,7 +633,7 @@ const char *variable__name(const struct variable *self)
|
||||||
else {
|
else {
|
||||||
struct variable *var;
|
struct variable *var;
|
||||||
|
|
||||||
var = cu__find_variable_by_id(self->cu,
|
var = cu__find_variable_by_id(cu,
|
||||||
self->abstract_origin);
|
self->abstract_origin);
|
||||||
return var == NULL ? NULL : var->name;
|
return var == NULL ? NULL : var->name;
|
||||||
}
|
}
|
||||||
|
@ -996,10 +995,7 @@ static void enumeration__add(struct class *self,
|
||||||
static void lexblock__init(struct lexblock *self,
|
static void lexblock__init(struct lexblock *self,
|
||||||
Dwarf_Addr low_pc, Dwarf_Addr high_pc)
|
Dwarf_Addr low_pc, Dwarf_Addr high_pc)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&self->inline_expansions);
|
INIT_LIST_HEAD(&self->tags);
|
||||||
INIT_LIST_HEAD(&self->labels);
|
|
||||||
INIT_LIST_HEAD(&self->lexblocks);
|
|
||||||
INIT_LIST_HEAD(&self->variables);
|
|
||||||
|
|
||||||
self->nr_inline_expansions =
|
self->nr_inline_expansions =
|
||||||
self->nr_labels =
|
self->nr_labels =
|
||||||
|
@ -1031,7 +1027,7 @@ static void lexblock__add_lexblock(struct lexblock *self,
|
||||||
struct lexblock *child)
|
struct lexblock *child)
|
||||||
{
|
{
|
||||||
++self->nr_lexblocks;
|
++self->nr_lexblocks;
|
||||||
list_add_tail(&child->tag.node, &self->lexblocks);
|
list_add_tail(&child->tag.node, &self->tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ftype__init(struct ftype *self, uint16_t tag,
|
static ftype__init(struct ftype *self, uint16_t tag,
|
||||||
|
@ -1105,19 +1101,19 @@ static void lexblock__add_inline_expansion(struct lexblock *self,
|
||||||
{
|
{
|
||||||
++self->nr_inline_expansions;
|
++self->nr_inline_expansions;
|
||||||
self->size_inline_expansions += exp->size;
|
self->size_inline_expansions += exp->size;
|
||||||
list_add_tail(&exp->tag.node, &self->inline_expansions);
|
list_add_tail(&exp->tag.node, &self->tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lexblock__add_variable(struct lexblock *self, struct variable *var)
|
static void lexblock__add_variable(struct lexblock *self, struct variable *var)
|
||||||
{
|
{
|
||||||
++self->nr_variables;
|
++self->nr_variables;
|
||||||
list_add_tail(&var->tag.node, &self->variables);
|
list_add_tail(&var->tag.node, &self->tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lexblock__add_label(struct lexblock *self, struct label *label)
|
static void lexblock__add_label(struct lexblock *self, struct label *label)
|
||||||
{
|
{
|
||||||
++self->nr_labels;
|
++self->nr_labels;
|
||||||
list_add_tail(&label->tag.node, &self->labels);
|
list_add_tail(&label->tag.node, &self->tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct class_member *class__find_bit_hole(const struct class *self,
|
const struct class_member *class__find_bit_hole(const struct class *self,
|
||||||
|
@ -1220,19 +1216,28 @@ struct class_member *class__find_member_by_name(const struct class *self,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void function__account_inline_expansions(struct function *self)
|
static void lexblock__account_inline_expansions(struct lexblock *self,
|
||||||
|
const struct cu *cu)
|
||||||
{
|
{
|
||||||
struct function *type;
|
struct function *type;
|
||||||
struct inline_expansion *pos;
|
struct tag *pos;
|
||||||
|
|
||||||
if (self->lexblock.nr_inline_expansions == 0)
|
if (self->nr_inline_expansions == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
list_for_each_entry(pos, &self->lexblock.inline_expansions, tag.node) {
|
list_for_each_entry(pos, &self->tags, node) {
|
||||||
type = cu__find_function_by_id(self->cu, pos->tag.type);
|
if (pos->tag == DW_TAG_lexical_block) {
|
||||||
|
lexblock__account_inline_expansions(tag__lexblock(pos),
|
||||||
|
cu);
|
||||||
|
continue;
|
||||||
|
} else if (pos->tag != DW_TAG_inlined_subroutine)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
type = cu__find_function_by_id(cu, pos->type);
|
||||||
if (type != NULL) {
|
if (type != NULL) {
|
||||||
type->cu_total_nr_inline_expansions++;
|
type->cu_total_nr_inline_expansions++;
|
||||||
type->cu_total_size_inline_expansions += pos->size;
|
type->cu_total_size_inline_expansions +=
|
||||||
|
tag__inline_expansion(pos)->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1243,7 +1248,7 @@ void cu__account_inline_expansions(struct cu *self)
|
||||||
struct function *pos;
|
struct function *pos;
|
||||||
|
|
||||||
list_for_each_entry(pos, &self->functions, proto.tag.node) {
|
list_for_each_entry(pos, &self->functions, proto.tag.node) {
|
||||||
function__account_inline_expansions(pos);
|
lexblock__account_inline_expansions(&pos->lexblock, self);
|
||||||
self->nr_inline_expansions += pos->lexblock.nr_inline_expansions;
|
self->nr_inline_expansions += pos->lexblock.nr_inline_expansions;
|
||||||
self->size_inline_expansions += pos->lexblock.size_inline_expansions;
|
self->size_inline_expansions += pos->lexblock.size_inline_expansions;
|
||||||
}
|
}
|
||||||
|
@ -1273,43 +1278,50 @@ static void tags__add(void *tags, const struct tag *tag)
|
||||||
tsearch(tag, tags, tags__compare);
|
tsearch(tag, tags, tags__compare);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lexblock__print(const struct lexblock *self);
|
static void lexblock__print(const struct lexblock *self, const struct cu *cu,
|
||||||
|
int indent);
|
||||||
|
|
||||||
static void function__tag_print(const struct tag *tag)
|
static void function__tag_print(const struct tag *tag, const struct cu *cu,
|
||||||
|
int indent)
|
||||||
{
|
{
|
||||||
char bf[512];
|
char bf[512];
|
||||||
const void *vtag = tag;
|
const void *vtag = tag;
|
||||||
int c = 8;
|
int c;
|
||||||
|
|
||||||
|
if (indent >= sizeof(tabs))
|
||||||
|
indent = sizeof(tabs) - 1;
|
||||||
|
c = indent * 8;
|
||||||
|
|
||||||
switch (tag->tag) {
|
switch (tag->tag) {
|
||||||
case DW_TAG_inlined_subroutine: {
|
case DW_TAG_inlined_subroutine: {
|
||||||
const struct inline_expansion *exp = vtag;
|
const struct inline_expansion *exp = vtag;
|
||||||
const struct function *alias =
|
const struct function *alias =
|
||||||
cu__find_function_by_id(exp->cu,
|
cu__find_function_by_id(cu, exp->tag.type);
|
||||||
exp->tag.type);
|
|
||||||
|
|
||||||
assert(alias != NULL);
|
assert(alias != NULL);
|
||||||
fputs(" ", stdout);
|
printf("%.*s", indent, tabs);
|
||||||
c += printf("%s(); /* low_pc=%#llx */",
|
c += printf("%s(); /* low_pc=%#llx */",
|
||||||
alias->name, exp->low_pc);
|
alias->name, exp->low_pc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DW_TAG_variable:
|
case DW_TAG_variable:
|
||||||
fputs(" ", stdout);
|
printf("%.*s", indent, tabs);
|
||||||
c += printf("%s %s;", variable__type_name(vtag, bf, sizeof(bf)),
|
c += printf("%s %s;", variable__type_name(vtag, cu,
|
||||||
variable__name(vtag));
|
bf, sizeof(bf)),
|
||||||
|
variable__name(vtag, cu));
|
||||||
break;
|
break;
|
||||||
case DW_TAG_label: {
|
case DW_TAG_label: {
|
||||||
const struct label *label = vtag;
|
const struct label *label = vtag;
|
||||||
|
printf("%.*s", indent, tabs);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
c = printf("%s:", label->name);
|
c = printf("%s:", label->name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DW_TAG_lexical_block:
|
case DW_TAG_lexical_block:
|
||||||
lexblock__print(vtag);
|
lexblock__print(vtag, cu, indent);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
fputs(" ", stdout);
|
printf("%.*s", indent, tabs);
|
||||||
c += printf("%s <%llx>", dwarf_tag_name(tag->tag), tag->id);
|
c += printf("%s <%llx>", dwarf_tag_name(tag->tag), tag->id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1317,46 +1329,17 @@ static void function__tag_print(const struct tag *tag)
|
||||||
printf("%-*.*s// %5u\n", 70 - c, 70 - c, " ", tag->decl_line);
|
printf("%-*.*s// %5u\n", 70 - c, 70 - c, " ", tag->decl_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void function__tags_action(const void *nodep, const VISIT which,
|
static void lexblock__print(const struct lexblock *self, const struct cu *cu,
|
||||||
const int depth)
|
int indent)
|
||||||
{
|
{
|
||||||
if (which == postorder || which == leaf) {
|
|
||||||
const struct tag *tag = *(struct tag **)nodep;
|
|
||||||
function__tag_print(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lexblock__print(const struct lexblock *self)
|
|
||||||
{
|
|
||||||
void *tags = NULL;
|
|
||||||
struct tag *pos;
|
struct tag *pos;
|
||||||
|
|
||||||
list_for_each_entry(pos, &self->variables, node) {
|
if (indent >= sizeof(tabs))
|
||||||
/* FIXME! this test shouln't be needed at all */
|
indent = sizeof(tabs) - 1;
|
||||||
if (pos->decl_line >= self->tag.decl_line)
|
printf("%.*s{\n", indent, tabs);
|
||||||
tags__add(&tags, pos);
|
list_for_each_entry(pos, &self->tags, node)
|
||||||
}
|
function__tag_print(pos, cu, indent + 1);
|
||||||
|
printf("%.*s}\n", indent, tabs);
|
||||||
list_for_each_entry(pos, &self->inline_expansions, node) {
|
|
||||||
/* FIXME! this test shouln't be needed at all */
|
|
||||||
if (pos->decl_line >= self->tag.decl_line)
|
|
||||||
tags__add(&tags, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(pos, &self->labels, node) {
|
|
||||||
/* FIXME! this test shouln't be needed at all */
|
|
||||||
if (pos->decl_line >= self->tag.decl_line)
|
|
||||||
tags__add(&tags, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(pos, &self->lexblocks, node)
|
|
||||||
tags__add(&tags, pos);
|
|
||||||
|
|
||||||
puts("{");
|
|
||||||
twalk(tags, function__tags_action);
|
|
||||||
puts("}\n");
|
|
||||||
|
|
||||||
tdestroy(tags, tags__free);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ftype__snprintf(const struct ftype *self, const struct cu *cu,
|
size_t ftype__snprintf(const struct ftype *self, const struct cu *cu,
|
||||||
|
@ -1434,7 +1417,7 @@ void function__print(const struct function *self, int show_stats,
|
||||||
|
|
||||||
if (show_variables || show_inline_expansions) {
|
if (show_variables || show_inline_expansions) {
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
lexblock__print(&self->lexblock);
|
lexblock__print(&self->lexblock, self->cu, 0);
|
||||||
} else
|
} else
|
||||||
puts(";");
|
puts(";");
|
||||||
|
|
||||||
|
@ -2102,7 +2085,6 @@ static void cu__create_new_inline_expansion(Dwarf *dwarf, Dwarf_Die *die,
|
||||||
if (exp == NULL)
|
if (exp == NULL)
|
||||||
oom("inline_expansion__new");
|
oom("inline_expansion__new");
|
||||||
|
|
||||||
exp->cu = cu;
|
|
||||||
lexblock__add_inline_expansion(lexblock, exp);
|
lexblock__add_inline_expansion(lexblock, exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
classes.h
27
classes.h
|
@ -116,10 +116,7 @@ struct class_member {
|
||||||
|
|
||||||
struct lexblock {
|
struct lexblock {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
struct list_head inline_expansions;
|
struct list_head tags;
|
||||||
struct list_head labels;
|
|
||||||
struct list_head variables;
|
|
||||||
struct list_head lexblocks;
|
|
||||||
Dwarf_Addr low_pc;
|
Dwarf_Addr low_pc;
|
||||||
Dwarf_Addr high_pc;
|
Dwarf_Addr high_pc;
|
||||||
uint16_t nr_inline_expansions;
|
uint16_t nr_inline_expansions;
|
||||||
|
@ -129,6 +126,11 @@ struct lexblock {
|
||||||
size_t size_inline_expansions;
|
size_t size_inline_expansions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline struct lexblock *tag__lexblock(const struct tag *self)
|
||||||
|
{
|
||||||
|
return (struct lexblock *)self;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tag.tag can be DW_TAG_subprogram_type or DW_TAG_subroutine_type.
|
* tag.tag can be DW_TAG_subprogram_type or DW_TAG_subroutine_type.
|
||||||
*/
|
*/
|
||||||
|
@ -166,20 +168,29 @@ struct parameter {
|
||||||
|
|
||||||
struct variable {
|
struct variable {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
struct cu *cu;
|
|
||||||
struct list_head cu_node;
|
struct list_head cu_node;
|
||||||
char *name;
|
char *name;
|
||||||
Dwarf_Off abstract_origin;
|
Dwarf_Off abstract_origin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline struct variable *tag__variable(const struct tag *self)
|
||||||
|
{
|
||||||
|
return (struct variable *)self;
|
||||||
|
}
|
||||||
|
|
||||||
struct inline_expansion {
|
struct inline_expansion {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
struct cu *cu;
|
|
||||||
size_t size;
|
size_t size;
|
||||||
Dwarf_Addr low_pc;
|
Dwarf_Addr low_pc;
|
||||||
Dwarf_Addr high_pc;
|
Dwarf_Addr high_pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline struct inline_expansion *
|
||||||
|
tag__inline_expansion(const struct tag *self)
|
||||||
|
{
|
||||||
|
return (struct inline_expansion *)self;
|
||||||
|
}
|
||||||
|
|
||||||
struct label {
|
struct label {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -293,8 +304,10 @@ extern size_t class_member__names(const struct tag *type,
|
||||||
char *member_name, size_t member_name_size);
|
char *member_name, size_t member_name_size);
|
||||||
extern size_t cacheline_size;
|
extern size_t cacheline_size;
|
||||||
|
|
||||||
extern const char *variable__name(const struct variable *self);
|
extern const char *variable__name(const struct variable *self,
|
||||||
|
const struct cu *cu);
|
||||||
extern const char *variable__type_name(const struct variable *self,
|
extern const char *variable__type_name(const struct variable *self,
|
||||||
|
const struct cu *cu,
|
||||||
char *bf, size_t len);
|
char *bf, size_t len);
|
||||||
|
|
||||||
extern const char *dwarf_tag_name(const uint32_t tag);
|
extern const char *dwarf_tag_name(const uint32_t tag);
|
||||||
|
|
29
prefcnt.c
29
prefcnt.c
|
@ -54,20 +54,21 @@ static void refcnt_parameter(const struct parameter *parameter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void refcnt_variable(const struct variable *variable)
|
static void refcnt_variable(const struct variable *variable,
|
||||||
|
const struct cu *cu)
|
||||||
{
|
{
|
||||||
if (variable->tag.type != 0) { /* if not void */
|
if (variable->tag.type != 0) { /* if not void */
|
||||||
struct tag *type = cu__find_tag_by_id(variable->cu,
|
struct tag *type = cu__find_tag_by_id(cu, variable->tag.type);
|
||||||
variable->tag.type);
|
|
||||||
if (type != NULL)
|
if (type != NULL)
|
||||||
refcnt_tag(type);
|
refcnt_tag(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void refcnt_inline_expansion(const struct inline_expansion *exp)
|
static void refcnt_inline_expansion(const struct inline_expansion *exp,
|
||||||
|
const struct cu *cu)
|
||||||
{
|
{
|
||||||
if (exp->tag.type != 0) { /* if not void */
|
if (exp->tag.type != 0) { /* if not void */
|
||||||
struct tag *type = cu__find_tag_by_id(exp->cu, exp->tag.type);
|
struct tag *type = cu__find_tag_by_id(cu, exp->tag.type);
|
||||||
if (type != NULL)
|
if (type != NULL)
|
||||||
refcnt_tag(type);
|
refcnt_tag(type);
|
||||||
}
|
}
|
||||||
|
@ -88,8 +89,7 @@ static void refcnt_tag(struct tag *tag)
|
||||||
static void refcnt_function(struct function *function)
|
static void refcnt_function(struct function *function)
|
||||||
{
|
{
|
||||||
struct parameter *parameter;
|
struct parameter *parameter;
|
||||||
struct inline_expansion *exp;
|
struct tag *pos;
|
||||||
struct variable *variable;
|
|
||||||
|
|
||||||
function->proto.tag.refcnt++;
|
function->proto.tag.refcnt++;
|
||||||
|
|
||||||
|
@ -103,11 +103,16 @@ static void refcnt_function(struct function *function)
|
||||||
list_for_each_entry(parameter, &function->proto.parms, tag.node)
|
list_for_each_entry(parameter, &function->proto.parms, tag.node)
|
||||||
refcnt_parameter(parameter, function->cu);
|
refcnt_parameter(parameter, function->cu);
|
||||||
|
|
||||||
list_for_each_entry(variable, &function->lexblock.variables, tag.node)
|
list_for_each_entry(pos, &function->lexblock.tags, node)
|
||||||
refcnt_variable(variable);
|
switch (pos->tag) {
|
||||||
|
case DW_TAG_variable:
|
||||||
list_for_each_entry(exp, &function->lexblock.inline_expansions, tag.node)
|
refcnt_variable(tag__variable(pos), function->cu);
|
||||||
refcnt_inline_expansion(exp);
|
break;
|
||||||
|
case DW_TAG_inlined_subroutine:
|
||||||
|
refcnt_inline_expansion(tag__inline_expansion(pos),
|
||||||
|
function->cu);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int refcnt_function_iterator(struct function *function, void *cookie)
|
static int refcnt_function_iterator(struct function *function, void *cookie)
|
||||||
|
|
Loading…
Reference in New Issue