diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index bf2b40453..fc4cf4cdf 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -70,6 +70,8 @@ typedef enum storage_class_e { st_local } storage_class_t; +extern storage_class_t current_storage; + def_t *new_def (const char *name, struct type_s *type, struct defspace_s *space, storage_class_t storage); def_t *alias_def (def_t *def, struct type_s *type); diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index bb1ffbb7d..17dbe64bf 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -56,6 +56,7 @@ typedef struct function_s { int function_num; string_t s_file; ///< source file with definition string_t s_name; + struct def_s *def; struct symbol_s *sym; struct symtab_s *symtab; struct reloc_s *refs; @@ -87,6 +88,10 @@ param_t *_reverse_params (param_t *params, param_t *next); param_t *reverse_params (param_t *params); param_t *copy_params (param_t *params); struct type_s *parse_params (struct type_s *type, param_t *params); + +enum storage_class_e; +void make_function (struct symbol_s *sym, const char *nice_name, + enum storage_class_e storage); struct symbol_s *function_symbol (struct symbol_s *sym, int overload, int create); struct expr_s *find_function (struct expr_s *fexpr, struct expr_s *params); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index a6da0dcba..6879986fc 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -71,9 +71,21 @@ get_operand_def (operand_t *op) return 0; switch (op->op_type) { case op_symbol: - if (op->type != op->o.symbol->type->type) - return alias_def (op->o.symbol->s.def, ev_types[op->type]); - return op->o.symbol->s.def; + switch (op->o.symbol->sy_type) { + case sy_var: + if (op->type != op->o.symbol->type->type) + return alias_def (op->o.symbol->s.def, + ev_types[op->type]); + return op->o.symbol->s.def; + case sy_func: + return op->o.symbol->s.func->def; + case sy_const: + //FIXME + case sy_type: + case sy_expr: + internal_error (0, "invalid operand type"); + } + break; case op_value: //FIXME share immediates def = new_def (".imm", ev_types[op->type], pr.near_data, diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 39d3efb65..cff3b5730 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -465,6 +465,27 @@ new_function (const char *name, const char *nice_name) return f; } +void +make_function (symbol_t *sym, const char *nice_name, storage_class_t storage) +{ + if (sym->sy_type != sy_func) + internal_error (0, "%s is not a function", sym->name); + if (storage == st_extern && sym->s.func) + return; + if (!sym->s.func) { + sym->s.func = new_function (sym->name, nice_name); + sym->s.func->sym = sym; + } + if (sym->s.func->def && sym->s.func->def->external + && storage != st_extern) { + free_def (sym->s.func->def); + sym->s.func->def = 0; + } + if (!sym->s.func->def) + sym->s.func->def = new_def (sym->name, sym->type, sym->table->space, + storage); +} + void add_function (function_t *f) { @@ -482,29 +503,30 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent) error (0, "%s is not a function", sym->name); return 0; } - if (sym->s.func) { + if (sym->s.func && sym->s.func->def && sym->s.func->def->initialized) { error (0, "%s redefined", sym->name); return 0; } - sym->s.func = new_function (sym->name, nicename); - sym->s.func->sym = sym; - //FIXME - //if (!def->external) { + make_function (sym, nicename, current_storage); + if (!sym->s.func->def->external) { + sym->s.func->def->initialized = 1; + sym->s.func->def->constant = 1; + sym->s.func->def->nosave = 1; add_function (sym->s.func); - //reloc_def_func (func, def->ofs); - //} - sym->s.func->code = pr.code->size; -#if 0 //FIXME - if (options.code.debug && func->aux) { - pr_lineno_t *lineno = new_lineno (); - func->aux->source_line = def->line; - func->aux->line_info = lineno - pr.linenos; - func->aux->local_defs = pr.num_locals; - func->aux->return_type = def->type->t.func.type->type; - - lineno->fa.func = func->aux - pr.auxfunctions; + reloc_def_func (sym->s.func, sym->s.func->def->offset); } -#endif + sym->s.func->code = pr.code->size; + + if (options.code.debug && sym->s.func->aux) { + pr_lineno_t *lineno = new_lineno (); + sym->s.func->aux->source_line = sym->s.func->def->line; + sym->s.func->aux->line_info = lineno - pr.linenos; + sym->s.func->aux->local_defs = pr.num_locals; + sym->s.func->aux->return_type = sym->type->t.func.type->type; + + lineno->fa.func = sym->s.func->aux - pr.auxfunctions; + } + build_scope (sym, parent); return sym->s.func; } @@ -531,7 +553,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val) error (bi_val, "%s is not a function", sym->name); return 0; } - if (sym->s.func) { + if (sym->s.func && sym->s.func->def && sym->s.func->def->initialized) { error (bi_val, "%s redefined", sym->name); return 0; } @@ -539,11 +561,10 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val) error (bi_val, "invalid constant for = #"); return 0; } - //if (sym->external) - // return 0; + make_function (sym, 0, current_storage); + if (sym->s.func->def->external) + return 0; - sym->s.func = new_function (sym->name, 0); - sym->s.func->sym = sym; add_function (sym->s.func); if (is_integer_val (bi_val)) @@ -551,7 +572,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val) else bi = expr_float (bi_val); sym->s.func->builtin = bi; - //reloc_def_func (sym->s.func, def->ofs); + reloc_def_func (sym->s.func, sym->s.func->def->offset); build_function (sym->s.func); finish_function (sym->s.func); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index bee632025..758d1a133 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -284,6 +284,9 @@ simple_def cfunction : cfunction_def ';' + { + make_function ($1, 0, st_extern);// FIME do I really want this? + } | cfunction_def '=' '#' fexpr ';' { build_builtin_function ($1, $4); @@ -584,6 +587,9 @@ non_code_func build_builtin_function ($0, $3); } | /* emtpy */ + { + make_function ($0, 0, current_storage); + } ; code_func diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index b942110ee..8ec9d6c3e 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -136,6 +136,7 @@ int yylex (void); %{ symtab_t *current_symtab; +storage_class_t current_storage = st_global; function_t *current_func; struct class_type_s *current_class; expr_t *local_expr;