shithub: mc

Download patch

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