From 66aa36b73f1b9ebc626bca9c10de0d61f29eca01 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Jun 2002 17:59:32 +0000 Subject: [PATCH] start implementing storage classes (extern, static, etc) --- tools/qfcc/include/def.h | 13 +++++++++++-- tools/qfcc/include/obj_file.h | 5 +++-- tools/qfcc/source/class.c | 22 +++++++++++----------- tools/qfcc/source/def.c | 14 ++++++++------ tools/qfcc/source/expr.c | 6 +++--- tools/qfcc/source/function.c | 8 ++++---- tools/qfcc/source/method.c | 7 +++---- tools/qfcc/source/obj_file.c | 6 ++++-- tools/qfcc/source/qc-lex.l | 2 ++ tools/qfcc/source/qc-parse.y | 16 ++++++++++++---- tools/qfcc/source/qfcc.c | 3 ++- tools/qfcc/source/struct.c | 6 +++--- tools/qfcc/source/switch.c | 3 ++- 13 files changed, 68 insertions(+), 43 deletions(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index ac375b1ee..aa573ec43 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -47,9 +47,10 @@ typedef struct def_s { unsigned freed:1; // already freed from the scope unsigned removed:1; // already removed from the symbol table unsigned used:1; // unused local detection - unsigned global:1; // globally declared def unsigned absolute:1; // don't relocate (for temps for shorts) unsigned managed:1; // managed temp + unsigned global:1; // globally declared def + unsigned external:1; // externally declared def string_t file; // source file int line; // source line @@ -93,6 +94,14 @@ typedef struct scope_s { struct scope_s *parent; } scope_t; +typedef enum { + st_none, + st_global, + st_extern, + st_static, + st_local +} storage_class_t; + extern def_t def_ret, def_parms[MAX_PARMS]; extern def_t def_void; extern def_t def_function; @@ -101,7 +110,7 @@ scope_t *new_scope (scope_type type, defspace_t *space, scope_t *parent); defspace_t *new_defspace (void); def_t *get_def (struct type_s *type, const char *name, scope_t *scope, - int allocate); + storage_class_t storage); def_t *new_def (struct type_s *type, const char *name, scope_t *scope); int new_location (struct type_s *type, defspace_t *space); void free_location (def_t *def); diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index a43620553..7d741a47b 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -67,8 +67,9 @@ typedef struct qfo_def_s { #define QFOD_INITIALIZED (1u<<0) #define QFOD_CONSTANT (1u<<1) -#define QFOD_GLOBAL (1u<<2) -#define QFOD_ABSOLUTE (1u<<3) +#define QFOD_ABSOLUTE (1u<<2) +#define QFOD_GLOBAL (1u<<3) +#define QFOD_EXTERNAL (1u<<4) typedef struct qfo_function_s { string_t name; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index cf970bc70..0acfe0968 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -161,7 +161,7 @@ class_begin (class_t *class) va ("_OBJ_CATEGORY_%s_%s", class->class_name, class->category_name), - pr.scope, 1); + pr.scope, st_static); class->def->initialized = class->def->constant = 1; category = &G_STRUCT (pr_category_t, class->def->ofs); category->category_name = ReuseString (class->category_name); @@ -177,7 +177,7 @@ class_begin (class_t *class) meta_def = get_def (type_Class.aux_type, va ("_OBJ_METACLASS_%s", class->class_name), - pr.scope, 1); + pr.scope, st_static); meta_def->initialized = meta_def->constant = 1; meta = &G_STRUCT (pr_class_t, meta_def->ofs); meta->class_pointer = ReuseString (class->class_name); @@ -192,7 +192,7 @@ class_begin (class_t *class) class->def = get_def (type_Class.aux_type, va ("_OBJ_CLASS_%s", class->class_name), - pr.scope, 1); + pr.scope, st_static); class->def->initialized = class->def->constant = 1; cls = &G_STRUCT (pr_class_t, class->def->ofs); cls->class_pointer = meta_def->ofs; @@ -400,7 +400,7 @@ class_def (class_t *class) def = get_def (class->type, va ("_OBJ_CLASS_POINTER_%s", class->class_name), - pr.scope, 1); + pr.scope, st_static); if (def->initialized) return def; if (class->def) { //FIXME need externals? @@ -453,7 +453,7 @@ class_finish_module (void) new_struct_field (symtab_type, &type_integer, "cat_def_cnt", vis_public); for (i = 0; i < num_classes + num_categories; i++) new_struct_field (symtab_type, &type_pointer, 0, vis_public); - symtab_def = get_def (symtab_type, "_OBJ_SYMTAB", pr.scope, 1); + symtab_def = get_def (symtab_type, "_OBJ_SYMTAB", pr.scope, st_static); symtab_def->initialized = symtab_def->constant = 1; symtab = &G_STRUCT (pr_symtab_t, symtab_def->ofs); symtab->cls_def_cnt = num_classes; @@ -466,7 +466,7 @@ class_finish_module (void) if ((*t)->def) *def_ptr++ = (*t)->def->ofs; - module_def = get_def (type_module, "_OBJ_MODULE", pr.scope, 1); + module_def = get_def (type_module, "_OBJ_MODULE", pr.scope, st_static); module_def->initialized = module_def->constant = 1; module = &G_STRUCT (pr_module_t, module_def->ofs); module->size = type_size (type_module); @@ -474,7 +474,7 @@ class_finish_module (void) module->symtab = symtab_def->ofs; exec_class_def = get_def (&type_obj_exec_class, "__obj_exec_class", - pr.scope, 1); + pr.scope, st_static); exec_class_func = new_function ("__obj_exec_class"); exec_class_func->builtin = 0; exec_class_func->def = exec_class_def; @@ -482,7 +482,7 @@ class_finish_module (void) build_function (exec_class_func); finish_function (exec_class_func); - init_def = get_def (&type_function, ".ctor", pr.scope, 1); + init_def = get_def (&type_function, ".ctor", pr.scope, st_static); init_func = new_function (".ctor"); init_func->def = init_def; init_func->refs = new_reloc (init_def->ofs, rel_def_func); @@ -548,7 +548,7 @@ protocol_add_protocol_methods (protocol_t *protocol, expr_t *protocols) def_t * protocol_def (protocol_t *protocol) { - return get_def (&type_Protocol, protocol->name, pr.scope, 1); + return get_def (&type_Protocol, protocol->name, pr.scope, st_static); } protocollist_t * @@ -578,7 +578,7 @@ emit_protocol (protocol_t *protocol) proto_def = get_def (type_Protocol.aux_type, va ("_OBJ_PROTOCOL_%s", protocol->name), - pr.scope, 1); + pr.scope, st_static); proto_def->initialized = proto_def->constant = 1; proto = &G_STRUCT (pr_protocol_t, proto_def->ofs); proto->class_pointer = 0; @@ -609,7 +609,7 @@ emit_protocol_list (protocollist_t *protocols, const char *name) new_struct_field (protocol_list, &type_pointer, 0, vis_public); proto_list_def = get_def (type_Protocol.aux_type, va ("_OBJ_PROTOCOLS_%s", name), - pr.scope, 1); + pr.scope, st_static); proto_list_def->initialized = proto_list_def->constant = 1; proto_list = &G_STRUCT (pr_protocol_list_t, proto_list_def->ofs); proto_list->next = 0; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 7f32ce78e..3ef789970 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -73,7 +73,8 @@ defs_get_key (void *_def, void *_tab) } static def_t * -check_for_name (type_t *type, const char *name, scope_t *scope, int allocate) +check_for_name (type_t *type, const char *name, scope_t *scope, + storage_class_t storage) { def_t *def; @@ -89,10 +90,10 @@ check_for_name (type_t *type, const char *name, scope_t *scope, int allocate) // see if the name is already in use def = (def_t *) Hash_Find (defs_by_name, name); if (def) { - if (allocate && scope == def->scope) + if (storage != st_none && scope == def->scope) if (type && def->type != type) error (0, "Type mismatch on redeclaration of %s", name); - if (!allocate || def->scope == scope) + if (storage == st_none || def->scope == scope) return def; } return 0; @@ -166,11 +167,12 @@ vector_field_component (def_t *vec, int comp, scope_t *scope) If allocate is true, a new def will be allocated if it can't be found */ def_t * -get_def (type_t *type, const char *name, scope_t *scope, int allocate) +get_def (type_t *type, const char *name, scope_t *scope, + storage_class_t storage) { - def_t *def = check_for_name (type, name, scope, allocate); + def_t *def = check_for_name (type, name, scope, storage); - if (def || !allocate) + if (def || storage == st_none) return def; // allocate a new def diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c25a7588c..ef1a03210 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -141,7 +141,7 @@ convert_name (expr_t *e) e->e.def = class_def (class); return; } - d = get_def (NULL, name, current_scope, 0); + d = get_def (NULL, name, current_scope, st_none); if (d) { if (d->global) { new = class_ivar_expr (current_class, name); @@ -520,7 +520,7 @@ new_def_expr (def_t *def) expr_t * new_self_expr (void) { - def_t *def = get_def (&type_entity, ".self", pr.scope, 1); + def_t *def = get_def (&type_entity, ".self", pr.scope, st_global); def_initialized (def); return new_def_expr (def); @@ -530,7 +530,7 @@ expr_t * new_this_expr (void) { type_t *type = field_type (&type_id); - def_t *def = get_def (type, ".this", pr.scope, 1); + def_t *def = get_def (type, ".this", pr.scope, st_global); def_initialized (def); return new_def_expr (def); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 11a3b4dd6..07be4d205 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -132,10 +132,10 @@ build_scope (function_t *f, def_t *func, param_t *params) f->scope = new_scope (sc_params, new_defspace (), pr.scope); if (func->type->num_parms < 0) { - def = get_def (&type_integer, ".argc", f->scope, 1); + def = get_def (&type_integer, ".argc", f->scope, st_local); def->used = 1; def_initialized (def); - argv = get_def (&type_pointer, ".argv", f->scope, 1); + argv = get_def (&type_pointer, ".argv", f->scope, st_local); argv->used = 1; def_initialized (argv); } @@ -145,7 +145,7 @@ build_scope (function_t *f, def_t *func, param_t *params) continue; // ellipsis marker if (!p->type) continue; // non-param selector - def = get_def (p->type, p->name, f->scope, 1); + def = get_def (p->type, p->name, f->scope, st_local); parm_ofs[i] = def->ofs; if (i > 0 && parm_ofs[i] < parm_ofs[i - 1]) { error (0, "bad parm order"); @@ -159,7 +159,7 @@ build_scope (function_t *f, def_t *func, param_t *params) if (argv) { while (i < MAX_PARMS) { - def = get_def (&type_vector, 0, f->scope, 1); + def = get_def (&type_vector, 0, f->scope, st_local); def->used = 1; if (argv->type == &type_pointer) argv->type = array_type (&type_vector, MAX_PARMS - i); diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 07ec02061..4e6c744f9 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -121,8 +121,7 @@ method_def (class_t *class, method_t *method) if (*s == ':') *s = '_'; //printf ("%s %s %s %ld\n", method->name, method->types, str->str, str->size); - // FIXME need a file scope - def = get_def (method->type, str->str, pr.scope, 1); + def = get_def (method->type, str->str, pr.scope, st_static); dstring_delete (str); return def; } @@ -175,7 +174,7 @@ make_message_def (const char *name, def_t **def) expr_t *zero = new_expr (); zero->type = ex_integer; - *def = get_def (&type_IMP, name, pr.scope, 1); + *def = get_def (&type_IMP, name, pr.scope, st_static); build_builtin_function (*def, zero); } @@ -298,7 +297,7 @@ emit_methods (methodlist_t *_methods, const char *name, int instance) for (i = 0; i < count; i++) new_struct_field (method_list, type_Method.aux_type, 0, vis_public); methods_def = get_def (method_list, va ("_OBJ_%s_METHODS_%s", type, name), - pr.scope, 1); + pr.scope, st_static); methods_def->initialized = methods_def->constant = 1; methods = &G_STRUCT (pr_method_list_t, methods_def->ofs); methods->method_next = 0; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 7110b4703..87de5680c 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -119,10 +119,12 @@ flags (def_t *d) flags |= QFOD_INITIALIZED; if (d->constant) flags |= QFOD_CONSTANT; - if (d->global) - flags |= QFOD_GLOBAL; if (d->absolute) flags |= QFOD_ABSOLUTE; + if (d->global) + flags |= QFOD_GLOBAL; + if (d->external) + flags |= QFOD_EXTERNAL; return flags; } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index c02f6178a..5d9607994 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -299,6 +299,8 @@ static keyword_t keywords[] = { {"@this", THIS, 0, 0, PROG_VERSION}, {"@argc", ARGC, 0, 0, PROG_VERSION}, {"@argv", ARGV, 0, 0, PROG_VERSION}, + {"@extern", EXTERN, 0, 0, PROG_VERSION}, + {"@static", STATIC, 0, 0, PROG_VERSION}, }; static const char * diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 532841726..44ff8ad0d 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -128,7 +128,7 @@ void free_local_inits (hashtab_t *def_list); %token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS NIL %token IFBE IFB IFAE IFA %token SWITCH CASE DEFAULT STRUCT UNION ENUM TYPEDEF SUPER SELF THIS -%token ARGC ARGV +%token ARGC ARGV EXTERN STATIC %token ELE_START %token TYPE @@ -179,6 +179,7 @@ type_t *struct_type; visibility_t current_visibility; type_t *current_ivars; scope_t *current_scope; +storage_class_t current_storage; string_t s_file; // filename for function definition @@ -195,7 +196,7 @@ defs ; def - : type { current_type = $1; } def_list + : storage_class type { current_type = $2; } def_list | STRUCT NAME { struct_type = new_struct ($2); } '=' '{' struct_defs '}' | UNION NAME @@ -211,6 +212,12 @@ def } ; +storage_class + : /* empty */ { current_storage = st_global; } + | EXTERN { current_storage = st_extern; } + | STATIC { current_storage = st_static; } + ; + struct_defs : /* empty */ | struct_defs struct_def ';' @@ -356,13 +363,13 @@ def_name { if (current_scope->type == sc_local && current_scope->parent->type == sc_params) { - def_t *def = get_def (0, $1, current_scope, 0); + def_t *def = get_def (0, $1, current_scope, st_none); if (def) { if (def->scope->type == sc_params) warning (0, "local %s shadows param %s", $1, def->name); } } - $$ = get_def (current_type, $1, current_scope, 1); + $$ = get_def (current_type, $1, current_scope, current_storage); current_def = $$; } ; @@ -628,6 +635,7 @@ statement } | LOCAL type { + current_storage = st_local; current_type = $2; local_expr = new_block_expr (); } diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 79331cd44..0d24b10b2 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -373,7 +373,8 @@ finish_compilation (void) if (options.code.debug) { e.type = ex_string; e.e.string_val = debugfile; - ReuseConstant (&e, get_def (&type_string, ".debug_file", pr.scope, 1)); + ReuseConstant (&e, get_def (&type_string, ".debug_file", pr.scope, + st_static)); } for (def = pr.scope->head; def; def = def->def_next) { diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 03952d834..51dc7e346 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -223,10 +223,10 @@ emit_struct(type_t *strct, const char *name) for (i = 0; i < count; i++) new_struct_field (ivar_list, type_ivar, 0, vis_public); dsprintf (ivars_name, "_OBJ_INSTANCE_VARIABLES_%s", name); - ivars_def = get_def (ivar_list, ivars_name->str, pr.scope, 0); + ivars_def = get_def (ivar_list, ivars_name->str, pr.scope, st_none); if (ivars_def) goto done; - ivars_def = get_def (ivar_list, ivars_name->str, pr.scope, 1); + ivars_def = get_def (ivar_list, ivars_name->str, pr.scope, st_static); ivars_def->initialized = ivars_def->constant = 1; ivars = &G_STRUCT (pr_ivar_list_t, ivars_def->ofs); ivars->ivar_count = count; @@ -280,7 +280,7 @@ process_enum (expr_t *enm) } if ((structs && find_struct (name->e.string_val)) || get_enum (name->e.string_val) - || get_def (NULL, name->e.string_val, pr.scope, 0)) { + || get_def (NULL, name->e.string_val, pr.scope, st_none)) { error (name, "%s redeclared", name->e.string_val); continue; } diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 7dfce2585..78dc49f33 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -298,7 +298,8 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, range->type = ex_uinteger; - def = get_def (array_type (&type_uinteger, high - low + 1), name, pr.scope, 1); + def = get_def (array_type (&type_uinteger, high - low + 1), name, + pr.scope, st_static); table = new_def_expr (def); if (tree->left) {