shithub: scc

Download patch

ref: 7d056d042a60919bb854929e776e138e0ee2817d
parent: cde67f41cb37d1c695d7de0a5100458bcc5de9c1
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Aug 5 16:01:45 EDT 2015

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.

--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -59,8 +59,8 @@
 {
 	Type dummy = {.n = {.elem = 0}, .pars = NULL};
 
-	pushctx();
 	parlist(&dummy);
+
 	return queue(dp, FTN, dummy.n.elem, dummy.pars);
 }
 
@@ -409,6 +409,7 @@
 		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 @@
 		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 @@
 	}
 
 	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 @@
 			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 @@
 	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