shithub: scc

Download patch

ref: 45e74e1d82c733ea83a2af7b06c2c897ff1df3e9
parent: 0289c983456b286aea8fcf95c4a2e9950964317f
author: Roberto E. Vargas Caballero <[email protected]>
date: Sun Nov 16 00:45:24 EST 2014

Rewrite struct data structures

Type had a special type for fields of structures, and we were looking
in a list of fields each time that a . ir -> were used. This list needed
special routines for everyting. This patch removes this list and use
the symbol hash to storing the fields of structs. It uses a unique hash
for all the fields of all the structs, so it is needed a field in the
symbols to store the namespace.

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -26,6 +26,7 @@
 	NS_IDEN = 0,
 	NS_TAG,
 	NS_LABEL,
+	NS_STRUCTS,
 	NR_NAMESPACES
 };
 
@@ -32,25 +33,19 @@
 typedef struct ctype Type;
 typedef struct symbol Symbol;
 
-typedef struct field {
-	char *name;
-	Type *type;
-	int id;
-	struct field *next;
-} Field;
-
 struct ctype {
 	uint8_t op;           /* type builder operator */
+	uint8_t ns;
 	char letter;          /* letter of the type */
 	bool defined : 1;     /* type defined (is not a forward reference) */
 	bool sign : 1;        /* sign type */
 	struct ctype *type;   /* base type */
 	struct ctype *next;   /* next element in the hash */
+	Type **pars;         /* type parameters */
 	union {
 		unsigned char rank;  /* convertion rank */
 		short elem;          /* number of type parameters */
 	} n;
-	void *pars;           /* type parameters */
 };
 
 
@@ -61,6 +56,7 @@
 	Type *type;
 	short id;
 	uint8_t ctx;
+	uint8_t ns;
 	uint8_t token;
 	struct {
 		bool isglobal : 1;
@@ -68,11 +64,11 @@
 		bool isauto : 1;
 		bool isregister : 1;
 		bool isdefined : 1;
+		bool isfield : 1;
 	} s;
 	union {
 		int i;
 		char *s;
-		struct symbol *sym;
 		uint8_t token;
 	} u;
 	struct symbol *next;
@@ -90,7 +86,6 @@
 typedef struct caselist Caselist;
 
 extern void compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
-extern Type *aggregate(Type *(*fun)(void));
 extern void context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
 
 extern Type *typename(void);
@@ -161,7 +156,6 @@
 		Symbol *sym;
 		Type *type;
 		char op;
-		Field *field;
 	} u;
 	struct node *childs[];
 } Node;
@@ -191,7 +185,8 @@
 	emitswitch(short, Node *), emitcase(Symbol *, Node *),
 	emitret(Type *tp),
 	emitfun(Symbol *sym),
-	emitdefault(Symbol *);
+	emitdefault(Symbol *),
+	emitstruct(Symbol *sym), emitestruct(void);
 
 extern Node
 	*node(void (*code)(Node *),
@@ -202,7 +197,7 @@
 	*sizeofcode(Type *tp), 
 	*ternarycode(Node *cond, Node *ifyes, Node *ifno),
 	*symcode(Symbol *sym),
-	*fieldcode(Node *child, struct field *fp);
+	*fieldcode(Node *child, Symbol *field);
 
 extern void freetree(Node *np);
 
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -92,6 +92,8 @@
 		c = 'G';
 	else if (sym->s.isregister)
 		c = 'R';
+	else if (sym->s.isfield)
+		c = 'M';
 	else
 		c = 'A';
 	printf("%c%d", c, sym->id);
@@ -113,6 +115,18 @@
 }
 
 void
+emitstruct(Symbol *sym)
+{
+	printf("S%d\t(\n", sym->id);
+}
+
+void
+emitestruct(void)
+{
+	puts(")");
+}
+
+void
 emitsym(Node *np)
 {
 	putchar('\t');
@@ -280,14 +294,14 @@
 
 	child = np->childs[0];
 	(*child->code)(child);
-
-	printf("\tM%d", np->u.field->id);
+	putchar('\t');
+	emitsym2(np->u.sym);
 }
 
 Node *
-fieldcode(Node *child, struct field *fp)
+fieldcode(Node *child, Symbol *field)
 {
-	Node *np = node(emitfield, fp->type, FIELD(fp), 1);
+	Node *np = node(emitfield, field->type, SYM(field), 1);
 	np->childs[0] = child;
 	return np;
 }
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -70,33 +70,33 @@
 }
 
 static Symbol *
