shithub: scc

Download patch

ref: 2cd872bc09250e9ba2c7f5e2bae693b28f06b56c
parent: 45376df5234d6bf2d9600627aaa89afd3cf166c2
author: Roberto E. Vargas Caballero <[email protected]>
date: Sun Feb 26 11:57:00 EST 2017

[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.

--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -14,15 +14,20 @@
 #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 @@
 	Symbol **pars;
 	Type *type;
 	Type *parent;
+	Symbol *bufpars[NR_DCL_ARG];
+	Type *buftpars[NR_DCL_ARG];
 };
 
 static void
@@ -57,7 +64,7 @@
 		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 @@
 		 * function. We  don't need
 		 * the parameter symbols anymore.
 		 */
-		free(dcl->pars);
 		popctx();
 		dcl->pars = NULL;
 	}
@@ -144,7 +150,6 @@
 {
 	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 @@
                      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 @@
 				       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);
+	if (yytoken == ')' || yytoken == IDEN) {
+		typefun = KRFTN;
+		fun = krfun;
+	} else {
+		typefun = FTN;
+		fun = ansifun;
+	}
+
+	ntypes = (*fun)(dp);
 	expect(')');
 
-	type.n.elem = ntypes;
-	if (ntypes <= 0) {
-		type.p.pars = NULL;
-	} else {
-		size = ntypes * sizeof(Type *);
-		type.p.pars = memcpy(xmalloc(size), types, size);
+	if (dp->nr_pars < NR_DCL_ARG) {
+		*dp->pars++ = NULL;
+		++dp->nr_pars;
 	}
-	if (nsyms <= 0) {
-		pars = NULL;
-	} else {
-		size = (nsyms + 1) * sizeof(Symbol *);
-		pars = memcpy(xmalloc(size), syms, size);
-		pars[nsyms] = NULL;
-	}
-	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 @@
 		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 @@
 		goto redeclaration;
 	}
 
-	sym->u.pars = pars;
+	sym->u.pars = parsdup(pars);
 
 	flags = sym->flags;
 	switch (sclass) {
@@ -764,7 +810,7 @@
 		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 @@
 	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);
 
--- a/cc1/types.c
+++ b/cc1/types.c
@@ -260,11 +260,17 @@
 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 @@
 
 	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);