Skip to content

Commit c1c1fe6

Browse files
authored
Merge pull request #3937 from rjmccall/sizeof-imported-structs-includes-tail-padding
Count tail-padding in the size of imported C types.
2 parents 6f743db + b51a69f commit c1c1fe6

File tree

4 files changed

+33
-34
lines changed

4 files changed

+33
-34
lines changed

lib/IRGen/GenStruct.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,6 @@ class ClangRecordLowering {
579579
const clang::ASTContext &ClangContext;
580580
const clang::ASTRecordLayout &ClangLayout;
581581
const Size TotalStride;
582-
Size TotalSize;
583582
const Alignment TotalAlignment;
584583
SpareBitVector SpareBits;
585584

@@ -595,9 +594,8 @@ class ClangRecordLowering {
595594
ClangDecl(clangDecl), ClangContext(clangDecl->getASTContext()),
596595
ClangLayout(ClangContext.getASTRecordLayout(clangDecl)),
597596
TotalStride(Size(ClangLayout.getSize().getQuantity())),
598-
TotalSize(TotalStride),
599597
TotalAlignment(Alignment(ClangLayout.getAlignment().getQuantity())) {
600-
SpareBits.reserve(TotalSize.getValue() * 8);
598+
SpareBits.reserve(TotalStride.getValue() * 8);
601599
}
602600

603601
void collectRecordFields() {
@@ -606,25 +604,20 @@ class ClangRecordLowering {
606604
} else {
607605
collectStructFields();
608606
}
609-
610-
// Lots of layout will get screwed up if our structure claims more
611-
// storage than we allocated to it.
612-
assert(NextOffset == TotalSize && NextOffset <= TotalStride);
613-
assert(TotalSize.roundUpToAlignment(TotalAlignment) == TotalStride);
614607
}
615608

616609
const TypeInfo *createTypeInfo(llvm::StructType *llvmType) {
617610
llvmType->setBody(LLVMFields, /*packed*/ true);
618611
return ClangRecordTypeInfo::create(FieldInfos, NextExplosionIndex,
619-
llvmType, TotalSize,
612+
llvmType, TotalStride,
620613
std::move(SpareBits), TotalAlignment,
621614
ClangDecl);
622615
}
623616

624617
private:
625618
/// Collect all the fields of a union.
626619
void collectUnionFields() {
627-
addOpaqueField(Size(0), TotalSize);
620+
addOpaqueField(Size(0), TotalStride);
628621
}
629622

630623
static bool isImportOfClangField(VarDecl *swiftField,
@@ -689,8 +682,14 @@ class ClangRecordLowering {
689682

690683
assert(sfi == sfe && "more Swift fields than there were Clang fields?");
691684

692-
// Treat this as the end of the value size.
693-
TotalSize = NextOffset;
685+
// We never take advantage of tail padding, because that would prevent
686+
// us from passing the address of the object off to C, which is a pretty
687+
// likely scenario for imported C types.
688+
assert(NextOffset <= TotalStride);
689+
assert(SpareBits.size() <= TotalStride.getValueInBits());
690+
if (NextOffset < TotalStride) {
691+
addPaddingField(TotalStride);
692+
}
694693
}
695694

696695
/// Place the next struct field at its appropriate offset.

test/IRGen/c_layout.sil

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import Swift
77

88
// TODO: Provide tests for other architectures
99

10-
// CHECK-x86_64: %VSC11BitfieldOne = type <{ %Vs6UInt32, %VSC6Nested, [1 x i8], [4 x i8], [4 x i8], %Sf, [1 x i8], [7 x i8], %Vs6UInt64, %Vs6UInt32 }>
11-
// CHECK-x86_64: %VSC6Nested = type <{ %Sf, [3 x i8] }>
10+
// CHECK-x86_64: %VSC11BitfieldOne = type <{ %Vs6UInt32, %VSC6Nested, [4 x i8], [4 x i8], %Sf, [1 x i8], [7 x i8], %Vs6UInt64, %Vs6UInt32, [4 x i8] }>
11+
// CHECK-x86_64: %VSC6Nested = type <{ %Sf, [3 x i8], [1 x i8] }>
1212

1313
// CHECK-x86_64: %VSC26BitfieldSeparatorReference = type [[BITFIELD_SEP_TYPE:<{ %Vs5UInt8, \[3 x i8\], %Vs5UInt8 }>]]
1414
// CHECK-x86_64: %VSC25BitfieldSeparatorSameName = type [[BITFIELD_SEP_TYPE]]
@@ -42,22 +42,22 @@ bb0:
4242
// CHECK-x86_64: [[ADDR_B_YZ:%.*]] = getelementptr inbounds %VSC6Nested, %VSC6Nested* [[ADDR_B]], i32 0, i32 1
4343
// CHECK-x86_64: [[ADDR_B_YZ_1:%.*]] = bitcast [3 x i8]* [[ADDR_B_YZ]] to i24*
4444
// CHECK-x86_64: [[B_YZ:%.*]] = load i24, i24* [[ADDR_B_YZ_1]], align 4
45-
// CHECK-x86_64: [[ADDR_CDE:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 3
45+
// CHECK-x86_64: [[ADDR_CDE:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 2
4646
// CHECK-x86_64: [[ADDR_CDE_1:%.*]] = bitcast [4 x i8]* [[ADDR_CDE]] to i32*
4747
// CHECK-x86_64: [[CDE:%.*]] = load i32, i32* [[ADDR_CDE_1]], align 4
48-
// CHECK-x86_64: [[ADDR_FGH:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 4
48+
// CHECK-x86_64: [[ADDR_FGH:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 3
4949
// CHECK-x86_64: [[ADDR_FGH_1:%.*]] = bitcast [4 x i8]* [[ADDR_FGH]] to i32*
5050
// CHECK-x86_64: [[FGH:%.*]] = load i32, i32* [[ADDR_FGH_1]], align 8
51-
// CHECK-x86_64: [[ADDR_I:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 5
51+
// CHECK-x86_64: [[ADDR_I:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 4
5252
// CHECK-x86_64: [[ADDR_I_V:%.*]] = getelementptr inbounds %Sf, %Sf* [[ADDR_I]], i32 0, i32 0
5353
// CHECK-x86_64: [[I:%.*]] = load float, float* [[ADDR_I_V]], align 4
54-
// CHECK-x86_64: [[ADDR_JK:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 6
54+
// CHECK-x86_64: [[ADDR_JK:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 5
5555
// CHECK-x86_64: [[ADDR_JK_1:%.*]] = bitcast [1 x i8]* [[ADDR_JK]] to i8*
5656
// CHECK-x86_64: [[JK:%.*]] = load i8, i8* [[ADDR_JK_1]], align 8
57-
// CHECK-x86_64: [[ADDR_L:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 8
57+
// CHECK-x86_64: [[ADDR_L:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 7
5858
// CHECK-x86_64: [[ADDR_L_V:%.*]] = getelementptr inbounds %Vs6UInt64, %Vs6UInt64* [[ADDR_L]], i32 0, i32 0
5959
// CHECK-x86_64: [[L:%.*]] = load i64, i64* [[ADDR_L_V]], align 8
60-
// CHECK-x86_64: [[ADDR_M:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 9
60+
// CHECK-x86_64: [[ADDR_M:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[RESULT]], i32 0, i32 8
6161
// CHECK-x86_64: [[ADDR_M_V:%.*]] = getelementptr inbounds %Vs6UInt32, %Vs6UInt32* [[ADDR_M]], i32 0, i32 0
6262
// CHECK-x86_64: [[M:%.*]] = load i32, i32* [[ADDR_M_V]], align 8
6363
// Put all of the values into the indirect argument and make the second call.
@@ -71,22 +71,22 @@ bb0:
7171
// CHECK-x86_64: [[ADDR_B_YZ:%.*]] = getelementptr inbounds %VSC6Nested, %VSC6Nested* [[ADDR_B]], i32 0, i32 1
7272
// CHECK-x86_64: [[ADDR_B_YZ_1:%.*]] = bitcast [3 x i8]* [[ADDR_B_YZ]] to i24*
7373
// CHECK-x86_64: store i24 [[B_YZ]], i24* [[ADDR_B_YZ_1]], align 4
74-
// CHECK-x86_64: [[ADDR_CDE:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 3
74+
// CHECK-x86_64: [[ADDR_CDE:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 2
7575
// CHECK-x86_64: [[ADDR_CDE_1:%.*]] = bitcast [4 x i8]* [[ADDR_CDE]] to i32*
7676
// CHECK-x86_64: store i32 [[CDE]], i32* [[ADDR_CDE_1]], align 4
77-
// CHECK-x86_64: [[ADDR_FGH:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 4
77+
// CHECK-x86_64: [[ADDR_FGH:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 3
7878
// CHECK-x86_64: [[ADDR_FGH_1:%.*]] = bitcast [4 x i8]* [[ADDR_FGH]] to i32*
7979
// CHECK-x86_64: store i32 [[FGH]], i32* [[ADDR_FGH_1]], align 8
80-
// CHECK-x86_64: [[ADDR_I:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 5
80+
// CHECK-x86_64: [[ADDR_I:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 4
8181
// CHECK-x86_64: [[ADDR_I_V:%.*]] = getelementptr inbounds %Sf, %Sf* [[ADDR_I]], i32 0, i32 0
8282
// CHECK-x86_64: store float [[I]], float* [[ADDR_I_V]], align 4
83-
// CHECK-x86_64: [[ADDR_JK:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 6
83+
// CHECK-x86_64: [[ADDR_JK:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 5
8484
// CHECK-x86_64: [[ADDR_JK_1:%.*]] = bitcast [1 x i8]* [[ADDR_JK]] to i8*
8585
// CHECK-x86_64: store i8 [[JK]], i8* [[ADDR_JK_1]], align 8
86-
// CHECK-x86_64: [[ADDR_L:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 8
86+
// CHECK-x86_64: [[ADDR_L:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 7
8787
// CHECK-x86_64: [[ADDR_L_V:%.*]] = getelementptr inbounds %Vs6UInt64, %Vs6UInt64* [[ADDR_L]], i32 0, i32 0
8888
// CHECK-x86_64: store i64 [[L]], i64* [[ADDR_L_V]], align 8
89-
// CHECK-x86_64: [[ADDR_M:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 9
89+
// CHECK-x86_64: [[ADDR_M:%.*]] = getelementptr inbounds %VSC11BitfieldOne, %VSC11BitfieldOne* [[ARG]], i32 0, i32 8
9090
// CHECK-x86_64: [[ADDR_M_V:%.*]] = getelementptr inbounds %Vs6UInt32, %Vs6UInt32* [[ADDR_M]], i32 0, i32 0
9191
// CHECK-x86_64: store i32 [[M]], i32* [[ADDR_M_V]], align 8
9292
// CHECK-x86_64: call void @consumeBitfieldOne(%VSC11BitfieldOne* byval align 8 [[ARG]])

test/Reflection/typeref_decoding_imported.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
// CHECK-64: ==============
8282

8383
// CHECK-64: - __C.MyCStruct:
84-
// CHECK-64: Size: 17
84+
// CHECK-64: Size: 24
8585
// CHECK-64: Alignment: 8
8686
// CHECK-64: Stride: 24
8787
// CHECK-64: NumExtraInhabitants: 0
@@ -99,7 +99,7 @@
9999
// CHECK-64: NumExtraInhabitants: 0
100100

101101
// CHECK-64: - __C.MyCStructWithBitfields:
102-
// CHECK-64: Size: 2
102+
// CHECK-64: Size: 4
103103
// CHECK-64: Alignment: 4
104104
// CHECK-64: Stride: 4
105105
// CHECK-64: NumExtraInhabitants: 0

test/Reflection/typeref_lowering_imported.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
V12TypeLowering9HasCTypes
99
// CHECK: (struct TypeLowering.HasCTypes)
10-
// CHECK-NEXT: (struct size=34 alignment=8 stride=40 num_extra_inhabitants=0
10+
// CHECK-NEXT: (struct size=44 alignment=8 stride=48 num_extra_inhabitants=0
1111
// CHECK-NEXT: (field name=mcs offset=0
12-
// CHECK-NEXT: (builtin size=17 alignment=8 stride=24 num_extra_inhabitants=0))
13-
// CHECK-NEXT: (field name=mce offset=20
12+
// CHECK-NEXT: (builtin size=24 alignment=8 stride=24 num_extra_inhabitants=0))
13+
// CHECK-NEXT: (field name=mce offset=24
1414
// CHECK-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))
15-
// CHECK-NEXT: (field name=mcu offset=24
15+
// CHECK-NEXT: (field name=mcu offset=32
1616
// CHECK-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))
17-
// CHECK-NEXT: (field name=mcsbf offset=32
18-
// CHECK-NEXT: (builtin size=2 alignment=4 stride=4 num_extra_inhabitants=0)))
17+
// CHECK-NEXT: (field name=mcsbf offset=40
18+
// CHECK-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))
1919

0 commit comments

Comments
 (0)