scc

suckless C compiler
git clone git://git.suckless.org/scc
Log | Files | Refs | README | LICENSE

commit 8a57ba149a24de43b6163d49f59aacd93b9c9c57
parent ce2ba80db757ad95bf1011ba2cfe451552f31735
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 26 Feb 2017 16:57:00 +0100

[cc1] Rewrite function declaration code

This code had the problem that it needed dynamic memory that
was allocated in one palce but had to be deallocted in other
totally unrelated place. This code removes the need of dynamic
memory and simplify the code in several places.

Diffstat:
cc1/decl.c | 170+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
cc1/types.c | 15+++++++--------
2 files changed, 116 insertions(+), 69 deletions(-)

diff --git a/cc1/decl.c b/cc1/decl.c @@ -14,15 +14,20 @@ static char sccsid[] = "@(#) ./cc1/decl.c"; #define NOREP 0 #define REP 1 +#define NR_DCL_TYP (NR_DECLARATORS+NR_FUNPARAM) +#define NR_DCL_ARG (NR_DECLARATORS+NR_FUNPARAM+1) struct declarators { - unsigned char nr; + unsigned nr; + unsigned nr_types, nr_pars; + Symbol **pars; + Type **tpars; struct declarator { unsigned char op; TINT nelem; Symbol *sym; - Type **tpars; Symbol **pars; + Type **tpars; } d [NR_DECLARATORS]; }; @@ -34,6 +39,8 @@ struct decl { Symbol **pars; Type *type; Type *parent; + Symbol *bufpars[NR_DCL_ARG]; + Type *buftpars[NR_DCL_ARG]; }; static void @@ -57,7 +64,7 @@ push(struct declarators *dp, int op, ...) break; case KRFTN: case FTN: - p->nelem = va_arg(va, TINT); + p->nelem = va_arg(va, unsigned); p->tpars = va_arg(va, Type **); p->pars = va_arg(va, Symbol **); break; @@ -87,7 +94,6 @@ pop(struct declarators *dp, struct decl *dcl) * function. We don't need * the parameter symbols anymore. */ - free(dcl->pars); popctx(); dcl->pars = NULL; } @@ -144,7 +150,6 @@ parameter(struct decl *dcl) { Symbol *sym = dcl->sym; Type *funtp = dcl->parent, *tp = dcl->type; - TINT n = funtp->n.elem; char *name = sym->name; int flags; @@ -201,12 +206,11 @@ static Symbol *dodcl(int rep, unsigned ns, Type *type); -static void -krfun(Type *tp, Type *types[], Symbol *syms[], int *ntypes, int *nsyms) +static unsigned +krfun(struct declarators *dp) { - int n = 0; Symbol *sym; - int toomany = 0; + unsigned toomany = 0, npars = 0; if (yytoken != ')') { do { @@ -219,85 +223,112 @@ krfun(Type *tp, Type *types[], Symbol *syms[], int *ntypes, int *nsyms) yylval.sym->name); continue; } - if (n < NR_FUNPARAM) { - ++n; - *syms++ = sym; + if (dp->nr_pars < NR_DCL_ARG-1) { + ++npars; + ++dp->nr_pars; + *dp->pars++ = sym; continue; } if (!toomany) - errorp("too much parameters in function definition"); + errorp("too many parameters in function definition"); toomany = 1; } while (accept(',')); } - *nsyms = n; - *ntypes = 1; - types[0] = ellipsistype; + if (dp->nr_types < NR_DCL_TYP) { + ++dp->nr_types; + *dp->tpars++ = ellipsistype; + } + + return 1; } -static void -ansifun(Type *tp, Type *types[], Symbol *syms[], int *ntypes, int *nsyms) +static unsigned +ansifun(struct declarators *dp) { - int npars = 0; Symbol *sym; - int toomany = 0, voidparam = 0; + unsigned ntype, toomany, distoomany, voidpar; + Type type, *tp; + type.n.elem = 0; + type.prop = 0; + ntype = toomany = toomany = distoomany = voidpar = 0; do { - ++npars; if (accept(ELLIPSIS)) { - if (npars < 2) + if (ntype < 1) errorp("a named argument is requiered before '...'"); - *syms = NULL; - *types++ = ellipsistype; - } else if ((sym = dodcl(NOREP, parameter, NS_IDEN, tp)) == NULL) { - if (tp->n.elem == 1) - voidparam = 1; - } else if (npars < NR_FUNPARAM) { - *syms++ = sym; - *types++ = sym->type; - } else if (!toomany) { + if (yytoken != ')') + errorp("... must be the last parameter"); + sym = NULL; + tp = ellipsistype; + } else if ((sym = dodcl(NOREP, parameter, NS_IDEN, &type)) == NULL) { + if (type.n.elem == 1 && ntype > 1) + voidpar = 1; + sym = NULL; + tp = NULL; + } else { + tp = sym->type; + } + + if (sym) { + if (dp->nr_pars == NR_DCL_ARG-1) { + toomany = 1; + } else { + dp->nr_pars++; + *dp->pars++ = sym; + } + } + + if (tp) { + if (dp->nr_types == NR_DCL_TYP) { + toomany = 1; + } else { + ntype++; + dp->nr_types++; + *dp->tpars++ = tp; + } + } + + if (toomany == 1 && !distoomany) { errorp("too many parameters in function definition"); - toomany = 1; + distoomany = 1; } - if (npars == 2 && voidparam) - errorp("'void' must be the only parameter"); } while (accept(',')); - *nsyms = *ntypes = voidparam ? 0 : npars; + if (voidpar && ntype > 1) + errorp("'void' must be the only parameter"); + + return ntype; } static void fundcl(struct declarators *dp) { - Type *types[NR_FUNPARAM], type; - Symbol *syms[NR_FUNPARAM+1], **pars; - int k_r, ntypes, nsyms; - size_t size; + Symbol **pars = dp->pars; + Type **types = dp->tpars; + unsigned ntypes, typefun; + unsigned (*fun)(struct declarators *dp); pushctx(); expect('('); - type.n.elem = 0; - type.prop = 0; - - k_r = (yytoken == ')' || yytoken == IDEN); - (k_r ? krfun : ansifun)(&type, types, syms, &ntypes, &nsyms); - expect(')'); - type.n.elem = ntypes; - if (ntypes <= 0) { - type.p.pars = NULL; + if (yytoken == ')' || yytoken == IDEN) { + typefun = KRFTN; + fun = krfun; } else { - size = ntypes * sizeof(Type *); - type.p.pars = memcpy(xmalloc(size), types, size); + typefun = FTN; + fun = ansifun; } - if (nsyms <= 0) { - pars = NULL; - } else { - size = (nsyms + 1) * sizeof(Symbol *); - pars = memcpy(xmalloc(size), syms, size); - pars[nsyms] = NULL; + + ntypes = (*fun)(dp); + expect(')'); + + if (dp->nr_pars < NR_DCL_ARG) { + *dp->pars++ = NULL; + ++dp->nr_pars; } - push(dp, (k_r) ? KRFTN : FTN, type.n.elem, type.p.pars, pars); + + push(dp, typefun, ntypes, types, pars); } static void declarator(struct declarators *dp, unsigned ns); @@ -670,6 +701,21 @@ bad_storage(Type *tp, char *name) errorp("invalid storage class for function '%s'", name); } +static Symbol ** +parsdup(Symbol **pars) +{ + Symbol **bp; + size_t n; + + if (!pars) + return NULL; + + for (n = 1, bp = pars; *bp; ++n, ++bp) + /* nothing */; + n *= sizeof(Symbol *); + return memcpy(xmalloc(n), pars, n); +} + static Symbol * redcl(Symbol *sym, Type *tp, Symbol **pars, int sclass) { @@ -692,7 +738,7 @@ redcl(Symbol *sym, Type *tp, Symbol **pars, int sclass) goto redeclaration; } - sym->u.pars = pars; + sym->u.pars = parsdup(pars); flags = sym->flags; switch (sclass) { @@ -764,7 +810,7 @@ identifier(struct decl *dcl) int flags = sym->flags | SDECLARED; sym->type = tp; - sym->u.pars = dcl->pars; + sym->u.pars = parsdup(dcl->pars); switch (sclass) { case REGISTER: @@ -816,9 +862,11 @@ dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent) base = specifier(&dcl.sclass, &dcl.qualifier); do { - stack.nr = 0; - dcl.pars = NULL; dcl.type = base; + dcl.pars = NULL; + stack.nr_pars = stack.nr_types = stack.nr = 0; + stack.pars = dcl.bufpars; + stack.tpars = dcl.buftpars; declarator(&stack, ns); diff --git a/cc1/types.c b/cc1/types.c @@ -260,11 +260,17 @@ static Type * newtype(Type *base) { Type *tp; + size_t siz; tp = xmalloc(sizeof(*tp)); *tp = *base; tp->id = newid(); + if (tp->op == FTN) { + siz = tp->n.elem * sizeof(Type *); + tp->p.pars = memcpy(xmalloc(siz), tp->p.pars, siz); + } + if (curfun) { /* it is a type defined in the body of a function */ tp->next = localtypes; @@ -331,15 +337,8 @@ mktype(Type *tp, int op, TINT nelem, Type *pars[]) tbl = &typetab[HASH(&type)]; for (bp = *tbl; bp; bp = bp->h_next) { - if (eqtype(bp, &type, 0)) { - /* - * pars was allocated by the caller - * but the type already exists, so - * we have to deallocte it - */ - free(pars); + if (eqtype(bp, &type, 0)) return bp; - } } bp = newtype(&type);