mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-31 13:10:34 +00:00
[qfcc] Support alignment in qfo spaces
The alignment is specified as a power of 2 (ie, actual alignment = 1 << alignment) allowing old object files to be compatible (as their alignment is 0). This is necessary for (in part for #30) as it turned out even global vectors were not aligned correctly. Currently, only data spaces even vaguely respect alignment. This may need to be fixed in the future.
This commit is contained in:
parent
732ea3a5fd
commit
f4ae24e0e0
7 changed files with 68 additions and 28 deletions
|
@ -56,6 +56,7 @@ typedef struct defspace_s {
|
|||
struct def_s *defs; ///< list of defs using this space
|
||||
struct def_s **def_tail; ///< for appending to \a defs
|
||||
pr_type_t *data; ///< backing memory for this space
|
||||
int alignment; ///< minimum alignment of the whole space
|
||||
int size; ///< current high-water mark for alloced data
|
||||
int max_size; ///< size of backing memory, or highwater mark
|
||||
///< for ds_virtual
|
||||
|
|
|
@ -91,7 +91,8 @@ typedef struct qfo_space_s {
|
|||
pr_uint_t data; ///< byte offset in qfo
|
||||
pr_uint_t data_size; ///< in elements. zero for entity spaces
|
||||
pr_uint_t id;
|
||||
pr_int_t reserved[2];
|
||||
pr_uint_t alignment; ///< min alignment for space (1<<alignment)
|
||||
pr_int_t reserved[1];
|
||||
} qfo_space_t;
|
||||
|
||||
/** Representation of a def in the object file.
|
||||
|
@ -259,6 +260,7 @@ typedef struct qfo_mspace_s {
|
|||
};
|
||||
pr_uint_t data_size;
|
||||
pr_uint_t id;
|
||||
pr_uint_t alignment;
|
||||
} qfo_mspace_t;
|
||||
|
||||
/** In-memory representation of a QFO object file.
|
||||
|
|
|
@ -242,6 +242,8 @@ void reloc_def_op (const struct ex_label_s *label,
|
|||
|
||||
void reloc_attach_relocs (reloc_t *relocs, reloc_t **location);
|
||||
|
||||
extern const char * const reloc_name[];
|
||||
|
||||
///@}
|
||||
|
||||
#endif//__reloc_h
|
||||
|
|
|
@ -198,6 +198,9 @@ defspace_alloc_aligned_loc (defspace_t *space, int size, int alignment)
|
|||
}
|
||||
ofs = space->size;
|
||||
pad = alignment * ((ofs + alignment - 1) / alignment) - ofs;
|
||||
if (alignment > space->alignment) {
|
||||
space->alignment = alignment;
|
||||
}
|
||||
space->size += size + pad;
|
||||
if (space->size > space->max_size) {
|
||||
if (!space->grow || !space->grow (space))
|
||||
|
@ -263,7 +266,7 @@ defspace_add_data (defspace_t *space, pr_type_t *data, int size)
|
|||
{
|
||||
int loc;
|
||||
|
||||
loc = defspace_alloc_loc (space, size);
|
||||
loc = defspace_alloc_highwater (space, size);
|
||||
if (data)
|
||||
memcpy (space->data + loc, data, size * sizeof (pr_type_t));
|
||||
return loc;
|
||||
|
@ -285,6 +288,9 @@ defspace_alloc_aligned_highwater (defspace_t *space, int size, int alignment)
|
|||
|
||||
int ofs = space->size;
|
||||
int pad = alignment * ((ofs + alignment - 1) / alignment) - ofs;
|
||||
if (alignment > space->alignment) {
|
||||
space->alignment = alignment;
|
||||
}
|
||||
space->size += size + pad;
|
||||
if (space->size > space->max_size) {
|
||||
if (!space->grow || !space->grow (space))
|
||||
|
|
|
@ -559,6 +559,17 @@ add_code (qfo_mspace_t *code)
|
|||
work->spaces[qfo_code_space].data_size = work_code->size;
|
||||
}
|
||||
|
||||
static void
|
||||
align_data (int space, qfo_mspace_t *data)
|
||||
{
|
||||
if (space < 0 || space >= qfo_num_spaces || !work_spaces[space])
|
||||
linker_internal_error ("bad space for align_data (): %d", space);
|
||||
defspace_alloc_aligned_highwater (*work_spaces[space], 0,
|
||||
1 << data->alignment);
|
||||
work->spaces[space].data = (*work_spaces[space])->data;
|
||||
work->spaces[space].data_size = (*work_spaces[space])->size;
|
||||
}
|
||||
|
||||
/** Add the data in a data space to the working qfo.
|
||||
|
||||
\param space The space to which the data will be added.
|
||||
|
@ -603,6 +614,7 @@ add_data_space (qfo_t *qfo, qfo_mspace_t *space)
|
|||
}
|
||||
ws->data_size = space->data_size;
|
||||
ws->id = space->id;
|
||||
ws->alignment = space->alignment;
|
||||
}
|
||||
|
||||
static defref_t *
|
||||
|
@ -765,18 +777,25 @@ process_code_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
|||
static int
|
||||
process_data_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
||||
{
|
||||
if (pass != 1)
|
||||
return 0;
|
||||
if (space->id == qfo_near_data_space) {
|
||||
add_defs (qfo, space, work->spaces + qfo_near_data_space,
|
||||
process_data_def);
|
||||
add_data (qfo_near_data_space, space);
|
||||
} else if (space->id == qfo_far_data_space) {
|
||||
add_defs (qfo, space, work->spaces + qfo_far_data_space,
|
||||
process_data_def);
|
||||
add_data (qfo_far_data_space, space);
|
||||
} else {
|
||||
add_data_space (qfo, space);
|
||||
if (pass == 0) {
|
||||
if (space->id == qfo_near_data_space) {
|
||||
align_data (qfo_near_data_space, space);
|
||||
} else if (space->id == qfo_far_data_space) {
|
||||
align_data (qfo_far_data_space, space);
|
||||
} else {
|
||||
}
|
||||
} else if (pass == 1) {
|
||||
if (space->id == qfo_near_data_space) {
|
||||
add_defs (qfo, space, work->spaces + qfo_near_data_space,
|
||||
process_data_def);
|
||||
add_data (qfo_near_data_space, space);
|
||||
} else if (space->id == qfo_far_data_space) {
|
||||
add_defs (qfo, space, work->spaces + qfo_far_data_space,
|
||||
process_data_def);
|
||||
add_data (qfo_far_data_space, space);
|
||||
} else {
|
||||
add_data_space (qfo, space);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -797,10 +816,12 @@ process_strings_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
|||
static int
|
||||
process_entity_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
||||
{
|
||||
if (pass != 1)
|
||||
return 0;
|
||||
add_defs (qfo, space, work->spaces + qfo_entity_space, process_field_def);
|
||||
add_data (qfo_entity_space, space);
|
||||
if (pass == 0) {
|
||||
align_data (qfo_entity_space, space);
|
||||
} else if (pass == 1) {
|
||||
add_defs (qfo, space, work->spaces + qfo_entity_space, process_field_def);
|
||||
add_data (qfo_entity_space, space);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -915,14 +936,16 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
|||
static int
|
||||
process_debug_space (qfo_t *qfo, qfo_mspace_t *space, int pass)
|
||||
{
|
||||
if (pass != 1)
|
||||
return 0;
|
||||
if (space->type != qfos_debug) {
|
||||
linker_internal_error ("bad space type for add_data_space (): %d",
|
||||
linker_internal_error ("bad space type for process_debug_space (): %d",
|
||||
space->type);
|
||||
}
|
||||
add_defs (qfo, space, work->spaces + qfo_debug_space, process_data_def);
|
||||
add_data (qfo_debug_space, space);
|
||||
if (pass == 0) {
|
||||
align_data (qfo_debug_space, space);
|
||||
} else if (pass == 1) {
|
||||
add_defs (qfo, space, work->spaces + qfo_debug_space, process_data_def);
|
||||
add_data (qfo_debug_space, space);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1032,9 +1055,6 @@ linker_add_qfo (qfo_t *qfo)
|
|||
qfo_mspace_t *space;
|
||||
|
||||
qfo_type_defs = 0;
|
||||
for (i = 0; i < qfo_num_spaces; i++) {
|
||||
work_base[i] = work->spaces[i].data_size;
|
||||
}
|
||||
work_func_base = work->num_funcs;
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
for (i = 0, space = qfo->spaces; i < qfo->num_spaces; i++, space++) {
|
||||
|
@ -1045,6 +1065,11 @@ linker_add_qfo (qfo_t *qfo)
|
|||
if (funcs[space->type] (qfo, space, pass))
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; i < qfo_num_spaces; i++) {
|
||||
if (pass == 0) {
|
||||
work_base[i] = work->spaces[i].data_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
process_funcs (qfo);
|
||||
process_lines (qfo);
|
||||
|
|
|
@ -237,6 +237,7 @@ qfo_init_data_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
|
|||
memcpy (space->data, data->data, size);
|
||||
}
|
||||
space->data_size = data->size;
|
||||
space->alignment = qfo_log2 (data->alignment);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -250,6 +251,7 @@ qfo_init_entity_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs,
|
|||
space->data = 0;
|
||||
space->data_size = data->size;
|
||||
space->id = qfo_entity_space;
|
||||
space->alignment = qfo_log2 (data->alignment);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -501,6 +503,7 @@ qfo_write (qfo_t *qfo, const char *filename)
|
|||
}
|
||||
spaces[i].data_size = LittleLong (qfo->spaces[i].data_size);
|
||||
spaces[i].id = LittleLong (qfo->spaces[i].id);
|
||||
spaces[i].alignment = LittleLong (qfo->spaces[i].alignment);
|
||||
}
|
||||
for (i = 0; i < qfo->num_relocs; i++) {
|
||||
relocs[i].space = LittleLong (qfo->relocs[i].space);
|
||||
|
@ -608,6 +611,7 @@ qfo_read (QFile *file)
|
|||
qfo->spaces[i].data_size, qfo->spaces[i].type);
|
||||
}
|
||||
qfo->spaces[i].id = LittleLong (spaces[i].id);
|
||||
qfo->spaces[i].alignment = LittleLong (spaces[i].alignment);
|
||||
}
|
||||
for (i = 0; i < qfo->num_relocs; i++) {
|
||||
qfo->relocs[i].space = LittleLong (qfo->relocs[i].space);
|
||||
|
@ -1041,7 +1045,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size)
|
|||
// these are in order in which they usually appear in the file rather
|
||||
// than the order they appear in the struct, though with the offsets
|
||||
// it doesn't matter too much. However, as people expect a certain
|
||||
// layout, ti does matter enough to preserve the traditional file order.
|
||||
// layout, it does matter enough to preserve the traditional file order.
|
||||
progs->strings.offset = *size;
|
||||
progs->strings.count = qfo->spaces[qfo_strings_space].data_size;
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
|
||||
static reloc_t *refs_freelist;
|
||||
|
||||
static const char *reloc_name[] = {
|
||||
const char * const reloc_name[] = {
|
||||
"rel_none",
|
||||
"rel_op_a_def",
|
||||
"rel_op_b_def",
|
||||
|
|
Loading…
Reference in a new issue