mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-31 13:10:34 +00:00
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:
parent
919ea8192a
commit
7412a45c65
3 changed files with 30 additions and 3 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue