From dda045bf96fc82596a2942227bbb98b7eb77a805 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 23:29:58 +0900 Subject: [PATCH] Do lazy computation of def sizes from type encodings The size is calculated when needed and cached. --- include/QF/pr_comp.h | 3 +- libs/gamecode/pr_debug.c | 69 +++++++++++++++++++++++++++++++++++---- libs/gamecode/pr_load.c | 2 ++ libs/gamecode/pr_opcode.c | 1 + 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 0430d35fe..451d3a9ab 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -434,7 +434,8 @@ typedef struct pr_xdefs_s { } pr_xdefs_t; typedef struct pr_def_s { - pr_uint_t type; + pr_ushort_t type; + pr_ushort_t size; ///< may not be correct pointer_t ofs; string_t name; pointer_t type_encoding; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 06ed76a5b..9b0deece5 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -195,6 +195,57 @@ pr_debug_expression_error (script_t *script, const char *msg) Sys_Printf ("%s\n", msg); } +#define RUP(x,a) (((x) + ((a) - 1)) & ~((a) - 1)) +static pr_short_t +pr_debug_type_size (progs_t *pr, qfot_type_t *type) +{ + pr_short_t size; + qfot_type_t *aux_type; + switch (type->meta) { + case ty_basic: + return pr_type_size[type->t.type]; + case ty_struct: + case ty_union: + size = 0; + for (pr_int_t i = 0; i < type->t.strct.num_fields; i++) { + qfot_var_t *field = &type->t.strct.fields[i]; + aux_type = &G_STRUCT (pr, qfot_type_t, field->type); + size = max (size, + field->offset + pr_debug_type_size (pr, aux_type)); + } + return size; + case ty_enum: + return pr_type_size[ev_integer]; + case ty_array: + aux_type = &G_STRUCT (pr, qfot_type_t, type->t.array.type); + size = pr_debug_type_size (pr, aux_type); + return type->t.array.size * size; + case ty_class: + return 1; //FIXME or should it return sizeof class struct? + case ty_alias: + aux_type = &G_STRUCT (pr, qfot_type_t, type->t.alias.aux_type); + return pr_debug_type_size (pr, aux_type); + } + return 0; +} + +static qfot_type_t * +get_def_type (progs_t *pr, pr_def_t *def, qfot_type_t *type) +{ + if (!def->type_encoding) { + // no type encoding, so use basic type data to fill in and return + // the dummy encoding + memset (type, 0, sizeof (*type)); + type->t.type = def->type; + } else { + type = &G_STRUCT (pr, qfot_type_t, def->type_encoding); + if (!def->size) { + def->size = pr_debug_type_size (pr, type); + } + } + return type; +} + static pr_def_t parse_expression (progs_t *pr, const char *expr, int conditional) { @@ -1379,7 +1430,7 @@ VISIBLE void ED_Print (progs_t *pr, edict_t *ed) { int l; - pr_uint_t i; + pr_uint_t i, j; const char *name; pr_def_t *d; pr_type_t *v; @@ -1398,17 +1449,21 @@ ED_Print (progs_t *pr, edict_t *ed) d = &pr->pr_fielddefs[i]; if (!d->name) // null field def (probably 1st) continue; - if (!d->type_encoding) { - dummy_type.t.type = d->type; - type = &dummy_type; - } else { - type = &G_STRUCT (pr, qfot_type_t, d->type_encoding); - } + type = get_def_type (pr, d, &dummy_type); name = PR_GetString (pr, d->name); if (name[strlen (name) - 2] == '_' && strchr ("xyz", name[strlen (name) -1])) continue; // skip _x, _y, _z vars + for (j = 0; j < d->size; j++) { + if (E_INT (ed, d->ofs + j)) { + break; + } + } + if (j == d->size) { + continue; + } + v = ed->v + d->ofs; l = 15 - strlen (name); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index a7dced537..994e9b581 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -281,11 +281,13 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->pr_globaldefs = calloc (pr->progs->numglobaldefs, sizeof (pr_def_t)); for (i = 0; i < pr->progs->numglobaldefs; i++) { + pr_ushort_t safe_type = global_ddefs[i].type & ~DEF_SAVEGLOBAL; global_ddefs[i].type = LittleShort (global_ddefs[i].type); global_ddefs[i].ofs = LittleShort (global_ddefs[i].ofs); global_ddefs[i].s_name = LittleLong (global_ddefs[i].s_name); pr->pr_globaldefs[i].type = global_ddefs[i].type; + pr->pr_globaldefs[i].size = pr_type_size[safe_type]; pr->pr_globaldefs[i].ofs = global_ddefs[i].ofs; pr->pr_globaldefs[i].name = global_ddefs[i].s_name; Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]); diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 3d2bc0c4d..ab266c84c 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -62,6 +62,7 @@ VISIBLE pr_ushort_t pr_type_size[ev_type_count] = { 1, // ev_uinteger 0, // ev_short value in opcode 2, // ev_double + 0, // ev_invalid not a valid/simple type }; VISIBLE const char *pr_type_name[ev_type_count] = {