-newiden(void)
+newiden(uint8_t ns)
 {
 	Symbol *sym;
 	extern uint8_t curctx;
 
-	if (yylval.sym && yylval.sym->ctx == curctx)
+	if (yylval.sym && yylval.sym->ctx == curctx && yylval.sym->ns == ns)
 		error("redeclaration of '%s'", yytext);
-	sym = install(yytext, NS_IDEN);
+	sym = install(yytext, ns);
 	next();
 	return sym;
 }
 
-static struct dcldata *declarator0(struct dcldata *dp);
+static struct dcldata *declarator0(struct dcldata *dp, uint8_t ns);
 
 static struct dcldata *
-directdcl(struct dcldata *dp)
+directdcl(struct dcldata *dp, uint8_t ns)
 {
 	register Symbol *sym;
 
 	if (accept('(')) {
-		dp = declarator0(dp);
+		dp = declarator0(dp, ns);
 		expect(')');
 	} else {
 		if (yytoken == IDEN || yytoken == TYPEIDEN)
-			sym = newiden();
+			sym = newiden(ns);
 		else
-			sym = install("", NS_IDEN);
+			sym = install("", ns);
 		dp = queue(dp, IDEN, 0, sym);
 	}
 
@@ -110,7 +110,7 @@
 }
 
 static struct dcldata*
-declarator0(struct dcldata *dp)
+declarator0(struct dcldata *dp, uint8_t ns)
 {
 	register uint8_t  n;
 
@@ -119,7 +119,7 @@
 			/* nothing */;
 	}
 
-	dp = directdcl(dp);
+	dp = directdcl(dp, ns);
 
 	while (n--)
 		dp = queue(dp, PTR, 0, NULL);
@@ -128,7 +128,7 @@
 }
 
 static Symbol *
