[hackers] [scc] [cc1] Fix calculation of alignment and size of structs || Roberto E. Vargas Caballero

From: <git_AT_suckless.org>
Date: Tue, 26 Jan 2016 10:57:42 +0100 (CET)

commit 60a0cff60f2c11945afc0026c2f6ed532dc60e87
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
AuthorDate: Mon Jan 25 15:43:46 2016 +0100
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
CommitDate: Mon Jan 25 17:55:41 2016 +0100

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

diff --git a/cc1/cc1.h b/cc1/cc1.h
index 1eda834..d929aab 100644
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
_AT_@ -352,6 +352,7 @@ extern Type *ctype(unsigned type, unsigned sign, unsigned size);
 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);
diff --git a/cc1/decl.c b/cc1/decl.c
index 17da330..992c77f 100644
--- a/cc1/decl.c
+++ b/cc1/decl.c
_AT_@ -486,7 +486,6 @@ newtag(void)
                         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",
_AT_@ -533,6 +532,7 @@ structdcl(void)
         }
         --nested;
 
+ typesize(tp);
         namespace = ns;
         expect('}');
         return tp;
diff --git a/cc1/tests/test052.c b/cc1/tests/test052.c
index 7670f4d..ce7da75 100644
--- a/cc1/tests/test052.c
+++ b/cc1/tests/test052.c
_AT_@ -23,10 +23,10 @@ L9
         j L11 G6 M4 .I #I2 =I
         r #I2
 L11
- j L12 G6 M3 .I #I3 =I
+ j L12 G6 'P #P4 +P _AT_S2 M3 .I #I3 =I
         r #I3
 L12
- j L13 G6 M4 .I #I4 =I
+ j L13 G6 'P #P4 +P _AT_S2 M4 .I #I4 =I
         r #I4
 L13
         r #I0
diff --git a/cc1/types.c b/cc1/types.c
index 2d57c84..4109052 100644
--- a/cc1/types.c
+++ b/cc1/types.c
_AT_@ -166,42 +166,70 @@ invalid_type:
         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 *
_AT_@ -242,7 +270,6 @@ mktype(Type *tp, int op, TINT nelem, Type *pars[])
         type.p.pars = pars;
         type.n.elem = nelem;
         type.ns = 0;
- /* TODO: Set aligment for new types */
 
         switch (op) {
         case ARY:
_AT_@ -279,7 +306,7 @@ mktype(Type *tp, int op, TINT nelem, Type *pars[])
                 }
         }
 
- type.size = typesize(&type);
+ typesize(&type);
         bp = duptype(&type);
         bp->next = *tbl;
         return *tbl = bp;
Received on Tue Jan 26 2016 - 10:57:42 CET

This archive was generated by hypermail 2.3.0 : Tue Jan 26 2016 - 11:00:28 CET