mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
[qfcc] Unify qc and c function symbol handling
This gets all the function symbol type handling into the one place, which will make dealing with generic functions much easier.
This commit is contained in:
parent
80df79a62f
commit
8eae02209e
9 changed files with 55 additions and 89 deletions
|
@ -197,7 +197,7 @@ struct defspace_s;
|
||||||
int value_too_large (const type_t *val_type) __attribute__((pure));
|
int value_too_large (const type_t *val_type) __attribute__((pure));
|
||||||
void make_function (symbol_t *sym, const char *nice_name,
|
void make_function (symbol_t *sym, const char *nice_name,
|
||||||
struct defspace_s *space, enum storage_class_e storage);
|
struct defspace_s *space, enum storage_class_e storage);
|
||||||
symbol_t *function_symbol (symbol_t *sym, specifier_t spec);
|
symbol_t *function_symbol (specifier_t spec);
|
||||||
const expr_t *find_function (const expr_t *fexpr, const expr_t *params);
|
const expr_t *find_function (const expr_t *fexpr, const expr_t *params);
|
||||||
function_t *begin_function (symbol_t *sym, const char *nicename,
|
function_t *begin_function (symbol_t *sym, const char *nicename,
|
||||||
symtab_t *parent, int far,
|
symtab_t *parent, int far,
|
||||||
|
|
|
@ -1634,18 +1634,15 @@ class_finish_module (void)
|
||||||
if (!exec_class_sym) {
|
if (!exec_class_sym) {
|
||||||
exec_class_sym = new_symbol_type ("__obj_exec_class",
|
exec_class_sym = new_symbol_type ("__obj_exec_class",
|
||||||
&type_exec_class);
|
&type_exec_class);
|
||||||
exec_class_sym = function_symbol (exec_class_sym,
|
exec_class_sym = function_symbol ((specifier_t) {
|
||||||
(specifier_t) {
|
.sym = exec_class_sym
|
||||||
.is_overload = false
|
|
||||||
});
|
});
|
||||||
make_function (exec_class_sym, 0, exec_class_sym->table->space,
|
make_function (exec_class_sym, 0, exec_class_sym->table->space,
|
||||||
sc_extern);
|
sc_extern);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_sym = new_symbol_type (".ctor", &type_func);
|
init_sym = new_symbol_type (".ctor", &type_func);
|
||||||
init_sym = function_symbol (init_sym, (specifier_t) {
|
init_sym = function_symbol ((specifier_t) { .sym = init_sym });
|
||||||
.is_overload = false
|
|
||||||
});
|
|
||||||
|
|
||||||
const expr_t *module_expr;
|
const expr_t *module_expr;
|
||||||
module_expr = address_expr (new_symbol_expr (module_sym), 0);
|
module_expr = address_expr (new_symbol_expr (module_sym), 0);
|
||||||
|
|
|
@ -3077,9 +3077,7 @@ think_expr (symbol_t *think_sym)
|
||||||
} else {
|
} else {
|
||||||
think_sym->type = &type_func;
|
think_sym->type = &type_func;
|
||||||
}
|
}
|
||||||
think_sym = function_symbol (think_sym, (specifier_t) {
|
think_sym = function_symbol ((specifier_t) { .sym = think_sym });
|
||||||
.is_overload = false
|
|
||||||
});
|
|
||||||
make_function (think_sym, 0, current_symtab->space, current_storage);
|
make_function (think_sym, 0, current_symtab->space, current_storage);
|
||||||
return new_symbol_expr (think_sym);
|
return new_symbol_expr (think_sym);
|
||||||
}
|
}
|
||||||
|
|
|
@ -577,8 +577,16 @@ get_function (const char *name, const type_t *type, specifier_t spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol_t *
|
symbol_t *
|
||||||
function_symbol (symbol_t *sym, specifier_t spec)
|
function_symbol (specifier_t spec)
|
||||||
{
|
{
|
||||||
|
if (!spec.is_generic && (!spec.sym->type || !spec.sym->type->encoding)) {
|
||||||
|
spec = default_type (spec, spec.sym);
|
||||||
|
spec.sym->type = append_type (spec.sym->type, spec.type);
|
||||||
|
set_func_type_attrs (spec.sym->type, spec);
|
||||||
|
spec.sym->type = find_type (spec.sym->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol_t *sym = spec.sym;
|
||||||
const char *name = sym->name;
|
const char *name = sym->name;
|
||||||
metafunc_t *func;
|
metafunc_t *func;
|
||||||
symbol_t *s;
|
symbol_t *s;
|
||||||
|
@ -1104,12 +1112,18 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent,
|
||||||
if (sym->sy_type != sy_func) {
|
if (sym->sy_type != sy_func) {
|
||||||
error (0, "%s is not a function", sym->name);
|
error (0, "%s is not a function", sym->name);
|
||||||
sym = new_symbol_type (sym->name, &type_func);
|
sym = new_symbol_type (sym->name, &type_func);
|
||||||
sym = function_symbol (sym, (specifier_t) { .is_overload = true });
|
sym = function_symbol ((specifier_t) {
|
||||||
|
.sym = sym,
|
||||||
|
.is_overload = true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (sym->func && sym->func->def && sym->func->def->initialized) {
|
if (sym->func && sym->func->def && sym->func->def->initialized) {
|
||||||
error (0, "%s redefined", sym->name);
|
error (0, "%s redefined", sym->name);
|
||||||
sym = new_symbol_type (sym->name, sym->type);
|
sym = new_symbol_type (sym->name, sym->type);
|
||||||
sym = function_symbol (sym, (specifier_t) { .is_overload = true });
|
sym = function_symbol ((specifier_t) {
|
||||||
|
.sym = sym,
|
||||||
|
.is_overload = true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
defspace_t *space = far ? pr.far_data : sym->table->space;
|
defspace_t *space = far ? pr.far_data : sym->table->space;
|
||||||
|
|
|
@ -241,7 +241,10 @@ function_definition
|
||||||
spec.sym->type = parse_params (spec.sym->type, spec.params);
|
spec.sym->type = parse_params (spec.sym->type, spec.params);
|
||||||
auto sym = function_sym_type (spec, spec.sym);
|
auto sym = function_sym_type (spec, spec.sym);
|
||||||
sym->params = spec.params;
|
sym->params = spec.params;
|
||||||
sym = function_symbol (sym, (specifier_t) { .is_overload = true });
|
sym = function_symbol ((specifier_t) {
|
||||||
|
.sym = sym,
|
||||||
|
.is_overload = true
|
||||||
|
});
|
||||||
current_func = begin_function (sym, nullptr, current_symtab,
|
current_func = begin_function (sym, nullptr, current_symtab,
|
||||||
false, spec.storage);
|
false, spec.storage);
|
||||||
current_symtab = current_func->locals;
|
current_symtab = current_func->locals;
|
||||||
|
|
|
@ -183,7 +183,7 @@ method_symbol (class_type_t *class_type, method_t *method)
|
||||||
//printf ("%s %s %s %ld\n", method->name, method->types, str->str,
|
//printf ("%s %s %s %ld\n", method->name, method->types, str->str,
|
||||||
// str->size);
|
// str->size);
|
||||||
sym = new_symbol_type (str->str, method->type);
|
sym = new_symbol_type (str->str, method->type);
|
||||||
sym = function_symbol (sym, (specifier_t) { .is_overload = false });
|
sym = function_symbol ((specifier_t) { .sym = sym });
|
||||||
sym->params = method->params;
|
sym->params = method->params;
|
||||||
dstring_delete (str);
|
dstring_delete (str);
|
||||||
return sym;
|
return sym;
|
||||||
|
@ -369,7 +369,7 @@ send_message (int super)
|
||||||
symtab_t *save = current_symtab;
|
symtab_t *save = current_symtab;
|
||||||
current_symtab = pr.symtab;
|
current_symtab = pr.symtab;
|
||||||
sym = new_symbol_type (sm_name, sm_type);
|
sym = new_symbol_type (sm_name, sm_type);
|
||||||
sym = function_symbol (sym, (specifier_t) { .is_overload = false });
|
sym = function_symbol ((specifier_t) { .sym = sym });
|
||||||
make_function (sym, 0, sym->table->space, sc_extern);
|
make_function (sym, 0, sym->table->space, sc_extern);
|
||||||
current_symtab = save;
|
current_symtab = save;
|
||||||
}
|
}
|
||||||
|
|
|
@ -432,8 +432,8 @@ function_spec (specifier_t spec, param_t *params)
|
||||||
internal_error (0, "unexpected type");
|
internal_error (0, "unexpected type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spec.is_function = !spec.sym->type; //FIXME do proper void(*)() -> ev_func
|
||||||
spec.sym->type = append_type (spec.sym->type, parse_params (0, params));
|
spec.sym->type = append_type (spec.sym->type, parse_params (0, params));
|
||||||
spec.is_function = true; //FIXME do proper void(*)() -> ev_func
|
|
||||||
spec.is_generic = generic_scope;
|
spec.is_generic = generic_scope;
|
||||||
spec.is_generic_block = generic_block;
|
spec.is_generic_block = generic_block;
|
||||||
spec.symtab = generic_symtab;
|
spec.symtab = generic_symtab;
|
||||||
|
@ -498,13 +498,16 @@ qc_function_spec (specifier_t spec, param_t *params)
|
||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static symbol_t *
|
static specifier_t
|
||||||
function_sym_type (specifier_t spec, symbol_t *sym)
|
qc_set_symbol (specifier_t spec, symbol_t *sym)
|
||||||
{
|
{
|
||||||
sym->type = append_type (spec.sym->type, spec.type);
|
// qc-style function declarations don't know the symbol name until the
|
||||||
set_func_type_attrs (sym->type, spec);
|
// declaration is fully parsed, so spec.sym's name is null but its type
|
||||||
sym->type = find_type (sym->type);
|
// carries any extra type information (field, pointer, array)
|
||||||
return sym;
|
sym->params = spec.sym->params;
|
||||||
|
sym->type = spec.sym->type;
|
||||||
|
spec.sym = sym;
|
||||||
|
return spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static param_t *
|
static param_t *
|
||||||
|
@ -774,50 +777,23 @@ qc_func_decl
|
||||||
qc_nocode_func
|
qc_nocode_func
|
||||||
: identifier '=' '#' expr
|
: identifier '=' '#' expr
|
||||||
{
|
{
|
||||||
specifier_t spec = $<spec>0;
|
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
||||||
symbol_t *sym = $1;
|
|
||||||
const expr_t *bi_val = $4;
|
const expr_t *bi_val = $4;
|
||||||
sym->params = spec.sym->params;
|
|
||||||
|
|
||||||
if (!spec.is_generic) {
|
symbol_t *sym = function_symbol (spec);
|
||||||
sym = function_sym_type (spec, sym);
|
|
||||||
}
|
|
||||||
sym = function_symbol (sym, spec);
|
|
||||||
build_builtin_function (sym, bi_val, 0, spec.storage);
|
build_builtin_function (sym, bi_val, 0, spec.storage);
|
||||||
}
|
}
|
||||||
| identifier '=' expr
|
| identifier '=' expr
|
||||||
{
|
{
|
||||||
specifier_t spec = $<spec>0;
|
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
||||||
symbol_t *sym = $1;
|
|
||||||
const expr_t *expr = $3;
|
const expr_t *expr = $3;
|
||||||
sym->params = spec.sym->params;
|
|
||||||
sym = function_sym_type (spec, sym);
|
|
||||||
sym = function_symbol (sym, spec);
|
|
||||||
spec.sym = sym;
|
|
||||||
spec.type = sym->type;
|
|
||||||
spec.is_function = false;
|
|
||||||
sym->type = nullptr;
|
|
||||||
declare_symbol (spec, expr, current_symtab);
|
declare_symbol (spec, expr, current_symtab);
|
||||||
}
|
}
|
||||||
| identifier
|
| identifier
|
||||||
{
|
{
|
||||||
specifier_t spec = $<spec>0;
|
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
||||||
symbol_t *sym = $1;
|
declare_symbol (spec, nullptr, current_symtab);
|
||||||
sym->params = spec.sym->params;
|
|
||||||
sym = function_sym_type (spec, sym);
|
|
||||||
if (!local_expr && !is_field (spec.sym->type)) {
|
|
||||||
sym = function_symbol (sym, spec);
|
|
||||||
}
|
|
||||||
if (!local_expr && !is_field (sym->type)) {
|
|
||||||
// things might be a confused mess from earlier errors
|
|
||||||
if (sym->sy_type == sy_func)
|
|
||||||
make_function (sym, 0, sym->table->space, spec.storage);
|
|
||||||
} else {
|
|
||||||
initialize_def (sym, 0, current_symtab->space, spec.storage,
|
|
||||||
current_symtab);
|
|
||||||
if (sym->def)
|
|
||||||
sym->def->nosave |= spec.nosave;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -829,11 +805,8 @@ qc_code_func
|
||||||
.symtab = current_symtab,
|
.symtab = current_symtab,
|
||||||
.function = current_func,
|
.function = current_func,
|
||||||
};
|
};
|
||||||
specifier_t spec = $<spec>0;
|
specifier_t spec = qc_set_symbol ($<spec>0, $1);
|
||||||
symbol_t *sym = $1;
|
symbol_t *sym = function_symbol (spec);
|
||||||
sym->params = spec.sym->params;
|
|
||||||
sym = function_sym_type (spec, sym);
|
|
||||||
sym = function_symbol (sym, spec);
|
|
||||||
current_func = begin_function (sym, 0, current_symtab, 0,
|
current_func = begin_function (sym, 0, current_symtab, 0,
|
||||||
spec.storage);
|
spec.storage);
|
||||||
current_symtab = current_func->locals;
|
current_symtab = current_func->locals;
|
||||||
|
@ -1134,8 +1107,7 @@ function_body
|
||||||
: method_optional_state_expr
|
: method_optional_state_expr
|
||||||
{
|
{
|
||||||
specifier_t spec = default_type ($<spec>0, $<spec>0.sym);
|
specifier_t spec = default_type ($<spec>0, $<spec>0.sym);
|
||||||
symbol_t *sym = function_sym_type (spec, spec.sym);
|
$<symbol>$ = function_symbol (spec);
|
||||||
$<symbol>$ = function_symbol (sym, spec);
|
|
||||||
}
|
}
|
||||||
save_storage
|
save_storage
|
||||||
{
|
{
|
||||||
|
@ -1158,14 +1130,9 @@ function_body
|
||||||
| '=' '#' expr ';'
|
| '=' '#' expr ';'
|
||||||
{
|
{
|
||||||
specifier_t spec = $<spec>0;
|
specifier_t spec = $<spec>0;
|
||||||
symbol_t *sym = spec.sym;
|
|
||||||
const expr_t *bi_val = $3;
|
const expr_t *bi_val = $3;
|
||||||
|
|
||||||
if (!spec.is_generic) {
|
symbol_t *sym = function_symbol (spec);
|
||||||
spec = default_type (spec, spec.sym);
|
|
||||||
sym = function_sym_type (spec, sym);
|
|
||||||
}
|
|
||||||
sym = function_symbol (sym, spec);
|
|
||||||
build_builtin_function (sym, bi_val, 0, spec.storage);
|
build_builtin_function (sym, bi_val, 0, spec.storage);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -2914,7 +2881,7 @@ qc_process_keyword (QC_YYSTYPE *lval, keyword_t *keyword, const char *token)
|
||||||
};
|
};
|
||||||
return QC_TYPE_NAME;
|
return QC_TYPE_NAME;
|
||||||
}
|
}
|
||||||
// id has been redelcared as a variable (hopefully)
|
// id has been redeclared as a variable (hopefully)
|
||||||
return QC_NAME;
|
return QC_NAME;
|
||||||
} else {
|
} else {
|
||||||
lval->spec = keyword->spec;
|
lval->spec = keyword->spec;
|
||||||
|
|
|
@ -169,7 +169,7 @@ build_dotmain (symbol_t *program)
|
||||||
dotmain->params = 0;
|
dotmain->params = 0;
|
||||||
dotmain->type = parse_params (&type_int, 0);
|
dotmain->type = parse_params (&type_int, 0);
|
||||||
dotmain->type = find_type (dotmain->type);
|
dotmain->type = find_type (dotmain->type);
|
||||||
dotmain = function_symbol (dotmain, (specifier_t) { .is_overload = false });
|
dotmain = function_symbol ((specifier_t) { .sym = dotmain });
|
||||||
|
|
||||||
exitcode = new_symbol_expr (symtab_lookup (current_symtab, "ExitCode"));
|
exitcode = new_symbol_expr (symtab_lookup (current_symtab, "ExitCode"));
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ program_head
|
||||||
}
|
}
|
||||||
$$->type = parse_params (&type_void, 0);
|
$$->type = parse_params (&type_void, 0);
|
||||||
$$->type = find_type ($$->type);
|
$$->type = find_type ($$->type);
|
||||||
$$ = function_symbol ($$, (specifier_t) { .is_overload = false });
|
$$ = function_symbol ((specifier_t) { .sym = $$ });
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -339,9 +339,7 @@ subprogram_head
|
||||||
$$->params = $3;
|
$$->params = $3;
|
||||||
$$->type = parse_params ($5, $3);
|
$$->type = parse_params ($5, $3);
|
||||||
$$->type = find_type ($$->type);
|
$$->type = find_type ($$->type);
|
||||||
$$ = function_symbol ($$, (specifier_t) {
|
$$ = function_symbol ((specifier_t) { .sym = $$ });
|
||||||
.is_overload = false
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| PROCEDURE ID arguments
|
| PROCEDURE ID arguments
|
||||||
|
@ -353,9 +351,7 @@ subprogram_head
|
||||||
$$->params = $3;
|
$$->params = $3;
|
||||||
$$->type = parse_params (&type_void, $3);
|
$$->type = parse_params (&type_void, $3);
|
||||||
$$->type = find_type ($$->type);
|
$$->type = find_type ($$->type);
|
||||||
$$ = function_symbol ($$, (specifier_t) {
|
$$ = function_symbol ((specifier_t) { .sym = $$ });
|
||||||
.is_overload = false
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -272,15 +272,9 @@ declare_symbol (specifier_t spec, const expr_t *init, symtab_t *symtab)
|
||||||
space = pr.near_data;
|
space = pr.near_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spec.type) {
|
if (spec.type && (spec.is_typedef || !s->type || !is_func (s->type))) {
|
||||||
s->type = append_type (spec.sym->type, spec.type);
|
s->type = append_type (spec.sym->type, spec.type);
|
||||||
}
|
}
|
||||||
//FIXME is_function is bad (this whole implementation of handling
|
|
||||||
//function prototypes is bad), and is actually broken for function
|
|
||||||
//pointers
|
|
||||||
if (spec.is_function && is_func (s->type)) {
|
|
||||||
set_func_type_attrs (s->type, spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spec.is_typedef) {
|
if (spec.is_typedef) {
|
||||||
if (init) {
|
if (init) {
|
||||||
|
@ -295,10 +289,7 @@ declare_symbol (specifier_t spec, const expr_t *init, symtab_t *symtab)
|
||||||
if (init) {
|
if (init) {
|
||||||
error (0, "function %s is initialized", s->name);
|
error (0, "function %s is initialized", s->name);
|
||||||
}
|
}
|
||||||
if (!spec.type_expr) {
|
s = function_symbol (spec);
|
||||||
s->type = find_type (s->type);
|
|
||||||
}
|
|
||||||
s = function_symbol (s, spec);
|
|
||||||
} else {
|
} else {
|
||||||
s->type = find_type (s->type);
|
s->type = find_type (s->type);
|
||||||
initialize_def (s, init, space, spec.storage, symtab);
|
initialize_def (s, init, space, spec.storage, symtab);
|
||||||
|
|
Loading…
Reference in a new issue