Refactor the def handling code a little.

This commit is contained in:
Bill Currie 2011-04-03 13:03:22 +09:00
parent 6d0b13dbf0
commit 7f67e6eb17

View file

@ -269,9 +269,8 @@ resolve_external_def (defref_t *ext, defref_t *def)
} }
static void static void
process_def (defref_t *ref, qfo_mspace_t *space, int field) define_def (defref_t *ref, int field)
{ {
qfo_def_t *def;
defref_t *r; defref_t *r;
const char *name; const char *name;
hashtab_t *extern_tab = extern_defs; hashtab_t *extern_tab = extern_defs;
@ -281,31 +280,17 @@ process_def (defref_t *ref, qfo_mspace_t *space, int field)
extern_tab = extern_field_defs; extern_tab = extern_field_defs;
defined_tab = defined_field_defs; defined_tab = defined_field_defs;
} }
def = REF (ref); name = WORKSTR (REF (ref)->name);
name = WORKSTR (def->name); if ((r = Hash_Find (defined_tab, name))) {
r = Hash_Find (defined_tab, name);
if (def->flags & QFOD_EXTERNAL) {
if (!def->num_relocs)
return;
if (r) {
resolve_external_def (ref, r);
} else {
Hash_Add (extern_tab, ref);
}
} else {
if (!(def->flags & QFOD_LOCAL))
def->offset += space->data_size;
if (def->flags & QFOD_GLOBAL) {
if (r) {
if (REF (r)->flags & QFOD_SYSTEM) { if (REF (r)->flags & QFOD_SYSTEM) {
/// System defs may be redefined only once. /// System defs may be redefined only once.
REF (r)->flags &= ~QFOD_SYSTEM; REF (r)->flags &= ~QFOD_SYSTEM;
// treat the new def as external // treat the new def as external
def->flags |= QFOD_EXTERNAL; REF (ref)->flags |= QFOD_EXTERNAL;
resolve_external_def (ref, r); resolve_external_def (ref, r);
//FIXME copy stuff from new def to existing def??? //FIXME copy stuff from new def to existing def???
} else { } else {
def_error (def, "%s redefined", WORKSTR (def->name)); def_error (REF (ref), "%s redefined", WORKSTR (REF (ref)->name));
def_error (REF (r), "previous definition"); def_error (REF (r), "previous definition");
} }
return; return;
@ -314,6 +299,34 @@ process_def (defref_t *ref, qfo_mspace_t *space, int field)
while ((r = Hash_Del (extern_tab, name))) while ((r = Hash_Del (extern_tab, name)))
resolve_external_def (r, ref); resolve_external_def (r, ref);
} }
static void
process_def (defref_t *ref, qfo_mspace_t *space, int field)
{
defref_t *r;
const char *name;
hashtab_t *extern_tab = extern_defs;
hashtab_t *defined_tab = defined_defs;
if (field) {
extern_tab = extern_field_defs;
defined_tab = defined_field_defs;
}
if (REF (ref)->flags & QFOD_EXTERNAL) {
name = WORKSTR (REF (ref)->name);
r = Hash_Find (defined_tab, name);
if (!REF (ref)->num_relocs)
return;
if (r) {
resolve_external_def (ref, r);
} else {
Hash_Add (extern_tab, ref);
}
} else {
if (!(REF (ref)->flags & QFOD_LOCAL))
REF (ref)->offset += space->data_size;
if (REF (ref)->flags & QFOD_GLOBAL)
define_def (ref, field);
} }
} }
@ -512,15 +525,15 @@ transfer_type (qfo_t *qfo, qfo_mspace_t *space, pointer_t type_offset)
} }
static defref_t * static defref_t *
define_def (const char *name, type_t *type, unsigned flags, int v) make_def (int s, const char *name, type_t *type, unsigned flags, int v)
{ {
qfo_def_t *def; qfo_def_t *def;
defref_t *ref; defref_t *ref;
qfo_mspace_t *space; qfo_mspace_t *space;
defspace_t *def_space; defspace_t *def_space;
space = &work->spaces[qfo_near_data_space]; space = &work->spaces[s];
def_space = work_near_data; def_space = *work_spaces[s];
space->defs = realloc (space->defs, space->defs = realloc (space->defs,
(space->num_defs + 1) * sizeof (qfo_def_t)); (space->num_defs + 1) * sizeof (qfo_def_t));
@ -541,7 +554,7 @@ define_def (const char *name, type_t *type, unsigned flags, int v)
work_defrefs = realloc (work_defrefs, work_defrefs = realloc (work_defrefs,
(num_work_defrefs + 1) * sizeof (defref_t *)); (num_work_defrefs + 1) * sizeof (defref_t *));
work_defrefs[num_work_defrefs++] = ref; work_defrefs[num_work_defrefs++] = ref;
Hash_Add (defined_defs, ref); define_def (ref, s == qfo_entity_space);
return ref; return ref;
} }
@ -549,7 +562,7 @@ define_def (const char *name, type_t *type, unsigned flags, int v)
void void
linker_add_def (const char *name, type_t *type, unsigned flags, int v) linker_add_def (const char *name, type_t *type, unsigned flags, int v)
{ {
define_def (name, type, flags, v); make_def (qfo_near_data_space, name, type, flags, v);
} }
/** Initialize the linker state. /** Initialize the linker state.
@ -611,7 +624,8 @@ linker_begin (void)
if (!options.partial_link) { if (!options.partial_link) {
for (i = 0; i < num_builtins; i++) { for (i = 0; i < num_builtins; i++) {
builtin_sym_t *bi = builtin_symbols + i; builtin_sym_t *bi = builtin_symbols + i;
bi->defref = define_def (bi->name, bi->type, bi->flags, 0); bi->defref = make_def (qfo_near_data_space, bi->name, bi->type,
bi->flags, 0);
} }
} }
} }