[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:
Bill Currie 2024-08-26 10:35:33 +09:00
parent 80df79a62f
commit 8eae02209e
9 changed files with 55 additions and 89 deletions

View file

@ -197,7 +197,7 @@ struct defspace_s;
int value_too_large (const type_t *val_type) __attribute__((pure));
void make_function (symbol_t *sym, const char *nice_name,
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);
function_t *begin_function (symbol_t *sym, const char *nicename,
symtab_t *parent, int far,

View file

@ -1634,18 +1634,15 @@ class_finish_module (void)
if (!exec_class_sym) {
exec_class_sym = new_symbol_type ("__obj_exec_class",
&type_exec_class);
exec_class_sym = function_symbol (exec_class_sym,
(specifier_t) {
.is_overload = false
exec_class_sym = function_symbol ((specifier_t) {
.sym = exec_class_sym
});
make_function (exec_class_sym, 0, exec_class_sym->table->space,
sc_extern);
}
init_sym = new_symbol_type (".ctor", &type_func);
init_sym = function_symbol (init_sym, (specifier_t) {
.is_overload = false
});
init_sym = function_symbol ((specifier_t) { .sym = init_sym });
const expr_t *module_expr;
module_expr = address_expr (new_symbol_expr (module_sym), 0);

View file

@ -3077,9 +3077,7 @@ think_expr (symbol_t *think_sym)
} else {
think_sym->type = &type_func;
}
think_sym = function_symbol (think_sym, (specifier_t) {
.is_overload = false
});
think_sym = function_symbol ((specifier_t) { .sym = think_sym });
make_function (think_sym, 0, current_symtab->space, current_storage);
return new_symbol_expr (think_sym);
}

View file

@ -577,8 +577,16 @@ get_function (const char *name, const type_t *type, specifier_t spec)
}
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;
metafunc_t *func;
symbol_t *s;
@ -1104,12 +1112,18 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent,
if (sym->sy_type != sy_func) {
error (0, "%s is not a function", sym->name);
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) {
error (0, "%s redefined", sym->name);
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;

View file

@ -241,7 +241,10 @@ function_definition
spec.sym->type = parse_params (spec.sym->type, spec.params);
auto sym = function_sym_type (spec, spec.sym);
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,
false, spec.storage);
current_symtab = current_func->locals;

View file

@ -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,
// str->size);
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;
dstring_delete (str);
return sym;
@ -369,7 +369,7 @@ send_message (int super)
symtab_t *save = current_symtab;
current_symtab = pr.symtab;
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);
current_symtab = save;
}

View file

