[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)); 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,

View file

@ -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);

View file

@ -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);
} }

View file

@ -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;

View file

@ -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;

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, //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;
} }

View file

@ -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;

View file

@ -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
});
} }
} }
; ;

View file

@ -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);