scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 60a0cff60f2c11945afc0026c2f6ed532dc60e87
parent 64ee117fc51af33bf4557d6405eefc506e269185
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 25 Jan 2016 15:43:46 +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.

Diffstat:
cc1/cc1.h | 1+
cc1/decl.c | 2+-
cc1/tests/test052.c | 4++--
cc1/types.c | 75+++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
4 files changed, 55 insertions(+), 27 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -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 @@ -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", @@ -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 @@ -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 @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 diff --git a/cc1/types.c b/cc1/types.c @@ -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 * @@ -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: @@ -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;