Get basic function creation working.

Even more FIXMEs, but the pascal parser can now create functions. The
function records even get emitted.
This commit is contained in:
Bill Currie 2011-01-18 12:37:12 +09:00
parent 8fb1b49a9d
commit 87ce9f5333
7 changed files with 199 additions and 169 deletions

View file

@ -56,8 +56,8 @@ typedef struct function_s {
int function_num;
string_t s_file; ///< source file with definition
string_t s_name;
struct def_s *def;
struct scope_s *scope;
struct symbol_s *sym;
struct symtab_s *symtab;
struct reloc_s *refs;
struct expr_s *var_init;
const char *name; ///< nice name for __PRETTY_FUNCTION__
@ -77,6 +77,7 @@ typedef struct param_s {
struct expr_s;
struct symbol_s;
struct symtab_s;
param_t *new_param (const char *selector, struct type_s *type,
const char *name);
@ -86,21 +87,20 @@ 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);
overloaded_function_t *get_function (const char *name, struct type_s *type,
int overload, int create);
struct symbol_s *function_symbol (struct symbol_s *sym,
int overload, int create);
struct def_s *get_function_def (const char *name, struct type_s *type,
struct scope_s *scope, storage_class_t storage,
int overload, int create);
struct expr_s *find_function (struct expr_s *fexpr, struct expr_s *params);
void build_scope (function_t *f, struct def_s *func, param_t *params);
function_t *new_function (struct def_s *func, const char *nice_name);
function_t *new_function (const char *name, const char *nice_name);
void add_function (function_t *f);
function_t *begin_function (struct def_s *def, const char *nicename,
param_t *params);
function_t *begin_function (struct symbol_s *sym, const char *nicename,
struct symtab_s *parent);
function_t *build_code_function (function_t *f, struct expr_s *state_expr,
struct expr_s *statements);
function_t *build_builtin_function (struct def_s *def, struct expr_s *bi_val,
param_t *params);
function_t *build_builtin_function (struct symbol_s *sym,
struct expr_s *bi_val);
void build_function (function_t *f);
void finish_function (function_t *f);
void emit_function (function_t *f, struct expr_s *e);

View file

@ -819,11 +819,11 @@ class_finish_module (void)
pr.scope, st_extern);
init_def = get_def (&type_function, ".ctor", pr.scope, st_static);
current_func = init_func = new_function (init_def, 0);
current_func = init_func = new_function (init_def->name, 0);
add_function (init_func);
reloc_def_func (init_func, init_def->ofs);
init_func->code = pr.code->size;
build_scope (init_func, init_def, 0);
//FIXME build_scope (init_func, init_def, 0);
build_function (init_func);
init_expr = new_block_expr ();
append_expr (init_expr,

View file

@ -459,7 +459,7 @@ new_label_name (void)
{
static int label = 0;
int lnum = ++label;
const char *fname = current_func->def->name;
const char *fname = current_func->sym->name;
char *lname;
lname = nva ("$%s_%d", fname, lnum);
@ -2007,7 +2007,7 @@ return_expr (function_t *f, expr_t *e)
type_t *t;
if (!e) {
if (f->def->type->t.func.type != &type_void) {
if (f->sym->type->t.func.type != &type_void) {
if (options.traditional) {
if (options.warnings.traditional)
warning (e,
@ -2025,15 +2025,15 @@ return_expr (function_t *f, expr_t *e)
if (e->type == ex_error)
return e;
if (f->def->type->t.func.type == &type_void) {
if (f->sym->type->t.func.type == &type_void) {
if (!options.traditional)
return error (e, "returning a value for a void function");
if (options.warnings.traditional)
warning (e, "returning a value for a void function");
}
if (e->type == ex_bool)
e = convert_from_bool (e, f->def->type->t.func.type);
if (f->def->type->t.func.type == &type_float && e->type == ex_integer) {
e = convert_from_bool (e, f->sym->type->t.func.type);
if (f->sym->type->t.func.type == &type_float && e->type == ex_integer) {
e->type = ex_float;
e->e.float_val = e->e.integer_val;
t = &type_float;
@ -2041,7 +2041,7 @@ return_expr (function_t *f, expr_t *e)
check_initialized (e);
if (t == &type_void) {
if (e->type == ex_nil) {
t = f->def->type->t.func.type;
t = f->sym->type->t.func.type;
e->type = expr_types[t->type];
if (e->type == ex_nil)
return error (e, "invalid return type for NIL");
@ -2053,16 +2053,16 @@ return_expr (function_t *f, expr_t *e)
//FIXME does anything need to be done here?
}
}
if (!type_assignable (f->def->type->t.func.type, t)) {
if (!type_assignable (f->sym->type->t.func.type, t)) {
if (!options.traditional)
return error (e, "type mismatch for return value of %s",
f->def->name);
f->sym->name);
if (options.warnings.traditional)
warning (e, "type mismatch for return value of %s",
f->def->name);
f->sym->name);
} else {
if (f->def->type->t.func.type != t)
e = cast_expr (f->def->type->t.func.type, e);
if (f->sym->type->t.func.type != t)
e = cast_expr (f->sym->type->t.func.type, e);
}
return new_unary_expr ('r', e);
}
@ -2741,7 +2741,7 @@ super_expr (class_type_t *class_type)
if (!class->super_class)
return error (0, "%s has no super class", class->name);
super_d = get_def (&type_Super, ".super", current_func->scope, st_local);
super_d = 0;//FIXME get_def (&type_Super, ".super", current_func->scope, st_local);
def_initialized (super_d);
super = new_def_expr (super_d);
super_block = new_block_expr ();

View file

@ -178,7 +178,7 @@ parse_params (type_t *type, param_t *parms)
return find_type (&new);
}
overloaded_function_t *
static overloaded_function_t *
get_function (const char *name, type_t *type, int overload, int create)
{
const char *full_name;
@ -231,6 +231,29 @@ get_function (const char *name, type_t *type, int overload, int create)
return func;
}
symbol_t *
function_symbol (symbol_t *sym, int overload, int create)
{
const char *name = sym->name;
overloaded_function_t *func;
symbol_t *s;
func = get_function (name, sym->type, overload, create);
if (func && func->overloaded)
name = func->full_name;
s = symtab_lookup (current_symtab, name);
if ((!s || s->table != current_symtab) && create) {
s = new_symbol (name);
s->sy_type = sy_func;
s->type = sym->type;
s->params = sym->params;
s->s.func = 0; // function not yet defined
symtab_addsymbol (current_symtab, s);
}
return s;
}
def_t *
get_function_def (const char *name, struct type_s *type,
scope_t *scope, storage_class_t storage,
@ -371,18 +394,19 @@ find_function (expr_t *fexpr, expr_t *params)
}
static void
check_function (def_t *func, param_t *params)
check_function (symbol_t *fsym)
{
param_t *params = fsym->params;
param_t *p;
int i;
if (!type_size (func->type->t.func.type)) {
if (!type_size (fsym->type->t.func.type)) {
error (0, "return type is an incomplete type");
func->type->t.func.type = &type_void;//FIXME
fsym->type->t.func.type = &type_void;//FIXME
}
if (type_size (func->type->t.func.type) > type_size (&type_param)) {
if (type_size (fsym->type->t.func.type) > type_size (&type_param)) {
error (0, "return value too large to be passed by value");
func->type->t.func.type = &type_void;//FIXME
fsym->type->t.func.type = &type_void;//FIXME
}
for (p = params, i = 0; p; p = p->next, i++) {
if (!p->selector && !p->type && !p->name)
@ -398,62 +422,54 @@ check_function (def_t *func, param_t *params)
}
}
void
build_scope (function_t *f, def_t *func, param_t *params)
static void
build_scope (symbol_t *fsym, symtab_t *parent)
{
int i;
def_t *def;
param_t *p;
def_t *args = 0;
int parm_ofs[MAX_PARMS];
symbol_t *args = 0;
symbol_t *param;
symtab_t *symtab;
check_function (func, params);
check_function (fsym);
f->scope = new_scope (sc_params, new_defspace (), pr.scope);
symtab = new_symtab (parent, stab_local);
fsym->s.func->symtab = symtab;
if (func->type->t.func.num_params < 0) {
args = get_def (&type_va_list, ".args", f->scope, st_local);
args->used = 1;
def_initialized (args);
if (fsym->type->t.func.num_params < 0) {
args = new_symbol_type (".args", &type_va_list);
symtab_addsymbol (symtab, args);
}
for (p = params, i = 0; p; p = p->next) {
for (p = fsym->params, i = 0; p; p = p->next) {
if (!p->selector && !p->type && !p->name)
continue; // ellipsis marker
if (!p->type)
continue; // non-param selector
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");
abort ();
}
//printf ("%s%s %d\n", p == params ? "" : " ", p->name, def->ofs);
def->used = 1; // don't warn for unused params
def_initialized (def); // params are assumed to be initialized
param = new_symbol_type (p->name, p->type);
symtab_addsymbol (symtab, param);
i++;
}
if (args) {
while (i < MAX_PARMS) {
def = get_def (&type_vector, 0, f->scope, st_local);//XXX param
def->used = 1;
param = new_symbol_type (va (".par%d", i), &type_param);
symtab_addsymbol (symtab, param);
i++;
}
}
}
function_t *
new_function (def_t *func, const char *nice_name)
new_function (const char *name, const char *nice_name)
{
function_t *f;
ALLOC (1024, function_t, functions, f);
f->s_name = ReuseString (func->name);
f->s_name = ReuseString (name);
f->s_file = pr.source_file;
f->def = func;
if (!(f->name = nice_name))
f->name = f->def->name;
f->name = name;
return f;
}
@ -468,18 +484,25 @@ add_function (function_t *f)
}
function_t *
begin_function (def_t *def, const char *nicename, param_t *params)
begin_function (symbol_t *sym, const char *nicename, symtab_t *parent)
{
function_t *func;
if (def->constant)
error (0, "%s redefined", def->name);
func = new_function (def, nicename);
if (!def->external) {
add_function (func);
reloc_def_func (func, def->ofs);
if (sym->sy_type != sy_func) {
error (0, "%s is not a function", sym->name);
return 0;
}
func->code = pr.code->size;
if (sym->s.func) {
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) {
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;
@ -489,8 +512,9 @@ begin_function (def_t *def, const char *nicename, param_t *params)
lineno->fa.func = func->aux - pr.auxfunctions;
}
build_scope (func, def, params);
return func;
#endif
build_scope (sym, parent);
return sym->s.func;
}
function_t *
@ -508,64 +532,69 @@ build_code_function (function_t *f, expr_t *state_expr, expr_t *statements)
}
function_t *
build_builtin_function (def_t *def, expr_t *bi_val, param_t *params)
build_builtin_function (symbol_t *sym, expr_t *bi_val)
{
function_t *f;
int bi;
if (def->type->type != ev_func) {
error (bi_val, "%s is not a function", def->name);
if (sym->sy_type != sy_func) {
error (bi_val, "%s is not a function", sym->name);
return 0;
}
if (def->constant) {
error (bi_val, "%s redefined", def->name);
if (sym->s.func) {
error (bi_val, "%s redefined", sym->name);
return 0;
}
if (bi_val->type != ex_integer && bi_val->type != ex_float) {
error (bi_val, "invalid constant for = #");
return 0;
}
if (def->external)
return 0;
//if (sym->external)
// return 0;
f = new_function (def, 0);
add_function (f);
sym->s.func = new_function (sym->name, 0);
sym->s.func->sym = sym;
add_function (sym->s.func);
f->builtin = bi_val->type == ex_integer ? bi_val->e.integer_val
: (int)bi_val->e.float_val;
reloc_def_func (f, def->ofs);
build_function (f);
finish_function (f);
bi = bi_val->e.integer_val;
if (bi_val->type == ex_integer)
bi = (int)bi_val->e.float_val;
sym->s.func->builtin = bi;
//reloc_def_func (sym->s.func, def->ofs);
build_function (sym->s.func);
finish_function (sym->s.func);
// for debug info
build_scope (f, f->def, params);
flush_scope (f->scope, 1);
return f;
//build_scope (f, f->def, sym->params);
//flush_scope (f->scope, 1);
return sym->s.func;
}
void
build_function (function_t *f)
{
f->def->constant = 1;
f->def->nosave = 1;
f->def->initialized = 1;
G_FUNCTION (f->def->ofs) = f->function_num;
// FIXME
// f->def->constant = 1;
// f->def->nosave = 1;
// f->def->initialized = 1;
// G_FUNCTION (f->def->ofs) = f->function_num;
}
void
finish_function (function_t *f)
{
if (f->aux) {
def_t *def;
f->aux->function = f->function_num;
if (f->scope) {
for (def = f->scope->head; def; def = def->def_next) {
if (def->name) {
def_to_ddef (def, new_local (), 0);
f->aux->num_locals++;
}
}
}
}
// FIXME
// if (f->aux) {
// def_t *def;
// f->aux->function = f->function_num;
// if (f->scope) {
// for (def = f->scope->head; def; def = def->def_next) {
// if (def->name) {
// def_to_ddef (def, new_local (), 0);
// f->aux->num_locals++;
// }
// }
// }
// }
}
void
@ -618,14 +647,15 @@ emit_function (function_t *f, expr_t *e)
int
function_parms (function_t *f, byte *parm_size)
{
//FIXME this is icky
int count, i;
if (f->def->type->t.func.num_params >= 0)
count = f->def->type->t.func.num_params;
if (f->sym->type->t.func.num_params >= 0)
count = f->sym->type->t.func.num_params;
else
count = -f->def->type->t.func.num_params - 1;
count = -f->sym->type->t.func.num_params - 1;
for (i = 0; i < count; i++)
parm_size[i] = type_size (f->def->type->t.func.param_types[i]);
return f->def->type->t.func.num_params;
parm_size[i] = type_size (f->sym->type->t.func.param_types[i]);
return f->sym->type->t.func.num_params;
}

View file

@ -96,12 +96,12 @@ allocate_stuff (pr_info_t *pr)
}
for (func = pr->func_head; func; func = func->next) {
num_relocs += count_relocs (func->refs);
if (func->scope) {
num_defs += func->scope->num_defs;
for (def = func->scope->head; def; def = def->def_next) {
num_relocs += count_relocs (def->refs);
}
}
//FIXME if (func->scope) {
//FIXME num_defs += func->scope->num_defs;
//FIXME for (def = func->scope->head; def; def = def->def_next) {
//FIXME num_relocs += count_relocs (def->refs);
//FIXME }
//FIXME }
}
num_relocs += count_relocs (pr->relocs);
if (num_defs)
@ -201,20 +201,20 @@ setup_data (pr_info_t *pr)
for (f = pr->func_head; f; f = f->next, func++) {
func->name = LittleLong (f->s_name);
func->file = LittleLong (f->s_file);
func->line = LittleLong (f->def->line);
//FIXME func->line = LittleLong (f->def->line);
func->builtin = LittleLong (f->builtin);
func->code = LittleLong (f->code);
if (f->def->obj_def)
func->def = LittleLong (f->def->obj_def);
else {
func->def = LittleLong (def - defs);
write_def (f->def, def++, &reloc);
}
if (f->scope) {
func->locals_size = LittleLong (f->scope->space->size);
func->local_defs = LittleLong (def - defs);
func->num_local_defs = LittleLong (f->scope->num_defs);
}
//FIXME if (f->def->obj_def)
//FIXME func->def = LittleLong (f->def->obj_def);
//FIXMEelse {
//FIXME func->def = LittleLong (def - defs);
//FIXME write_def (f->def, def++, &reloc);
//FIXME}
//FIXME if (f->scope) {
//FIXME func->locals_size = LittleLong (f->scope->space->size);
//FIXME func->local_defs = LittleLong (def - defs);
//FIXME func->num_local_defs = LittleLong (f->scope->num_defs);
//FIXME }
if (f->aux)
func->line_info = LittleLong (f->aux->line_info);
func->num_parms = LittleLong (function_parms (f, func->parm_size));
@ -222,9 +222,9 @@ setup_data (pr_info_t *pr)
func->num_relocs = LittleLong (count_relocs (f->refs));
write_relocs (f->refs, &reloc, func - funcs);
if (f->scope)
for (d = f->scope->head; d; d = d->def_next)
write_def (d, def++, &reloc);
//FIXME if (f->scope)
//FIXME for (d = f->scope->head; d; d = d->def_next)
//FIXME write_def (d, def++, &reloc);
}
for (r = pr->relocs; r; r = r->next)
if (r->type == rel_def_op)
@ -567,34 +567,34 @@ qfo_to_progs (qfo_t *qfo, pr_info_t *pr)
i < qfo->num_funcs; i++, pf++, qf++) {
*pr->func_tail = pf;
pr->func_tail = &pf->next;
pf->def = pr->scope->head + qf->def;
//FIXME pf->def = pr->scope->head + qf->def;
pf->aux = new_auxfunction ();
pf->aux->function = i + 1;
pf->aux->source_line = qf->line;
pf->aux->line_info = qf->line_info;
pf->aux->local_defs = 0;
pf->aux->num_locals = 0;
pf->aux->return_type = pf->def->type->t.func.type->type;
//FIXME pf->aux->return_type = pf->def->type->t.func.type->type;
pf->builtin = qf->builtin;
pf->code = qf->code;
pf->function_num = i + 1;
pf->s_file = qf->file;
pf->s_name = qf->name;
pf->scope = new_scope (sc_params, init_space (qf->locals_size, 0),
pr->scope);
//FIXME pf->scope = new_scope (sc_params, init_space (qf->locals_size, 0),
//FIXME pr->scope);
if (qf->num_local_defs) {
if (first_local > qf->local_defs)
first_local = qf->local_defs;
pf->scope->head = pr->scope->head + qf->local_defs;
pf->scope->tail = &pf->scope->head[qf->num_local_defs - 1].def_next;
*pf->scope->tail = 0;
//FIXME pf->scope->head = pr->scope->head + qf->local_defs;
//FIXME pf->scope->tail = &pf->scope->head[qf->num_local_defs - 1].def_next;
//FIXME *pf->scope->tail = 0;
pf->aux->local_defs = pr->num_locals;
for (pd = pf->scope->head; pd; pd = pd->def_next) {
if (pd->name) {
def_to_ddef (pd, new_local (), 0);
pf->aux->num_locals++;
}
}
//FIXME for (pd = pf->scope->head; pd; pd = pd->def_next) {
//FIXME if (pd->name) {
//FIXME def_to_ddef (pd, new_local (), 0);
//FIXME pf->aux->num_locals++;
//FIXME }
//FIXME }
}
if (qf->num_relocs) {
pf->refs = relocs + qf->relocs;

View file

@ -631,8 +631,8 @@ finish_compilation (void)
df->s_name = f->s_name;
df->s_file = f->s_file;
df->numparms = function_parms (f, df->parm_size);
if (f->scope)
df->locals = f->scope->space->size;
//FIXME if (f->scope)
//FIXME df->locals = f->scope->space->size;
if (f->builtin) {
df->first_statement = -f->builtin;
continue;
@ -641,22 +641,22 @@ finish_compilation (void)
continue;
df->first_statement = f->code;
if (options.code.local_merging) {
if (f->scope->space->size > num_localdefs) {
num_localdefs = f->scope->space->size;
big_function = f->def->name;
}
//FIXME if (f->scope->space->size > num_localdefs) {
//FIXME num_localdefs = f->scope->space->size;
//FIXME big_function = f->def->name;
//FIXME }
df->parm_start = pr.near_data->size;
} else {
df->parm_start = defspace_new_loc (pr.near_data,
f->scope->space->size);
num_localdefs += f->scope->space->size;
}
for (def = f->scope->head; def; def = def->def_next) {
if (!def->local)
continue;
def->ofs += df->parm_start;
relocate_refs (def->refs, def->ofs);
//FIXME df->parm_start = defspace_new_loc (pr.near_data,
//FIXME f->scope->space->size);
//FIXME num_localdefs += f->scope->space->size;
}
//FIXME for (def = f->scope->head; def; def = def->def_next) {
//FIXME if (!def->local)
//FIXME continue;
//FIXME def->ofs += df->parm_start;
//FIXME relocate_refs (def->refs, def->ofs);
//FIXME }
}
if (options.code.local_merging) {
int ofs;

View file

@ -153,17 +153,21 @@ program
// move the symbol for the program name to the end of the list
symtab_removesymbol (current_symtab, $1);
symtab_addsymbol (current_symtab, $1);
$<symtab>$ = current_symtab;
current_func = begin_function ($1, 0, current_symtab);
current_symtab = current_func->symtab;
}
;
program_head
: PROGRAM ID '(' opt_identifier_list ')' ';'
{
$$ = $2;
current_symtab = new_symtab (0, stab_global);
$$->type = parse_params (&type_void, 0);
symtab_addsymbol (current_symtab, $2);
$$ = function_symbol ($$, 0, 1);
}
;
@ -224,13 +228,9 @@ subprogram_declarations
subprogram_declaration
: subprogram_head ';'
{
param_t *p;
$<symtab>$ = current_symtab;
current_symtab = new_symtab (current_symtab, stab_local);
for (p = $1->params; p; p = p->next)
symtab_addsymbol (current_symtab, copy_symbol (p->symbol));
current_func = begin_function ($1, 0, current_symtab);
current_symtab = current_func->symtab;
}
declarations compound_statement ';'
{
@ -242,12 +242,12 @@ subprogram_declaration
print_type_str (str, s->type);
printf (" %s %s\n", s->name, str->str);
}
current_symtab = current_symtab->parent;
current_symtab = $<symtab>3;
dstring_delete (str);
}
| subprogram_head ASSIGNOP '#' CONST ';'
{
//build_builtin_function ($1, $4, $1->params);
build_builtin_function ($1, $4);
}
;
@ -260,7 +260,7 @@ subprogram_head
} else {
$$->params = $3;
$$->type = parse_params ($5, $3);
symtab_addsymbol (current_symtab, $$);
$$ = function_symbol ($$, 0, 1);
}
}
| PROCEDURE ID arguments
@ -271,7 +271,7 @@ subprogram_head
} else {
$$->params = $3;
$$->type = parse_params (&type_void, $3);
symtab_addsymbol (current_symtab, $$);
$$ = function_symbol ($$, 0, 1);
}
}
;