Skip to content

Commit 09df963

Browse files
committed
Look for next limit after barriers
1 parent f59f023 commit 09df963

File tree

2 files changed

+34
-23
lines changed

2 files changed

+34
-23
lines changed

clang/lib/CodeGen/CGRecordLayoutBuilder.cpp

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -554,30 +554,41 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
554554
// Bitfield potentially begins a new span. This includes zero-length
555555
// bitfields on non-aligning targets that lie at character boundaries
556556
// (those are barriers to merging).
557-
LimitOffset = bitsToCharUnits(BitOffset);
558557
if (Field->isZeroLengthBitField(Context))
558+
// This is a barrier, but it might be followed by padding we could
559+
// use. Hence handle exactly as if we reached the end of the bitfield
560+
// run.
559561
Barrier = true;
560-
AtAlignedBoundary = true;
562+
else {
563+
LimitOffset = bitsToCharUnits(BitOffset);
564+
AtAlignedBoundary = true;
565+
}
561566
}
562-
} else if (Begin == FieldEnd) {
563-
// Completed the bitfields.
564-
break;
565567
} else {
566-
// We've reached the end of the bitfield run while accumulating a span.
567-
// Determine the limit of that span: either the offset of the next field,
568-
// or if we're at the end of the record the end of its non-reuseable tail
569-
// padding. (I.e. treat the next unusable char as the start of an
570-
// unmergeable span.)
568+
// We've reached the end of the bitfield run. Either we're done, or this
569+
// is a barrier for the current span.
570+
if (Begin == FieldEnd)
571+
break;
572+
573+
Barrier = true;
574+
}
575+
576+
if (Barrier) {
577+
// We're at a barrier, find the next used storage to determine what the
578+
// limit of the current span is. That's wither the offset of the next
579+
// field with storage or the end of the non-reusable tail padding.
571580
auto Probe = Field;
572581
while (Probe != FieldEnd && Probe->isZeroSize(Context))
573582
++Probe;
574-
// We can't necessarily use tail padding in C++ structs, so the NonVirtual
575-
// size is what we must use there.
576-
LimitOffset = Probe != FieldEnd
577-
? bitsToCharUnits(getFieldBitOffset(*Probe))
578-
: RD ? Layout.getNonVirtualSize()
579-
: Layout.getDataSize();
580-
Barrier = true;
583+
if (Probe != FieldEnd) {
584+
assert((getFieldBitOffset(*Field) % CharBits) == 0 &&
585+
"Next storage is not byte-aligned");
586+
LimitOffset = bitsToCharUnits(getFieldBitOffset(*Probe));
587+
} else {
588+
// We can't necessarily use tail padding in C++ structs, so the
589+
// NonVirtual size is what we must use there.
590+
LimitOffset = RD ? Layout.getNonVirtualSize() : Layout.getDataSize();
591+
}
581592
AtAlignedBoundary = true;
582593
}
583594

clang/test/CodeGen/bitfield-access-pad.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,8 @@ struct __attribute__((aligned(4))) P10 {
334334
char : 0;
335335
} p10;
336336
// CHECK-LABEL: LLVMType:%struct.P10 =
337-
// LAYOUT-T-SAME: type { i24 }
338-
// LAYOUT-ARM64-T-SAME: type { i24 }
337+
// LAYOUT-T-SAME: type { i32 }
338+
// LAYOUT-ARM64-T-SAME: type { i32 }
339339
// LAYOUT-NT-SAME: type { i32 }
340340
// LAYOUT-STRICT-NT-SAME: type { i32 }
341341
// LAYOUT-DWN32-SAME: type { i32 }
@@ -368,10 +368,10 @@ struct __attribute__((aligned(4))) P11 {
368368
char : 0; // at a char boundary
369369
} p11;
370370
// CHECK-LABEL: LLVMType:%struct.P11 =
371-
// LAYOUT-T-SAME: type { i24 }
372-
// LAYOUT-ARM64-T-SAME: type { i24 }
373-
// LAYOUT-NT-SAME: type { i24 }
374-
// LAYOUT-STRICT-NT-SAME: type { i24 }
371+
// LAYOUT-T-SAME: type { i32 }
372+
// LAYOUT-ARM64-T-SAME: type { i32 }
373+
// LAYOUT-NT-SAME: type { i32 }
374+
// LAYOUT-STRICT-NT-SAME: type { i32 }
375375
// LAYOUT-DWN32-SAME: type { i32 }
376376
// CHECK: BitFields:[
377377
// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0

0 commit comments

Comments
 (0)