diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index b2d3aadeb..371af492e 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -39,10 +39,18 @@ */ //@{ +typedef enum { + ds_backed, ///< data space is globally addressable (near/far/type) and + ///< has backing store + ds_virtual, ///< data space has no backing store (local vars, entity + ///< fields) +} ds_type_t; + /** Represent a block of memory in the progs data space. */ typedef struct defspace_s { struct defspace_s *next; ///< for ALLOC + ds_type_t type; ///< basic type of defspace struct locref_s *free_locs; ///< list of free blocks in this space struct def_s *defs; ///< list of defs using this space struct def_s **def_tail; ///< for appending to \a defs @@ -52,13 +60,17 @@ typedef struct defspace_s { /** Grow the backing memory of the defspace. This function is called when more memory is needed for the space. - The default \a grow function expands the backing memory by 1024 - pr_type_t words and initializes them to 0. If null, more space cannot - be allocated and an internal error will be generated. + The default \a grow function for ds_backed defspaces expands the + backing memory by 1024 pr_type_t words and initializes them to 0. + Other defspace types do not actually allocate backing memory as it + is not needed. If null, more space cannot be allocated and an + internal error will be generated. \param space This defspace. \return 1 for success, 0 for failure. On failure, an internal error will be generated. + + \note Setting to null forces failure and thus an internal error. */ int (*grow) (struct defspace_s *space); int qfo_space; ///< index to space in qfo spaces @@ -70,9 +82,13 @@ typedef struct defspace_s { initialized to the default grow function so the backing memory may be accessed after space has been allocated via defspace_alloc_loc(). + \param type The type of defspace to create. Affects only the default + defspace_t::grow function: ds_backed uses a grow function + that allocates backing memory, while ds_virtual uses a + grow function that only increases defspace_t::max_size \return The new, empty defspace. */ -defspace_t *defspace_new (void); +defspace_t *defspace_new (ds_type_t type); /** Allocate space from the defspace's backing memory. diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index 870218bc9..bfa5a47aa 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -65,7 +65,7 @@ static locref_t *free_locrefs; #define GROW 1024 static int -grow_space (defspace_t *space) +grow_space_global (defspace_t *space) { int size; @@ -80,14 +80,35 @@ grow_space (defspace_t *space) return 1; } +static int +grow_space_virtual (defspace_t *space) +{ + int size; + + if (space->size <= space->max_size) + return 1; + + size = space->size + GROW; + size -= size % GROW; + space->max_size = size; + return 1; +} + defspace_t * -defspace_new (void) +defspace_new (ds_type_t type) { defspace_t *space; ALLOC (1024, defspace_t, spaces, space); space->def_tail = &space->defs; - space->grow = grow_space; + space->type = type; + if (type == ds_backed) { + space->grow = grow_space_global; + } else if (type == ds_virtual) { + space->grow = grow_space_virtual; + } else { + internal_error (0, "unknown defspace type"); + } return space; } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index f08b35d97..feba863bd 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -452,7 +452,7 @@ build_scope (symbol_t *fsym, symtab_t *parent) symtab = new_symtab (parent, stab_local); fsym->s.func->symtab = symtab; - symtab->space = defspace_new (); + symtab->space = defspace_new (ds_virtual); current_symtab = symtab; if (fsym->type->t.func.num_params < 0) { diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 309e8f256..7d843af6b 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -649,10 +649,10 @@ linker_begin (void) work_strings = strpool_new (); work_code = codespace_new (); - work_near_data = defspace_new (); - work_far_data = defspace_new (); - work_entity_data = defspace_new (); - work_type_data = defspace_new (); + work_near_data = defspace_new (ds_backed); + work_far_data = defspace_new (ds_backed); + work_entity_data = defspace_new (ds_virtual); + work_type_data = defspace_new (ds_backed); pr.strings = work_strings; diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index ba7610929..6e4f6cb28 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -155,21 +155,21 @@ InitData (void) line->fa.func = -1; line->line = -1; - pr.far_data = defspace_new (); + pr.far_data = defspace_new (ds_backed); - pr.near_data = defspace_new (); + pr.near_data = defspace_new (ds_backed); pr.near_data->data = calloc (65536, sizeof (pr_type_t)); pr.near_data->max_size = 65536; pr.near_data->grow = 0; - pr.type_data = defspace_new (); + pr.type_data = defspace_new (ds_backed); defspace_alloc_loc (pr.type_data, 4);// reserve space for a null descriptor pr.symtab = new_symtab (0, stab_global); pr.symtab->space = pr.near_data; current_symtab = pr.symtab; - pr.entity_data = defspace_new (); + pr.entity_data = defspace_new (ds_virtual); pr.entity_fields = new_symtab (0, stab_global); pr.entity_fields->space = pr.entity_data;;