mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-30 04:30:43 +00:00
better relocations: pointers to structure members now work
This commit is contained in:
parent
59d321ded5
commit
11c7c27f70
6 changed files with 89 additions and 22 deletions
|
@ -45,6 +45,10 @@ typedef enum {
|
|||
rel_def_func,
|
||||
rel_def_string,
|
||||
rel_def_field,
|
||||
rel_op_a_def_ofs,
|
||||
rel_op_b_def_ofs,
|
||||
rel_op_c_def_ofs,
|
||||
rel_def_def_ofs,
|
||||
} reloc_type;
|
||||
|
||||
typedef struct reloc_s {
|
||||
|
@ -59,7 +63,10 @@ struct statement_s;
|
|||
|
||||
reloc_t *new_reloc (int ofs, reloc_type type);
|
||||
void relocate_refs (reloc_t *refs, int ofs);
|
||||
void reloc_op_def (struct def_s *def, int ofs, int field);
|
||||
void reloc_op_def_ofs (struct def_s *def, int ofs, int field);
|
||||
void reloc_def_def (struct def_s *def, int ofs);
|
||||
void reloc_def_def_ofs (struct def_s *def, int ofs);
|
||||
void reloc_def_func (struct function_s *func, int ofs);
|
||||
void reloc_def_string (int ofs);
|
||||
void reloc_def_field (struct def_s *def, int ofs);
|
||||
|
|
|
@ -97,16 +97,16 @@ codespace_newstatement (codespace_t *codespace)
|
|||
}
|
||||
|
||||
static void
|
||||
add_statement_ref (def_t *def, dstatement_t *st, reloc_type type)
|
||||
add_statement_ref (def_t *def, dstatement_t *st, int field)
|
||||
{
|
||||
if (def) {
|
||||
reloc_t *ref = new_reloc (st - pr.code->code, type);
|
||||
int st_ofs = st - pr.code->code;
|
||||
|
||||
if (def->alias)
|
||||
if (def->alias) {
|
||||
def = def->alias;
|
||||
|
||||
ref->next = def->refs;
|
||||
def->refs = ref;
|
||||
reloc_op_def_ofs (def, st_ofs, field);
|
||||
} else
|
||||
reloc_op_def (def, st_ofs, field);
|
||||
|
||||
def->users--;
|
||||
def->used = 1;
|
||||
|
@ -162,9 +162,9 @@ emit_statement (expr_t *e, opcode_t *op, def_t *var_a, def_t *var_b,
|
|||
var_c ? var_c->name : "", statement->c);
|
||||
#endif
|
||||
|
||||
add_statement_ref (var_a, statement, rel_op_a_def);
|
||||
add_statement_ref (var_b, statement, rel_op_b_def);
|
||||
add_statement_ref (var_c, statement, rel_op_c_def);
|
||||
add_statement_ref (var_a, statement, 0);
|
||||
add_statement_ref (var_b, statement, 1);
|
||||
add_statement_ref (var_c, statement, 2);
|
||||
|
||||
if (op->right_associative)
|
||||
return var_a;
|
||||
|
@ -384,11 +384,10 @@ emit_deref_expr (expr_t *e, def_t *dest)
|
|||
e = e->e.expr.e1;
|
||||
if (e->type == ex_pointer) {
|
||||
if (e->e.pointer.def) {
|
||||
d = new_def (e->e.pointer.type, 0, current_scope);
|
||||
d = new_def (e->e.pointer.type, 0, e->e.pointer.def->scope);
|
||||
d->local = e->e.pointer.def->local;
|
||||
d->ofs = POINTER_VAL (e->e.pointer);
|
||||
if (d->ofs == e->e.pointer.def->ofs)
|
||||
d->alias = e->e.pointer.def;
|
||||
d->ofs = e->e.pointer.val;
|
||||
d->alias = e->e.pointer.def;
|
||||
} else if (e->e.pointer.val >= 0 && e->e.pointer.val < 65536) {
|
||||
d = new_def (e->e.pointer.type, 0, current_scope);
|
||||
d->ofs = e->e.pointer.val;
|
||||
|
|
|
@ -1249,7 +1249,7 @@ field_expr (expr_t *e1, expr_t *e2)
|
|||
e = new_expr ();
|
||||
e->type = ex_pointer;
|
||||
e1 = e1->e.expr.e1;
|
||||
i = POINTER_VAL (e1->e.pointer);
|
||||
i = e1->e.pointer.val;
|
||||
e->e.pointer.val = i + field->offset;
|
||||
e->e.pointer.type = field->type;
|
||||
return unary_expr ('.', e);
|
||||
|
|
|
@ -215,6 +215,9 @@ add_relocs (qfo_t *qfo)
|
|||
case rel_op_a_def:
|
||||
case rel_op_b_def:
|
||||
case rel_op_c_def:
|
||||
case rel_op_a_def_ofs:
|
||||
case rel_op_b_def_ofs:
|
||||
case rel_op_c_def_ofs:
|
||||
reloc->ofs += code_base;
|
||||
break;
|
||||
case rel_op_a_op:
|
||||
|
@ -232,6 +235,7 @@ add_relocs (qfo_t *qfo)
|
|||
DATA (reloc->ofs)->func_var = reloc->def + 1;
|
||||
break;
|
||||
case rel_def_def:
|
||||
case rel_def_def_ofs:
|
||||
reloc->ofs += data_base;
|
||||
break;
|
||||
case rel_def_string:
|
||||
|
@ -470,6 +474,10 @@ fixup_relocs (void)
|
|||
case rel_op_c_def:
|
||||
case rel_def_def:
|
||||
case rel_def_field:
|
||||
case rel_op_a_def_ofs:
|
||||
case rel_op_b_def_ofs:
|
||||
case rel_op_c_def_ofs:
|
||||
case rel_def_def_ofs:
|
||||
def = defs.defs + reloc->def;
|
||||
if (def->flags & (QFOD_EXTERNAL | QFOD_LOCAL | QFOD_ABSOLUTE))
|
||||
continue;
|
||||
|
@ -498,6 +506,10 @@ fixup_relocs (void)
|
|||
case rel_op_a_op:
|
||||
case rel_op_b_op:
|
||||
case rel_op_c_op:
|
||||
case rel_op_a_def_ofs:
|
||||
case rel_op_b_def_ofs:
|
||||
case rel_op_c_def_ofs:
|
||||
case rel_def_def_ofs:
|
||||
break;
|
||||
case rel_def_op:
|
||||
DATA (reloc->ofs)->integer_var = reloc->def;
|
||||
|
@ -806,8 +818,12 @@ undefined_def (qfo_def_t *def)
|
|||
qfo_reloc_t *reloc = relocs.relocs + def->relocs;
|
||||
|
||||
for (i = 0; i < def->num_relocs; i++, reloc++) {
|
||||
if ((reloc->type == rel_op_a_def || reloc->type == rel_op_b_def
|
||||
|| reloc->type == rel_op_c_def)
|
||||
if ((reloc->type == rel_op_a_def
|
||||
|| reloc->type == rel_op_b_def
|
||||
|| reloc->type == rel_op_c_def
|
||||
|| reloc->type == rel_op_a_def_ofs
|
||||
|| reloc->type == rel_op_b_def_ofs
|
||||
|| reloc->type == rel_op_c_def_ofs)
|
||||
&& lines.lines) {
|
||||
qfo_func_t *func = funcs.funcs;
|
||||
qfo_func_t *best = func;
|
||||
|
|
|
@ -426,11 +426,8 @@ finish_compilation (void)
|
|||
st_global));
|
||||
}
|
||||
|
||||
for (def = pr.scope->head; def; def = def->def_next) {
|
||||
if (def->global || def->absolute)
|
||||
continue;
|
||||
for (def = pr.scope->head; def; def = def->def_next)
|
||||
relocate_refs (def->refs, def->ofs);
|
||||
}
|
||||
|
||||
pr.functions = calloc (pr.num_functions + 1, sizeof (dfunction_t));
|
||||
for (df = pr.functions + 1, f = pr.func_head; f; df++, f = f->next) {
|
||||
|
@ -452,8 +449,6 @@ finish_compilation (void)
|
|||
}
|
||||
df->parm_start = pr.near_data->size;
|
||||
for (def = f->scope->head; def; def = def->def_next) {
|
||||
if (def->absolute)
|
||||
continue;
|
||||
def->ofs += pr.near_data->size;
|
||||
relocate_refs (def->refs, def->ofs);
|
||||
}
|
||||
|
|
|
@ -114,6 +114,30 @@ relocate_refs (reloc_t *refs, int ofs)
|
|||
break;
|
||||
case rel_def_field:
|
||||
break;
|
||||
case rel_op_a_def_ofs:
|
||||
o = ofs + pr.code->code[refs->ofs].a;
|
||||
if (o < 0 || o > 65535)
|
||||
error (0, "def offset out of range");
|
||||
else
|
||||
pr.code->code[refs->ofs].a = o;
|
||||
break;
|
||||
case rel_op_b_def_ofs:
|
||||
o = ofs + pr.code->code[refs->ofs].b;
|
||||
if (o < 0 || o > 65535)
|
||||
error (0, "def offset out of range");
|
||||
else
|
||||
pr.code->code[refs->ofs].b = o;
|
||||
break;
|
||||
case rel_op_c_def_ofs:
|
||||
o = ofs + pr.code->code[refs->ofs].c;
|
||||
if (o < 0 || o > 65535)
|
||||
error (0, "def offset out of range");
|
||||
else
|
||||
pr.code->code[refs->ofs].c = o;
|
||||
break;
|
||||
case rel_def_def_ofs:
|
||||
G_INT (refs->ofs) += ofs;
|
||||
break;
|
||||
}
|
||||
refs = refs->next;
|
||||
}
|
||||
|
@ -132,6 +156,24 @@ new_reloc (int ofs, reloc_type type)
|
|||
return ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_op_def (def_t *def, int ofs, int field)
|
||||
{
|
||||
reloc_t *ref = new_reloc (ofs, rel_op_a_def + field);
|
||||
ref->next = def->refs;
|
||||
def->refs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_op_def_ofs (def_t *def, int ofs, int field)
|
||||
{
|
||||
reloc_t *ref = new_reloc (ofs, rel_op_a_def_ofs + field);
|
||||
unsigned short x = (&pr.code->code[ofs].a)[field];
|
||||
printf ("%3d %c %3d %3d %s\n", ofs, 'a' + field, x, def->ofs, def->name);
|
||||
ref->next = def->refs;
|
||||
def->refs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_def (def_t *def, int ofs)
|
||||
{
|
||||
|
@ -140,6 +182,14 @@ reloc_def_def (def_t *def, int ofs)
|
|||
def->refs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_def_ofs (def_t *def, int ofs)
|
||||
{
|
||||
reloc_t *ref = new_reloc (ofs, rel_def_def_ofs);
|
||||
ref->next = def->refs;
|
||||
def->refs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_func (function_t *func, int ofs)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue