From 7a399c956be525b386c232047a38dea441b6a688 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 17:10:43 +0900 Subject: [PATCH] Encode function parameter alignment The encoding is 3:5 giving 3 bits for alignment (log2) and 5 bits for size, with alignment in the 3 most significant bits. This keeps the format backwards compatible as until doubles were added, all types were aligned to 1 word which gets encoded as 0, and the size is unaffected. --- include/QF/pr_comp.h | 7 +++- tools/qfcc/include/obj_file.h | 2 + tools/qfcc/source/Makefile.am | 2 +- tools/qfcc/source/dump_globals.c | 3 +- tools/qfcc/source/obj_file.c | 63 ++++++++++++++++++++++++++++++-- tools/qfcc/source/qfcc.c | 3 ++ tools/qfcc/source/stub.c | 18 ++++++++- 7 files changed, 91 insertions(+), 7 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 7d7589c4d..185a802ad 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -423,6 +423,11 @@ typedef struct ddef_s { pr_int_t s_name; } ddef_t; +typedef struct dparmsize_s { + uint8_t size:5; + uint8_t alignment:3; +} dparmsize_t; + #define DEF_SAVEGLOBAL (1<<15) #define MAX_PARMS 8 @@ -438,7 +443,7 @@ typedef struct dfunction_s { pr_int_t s_file; // source file defined in pr_int_t numparms; - uint8_t parm_size[MAX_PARMS]; + dparmsize_t parm_size[MAX_PARMS]; } dfunction_t; typedef union pr_type_u { diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index c32c67eb2..ae1986245 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -497,6 +497,8 @@ qfo_t *qfo_new (void); */ void qfo_delete (qfo_t *qfo); +__attribute__((const)) int qfo_log2 (unsigned x); + ///@} #endif//__obj_file_h diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index e63edc20d..7feed1dca 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -53,7 +53,7 @@ qfcc_DEPENDENCIES= $(QFCC_DEPS) qfprogs_SOURCES= \ disassemble.c dump_globals.c dump_lines.c dump_modules.c dump_strings.c \ - obj_file.c qfprogs.c strpool.c stub.c + obj_file.c qfprogs.c strpool.c stub.c type.c qfprogs_LDADD= $(QFCC_LIBS) qfprogs_DEPENDENCIES= $(QFCC_DEPS) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 6bebf5bb5..9e0b5bd5f 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -217,7 +217,8 @@ dump_functions (progs_t *pr) else count = func->numparms; for (j = 0; j < count; j++) - printf (" %d", func->parm_size[j]); + printf (" %d:%d", func->parm_size[j].alignment, + func->parm_size[j].size); printf (") %d @ %x", func->locals, func->parm_start); puts (""); if (pr->debug) { diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index c809a4a8b..44148eec8 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -665,7 +665,7 @@ get_def_type (qfo_t *qfo, pointer_t type) return ev_invalid; } -static __attribute__((pure)) etype_t +static __attribute__((pure)) int get_type_size (qfo_t *qfo, pointer_t type) { qfot_type_t *type_def; @@ -701,6 +701,62 @@ get_type_size (qfo_t *qfo, pointer_t type) return 0; } +int +qfo_log2 (unsigned x) +{ + int log2 = 0; + + while (x > 1) { + x >>= 1; + log2++; + } + return log2; +} + +static __attribute__((pure)) int +get_type_alignment_log (qfo_t *qfo, pointer_t type) +{ + qfot_type_t *type_def; + int i, alignment; + if (type >= qfo->spaces[qfo_type_space].data_size) + return 0; + type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); + switch ((ty_meta_e)type_def->meta) { + case ty_none: + // field, pointer and function types store their basic type in + // the same location. + return qfo_log2 (ev_types[type_def->t.type]->alignment); + case ty_struct: + case ty_union: + for (i = alignment = 0; i < type_def->t.strct.num_fields; i++) { + qfot_var_t *field = type_def->t.strct.fields + i; + int a; + a = get_type_alignment_log (qfo, field->type); + if (a > alignment) { + alignment = a; + } + } + return alignment; + case ty_enum: + return qfo_log2 (ev_types[ev_integer]->alignment); + case ty_array: + return get_type_alignment_log (qfo, type_def->t.array.type); + case ty_class: + return 0; // FIXME + } + return 0; +} + +static __attribute__((pure)) dparmsize_t +get_parmsize (qfo_t *qfo, pointer_t type) +{ + dparmsize_t parmsize = { + get_type_size (qfo, type), + get_type_alignment_log (qfo, type), + }; + return parmsize; +} + static void function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) { @@ -716,8 +772,9 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) df->numparms = num_params = type->t.func.num_params; if (num_params < 0) num_params = ~num_params; - for (i = 0; i < num_params; i++) - df->parm_size[i] = get_type_size (qfo, type->t.func.param_types[i]); + for (i = 0; i < num_params; i++) { + df->parm_size[i] = get_parmsize (qfo, type->t.func.param_types[i]); + } } static void diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 0da2caf88..780db073a 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -418,8 +418,11 @@ finish_link (void) flags = (QFOD_GLOBAL | QFOD_CONSTANT | QFOD_INITIALIZED | QFOD_NOSAVE); if (options.code.progsversion != PROG_ID_VERSION) { pr_int_t param_size = type_size (&type_param); + pr_int_t param_alignment = qfo_log2 (type_param.alignment); linker_add_def (".param_size", &type_integer, flags, ¶m_size); + linker_add_def (".param_alignment", &type_integer, flags, + ¶m_alignment); } if (options.code.debug) { diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index c10aff34a..4ff08975c 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -2,6 +2,8 @@ # include "config.h" #endif +#include + #include "class.h" #include "codespace.h" #include "diagnostic.h" @@ -12,9 +14,12 @@ #include "expr.h" #include "function.h" #include "obj_file.h" +#include "obj_type.h" #include "options.h" #include "qfcc.h" #include "strpool.h" +#include "struct.h" +#include "symtab.h" #include "type.h" #include "value.h" @@ -23,11 +28,22 @@ options_t options; int num_linenos; pr_lineno_t *linenos; pr_info_t pr; +type_t type_Class; +type_t type_SEL; +type_t type_id; __attribute__((const)) string_t ReuseString (const char *str) {return 0;} -void encode_type (struct dstring_s *str, const type_t *type) {} __attribute__((const)) codespace_t *codespace_new (void) {return 0;} void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {} __attribute__((const)) int function_parms (function_t *f, byte *parm_size) {return 0;} void def_to_ddef (def_t *def, ddef_t *ddef, int aux) {} +__attribute__((noreturn)) void _internal_error (expr_t *e, const char *file, int line, const char *fmt, ...) {abort();} __attribute__((const)) expr_t *_warning (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;} __attribute__((const)) expr_t *_error (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;} +__attribute__((const)) symbol_t *make_structure (const char *name, int su, struct_def_t *defs, type_t *type) {return 0;} +__attribute__((const)) symbol_t *symtab_addsymbol (symtab_t *symtab, symbol_t *symbol) {return 0;} +__attribute__((const)) symbol_t *new_symbol_type (const char *name, type_t *type) {return 0;} +__attribute__((const)) def_t *qfo_encode_type (type_t *type) {return 0;} +__attribute__((const)) int obj_types_assignable (const type_t *dst, const type_t *src) {return 0;} +void print_protocollist (struct dstring_s *dstr, protocollist_t *protocollist) {} +int obj_is_id (const type_t *type){return type->type;} +int compare_protocols (protocollist_t *protos1, protocollist_t *protos2){return protos1->count - protos2->count;}