scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 7d056d042a60919bb854929e776e138e0ee2817d
parent cde67f41cb37d1c695d7de0a5100458bcc5de9c1
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed,  5 Aug 2015 20:01:45 +0200

Emit parameters in functions

Parameters are marked with a P, and in this case are
emited before of the body of the function, but this is
something we should change because we are loosing the
storage specifier.

Diffstat:
Mcc1/decl.c | 55+++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 39 insertions(+), 16 deletions(-)

diff --git a/cc1/decl.c b/cc1/decl.c @@ -59,8 +59,8 @@ fundcl(struct dcldata *dp) { Type dummy = {.n = {.elem = 0}, .pars = NULL}; - pushctx(); parlist(&dummy); + return queue(dp, FTN, dummy.n.elem, dummy.pars); } @@ -409,6 +409,7 @@ parameter(Symbol *sym, int sclass, Type *data) error("bad storage class in function parameter"); if (n++ == NR_FUNPARAM) error("too much parameters in function definition"); + sym->flags |= ISPARAM; funtp->pars = xrealloc(funtp->pars, n); funtp->pars[n-1] = tp; funtp->n.elem = n; @@ -462,27 +463,23 @@ prototype(Symbol *sym) if (sym->token == TYPEIDEN) error("function definition declared 'typedef'"); - /* TODO: emit parameters emit(ODECL, *sp++); */ sym->flags |= ISDEFINED; curfun = sym; emit(OFUN, sym); compound(NULL, NULL, NULL); emit(OEFUN, NULL); + popctx(); r = 0; } - /* - * fundcl() creates a new context for the parameters - * and in this point we have to destroy the context - */ - popctx(); return r; } -static bool +static Symbol * dodcl(int rep, void (*fun)(Symbol *, int, Type *), uint8_t ns, Type *type) { - Type *base; + Symbol *sym; + Type *base, *tp; int sclass; /* FIXME: curctx == PARCTX is incorrect. Structs also @@ -496,8 +493,8 @@ dodcl(int rep, void (*fun)(Symbol *, int, Type *), uint8_t ns, Type *type) } do { - Symbol *sym = declarator(base, ns); - Type *tp = sym->type; + sym = declarator(base, ns); + tp = sym->type; switch (sclass) { case REGISTER: @@ -516,13 +513,13 @@ dodcl(int rep, void (*fun)(Symbol *, int, Type *), uint8_t ns, Type *type) sym->token = TYPEIDEN; break; } - if (tp->op == FTN && !prototype(sym)) - return 0; + return NULL; (*fun)(sym, sclass, type); + } while (rep && accept(',')); - return 1; + return sym; } void @@ -535,20 +532,46 @@ decl(void) expect(';'); } +/* + * parlist() is called every time there is a argument list. + * It means that is called for prototypes and for functions. + * In both cases a new context is needed for the arguments, + * but in the case of prototypes we need pop the context + * before parsing anything else or we can have name conflicts. + * The heuristic used here to detect a function is check if + * next token will be '{', but it implies that K&R alike + * functions are not allowed. + */ static void parlist(Type *tp) { + Symbol *pars[NR_FUNPARAM], **sp = pars, *sym; + bool isfun; + int n; + + pushctx(); expect('('); if (accept(')')) { - /* TODO: implement k&r functions */ + tp->n.elem = -1; return; } + do - dodcl(0, parameter, NS_IDEN, tp); + *sp++ = dodcl(0, parameter, NS_IDEN, tp); while (accept(',')); + isfun = ahead() == '{'; + if (!isfun) + popctx(); expect(')'); + + if (!isfun) + return; + + n = tp->n.elem; + for (sp = pars; n-- > 0; ++sp) + emit(ODECL, *sp); } static void