@ -432,8 +432,8 @@ function_spec (specifier_t spec, param_t *params)
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.is_function = true; //FIXME do proper void(*)() -> ev_func
spec.is_generic = generic_scope;
spec.is_generic_block = generic_block;
spec.symtab = generic_symtab;
@ -498,13 +498,16 @@ qc_function_spec (specifier_t spec, param_t *params)
return spec;
}
static symbol_t *
function_sym_type (specifier_t spec, symbol_t *sym)
static specifier_t
qc_set_symbol (specifier_t spec, symbol_t *sym)
{
sym->type = append_type (spec.sym->type, spec.type);
set_func_type_attrs (sym->type, spec);
sym->type = find_type (sym->type);
return sym;
// qc-style function declarations don't know the symbol name until the
// declaration is fully parsed, so spec.sym's name is null but its type
// carries any extra type information (field, pointer, array)
sym->params = spec.sym->params;
sym->type = spec.sym->type;
spec.sym = sym;
return spec;
}
static param_t *
@ -774,50 +777,23 @@ qc_func_decl
qc_nocode_func
: identifier '=' '#' expr
{
specifier_t spec = $<spec>0;
symbol_t *sym = $1;
specifier_t spec = qc_set_symbol ($<spec>0, $1);
const expr_t *bi_val = $4;
sym->params = spec.sym->params;
if (!spec.is_generic) {
sym = function_sym_type (spec, sym);
}
sym = function_symbol (sym, spec);
symbol_t *sym = function_symbol (spec);
build_builtin_function (sym, bi_val, 0, spec.storage);
}
| identifier '=' expr
{
specifier_t spec = $<spec>0;
symbol_t *sym = $1;
specifier_t spec = qc_set_symbol ($<spec>0, $1);
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);
}
| identifier
{
specifier_t spec = $<spec>0;
symbol_t *sym = $1;
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;
}
specifier_t spec = qc_set_symbol ($<spec>0, $1);
declare_symbol (spec, nullptr, current_symtab);
}
;
@ -829,11 +805,8 @@ qc_code_func
.symtab = current_symtab,
.function = current_func,
};
specifier_t spec = $<spec>0;
symbol_t *sym = $1;
sym->params = spec.sym->params;
sym = function_sym_type (spec, sym);
sym = function_symbol (sym, spec);
specifier_t spec = qc_set_symbol ($<spec>0, $1);
symbol_t *sym = function_symbol (spec);
current_func = begin_function (sym, 0, current_symtab, 0,
spec.storage);
current_symtab = current_func->locals;
@ -1134,8 +1107,7 @@ function_body
: method_optional_state_expr
{
specifier_t spec = default_type ($<spec>0, $<spec>0.sym);
symbol_t *sym = function_sym_type (spec, spec.sym);
$<symbol>$ = function_symbol (sym, spec);
$<symbol>$ = function_symbol (spec);
}
save_storage
{
@ -1158,14 +1130,9 @@ function_body
| '=' '#' expr ';'
{
specifier_t spec = $<spec>0;
symbol_t *sym = spec.sym;
const expr_t *bi_val = $3;
if (!spec.is_generic) {
spec = default_type (spec, spec.sym);
sym = function_sym_type (spec, sym);
}
sym = function_symbol (sym, spec);
symbol_t *sym = function_symbol (spec);
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;
}
// id has been redelcared as a variable (hopefully)
// id has been redeclared as a variable (hopefully)
return QC_NAME;
} else {
lval->spec = keyword->spec;

View file

@ -169,7 +169,7 @@ build_dotmain (symbol_t *program)
dotmain->params = 0;
dotmain->type = parse_params (&type_int, 0);
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"));
@ -252,7 +252,7 @@ program_head
}
$$->type = parse_params (&type_void, 0);
$$->type = find_type ($$->type);
$$ = function_symbol ($$, (specifier_t) { .is_overload = false });
$$ = function_symbol ((specifier_t) { .sym = $$ });
}
;
@ -339,9 +339,7 @@ subprogram_head
$$->params = $3;
$$->type = parse_params ($5, $3);
$$->type = find_type ($$->type);
$$ = function_symbol ($$, (specifier_t) {
.is_overload = false
});
$$ = function_symbol ((specifier_t) { .sym = $$ });
}
}
| PROCEDURE ID arguments
@ -353,9 +351,7 @@ subprogram_head
$$->params = $3;
$$->type = parse_params (&type_void, $3);
$$->type = find_type ($$->type);
$$ = function_symbol ($$, (specifier_t) {
.is_overload = false
});
$$ = function_symbol ((specifier_t) { .sym = $$ });
}
}
;

View file

@ -272,15 +272,9 @@ declare_symbol (specifier_t spec, const expr_t *init, symtab_t *symtab)
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);
}
//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 (init) {
@ -295,10 +289,7 @@ declare_symbol (specifier_t spec, const expr_t *init, symtab_t *symtab)
if (init) {
error (0, "function %s is initialized", s->name);
}
if (!spec.type_expr) {
s->type = find_type (s->type);
}
s = function_symbol (s, spec);
s = function_symbol (spec);
} else {
s->type = find_type (s->type);
initialize_def (s, init, space, spec.storage, symtab);