mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-19 08:51:59 +00:00
start implementing storage classes (extern, static, etc)
This commit is contained in:
parent
a49177c605
commit
66aa36b73f
13 changed files with 68 additions and 43 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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> 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 ();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue