Attach alias defs to their base def.

With this, alias defs become singletons based on the def they alias and the
type and offset of the alias. Thus, the removal of the free_def call in
emit.c.
This commit is contained in:
Bill Currie 2012-12-03 12:40:00 +09:00
parent 919ea8192a
commit 7412a45c65
3 changed files with 30 additions and 3 deletions

View file

@ -61,6 +61,7 @@ typedef struct def_s {
struct defspace_s *space; ///< defspace to which this def belongs
int offset; ///< address of this def in its defspace
struct def_s *alias_defs; ///< defs that alias this def
struct def_s *alias; ///< real def which this def aliases
struct reloc_s *relocs; ///< for relocations
struct expr_s *initializer;///< initialer expression
@ -81,6 +82,7 @@ typedef struct def_s {
int qfo_def; ///< index to def in qfo defs
void *return_addr; ///< who allocated this
void *free_addr; ///< who freed this
} def_t;
/** Specify the storage class of a def.
@ -123,6 +125,12 @@ def_t *new_def (const char *name, struct type_s *type,
is greater than the size of the def's type, then an internal error will
be generated.
The alias def keeps track of its base def and is attached to the base def
so any aliases of that def can be found.
For any combination of type and offset, there will be only one alias def
created.
\param def The def to be aliased.
\param type The type of the alias.
\param offset Offset of the alias relative to the def.

View file

@ -159,6 +159,10 @@ alias_def (def_t *def, type_t *type, int offset)
internal_error (0, "aliasing a def to a larger type");
if (offset < 0 || offset + type_size (type) > type_size (def->type))
internal_error (0, "invalid alias offset");
for (alias = def->alias_defs; alias; alias = alias->next) {
if (alias->type == type && alias->offset == offset)
return alias;
}
ALLOC (16384, def_t, defs, alias);
alias->return_addr = __builtin_return_address (0);
alias->offset = offset;
@ -167,6 +171,8 @@ alias_def (def_t *def, type_t *type, int offset)
alias->alias = def;
alias->line = pr.source_line;
alias->file = pr.source_file;
alias->next = def->alias_defs;
def->alias_defs = alias;
return alias;
}
@ -206,7 +212,20 @@ free_temp_def (def_t *temp)
void
free_def (def_t *def)
{
if (!def->alias && def->space) {
if (!def->return_addr)
internal_error (0, "double free of def");
if (def->alias) {
def_t **a;
// pull the alias out of the base def's list of alias defs to avoid
// messing up the list when the alias def is freed.
for (a = &def->alias->alias_defs; *a; a = &(*a)->next) {
if (*a == def) {
*a = def->next;
break;
}
}
} else if (def->space) {
def_t **d;
for (d = &def->space->defs; *d && *d != def; d = &(*d)->next)
@ -219,6 +238,8 @@ free_def (def_t *def)
if (!def->external)
defspace_free_loc (def->space, def->offset, type_size (def->type));
}
def->return_addr = 0;
def->free_addr = __builtin_return_address (0);
def->next = free_defs;
free_defs = def;
}

View file

@ -143,10 +143,8 @@ add_statement_def_ref (def_t *def, dstatement_t *st, int field)
alias_depth_expr.line = def->line;
}
alias_depth++;
def_t *a = def;
offset_reloc |= def->offset_reloc;
def = def->alias;
free_def (a);
}
if (alias_depth > 1) {
internal_error (&alias_depth_expr, "alias chain detected: %d %s",