commit f3414a492bf4623731f3850aaae5b4a7a2a83a4d
parent 2bbfcf61b38edfe3c347cd270380e5117454c0cf
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 17 Aug 2021 15:18:00 +0200
parsefields: fix padding calculation
This was causing issues with aggregate types. A simple reproduction is:
type :type.1 = align 8 { 24 }
type :type.2 = align 8 { w 1, :type.1 1 }
The size of type.2 should be 32, adding only 4 bytes of padding between
the first and second field. Prior to this patch, 20 bytes of padding was
added instead, causing the type to have a size of 48.
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/parse.c b/parse.c
@@ -867,9 +867,9 @@ parsefields(Field *fld, Typ *ty, int t)
}
if (a > al)
al = a;
- a = sz & (s-1);
+ a = (1 << a) - 1;
+ a = ((sz + a) & ~a) - sz;
if (a) {
- a = s - a;
if (n < NField) {
/* padding */
fld[n].type = FPad;
diff --git a/test/abi7.ssa b/test/abi7.ssa
@@ -0,0 +1,21 @@
+# test padding calculation with
+# embedded struct
+
+type :s1 = align 4 { w 3 }
+type :s2 = align 4 { b 1, :s1 1 }
+
+export function :s2 $test() {
+@start
+ ret $s
+}
+
+# >>> driver
+# struct s2 {
+# char x;
+# struct { int a[3]; } s1;
+# } s = { .x = 123 };
+# extern struct s2 test(void);
+# int main(void) {
+# return !(test().x == 123);
+# }
+# <<<