mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 15:01:41 +00:00
Make relocation records store the space of the relocation.
The space is meaningless for op_* relocations as they are always in the code space, but def_* relocations need to know which space holds the location to be adjusted.
This commit is contained in:
parent
cfdc2e5d6b
commit
181596f5bf
9 changed files with 146 additions and 73 deletions
|
@ -36,26 +36,35 @@ struct sblock_s;
|
|||
|
||||
void emit_statements (struct sblock_s *first_sblock);
|
||||
|
||||
#define EMIT_STRING(s,dest,str) \
|
||||
do { \
|
||||
(dest) = ReuseString (str); \
|
||||
reloc_def_string (POINTER_OFS (s, &(dest)));\
|
||||
#define EMIT_STRING(s,dest,str) \
|
||||
do { \
|
||||
def_t loc; \
|
||||
loc.space = s; \
|
||||
loc.offset = POINTER_OFS (s, &(dest)); \
|
||||
(dest) = ReuseString (str); \
|
||||
reloc_def_string (&loc);\
|
||||
} while (0)
|
||||
|
||||
#define EMIT_DEF(s,dest,def) \
|
||||
do { \
|
||||
def_t *d = (def); \
|
||||
(dest) = d ? d->offset : 0; \
|
||||
if (d) \
|
||||
reloc_def_def (d, POINTER_OFS (s, &(dest)));\
|
||||
#define EMIT_DEF(s,dest,def) \
|
||||
do { \
|
||||
def_t *d = (def); \
|
||||
def_t loc; \
|
||||
loc.space = s; \
|
||||
loc.offset = POINTER_OFS (s, &(dest)); \
|
||||
(dest) = d ? d->offset : 0; \
|
||||
if (d) \
|
||||
reloc_def_def (d, &loc); \
|
||||
} while (0)
|
||||
|
||||
#define EMIT_DEF_OFS(s,dest,def) \
|
||||
do { \
|
||||
def_t *d = (def); \
|
||||
(dest) = d ? d->offset : 0; \
|
||||
if (d) \
|
||||
reloc_def_def_ofs (d, POINTER_OFS (s, &(dest)));\
|
||||
#define EMIT_DEF_OFS(s,dest,def) \
|
||||
do { \
|
||||
def_t *d = (def); \
|
||||
def_t loc; \
|
||||
loc.space = s; \
|
||||
loc.offset = POINTER_OFS (s, &(dest)); \
|
||||
(dest) = d ? d->offset : 0; \
|
||||
if (d) \
|
||||
reloc_def_def_ofs (d, &loc); \
|
||||
} while (0)
|
||||
|
||||
#endif//__emit_h
|
||||
|
|
|
@ -70,7 +70,11 @@ typedef enum {
|
|||
typedef struct reloc_s {
|
||||
struct reloc_s *next; ///< next reloc in reloc chain
|
||||
struct ex_label_s *label; ///< instruction label for *_op relocs
|
||||
int offset; ///< the addressof the location in need of
|
||||
struct defspace_s *space; ///< the space containing the location in
|
||||
///< need of adjustment for def_* relocations
|
||||
///< (op_* relocations always use the code
|
||||
///< space)
|
||||
int offset; ///< the address of the location in need of
|
||||
///< adjustment
|
||||
reloc_type type; ///< type type of relocation to perform
|
||||
int line; ///< current source line when creating reloc
|
||||
|
@ -95,10 +99,11 @@ void relocate_refs (reloc_t *refs, int offset);
|
|||
The current source file and line will be preserved in the relocation
|
||||
record.
|
||||
|
||||
\param offset The address of the instruction that will be adjusted.
|
||||
\param space The defspace containting the location to be adjusted.
|
||||
\param offset The address of the location to be adjusted.
|
||||
\param type The type of relocation to be performed.
|
||||
*/
|
||||
reloc_t *new_reloc (int offset, reloc_type type);
|
||||
reloc_t *new_reloc (struct defspace_s *space, int offset, reloc_type type);
|
||||
|
||||
/** Create a relocation record for an instruction referencing a def.
|
||||
|
||||
|
@ -139,9 +144,11 @@ void reloc_op_def_ofs (struct def_s *def, int offset, int field);
|
|||
value stored in the data location.
|
||||
|
||||
\param def The def being referenced.
|
||||
\param offset The address of the data location that will be adjusted.
|
||||
\param location Def describing the location of the reference to be
|
||||
adjusted. As the def's space and offset will be copied
|
||||
into the relocation record, a dummy def may be used.
|
||||
*/
|
||||
void reloc_def_def (struct def_s *def, int offset);
|
||||
void reloc_def_def (struct def_s *def, struct def_s *location);
|
||||
|
||||
/** Create a relocation record for a data location referencing a def.
|
||||
|
||||
|
@ -152,9 +159,11 @@ void reloc_def_def (struct def_s *def, int offset);
|
|||
the value stored in the data location.
|
||||
|
||||
\param def The def being referenced.
|
||||
\param offset The address of the data location that will be adjusted.
|
||||
\param location Def describing the location of the reference to be
|
||||
adjusted. As the def's space and offset will be copied
|
||||
into the relocation record, a dummy def may be used.
|
||||
*/
|
||||
void reloc_def_def_ofs (struct def_s *def, int offset);
|
||||
void reloc_def_def_ofs (struct def_s *def, struct def_s *location);
|
||||
|
||||
/** Create a relocation record for a data location referencing a function.
|
||||
|
||||
|
@ -165,9 +174,11 @@ void reloc_def_def_ofs (struct def_s *def, int offset);
|
|||
value stored in the data location.
|
||||
|
||||
\param func The function being referenced.
|
||||
\param offset The address of the data location that will be adjusted.
|
||||
\param location Def describing the location of the reference to be
|
||||
adjusted. As the def's space and offset will be copied
|
||||
into the relocation record, a dummy def may be used.
|
||||
*/
|
||||
void reloc_def_func (struct function_s *func, int offset);
|
||||
void reloc_def_func (struct function_s *func, struct def_s *location);
|
||||
|
||||
/** Create a relocation record for a data location referencing a string.
|
||||
|
||||
|
@ -177,9 +188,11 @@ void reloc_def_func (struct function_s *func, int offset);
|
|||
When the relocation is performed, the string index will replace the
|
||||
value stored in the data location.
|
||||
|
||||
\param offset The address of the data location that will be adjusted.
|
||||
\param location Def describing the location of the reference to be
|
||||
adjusted. As the def's space and offset will be copied
|
||||
into the relocation record, a dummy def may be used.
|
||||
*/
|
||||
void reloc_def_string (int offset);
|
||||
void reloc_def_string (struct def_s *location);
|
||||
|
||||
/** Create a relocation record for a data location referencing a field.
|
||||
|
||||
|
@ -190,9 +203,11 @@ void reloc_def_string (int offset);
|
|||
value stored in the data location.
|
||||
|
||||
\param def The def representing the field being referenced.
|
||||
\param offset The address of the data location that will be adjusted.
|
||||
\param location Def describing the location of the reference to be
|
||||
adjusted. As the def's space and offset will be copied
|
||||
into the relocation record, a dummy def may be used.
|
||||
*/
|
||||
void reloc_def_field (struct def_s *def, int offset);
|
||||
void reloc_def_field (struct def_s *def, struct def_s *location);
|
||||
|
||||
/** Create a relocation record for a data location referencing a field.
|
||||
|
||||
|
@ -203,9 +218,11 @@ void reloc_def_field (struct def_s *def, int offset);
|
|||
the value stored in the data location.
|
||||
|
||||
\param def The def representing the field being referenced.
|
||||
\param offset The address of the data location that will be adjusted.
|
||||
\param location Def describing the location of the reference to be
|
||||
adjusted. As the def's space and offset will be copied
|
||||
into the relocation record, a dummy def may be used.
|
||||
*/
|
||||
void reloc_def_field_ofs (struct def_s *def, int offset);
|
||||
void reloc_def_field_ofs (struct def_s *def, struct def_s *location);
|
||||
|
||||
/** Create a relocation record for a data location referencing an
|
||||
instruction.
|
||||
|
@ -217,9 +234,11 @@ void reloc_def_field_ofs (struct def_s *def, int offset);
|
|||
value stored in the data location.
|
||||
|
||||
\param label The label representing the instruction being referenced.
|
||||
\param offset The address of the data location that will be adjusted.
|
||||
\param location Def describing the location of the reference to be
|
||||
adjusted. As the def's space and offset will be copied
|
||||
into the relocation record, a dummy def may be used.
|
||||
*/
|
||||
void reloc_def_op (struct ex_label_s *label, int offset);
|
||||
void reloc_def_op (struct ex_label_s *label, struct def_s *location);
|
||||
|
||||
///@}
|
||||
|
||||
|
|
|
@ -589,7 +589,7 @@ emit_class_ref (const char *class_name)
|
|||
name_def = name_sym->s.def;
|
||||
if (!name_def->external)
|
||||
D_INT (ref_def) = name_def->offset;
|
||||
reloc_def_def (name_def, ref_def->offset);
|
||||
reloc_def_def (name_def, ref_def);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -636,7 +636,7 @@ emit_category_ref (const char *class_name, const char *category_name)
|
|||
name_def = name_sym->s.def;
|
||||
if (!name_def->external)
|
||||
D_INT (ref_def) = name_def->offset;
|
||||
reloc_def_def (name_def, ref_def->offset);
|
||||
reloc_def_def (name_def, ref_def);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1030,7 +1030,7 @@ class_pointer_symbol (class_t *class)
|
|||
class->def = class_symbol (&class_type, 1)->s.def;
|
||||
if (!class->def->external)
|
||||
D_INT (def) = class->def->offset;
|
||||
reloc_def_def (class->def, def->offset);
|
||||
reloc_def_def (class->def, def);
|
||||
return sym;
|
||||
}
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ add_statement_op_ref (operand_t *op, dstatement_t *st, int field)
|
|||
{
|
||||
if (op && op->op_type == op_label) {
|
||||
int st_ofs = st - pr.code->code;
|
||||
reloc_t *reloc = new_reloc (st_ofs, rel_op_a_op + field);
|
||||
reloc_t *reloc = new_reloc (0, st_ofs, rel_op_a_op + field);
|
||||
|
||||
reloc->next = op->o.label->dest->relocs;
|
||||
op->o.label->dest->relocs = reloc;
|
||||
|
|
|
@ -542,7 +542,7 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent)
|
|||
sym->s.func->def->constant = 1;
|
||||
sym->s.func->def->nosave = 1;
|
||||
add_function (sym->s.func);
|
||||
reloc_def_func (sym->s.func, sym->s.func->def->offset);
|
||||
reloc_def_func (sym->s.func, sym->s.func->def);
|
||||
}
|
||||
sym->s.func->code = pr.code->size;
|
||||
|
||||
|
@ -603,7 +603,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val)
|
|||
else
|
||||
bi = expr_float (bi_val);
|
||||
sym->s.func->builtin = bi;
|
||||
reloc_def_func (sym->s.func, sym->s.func->def->offset);
|
||||
reloc_def_func (sym->s.func, sym->s.func->def);
|
||||
build_function (sym->s.func);
|
||||
finish_function (sym->s.func);
|
||||
|
||||
|
|
|
@ -162,7 +162,6 @@ ReuseConstant (expr_t *expr, def_t *def)
|
|||
hashtab_t *tab = 0;
|
||||
type_t *type;
|
||||
expr_t e = *expr;
|
||||
reloc_t *reloc = 0;
|
||||
immediate_t *imm, search;
|
||||
|
||||
if (!string_imm_defs) {
|
||||
|
@ -266,15 +265,19 @@ ReuseConstant (expr_t *expr, def_t *def)
|
|||
// copy the immediate to the global area
|
||||
switch (e.e.value.type) {
|
||||
case ev_string:
|
||||
reloc = new_reloc (cn->offset, rel_def_string);
|
||||
reloc_def_string (cn);
|
||||
break;
|
||||
case ev_func:
|
||||
if (e.e.value.v.func_val)
|
||||
reloc = new_reloc (cn->offset, rel_def_func);
|
||||
if (e.e.value.v.func_val) {
|
||||
reloc_t *reloc;
|
||||
reloc = new_reloc (cn->space, cn->offset, rel_def_func);
|
||||
reloc->next = pr.relocs;
|
||||
pr.relocs = reloc;
|
||||
}
|
||||
break;
|
||||
case ev_field:
|
||||
if (e.e.value.v.pointer.def)
|
||||
reloc_def_field_ofs (e.e.value.v.pointer.def, cn->offset);
|
||||
reloc_def_field_ofs (e.e.value.v.pointer.def, cn);
|
||||
break;
|
||||
case ev_pointer:
|
||||
if (e.e.value.v.pointer.def) {
|
||||
|
@ -285,10 +288,6 @@ ReuseConstant (expr_t *expr, def_t *def)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if (reloc) {
|
||||
reloc->next = pr.relocs;
|
||||
pr.relocs = reloc;
|
||||
}
|
||||
|
||||
memcpy (D_POINTER (void, cn), &e.e, 4 * type_size (type));
|
||||
|
||||
|
|
|
@ -451,8 +451,12 @@ emit_methods_list_item (def_t *def, void *data, int index)
|
|||
EMIT_STRING (def->space, meth->method_name, m->name);
|
||||
EMIT_STRING (def->space, meth->method_types, m->types);
|
||||
meth->method_imp = D_FUNCTION (m->def);
|
||||
if (m->func)
|
||||
reloc_def_func (m->func, POINTER_OFS (def->space, &meth->method_imp));
|
||||
if (m->func) {
|
||||
def_t loc;
|
||||
loc.space = def->space;
|
||||
loc.offset = POINTER_OFS (def->space, &meth->method_imp);
|
||||
reloc_def_func (m->func, &loc);
|
||||
}
|
||||
}
|
||||
|
||||
def_t *
|
||||
|
|
|
@ -54,7 +54,27 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
|
||||
static reloc_t *free_refs;
|
||||
|
||||
#define G_INT(o) pr.near_data->data[o].integer_var
|
||||
static const char *reloc_name[] = {
|
||||
"rel_none",
|
||||
"rel_op_a_def",
|
||||
"rel_op_b_def",
|
||||
"rel_op_c_def",
|
||||
"rel_op_a_op",
|
||||
"rel_op_b_op",
|
||||
"rel_op_c_op",
|
||||
"rel_def_op",
|
||||
"rel_def_def",
|
||||
"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",
|
||||
"rel_def_field_ofs",
|
||||
};
|
||||
|
||||
#define RELOC(r) (r)->space->data[(r)->offset].integer_var
|
||||
|
||||
void
|
||||
relocate_refs (reloc_t *reloc, int offset)
|
||||
|
@ -62,6 +82,10 @@ relocate_refs (reloc_t *reloc, int offset)
|
|||
int o;
|
||||
|
||||
while (reloc) {
|
||||
debug (0, "reloc %s:%x %s %x",
|
||||
reloc->space ? (reloc->space == pr.near_data ? "near" : "far")
|
||||
: "code",
|
||||
reloc->offset, reloc_name[reloc->type], offset);
|
||||
switch (reloc->type) {
|
||||
case rel_none:
|
||||
break;
|
||||
|
@ -109,11 +133,11 @@ relocate_refs (reloc_t *reloc, int offset)
|
|||
error (0, "invalid statement offset: %d >= %d, %d",
|
||||
offset, pr.code->size, reloc->offset);
|
||||
} else
|
||||
G_INT (reloc->offset) = offset;
|
||||
RELOC (reloc) = offset;
|
||||
break;
|
||||
case rel_def_def:
|
||||
case rel_def_func:
|
||||
G_INT (reloc->offset) = offset;
|
||||
RELOC (reloc) = offset;
|
||||
break;
|
||||
case rel_def_string:
|
||||
break;
|
||||
|
@ -141,10 +165,10 @@ relocate_refs (reloc_t *reloc, int offset)
|
|||
pr.code->code[reloc->offset].c = o;
|
||||
break;
|
||||
case rel_def_def_ofs:
|
||||
G_INT (reloc->offset) += offset;
|
||||
RELOC (reloc) += offset;
|
||||
break;
|
||||
case rel_def_field_ofs:
|
||||
G_INT (reloc->offset) += G_INT (offset);
|
||||
RELOC (reloc) += pr.data->data[offset].integer_var;
|
||||
break;
|
||||
}
|
||||
reloc = reloc->next;
|
||||
|
@ -152,11 +176,12 @@ relocate_refs (reloc_t *reloc, int offset)
|
|||
}
|
||||
|
||||
reloc_t *
|
||||
new_reloc (int offset, reloc_type type)
|
||||
new_reloc (defspace_t *space, int offset, reloc_type type)
|
||||
{
|
||||
reloc_t *ref;
|
||||
|
||||
ALLOC (16384, reloc_t, refs, ref);
|
||||
ref->space = space;
|
||||
ref->offset = offset;
|
||||
ref->type = type;
|
||||
ref->line = pr.source_line;
|
||||
|
@ -168,7 +193,7 @@ new_reloc (int offset, reloc_type type)
|
|||
void
|
||||
reloc_op_def (def_t *def, int offset, int field)
|
||||
{
|
||||
reloc_t *ref = new_reloc (offset, rel_op_a_def + field);
|
||||
reloc_t *ref = new_reloc (0, offset, rel_op_a_def + field);
|
||||
ref->return_address = __builtin_return_address (0);
|
||||
ref->next = def->relocs;
|
||||
def->relocs = ref;
|
||||
|
@ -177,70 +202,84 @@ reloc_op_def (def_t *def, int offset, int field)
|
|||
void
|
||||
reloc_op_def_ofs (def_t *def, int offset, int field)
|
||||
{
|
||||
reloc_t *ref = new_reloc (offset, rel_op_a_def_ofs + field);
|
||||
reloc_t *ref = new_reloc (0, offset, rel_op_a_def_ofs + field);
|
||||
ref->return_address = __builtin_return_address (0);
|
||||
ref->next = def->relocs;
|
||||
def->relocs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_def (def_t *def, int offset)
|
||||
reloc_def_def (def_t *def, def_t *location)
|
||||
{
|
||||
reloc_t *ref = new_reloc (offset, rel_def_def);
|
||||
reloc_t *ref;
|
||||
|
||||
ref = new_reloc (location->space, location->offset, rel_def_def);
|
||||
ref->return_address = __builtin_return_address (0);
|
||||
ref->next = def->relocs;
|
||||
def->relocs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_def_ofs (def_t *def, int offset)
|
||||
reloc_def_def_ofs (def_t *def, def_t *location)
|
||||
{
|
||||
reloc_t *ref = new_reloc (offset, rel_def_def_ofs);
|
||||
reloc_t *ref;
|
||||
|
||||
ref = new_reloc (location->space, location->offset, rel_def_def_ofs);
|
||||
ref->return_address = __builtin_return_address (0);
|
||||
ref->next = def->relocs;
|
||||
def->relocs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_func (function_t *func, int offset)
|
||||
reloc_def_func (function_t *func, def_t *location)
|
||||
{
|
||||
reloc_t *ref = new_reloc (offset, rel_def_func);
|
||||
reloc_t *ref;
|
||||
|
||||
ref = new_reloc (location->space, location->offset, rel_def_func);
|
||||
ref->return_address = __builtin_return_address (0);
|
||||
ref->next = func->refs;
|
||||
func->refs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_string (int offset)
|
||||
reloc_def_string (def_t *location)
|
||||
{
|
||||
reloc_t *ref = new_reloc (offset, rel_def_string);
|
||||
reloc_t *ref;
|
||||
|
||||
ref = new_reloc (location->space, location->offset, rel_def_string);
|
||||
ref->return_address = __builtin_return_address (0);
|
||||
ref->next = pr.relocs;
|
||||
pr.relocs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_field (def_t *def, int offset)
|
||||
reloc_def_field (def_t *def, def_t *location)
|
||||
{
|
||||
reloc_t *ref = new_reloc (offset, rel_def_field);
|
||||
reloc_t *ref;
|
||||
|
||||
ref = new_reloc (location->space, location->offset, rel_def_field);
|
||||
ref->return_address = __builtin_return_address (0);
|
||||
ref->next = def->relocs;
|
||||
def->relocs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_field_ofs (def_t *def, int offset)
|
||||
reloc_def_field_ofs (def_t *def, def_t *location)
|
||||
{
|
||||
reloc_t *ref = new_reloc (offset, rel_def_field_ofs);
|
||||
reloc_t *ref;
|
||||
|
||||
ref = new_reloc (location->space, location->offset, rel_def_field_ofs);
|
||||
ref->return_address = __builtin_return_address (0);
|
||||
ref->next = def->relocs;
|
||||
def->relocs = ref;
|
||||
}
|
||||
|
||||
void
|
||||
reloc_def_op (ex_label_t *label, int offset)
|
||||
reloc_def_op (ex_label_t *label, def_t *location)
|
||||
{
|
||||
reloc_t *ref = new_reloc (offset, rel_def_op);
|
||||
reloc_t *ref;
|
||||
|
||||
ref = new_reloc (location->space, location->offset, rel_def_op);
|
||||
ref->return_address = __builtin_return_address (0);
|
||||
ref->next = pr.relocs;
|
||||
ref->label = label;
|
||||
|
|
|
@ -340,7 +340,10 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
|
|||
build_switch (sw, tree->right, op, sw_val, temp, default_label);
|
||||
}
|
||||
for (i = 0; i <= high - low; i++) {
|
||||
reloc_def_op (&tree->labels[i]->e.label, sym->s.def->offset + i);
|
||||
def_t loc;
|
||||
loc.space = sym->s.def->space;
|
||||
loc.offset = sym->s.def->offset + i;
|
||||
reloc_def_op (&tree->labels[i]->e.label, &loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue