shithub: scc

Download patch

ref: 60a0cff60f2c11945afc0026c2f6ed532dc60e87
parent: 64ee117fc51af33bf4557d6405eefc506e269185
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Jan 25 10:43:46 EST 2016

[cc1] Fix calculation of alignment and size of structs

The alignment of a struct is the he alignment of the largest
included type, and the size is the sum of all included types
plus padding bytes between them plus padding bytes at the
end to fit the asignment requirement.

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -352,6 +352,7 @@
 extern Type *mktype(Type *tp, int op, TINT nelem, Type *data[]);
 extern Type *duptype(Type *base);
 extern struct limits *getlimits(Type *tp);
+extern void typesize(Type *tp);
 
 /* symbol.c */
 extern void dumpstab(char *msg);
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -486,7 +486,6 @@
 			error("too much tags declared");
 		tp = mktype(NULL, tag, 0, NULL);
 		tp->ns = ns++;
-		tp->p.fields = NULL;
 		sym->type = tp;
 		tp->tag = sym;
 		DBG("declared tag '%s' with ns = %d\n",
@@ -533,6 +532,7 @@
 	}
 	--nested;
 
+	typesize(tp);
 	namespace = ns;
 	expect('}');
 	return tp;
--- a/cc1/tests/test052.c
+++ b/cc1/tests/test052.c
@@ -23,10 +23,10 @@
 	j	L11	G6	M4	.I	#I2	=I
 	r	#I2
 L11
-	j	L12	G6	M3	.I	#I3	=I
+	j	L12	G6	'P	#P4	+P	@S2	M3	.I	#I3	=I
 	r	#I3
 L12
-	j	L13	G6	M4	.I	#I4	=I
+	j	L13	G6	'P	#P4	+P	@S2	M4	.I	#I4	=I
 	r	#I4
 L13
 	r	#I0
--- a/cc1/types.c
+++ b/cc1/types.c
@@ -166,42 +166,70 @@
 	error("invalid type specification");
 }
 
-static TSIZE
+void
 typesize(Type *tp)
 {
 	Symbol **sp;
-	TSIZE n, size, align;
+	Type *aux;
+	TSIZE n, size, align, a;
 
 	switch (tp->op) {
 	case ARY:
-		return tp->n.elem * tp->type->size;
+		/* FIXME: Control overflow */
+		tp->size = tp->n.elem * tp->type->size;
+		tp->align = tp->type->align;
+		return;
 	case PTR:
-		return pvoidtype->size;
+		tp->size = pvoidtype->size;
+		tp->align = pvoidtype->align;
+		return;
 	case STRUCT:
-		size = 0;
-		n = tp->n.elem;
-		for (sp = tp->p.fields; n--; ++sp) {
-			tp = (*sp)->type;
-			align = tp->align-1;
-			size = size + align & ~align;
-			size += tp->size;
-		}
-		/* TODO: Add aligment of the first field */
-		return size;
 	case UNION:
-		size = 0;
+		/* FIXME: Control overflow */
+		/*
+		 * The alignment of the struct/union is
+		 * he alignment of the largest included type.
+		 * The size of an union is the size of the largest
+		 * field, and the size of a struct is the sum
+		 * of the size of every field plus padding bits.
+		 */
+		align = size = 0;
 		n = tp->n.elem;
 		for (sp = tp->p.fields; n--; ++sp) {
-			tp = (*sp)->type;
-			if (tp->size > size)
-				size = tp->size;
+			(*sp)->u.i = size;
+			aux = (*sp)->type;
+			a = aux->align;
+			if (a > align)
+				align = a;
+			if (tp->op == STRUCT) {
+				if (--a != 0)
+					size += (size + a) & ~a;
+				size += aux->size;
+			} else {
+				if (tp->size > size)
+					size = aux->size;
+			}
 		}
-		/* TODO: Add aligment of the worst field */
-		return size;
+
+		tp->align = align;
+		/*
+		 * We have to add the padding bits to
+		 * ensure next struct in an array is well
+		 * alignment.
+		 */
+		if (tp->op == STRUCT && align-- > 1)
+			size += size + align & ~align;
+		tp->size = size;
+		return;
 	case ENUM:
-		return inttype->size;
+		tp->size = inttype->size;
+		tp->align = inttype->align;
+		return;
+	case FTN:
+		return;
+	default:
+		abort();
 	}
-	return 0;
 }
 
 Type *
@@ -242,7 +270,6 @@
 	type.p.pars = pars;
 	type.n.elem = nelem;
 	type.ns = 0;
-	/* TODO: Set aligment for new types */
 
 	switch (op) {
 	case ARY:
@@ -279,7 +306,7 @@
 		}
 	}
 
-	type.size = typesize(&type);
+	typesize(&type);
 	bp = duptype(&type);
 	bp->next = *tbl;
 	return *tbl = bp;