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:
Bill Currie 2011-02-12 22:34:38 +09:00
parent cfdc2e5d6b
commit 181596f5bf
9 changed files with 146 additions and 73 deletions

View file

@ -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

View file

@ -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);
///@}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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));

View file

@ -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 *

View file

@ -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;

View file

@ -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);
}
}
}