Skip to content

Commit 0e7afc4

Browse files
committed
Add BitFieldStyle.Gcc_Clang_ARM
Required for 32-bit ARM, and non-Apple 64-bit ARM targets. The only difference to `Gcc_Clang` is that anonymous and 0-length bit-fields do contribute to the aggregate alignment. Caught by existing proper C interop tests in runnable_cxx/testbitfields.d on such targets. The hardcoded bad tests in runnable/{bitfieldsposix64.c,dbitfieldsposix64.d} however now fail after the fix, on such targets again.
1 parent 4636872 commit 0e7afc4

File tree

5 files changed

+45
-45
lines changed

5 files changed

+45
-45
lines changed

compiler/src/dmd/dsymbolsem.d

+37-45
Original file line numberDiff line numberDiff line change
@@ -7186,12 +7186,23 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
71867186
error(bfd.loc, "bit field width %d is larger than type", bfd.fieldWidth);
71877187

71887188
const style = target.c.bitFieldStyle;
7189+
if (style != TargetC.BitFieldStyle.MS &&
7190+
style != TargetC.BitFieldStyle.Gcc_Clang &&
7191+
style != TargetC.BitFieldStyle.Gcc_Clang_ARM)
7192+
{
7193+
assert(0, "unsupported bit-field style");
7194+
}
7195+
7196+
const isMicrosoftStyle = style == TargetC.BitFieldStyle.MS;
7197+
const contributesToAggregateAlignment = !anon || style != TargetC.BitFieldStyle.Gcc_Clang;
71897198

71907199
void startNewField()
71917200
{
71927201
if (log) printf("startNewField()\n");
71937202
uint alignsize;
7194-
if (style == TargetC.BitFieldStyle.Gcc_Clang)
7203+
if (isMicrosoftStyle)
7204+
alignsize = memsize; // not memalignsize
7205+
else
71957206
{
71967207
if (bfd.fieldWidth > 32)
71977208
alignsize = memalignsize;
@@ -7202,15 +7213,13 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
72027213
else
72037214
alignsize = 1;
72047215
}
7205-
else
7206-
alignsize = memsize; // not memalignsize
72077216

72087217
uint dummy;
72097218
bfd.offset = placeField(
72107219
fieldState.offset,
72117220
memsize, alignsize, bfd.alignment,
72127221
ad.structsize,
7213-
(anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? dummy : ad.alignsize,
7222+
contributesToAggregateAlignment ? ad.alignsize : dummy,
72147223
isunion);
72157224

72167225
fieldState.inFlight = true;
@@ -7219,53 +7228,38 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
72197228
fieldState.fieldSize = memsize;
72207229
}
72217230

7222-
if (style == TargetC.BitFieldStyle.Gcc_Clang)
7231+
if (ad.alignsize == 0)
7232+
ad.alignsize = 1;
7233+
if (!isMicrosoftStyle && contributesToAggregateAlignment && ad.alignsize < memalignsize)
7234+
ad.alignsize = memalignsize;
7235+
7236+
if (bfd.fieldWidth == 0)
72237237
{
7224-
if (bfd.fieldWidth == 0)
7238+
if (!isMicrosoftStyle && !isunion)
72257239
{
7226-
if (!isunion)
7227-
{
7228-
// Use type of zero width field to align to next field
7229-
fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
7230-
ad.structsize = fieldState.offset;
7231-
}
7232-
7233-
fieldState.inFlight = false;
7234-
return;
7240+
// Use type of zero width field to align to next field
7241+
fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1);
7242+
ad.structsize = fieldState.offset;
72357243
}
7236-
7237-
if (ad.alignsize == 0)
7238-
ad.alignsize = 1;
7239-
if (!anon &&
7240-
ad.alignsize < memalignsize)
7241-
ad.alignsize = memalignsize;
7242-
}
7243-
else if (style == TargetC.BitFieldStyle.MS)
7244-
{
7245-
if (ad.alignsize == 0)
7246-
ad.alignsize = 1;
7247-
if (bfd.fieldWidth == 0)
7244+
else if (isMicrosoftStyle && fieldState.inFlight && !isunion)
72487245
{
7249-
if (fieldState.inFlight && !isunion)
7250-
{
7251-
// documentation says align to next int
7252-
//const alsz = cast(uint)Type.tint32.size();
7253-
const alsz = memsize; // but it really does this
7254-
fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
7255-
ad.structsize = fieldState.offset;
7256-
}
7257-
7258-
fieldState.inFlight = false;
7259-
return;
7246+
// documentation says align to next int
7247+
//const alsz = cast(uint)Type.tint32.size();
7248+
const alsz = memsize; // but it really does this
7249+
fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1);
7250+
ad.structsize = fieldState.offset;
72607251
}
7252+
7253+
fieldState.inFlight = false;
7254+
return;
72617255
}
72627256

