Skip to content

Commit c877900

Browse files
committed
IRGen: Set instanceStart correctly in ObjC rodata when first stored property is empty.
Give empty fields a notional byte offset so we can still use the offset of the first field as an approximation of the instanceStart of a class. Fixes SR-1055.
1 parent 56e3875 commit c877900

File tree

4 files changed

+42
-4
lines changed

4 files changed

+42
-4
lines changed

lib/IRGen/GenClass.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,9 @@ namespace {
10181018
|| Layout->getElements().size() == FirstFieldIndex) {
10191019
instanceStart = instanceSize;
10201020
} else if (Layout->getElement(FirstFieldIndex).getKind()
1021-
== ElementLayout::Kind::Fixed) {
1021+
== ElementLayout::Kind::Fixed ||
1022+
Layout->getElement(FirstFieldIndex).getKind()
1023+
== ElementLayout::Kind::Empty) {
10221024
// FIXME: assumes layout is always sequential!
10231025
instanceStart = Layout->getElement(FirstFieldIndex).getByteOffset();
10241026
} else {

lib/IRGen/StructLayout.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@ void StructLayoutBuilder::addNonFixedSizeElement(ElementLayout &elt) {
307307

308308
/// Add an empty element to the aggregate.
309309
void StructLayoutBuilder::addEmptyElement(ElementLayout &elt) {
310-
elt.completeEmpty(elt.getType().isPOD(ResilienceExpansion::Maximal));
310+
elt.completeEmpty(elt.getType().isPOD(ResilienceExpansion::Maximal),
311+
CurSize);
311312
}
312313

313314
/// Add an element at the fixed offset of the current end of the

lib/IRGen/StructLayout.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,13 @@ class ElementLayout {
137137
Index = other.Index;
138138
}
139139

140-
void completeEmpty(IsPOD_t isPOD) {
140+
void completeEmpty(IsPOD_t isPOD, Size byteOffset) {
141141
TheKind = unsigned(Kind::Empty);
142142
IsPOD = unsigned(isPOD);
143+
// We still want to give empty fields an offset for use by things like
144+
// ObjC ivar emission. We use the first field in a class layout as the
145+
// instanceStart.
146+
ByteOffset = byteOffset.getValue();
143147
Index = 0; // make a complete write of the bitfield
144148
}
145149

@@ -187,7 +191,8 @@ class ElementLayout {
187191

188192
/// Given that this element has a fixed offset, return that offset in bytes.
189193
Size getByteOffset() const {
190-
assert(isCompleted() && getKind() == Kind::Fixed);
194+
assert(isCompleted() &&
195+
(getKind() == Kind::Fixed || getKind() == Kind::Empty));
191196
return Size(ByteOffset);
192197
}
193198

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir | FileCheck %s --check-prefix=CHECK-%target-ptrsize
2+
3+
// REQUIRES: objc_interop
4+
5+
// SR-1055
6+
7+
// CHECK-64: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 16, i32 24
8+
// CHECK-32: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 12, i32 16
9+
10+
enum OneCaseEnum {
11+
case X
12+
}
13+
14+
class OneEnumWrapper {
15+
var myVar: OneCaseEnum
16+
var whyVar: OneCaseEnum
17+
var x: Int
18+
19+
init(v: OneCaseEnum)
20+
{
21+
self.myVar = v
22+
self.whyVar = v
23+
self.x = 0
24+
}
25+
}
26+
27+
let e = OneCaseEnum.X
28+
print(e)
29+
let x = OneEnumWrapper(v: e)
30+
print(x)

0 commit comments

Comments
 (0)