ref: 994d0ecb8ed4f5f78801669a607dad572c0d93a1
parent: 4989e1b4e1184e1241c01d7d6f31a073d5a52a20
author: Ori Bernstein <[email protected]>
date: Mon Jun 16 18:45:09 EDT 2014
Fix alignment on structs. We were aligning big aggregates to 8, instead of to their most strict member. Oops.
--- a/6/asm.h
+++ b/6/asm.h
@@ -230,5 +230,5 @@
void breakhere();
void dumpasm(Isel *s, FILE *fd);
-size_t tyalign(size_t sz, size_t eltsz);
+size_t alignto(size_t sz, Type *t);
--- a/6/isel.c
+++ b/6/isel.c
@@ -1095,7 +1095,7 @@
Node **dcl;
int found;
size_t i, j;
- size_t sz, end;
+ size_t sz, pad, end;
size_t ndcl;
sz = 0;
@@ -1104,7 +1104,8 @@
dcl = t->sdecls;
ndcl = t->nmemb;
for (i = 0; i < ndcl; i++) {
- sz += writepad(fd, tyalign(sz, size(dcl[i])) - sz);
+ pad = alignto(sz, decltype(dcl[i]));
+ sz += writepad(fd, pad - sz);
found = 0;
for (j = 0; j < n->expr.nargs; j++)
if (!strcmp(namestr(n->expr.args[j]->expr.idx), declname(dcl[i]))) {
@@ -1114,9 +1115,7 @@
if (!found)
sz += writepad(fd, size(dcl[i]));
}
- end = sz;
- for (i = 0; i < ndcl; i++)
- end = tyalign(end, size(dcl[i]));
+ end = alignto(sz, t);
sz += writepad(fd, end - sz);
return sz;
}
--- a/6/simp.c
+++ b/6/simp.c
@@ -70,9 +70,30 @@
static Type *tyword;
static Type *tyvoid;
-size_t tyalign(size_t sz, size_t eltsz)
+size_t alignto(size_t sz, Type *t)
{
- return align(sz, min(eltsz, Ptrsz));
+ size_t a;
+ size_t i;
+
+ t = tybase(t);
+ a = 0;
+ switch (t->type) {
+ case Tyarray:
+ a = alignto(1, t->sub[0]);
+ case Tytuple:
+ for (i = 0; i < t->nsub; i++)
+ a = max(alignto(1, t->sub[i]), a);
+ break;
+ case Tystruct:
+ for (i = 0; i < t->nmemb; i++)
+ a = max(alignto(1, decltype(t->sdecls[i])), a);
+ break;
+ default:
+ a = tysize(t);
+ break;
+ }
+
+ return align(sz, min(a, Ptrsz));
}
static Type *base(Type *t)
@@ -334,21 +355,18 @@
return t->asize->expr.args[0]->lit.intval * tysize(t->sub[0]);
case Tytuple:
for (i = 0; i < t->nsub; i++) {
- sz = tyalign(sz, tysize(t->sub[i]));
+ sz = alignto(sz, t->sub[i]);
sz += tysize(t->sub[i]);
}
- for (i = 0; i < t->nsub; i++)
- sz = tyalign(sz, tysize(t->sub[i]));
+ sz = alignto(sz, t);
return sz;
break;
case Tystruct:
for (i = 0; i < t->nmemb; i++) {
- sz = tyalign(sz, size(t->sdecls[i]));
+ sz = alignto(sz, decltype(t->sdecls[i]));
sz += size(t->sdecls[i]);
}
- /* the whole struct size should match the biggest alignment */
- for (i = 0; i < t->nmemb; i++)
- sz = tyalign(sz, size(t->sdecls[i]));
+ sz = alignto(sz, t);
return sz;
break;
case Tyunion:
@@ -691,7 +709,7 @@
patarg = pat->expr.args;
off = 0;
for (i = 0; i < pat->expr.nargs; i++) {
- off = tyalign(off, size(patarg[i]));
+ off = alignto(off, exprtype(patarg[i]));
next = genlbl();
v = load(addk(addr(s, val, exprtype(patarg[i])), off));
umatch(s, patarg[i], v, exprtype(patarg[i]), next, iffalse);
@@ -789,7 +807,6 @@
static size_t offset(Node *aggr, Node *memb)
{
Type *ty;
- Node **nl;
size_t i;
size_t off;
@@ -798,13 +815,12 @@
ty = tybase(ty->sub[0]);
assert(ty->type == Tystruct);
- nl = ty->sdecls;
off = 0;
for (i = 0; i < ty->nmemb; i++) {
- off = tyalign(off, size(nl[i]));
- if (!strcmp(namestr(memb), declname(nl[i])))
+ off = alignto(off, decltype(ty->sdecls[i]));
+ if (!strcmp(namestr(memb), declname(ty->sdecls[i])))
return off;
- off += size(nl[i]);
+ off += size(ty->sdecls[i]);
}
die("Could not find member %s in struct", namestr(memb));
return -1;
@@ -1094,7 +1110,7 @@
off = 0;
for (i = 0; i < lhs->expr.nargs; i++) {
lv = lval(s, args[i]);
- off = tyalign(off, size(lv));
+ off = alignto(off, exprtype(lv));
prv = add(addr(s, rhs, exprtype(args[i])), disp(rhs->line, off));
if (stacknode(args[i])) {
sz = disp(lhs->line, size(lv));
@@ -1173,7 +1189,7 @@
off = 0;
for (i = 0; i < n->expr.nargs; i++) {
- off = tyalign(off, size(args[i]));
+ off = alignto(off, exprtype(args[i]));
assignat(s, r, off, args[i]);
off += size(args[i]);
}
--- /dev/null
+++ b/test/align.myr
@@ -1,0 +1,64 @@
+use std
+
+/* size should be 16 */
+type alignstruct1 = struct
+ a : byte
+ b : byte[15]
+;;
+
+/* size should be 20 */
+type alignstruct2 = struct
+ a : int
+ b : byte[15]
+ /* 1 byte padding */
+;;
+
+/* size should be 20 */
+type alignstruct3 = struct
+ b : byte[15]
+ a : int
+;;
+
+/* size should be 8 */
+type alignstruct4 = struct
+ a : byte
+ b : int[1]
+;;
+
+/* size should be 24 */
+type alignstruct5 = struct
+ a : byte
+ b : byte[:]
+;;
+
+/* size should be 8 */
+type alignstruct6 = struct
+ a : byte
+ b : byte
+ c : byte
+ d : byte
+ e : int32
+;;
+
+/* size should be 24 */
+type alignstruct7 = struct
+ a : byte
+ b : int32
+ c : byte[:]
+;;
+
+const main = {
+ std.put("size = %i\n", sizeof(alignstruct1))
+ std.put("size = %i\n", sizeof(alignstruct2))
+ std.put("size = %i\n", sizeof(alignstruct3))
+ std.put("size = %i\n", sizeof(alignstruct4))
+ std.put("size = %i\n", sizeof(alignstruct5))
+ std.put("size = %i\n", sizeof(alignstruct6))
+ std.put("size = %i\n", sizeof(alignstruct7))
+ /* size should be 8 */
+ std.put("size = %i\n", sizeof([int, byte, byte]))
+ /* size should be 16 */
+ std.put("size = %i\n", sizeof([int, byte, int, byte]))
+ /* size should be 12 */
+ std.put("size = %i\n", sizeof([int, int, byte, byte]))
+}
--- /dev/null
+++ b/test/data/align-expected
@@ -1,0 +1,10 @@
+size = 16
+size = 20
+size = 20
+size = 8
+size = 24
+size = 8
+size = 24
+size = 8
+size = 16
+size = 12