-declarator(Type *tp, int8_t flags)
+declarator(Type *tp, int8_t flags, uint8_t ns)
 {
 	struct dcldata data[NR_DECLARATORS+2];
 	register struct dcldata *bp;
@@ -136,7 +136,7 @@
 
 	memset(data, 0, sizeof(data));
 	data[NR_DECLARATORS].op = 255;
-	for (bp = declarator0(data)-1; bp >= data; --bp) {
+	for (bp = declarator0(data, ns)-1; bp >= data; --bp) {
 		if (bp->op != IDEN) {
 			tp = mktype(tp, bp->op, bp->nelem, bp->data);
 		} else {
@@ -212,7 +212,7 @@
 		if (dcl) {
 			if (size || sign)
 				goto invalid_type;
-			tp = aggregate(dcl);
+			tp = (*dcl)();
 		} else {
 			next();
 		}
@@ -248,70 +248,11 @@
 	return NULL;
 }
 
-/* TODO: bitfields */
-
-static void
-newfield(Type *tp, Symbol *sym)
-{
-	register Field *p, *q;
-	register char *s, *t;
-
-	s = sym->name;
-	for (q = p = tp->pars; p; q = p, p = p->next) {
-		t = p->name;
-		if (*s == *t && !strcmp(s, t))
-			error("duplicated fields '%s' and '%s'", s, t);
-		if (sym->u.i == p->id)
-			error("duplicated enumeration fields '%s' and '%s'",
-			      s, t);
-	}
-
-	p = xmalloc(sizeof(*p));
-	p->name = xstrdup(s);
-	p->next = NULL;
-	p->id = sym->id;
-	p->type = sym->type;
-	if (!q)
-		tp->pars= p;
-	else
-		q->next = p;
-
-	return;
-}
-
-static void
-fielddcl(Type *base)
-{
-	Type *tp;
-	Symbol *sym;
-
-	switch (yytoken) {
-	case SCLASS:
-		error("storage class '%s' in struct/union field", yytext);
-	case IDEN: case TYPE: case TYPEIDEN: case TQUALIFIER:
-		tp = specifier(NULL);
-	case ';':
-		break;
-	default:
-		unexpected();
-	}
-
-	if (yytoken != ';') {
-		do {
-			sym = declarator(tp, ID_EXPECTED);
-			newfield(base, sym);
-		} while (accept(','));
-	}
-
-	expect(';');
-	return;
-}
-
-static Type *
+static Symbol *
 newtag(uint8_t tag)
 {
 	register Symbol *sym;
-	register Type *tp;
+	static uint8_t ns = NS_STRUCTS;
 
 	switch (yytoken) {
 	case IDEN: case TYPEIDEN:
@@ -323,32 +264,80 @@
 		sym = install("", NS_TAG);
 		break;
 	}
-	if (!sym->type)
+	if (!sym->type) {
+		if (ns == NS_STRUCTS + NR_MAXSTRUCTS)
+			error("too much tags declared");
 		sym->type = mktype(NULL, tag, 0, NULL);
-	tp = sym->type;
-	if (tp->op != tag)
+		sym->type->ns = ns++;
+	}
+	
+	if (sym->type->op != tag)
 		error("'%s' defined as wrong kind of tag", yytext);
-	return tp;
+	return sym;
 }
 
+/* TODO: bitfields */
+
 static Type *
 structdcl(void)
 {
-	Type *tp;
-	uint8_t tag;
+	Type *tagtype, *buff[NR_MAXSTRUCTS], **bp = &buff[0];
+	Symbol *tagsym, *sym;
+	uint8_t tag, n;
+	size_t siz;
 
 	tag = yylval.token;
 	next();
-	tp = newtag(tag);
-	if (accept('{')) {
-		if (tp->defined)
-			error("redefinition of struct/union '%s'", yytext);
-		tp->defined = 1;
-		while (!accept('}'))
-			fielddcl(tp);
+	tagsym = newtag(tag);
+	tagtype = tagsym->type;
+	if (!accept('{'))
+		return tagtype;
+
+	if (tagtype->defined)
+		error("redefinition of struct/union '%s'", yytext);
+	tagtype->defined = 1;
+	emitstruct(tagsym);
+
+	while (!accept('}')) {
+		Type *base, *tp;
+
+		switch (yytoken) {
+		case SCLASS:
+			error("storage class '%s' in struct/union field",
+			      yytext);
+		case IDEN: case TYPE: case TYPEIDEN: case TQUALIFIER:
+			base = specifier(NULL);
+			break;
+		case ';':
+			next();
+			continue;
+		default:
+			unexpected();
+		}
+
+		if (accept(';'))
+			error("identifier expected");
+
+		do {
+			sym = declarator(base, ID_EXPECTED, tagtype->ns);
+			sym->s.isfield = 1;
+			tp = sym->type;
+			if (tp->op == FTN)
+				error("invalid type in struct/union");
+			if (bp == &buff[NR_MAXSTRUCTS])
+				error("too much fields in struct/union");
+			*bp++ = sym->type;
+			emitdcl(sym);
+		} while (accept(','));
+		expect(';');
 	}
 
-	return tp;
+	emitestruct();
+	n = bp - buff - 1;
+	siz = sizeof(Type *) * n;
+	tagtype->n.elem = n;
+	tagtype->pars = memcpy(xmalloc(siz), buff, siz);
+	return tagtype;
 }
 
 static Type *
@@ -359,7 +348,8 @@
 	int val = 0;
 
 	next();
-	tp = newtag(ENUM);
+	tp = newtag(ENUM)->type;
+
 	if (yytoken == ';')
 		return tp;
 
@@ -370,12 +360,11 @@
 	while (yytoken != '}') {
 		if (yytoken != IDEN)
 			unexpected();
-		sym = newiden();
+		sym = newiden(NS_IDEN);
 		sym->type = inttype;
 		if (accept('='))
 			initializer(sym);
 		sym->u.i = val++;
-		newfield(tp, sym);
 		if (!accept(','))
 			break;
 	}
@@ -393,7 +382,7 @@
 
 	if ((tp = specifier(&sclass)) == voidtype)
 		return tp;
-	sym = declarator(tp, ID_ACCEPTED);
+	sym = declarator(tp, ID_ACCEPTED, NS_IDEN);
 	sym->s.isdefined = 1;
 	/* TODO: check type of the parameter */
 	switch (sclass) {
@@ -421,7 +410,7 @@
 		return;
 
 	do {
-		sym = declarator(tp, ID_EXPECTED);
+		sym = declarator(tp, ID_EXPECTED, NS_IDEN);
 		sym->s.isdefined = 1;
 		isfun = sym->type->op == FTN;
 
@@ -470,7 +459,7 @@
 	tp = specifier(&sclass);
 	if (sclass)
 		error("class storage in type name");
-	sym = declarator(tp, ID_FORBIDDEN);
+	sym = declarator(tp, ID_FORBIDDEN, NS_IDEN);
 	return  sym->type;
 }
 
@@ -488,7 +477,7 @@
 		if (accept(';'))
 			return;
 		do {
-			sym = declarator(base, ID_EXPECTED);
+			sym = declarator(base, ID_EXPECTED, NS_IDEN);
 			tp = sym->type;
 			sym->s.isstatic = 1;
 			sym->s.isglobal= 1;
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -292,19 +292,20 @@
 static Node *
 field(Node *np)
 {
-	Field *fp;
+	extern uint8_t lex_ns;
+	Symbol *sym;
 
-	if (yytoken != IDEN)
-		unexpected();
 	switch (np->typeop) {
 	case STRUCT: case UNION:
-		for (fp = np->type->pars; fp; fp = fp->next) {
-			if (!strcmp(fp->name, yytext)) {
-				next();
-				return fieldcode(np, fp);
-			}
-		}
-		error("field '%s' not found", yytext);
+		lex_ns = np->type->ns;
+		next();
+		if (yytoken != IDEN)
+			unexpected();
+		if ((sym = yylval.sym) == NULL)
+			error("incorrect field in struct/union");
+		lex_ns = NS_IDEN;
+		next();
+		return fieldcode(np, sym);
 	default:
 		error("struct or union expected");
 	}
@@ -482,7 +483,6 @@
 		case INDIR:
 			np1 = content(OPTR, np1);
 		case '.':
-			next();
 			np1 = field(np1);
 			break;
 		case '(':
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -10,6 +10,7 @@
 #include "cc1.h"
 
 static FILE *yyin;
+uint8_t lex_ns = NS_IDEN;
 const char *filename;
 unsigned linenum;
 
@@ -202,7 +203,7 @@
 	*bp = '\0';
 	ungetc(c, yyin);
 
-	sym = yylval.sym = lookup(yytext, NS_IDEN);
+	sym = yylval.sym = lookup(yytext, lex_ns);
 	if (!sym || sym->token == IDEN)
 		return IDEN;
 	yylval.token = sym->u.token;
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
@@ -47,18 +47,6 @@
 	}
 }
 
-Type *
-aggregate(Type * (*fun)(void))
-{
-	Type *tp;
-
-	++curctx;
-	tp = (*fun)();
-	--curctx;
-	freesyms(NS_IDEN);
-	return tp;
-}
-
 void
 context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
 {
@@ -67,6 +55,7 @@
 	--curctx;
 	freesyms(NS_IDEN);
 	freesyms(NS_TAG);
+	freesyms(NS_STRUCTS);
 	if (curctx == 0) {
 		localcnt = 0;
 		freesyms(NS_LABEL);
@@ -79,9 +68,9 @@
 	struct symtab *tbl;
 	register Symbol *sym;
 
-	tbl = &symtab[ns];
+	tbl = &symtab[(ns > NS_STRUCTS) ? NS_STRUCTS : ns];
 	for (sym = tbl->htab[hash(s)]; sym; sym = sym->hash) {
-		if (!strcmp(sym->name, s))
+		if (!strcmp(sym->name, s) && sym->ns == ns)
 			return sym;
 	}
 
@@ -99,8 +88,9 @@
 	sym->ctx = curctx;
 	sym->token = IDEN;
 	sym->id = (curctx) ? ++localcnt : ++globalcnt;
-	sym->s.isdefined = 1;
-	tbl = &symtab[ns];
+	sym->s.isdefined = 0;
+	sym->ns = ns;
+	tbl = &symtab[(ns > NS_STRUCTS) ? NS_STRUCTS : ns];
 	sym->next = tbl->head;
 	tbl->head = sym;
 
--- a/cc1/types.c
+++ b/cc1/types.c
@@ -206,6 +206,7 @@
 	type.letter = letters[op];
 	type.pars = data;
 	type.n.elem = nelem;
+	type.ns = 0;
 
 	if (op == ARY && nelem == 0 || op == STRUCT || op == UNION)
 		type.defined = 0;
@@ -236,9 +237,11 @@
 	if (tp1->op != tp2->op || tp1->n.elem != tp2->n.elem)
 		return 0;
 	switch (tp1->op) {
+	case ARY:
 	case PTR:
 		return eqtype(tp1->type, tp2->type);
-	/* TODO: use the same struct for function parameters and fields */
+	case UNION:
+	case STRUCT:
 	case FTN:
 		p1 = tp1->pars, p2 = tp2->pars;
 		for (n = tp1->n.elem; n != 0; --n) {
@@ -246,23 +249,9 @@
 				return 0;
 		}
 		return 1;
-	case UNION:
-	case STRUCT: {
-		Field *fp1 = tp1->pars, *fp2 = tp2->pars;
-
-		while (fp1 && fp2) {
-			if (!eqtype(fp1->type, fp2->type))
-				break;
-			fp1 = fp1->next;
-			fp2 = fp2->next;
-		}
-		return fp1 == fp2;
-	}
-	case ARY:
-		if (!eqtype(tp1->type, tp2->type))
-			return 0;
-		return 1;
-	case ENUM: case INT: case FLOAT:
+	case ENUM:
+		/* TODO: Check when two enum are the same type */
+	case INT: case FLOAT:
 		return tp1->letter == tp2->letter;
 	default:
 		fputs("internal type error, aborting\n", stderr);