72637257
if (!fieldState.inFlight)
72647258
{
72657259
//printf("not in flight\n");
72667260
startNewField();
72677261
}
7268-
else if (style == TargetC.BitFieldStyle.Gcc_Clang)
7262+
else if (!isMicrosoftStyle)
72697263
{
72707264
// If the bit-field spans more units of alignment than its type,
72717265
// start a new field at the next alignment boundary.
@@ -7288,7 +7282,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
72887282
}
72897283
}
72907284
}
7291-
else if (style == TargetC.BitFieldStyle.MS)
7285+
else
72927286
{
72937287
if (memsize != fieldState.fieldSize ||
72947288
fieldState.bitOffset + bfd.fieldWidth > fieldState.fieldSize * 8)
@@ -7297,14 +7291,14 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
72977291
startNewField();
72987292
}
72997293
}
7300-
else
7301-
assert(0);
73027294

73037295
bfd.offset = fieldState.fieldOffset;
73047296
bfd.bitOffset = fieldState.bitOffset;
73057297

73067298
const pastField = bfd.bitOffset + bfd.fieldWidth;
7307-
if (style == TargetC.BitFieldStyle.Gcc_Clang)
7299+
if (isMicrosoftStyle)
7300+
fieldState.fieldSize = memsize;
7301+
else
73087302
{
73097303
auto size = (pastField + 7) / 8;
73107304
fieldState.fieldSize = size;
@@ -7318,8 +7312,6 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
73187312
else
73197313
ad.structsize = bfd.offset + size;
73207314
}
7321-
else
7322-
fieldState.fieldSize = memsize;
73237315
//printf("at end: ad.structsize = %d\n", cast(int)ad.structsize);
73247316
//print(fieldState);
73257317

compiler/src/dmd/frontend.h

+1
Original file line numberDiff line numberDiff line change
@@ -5938,6 +5938,7 @@ struct TargetC final
59385938
Unspecified = 0u,
59395939
MS = 1u,
59405940
Gcc_Clang = 2u,
5941+
Gcc_Clang_ARM = 3u,
59415942
};
59425943

59435944
bool crtDestructorsSupported;

compiler/src/dmd/target.d

+3
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,9 @@ struct TargetC
13791379
/// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160
13801380
/// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
13811381
Gcc_Clang, /// gcc and clang
1382+
Gcc_Clang_ARM, /// Like `Gcc_Clang`, except that anonymous and 0-length bit fields contribute
1383+
/// to the aggregate alignment. Used for 32 & 64 bit ARM targets, except for
1384+
/// Apple ARM64.
13821385
}
13831386
bool crtDestructorsSupported = true; /// Not all platforms support crt_destructor
13841387
ubyte boolsize; /// size of a C `_Bool` type

compiler/src/dmd/target.h

+3
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ struct TargetC
6565
// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160
6666
// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160
6767
Gcc_Clang, // gcc and clang
68+
Gcc_Clang_ARM, // Like `Gcc_Clang`, except that anonymous and 0-length bit fields contribute
69+
// to the aggregate alignment. Used for 32 & 64 bit ARM targets, except for
70+
// Apple ARM64.
6871
};
6972

7073
uint8_t crtDestructorsSupported; // Not all platforms support crt_destructor

compiler/src/dmd/todt.d

+1
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,7 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb,
958958
switch (target.c.bitFieldStyle)
959959
{
960960
case TargetC.BitFieldStyle.Gcc_Clang:
961+
case TargetC.BitFieldStyle.Gcc_Clang_ARM:
961962
bitFieldSize = (bf.bitOffset + bf.fieldWidth + 7) / 8;
962963
break;
963964

0 commit comments

Comments
 (0)