Skip to content

Commit 5350591

Browse files
committed
arm64: Fix alignment of structs with zero width bitfields
1 parent 35727fd commit 5350591

3 files changed

Lines changed: 190 additions & 3 deletions

File tree

compiler/src/dmd/dsymbolsem.d

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9987,14 +9987,23 @@ private extern(C++) class FinalizeSizeVisitor : Visitor
99879987
if (sd.structsize == 0)
99889988
{
99899989
sd.hasNoFields = true;
9990-
sd.alignsize = 1;
9990+
9991+
// alignsize has already been set when the struct consists only of
9992+
// zero sized fields.
9993+
if (sd.alignsize == 0)
9994+
sd.alignsize = 1;
99919995

99929996
// A fine mess of what size a zero sized struct should be
99939997
final switch (sd.classKind)
99949998
{
99959999
case ClassKind.d:
999610000
case ClassKind.cpp:
9997-
sd.structsize = 1;
10001+
// Give struct a size when there's no named fields
10002+
if (sd.fields.length == 0 ||
10003+
target.c.bitFieldStyle == TargetC.BitFieldStyle.MS)
10004+
{
10005+
sd.structsize = 1;
10006+
}
999810007
break;
999910008

1000010009
case ClassKind.c:

compiler/src/dmd/target.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1491,7 +1491,7 @@ struct TargetC
14911491
if (bitFieldStyle == BitFieldStyle.Gcc_Clang)
14921492
{
14931493
// sufficient for DMD's currently supported architectures
1494-
return !bfd.isAnonymous();
1494+
return !bfd.isAnonymous() || target.isAArch64;
14951495
}
14961496
assert(0);
14971497
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Test anonymous bitfields where TargetC.contributesToAlignment
2+
extern(D)
3+
{
4+
struct D0 { }
5+
struct D1 { byte : 0; }
6+
struct D2 { short : 0; }
7+
struct D3 { int : 0; }
8+
struct D4 { long : 0; }
9+
struct D5 { byte[0] f; }
10+
struct D6 { short[0] f; }
11+
struct D7 { int[0] f; }
12+
struct D8 { long[0] f; }
13+
struct D9 { int : 0; short[0] f; }
14+
align(16)
15+
{
16+
struct D10 { }
17+
struct D11 { byte : 0; }
18+
struct D12 { short : 0; }
19+
struct D13 { int : 0; }
20+
struct D14 { long : 0; }
21+
struct D15 { byte[0] f; }
22+
struct D16 { short[0] f; }
23+
struct D17 { int[0] f; }
24+
struct D18 { long[0] f; }
25+
struct D19 { int : 0; short[0] f; }
26+
}
27+
}
28+
29+
extern(C)
30+
{
31+
struct C0 { }
32+
struct C1 { byte : 0; }
33+
struct C2 { short : 0; }
34+
struct C3 { int : 0; }
35+
struct C4 { long : 0; }
36+
struct C5 { byte[0] f; }
37+
struct C6 { short[0] f; }
38+
struct C7 { int[0] f; }
39+
struct C8 { long[0] f; }
40+
struct C9 { int : 0; short[0] f; }
41+
align(16)
42+
{
43+
struct C10 { }
44+
struct C11 { byte : 0; }
45+
struct C12 { short : 0; }
46+
struct C13 { int : 0; }
47+
struct C14 { long : 0; }
48+
struct C15 { byte[0] f; }
49+
struct C16 { short[0] f; }
50+
struct C17 { int[0] f; }
51+
struct C18 { long[0] f; }
52+
struct C19 { int : 0; short[0] f; }
53+
}
54+
}
55+
56+
version (Posix):
57+
58+
// Anonymous bitfields don't contribute to alignment.
59+
version (X86_64)
60+
{
61+
// Empty
62+
static assert(D0.sizeof == 1 && D0.alignof == 1);
63+
static assert(D10.sizeof == 16 && D10.alignof == 16);
64+
65+
// Zero width bitfields
66+
static assert(D1.sizeof == 1 && D1.alignof == 1);
67+
static assert(D2.sizeof == 1 && D2.alignof == 1);
68+
static assert(D3.sizeof == 1 && D3.alignof == 1);
69+
static assert(D4.sizeof == 1 && D4.alignof == 1);
70+
static assert(D11.sizeof == 16 && D11.alignof == 16);
71+
static assert(D12.sizeof == 16 && D12.alignof == 16);
72+
static assert(D13.sizeof == 16 && D13.alignof == 16);
73+
static assert(D14.sizeof == 16 && D14.alignof == 16);
74+
75+
// Zero sized arrays
76+
static assert(D5.sizeof == 0 && D5.alignof == 1);
77+
static assert(D6.sizeof == 0 && D6.alignof == 2);
78+
static assert(D7.sizeof == 0 && D7.alignof == 4);
79+
static assert(D8.sizeof == 0 && D8.alignof == 8);
80+
static assert(D15.sizeof == 0 && D15.alignof == 16);
81+
static assert(D16.sizeof == 0 && D16.alignof == 16);
82+
static assert(D17.sizeof == 0 && D17.alignof == 16);
83+
static assert(D18.sizeof == 0 && D18.alignof == 16);
84+
85+
// Mixed zero sized bitfields and arrays
86+
static assert(D9.sizeof == 0 && D9.alignof == 2);
87+
static assert(D19.sizeof == 0 && D19.alignof == 16);
88+
89+
// Empty
90+
static assert(C0.sizeof == 0 && C0.alignof == 1);
91+
static assert(C10.sizeof == 0 && C10.alignof == 16);
92+
93+
// Zero width bitfields
94+
static assert(C1.sizeof == 0 && C1.alignof == 1);
95+
static assert(C2.sizeof == 0 && C2.alignof == 1);
96+
static assert(C3.sizeof == 0 && C3.alignof == 1);
97+
static assert(C4.sizeof == 0 && C4.alignof == 1);
98+
static assert(C11.sizeof == 0 && C11.alignof == 16);
99+
static assert(C12.sizeof == 0 && C12.alignof == 16);
100+
static assert(C13.sizeof == 0 && C13.alignof == 16);
101+
static assert(C14.sizeof == 0 && C14.alignof == 16);
102+
103+
// Zero sized arrays
104+
static assert(C5.sizeof == 0 && C5.alignof == 1);
105+
static assert(C6.sizeof == 0 && C6.alignof == 2);
106+
static assert(C7.sizeof == 0 && C7.alignof == 4);
107+
static assert(C8.sizeof == 0 && C8.alignof == 8);
108+
static assert(C15.sizeof == 0 && C15.alignof == 16);
109+
static assert(C16.sizeof == 0 && C16.alignof == 16);
110+
static assert(C17.sizeof == 0 && C17.alignof == 16);
111+
static assert(C18.sizeof == 0 && C18.alignof == 16);
112+
113+
// Mixed zero sized bitfields and arrays
114+
static assert(C9.sizeof == 0 && C9.alignof == 2);
115+
static assert(C19.sizeof == 0 && C19.alignof == 16);
116+
}
117+
118+
// Anonymous bitfields *do* contribute to alignment.
119+
version (AArch64)
120+
{
121+
// Empty
122+
static assert(D0.sizeof == 1 && D0.alignof == 1);
123+
static assert(D10.sizeof == 16 && D10.alignof == 16);
124+
125+
// Zero width bitfields
126+
static assert(D1.sizeof == 1 && D1.alignof == 1);
127+
static assert(D2.sizeof == 2 && D2.alignof == 2);
128+
static assert(D3.sizeof == 4 && D3.alignof == 4);
129+
static assert(D4.sizeof == 8 && D4.alignof == 8);
130+
static assert(D11.sizeof == 16 && D11.alignof == 16);
131+
static assert(D12.sizeof == 16 && D12.alignof == 16);
132+
static assert(D13.sizeof == 16 && D13.alignof == 16);
133+
static assert(D14.sizeof == 16 && D14.alignof == 16);
134+
135+
// Zero sized arrays
136+
static assert(D5.sizeof == 0 && D5.alignof == 1);
137+
static assert(D6.sizeof == 0 && D6.alignof == 2);
138+
static assert(D7.sizeof == 0 && D7.alignof == 4);
139+
static assert(D8.sizeof == 0 && D8.alignof == 8);
140+
static assert(D15.sizeof == 0 && D15.alignof == 16);
141+
static assert(D16.sizeof == 0 && D16.alignof == 16);
142+
static assert(D17.sizeof == 0 && D17.alignof == 16);
143+
static assert(D18.sizeof == 0 && D18.alignof == 16);
144+
145+
// Mixed zero sized bitfields and arrays
146+
static assert(D9.sizeof == 0 && D9.alignof == 4);
147+
static assert(D19.sizeof == 0 && D19.alignof == 16);
148+
149+
/// extern(C):
150+
151+
// Empty
152+
static assert(C0.sizeof == 0 && C0.alignof == 1);
153+
static assert(C10.sizeof == 0 && C10.alignof == 16);
154+
155+
// Zero width bitfields
156+
static assert(C1.sizeof == 0 && C1.alignof == 1);
157+
static assert(C2.sizeof == 0 && C2.alignof == 2);
158+
static assert(C3.sizeof == 0 && C3.alignof == 4);
159+
static assert(C4.sizeof == 0 && C4.alignof == 8);
160+
static assert(C11.sizeof == 0 && C11.alignof == 16);
161+
static assert(C12.sizeof == 0 && C12.alignof == 16);
162+
static assert(C13.sizeof == 0 && C13.alignof == 16);
163+
static assert(C14.sizeof == 0 && C14.alignof == 16);
164+
165+
// Zero sized arrays
166+
static assert(C5.sizeof == 0 && C5.alignof == 1);
167+
static assert(C6.sizeof == 0 && C6.alignof == 2);
168+
static assert(C7.sizeof == 0 && C7.alignof == 4);
169+
static assert(C8.sizeof == 0 && C8.alignof == 8);
170+
static assert(C15.sizeof == 0 && C15.alignof == 16);
171+
static assert(C16.sizeof == 0 && C16.alignof == 16);
172+
static assert(C17.sizeof == 0 && C17.alignof == 16);
173+
static assert(C18.sizeof == 0 && C18.alignof == 16);
174+
175+
// Mixed zero sized bitfields and arrays
176+
static assert(C9.sizeof == 0 && C9.alignof == 4);
177+
static assert(C19.sizeof == 0 && C19.alignof == 16);
178+
}

0 commit comments

Comments
 (0)