shithub: scc

Download patch

ref: 40566c3a7324fdb0e23dcee2e207c630f4460098
parent: b2ce2879bce1b20bd28c99ca44d0dd46d50078aa
author: Roberto E. Vargas Caballero <[email protected]>
date: Mon Mar 17 15:56:44 EDT 2014

Add struct/union fields and calculate offset of every field

--- a/decl.c
+++ b/decl.c
@@ -8,6 +8,7 @@
 #include "tokens.h"
 #include "syntax.h"
 #include "symbol.h"
+#include "machine.h"
 
 int8_t forbid_eof;
 
@@ -251,12 +252,48 @@
 
 /* TODO: add define for the 3 parameter of declarator */
 /* TODO: bitfields */
-static short
-fielddcl(uint8_t ns, uint8_t type)
+
+static void
+newfield(struct ctype *tp, struct symbol *sym)
 {
+	struct field *p, *q;
+	short size, offset;
+	char *s, *t;
+
+	s = sym->name;
+	for (q = p = tp->u.fields; p; q = p, p = p->next) {
+		t = p->sym->name;
+		if (*s == *t && !strcmp(s, t))
+			error("duplicated field '%s'", s);
+	}
+
+	p = xmalloc(sizeof(*p));
+	p->next = NULL;
+	p->sym = sym;
+	size = sym->type->size;
+	if (!q) {
+		tp->u.fields = p;
+		tp->size = size;
+		sym->u.offset = 0;
+	} else {
+		q->next = p;
+		if (tp->op == STRUCT) {
+			offset = ALIGN(size, tp->size);
+			sym->u.offset = offset;
+			tp->size = offset + size;
+		} else {
+			sym->u.offset = 0;
+			if (tp->size < size)
+				tp->size = size;
+		}
+	}
+}
+
+static void
+fielddcl(struct ctype *base, uint8_t ns)
+{
 	struct ctype *tp;
 	struct symbol *sym;
-	short offset = 0, size;
 
 	switch (yytoken) {
 	case IDEN:
@@ -278,17 +315,11 @@
 	if (yytoken != ';') {
 		do {
 			sym = declarator(tp, ns, 1);
-			sym->u.offset = offset;
-			size = sym->type->size;
-			if (type == STRUCT)
-				offset += size;
-			else if (offset < size)
-				offset = size;
+			newfield(tp, sym);
 		} while (accept(','));
 	}
 
 	expect(';');
-	return offset;
 }
 
 static struct ctype *
@@ -295,6 +326,7 @@
 newtag(uint8_t tag)
 {
 	register struct symbol *sym;
+	struct ctype *tp;
 	extern uint8_t namespace;
 
 	if (yytoken == IDEN) {
@@ -309,8 +341,10 @@
 	} else {
 		sym = install(NULL, NS_TAG);
 	}
-	++namespace;
-	return sym->type = mktype(NULL, tag, NULL, 0);
+	tp = sym->type = mktype(NULL, tag, NULL, 0);
+	sym->u.ns = ++namespace;
+	tp->sym = sym;
+	return tp;
 
 bad_tag:
 	error("'%s' defined as wrong kind of tag", yytext);
@@ -320,9 +354,11 @@
 structdcl(uint8_t tag)
 {
 	struct ctype *tp;
-	short size = 0;
+	uint8_t ns;
 
 	tp = newtag(tag);
+	tp->u.fields = NULL;
+	ns = tp->sym->u.ns;
 	if (yytoken != ';') {
 		expect('{');
 		if (tp->defined)
@@ -329,8 +365,7 @@
 			goto redefined;
 		tp->defined = 1;
 		while (!accept('}'))
-			size = fielddcl(namespace, tag);/* TODO: check duplicated */
-		tp->size = size;
+			 fielddcl(tp, ns);
 	}
 
 	return tp;
--- /dev/null
+++ b/machine.h
@@ -1,0 +1,16 @@
+
+#ifndef MACHINE_H_
+#define MACHINE_H_
+
+#define ALIGN(size, offset) ((size) + (offset))
+#define PTRSIZE      2
+#define CHARSIZE     1
+#define SHORTSIZE    2
+#define INTSIZE      2
+#define LONGSIZE     4
+#define LLONGSIZE    8
+#define FLOATSIZE    4
+#define LFLOATSIZE   8
+#define LLFLOATSIZE 16
+
+#endif
--- a/symbol.h
+++ b/symbol.h
@@ -30,12 +30,20 @@
 	struct symbol *sym;   /* symbol of the tag identifier */
 	struct ctype *type;   /* base type */
 	struct ctype *next;   /* next element in the hash */
-	struct funpars *pars; /* function parameters */
+	union {
+		struct funpar *pars;  /* function parameters */
+		struct field *fields; /* aggregate fields */
+	} u;
 };
 
-struct funpars {
+struct field {
+	struct symbol *sym;
+	struct field *next;
+};
+
+struct funpar {
 	struct ctype *type;
-	struct funpars *next;
+	struct funpar *next;
 };
 
 struct symbol {
@@ -47,6 +55,7 @@
 	union {
 		char c;
 		int i;
+		uint8_t ns;
 		short offset;
 	} u;
 	struct symbol *next;
--- a/types.c
+++ b/types.c
@@ -7,17 +7,9 @@
 #include "cc.h"
 #include "tokens.h"
 #include "symbol.h"
+#include "machine.h"
 
 #define NR_TYPE_HASH 16
-#define PTRSIZE      2
-#define CHARSIZE     1
-#define SHORTSIZE    2
-#define INTSIZE      2
-#define LONGSIZE     4
-#define LLONGSIZE    8
-#define FLOATSIZE    4
-#define LFLOATSIZE   8
-#define LLFLOATSIZE 16
 
 struct ctype
 	*voidtype = &(struct ctype) {
@@ -185,7 +177,6 @@
 	bp->op = op;
 	bp->nelem = nelem;
 	bp->sym = sym;
-	bp->pars = NULL;
 	bp->size = size;
 	return *tbl = bp;
 }
@@ -210,7 +201,7 @@
 ptype(struct ctype *tp)
 {
 	uint8_t op;
-	struct funpars *fp;
+	struct funpar *fp;
 
 	if (!tp)
 		return;
@@ -241,7 +232,7 @@
 			break;
 		case FTN:
 			fputs("function(", stdout);
-			for (fp = tp->pars; fp; fp = fp->next) {
+			for (fp = tp->u.pars; fp; fp = fp->next) {
 				ptype(tp);
 				if (fp->next)
 					fputs(", ", stdout);