diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index eea13bf71..1152bf5a5 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -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 diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index d1bc0a268..4c4eee75d 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -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<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)) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index cc34e79b6..e058f190d 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -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); diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 997d4a9a5..c19520c46 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -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; diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 674be505f..252b8e404 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -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",