Skip to content

Commit 2a27acd

Browse files
committed
IRGen: Fix resilient class layout on Linux
When there's no Objective-C runtime, we have to store the field offset globals ourselves.
1 parent e786a6d commit 2a27acd

File tree

3 files changed

+68
-22
lines changed

3 files changed

+68
-22
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ using namespace irgen;
5959

6060
static llvm::Value *emitLoadOfObjCHeapMetadataRef(IRGenFunction &IGF,
6161
llvm::Value *object);
62+
static llvm::LoadInst *
63+
emitLoadFromMetadataAtIndex(IRGenFunction &IGF,
64+
llvm::Value *metadata,
65+
int index,
66+
llvm::Type *objectTy,
67+
const llvm::Twine &suffix = "");
6268

6369
/// Produce a constant to place in a metatype's isa field
6470
/// corresponding to the given metadata kind.
@@ -3392,6 +3398,34 @@ namespace {
33923398
}
33933399
}
33943400

3401+
void emitInitializeFieldOffsets(IRGenFunction &IGF,
3402+
llvm::Value *metadata) {
3403+
// The Objective-C runtime will copy field offsets from the field offset
3404+
// vector into field offset globals for us, if present. If there's no
3405+
// Objective-C runtime, we have to do this ourselves.
3406+
unsigned index = FieldLayout.InheritedStoredProperties.size();
3407+
3408+
for (auto prop : Target->getStoredProperties()) {
3409+
auto access = FieldLayout.AllFieldAccesses[index];
3410+
if (access == FieldAccess::NonConstantDirect) {
3411+
Address offsetA = IGF.IGM.getAddrOfFieldOffset(prop,
3412+
/*indirect*/ false,
3413+
ForDefinition);
3414+
3415+
// We can't use emitClassFieldOffset() here because that creates
3416+
// an invariant load, which could be hoisted above the point
3417+
// where the metadata becomes fully initialized
3418+
Size offset = getClassFieldOffset(IGF.IGM, Target, prop);
3419+
int index = getOffsetInWords(IGF.IGM, offset);
3420+
auto offsetVal = emitLoadFromMetadataAtIndex(IGF, metadata, index,
3421+
IGF.IGM.SizeTy);
3422+
IGF.Builder.CreateStore(offsetVal, offsetA);
3423+
}
3424+
3425+
index++;
3426+
}
3427+
}
3428+
33953429
void emitInitializeMetadata(IRGenFunction &IGF,
33963430
llvm::Value *metadata,
33973431
llvm::Value *vwtable) {
@@ -3555,8 +3589,9 @@ namespace {
35553589
llvm::ConstantInt::get(IGF.IGM.Int1Ty,
35563590
copyFieldOffsetVectors)});
35573591
}
3592+
3593+
emitInitializeFieldOffsets(IGF, metadata);
35583594
}
3559-
35603595
};
35613596
}
35623597

@@ -3647,7 +3682,7 @@ static llvm::LoadInst *emitLoadFromMetadataAtIndex(IRGenFunction &IGF,
36473682
llvm::Value *metadata,
36483683
int index,
36493684
llvm::Type *objectTy,
3650-
const llvm::Twine &suffix = ""){
3685+
const llvm::Twine &suffix) {
36513686
// Require the metadata to be some type that we recognize as a
36523687
// metadata pointer.
36533688
assert(metadata->getType() == IGF.IGM.TypeMetadataPtrTy);
@@ -3676,12 +3711,12 @@ static llvm::LoadInst *emitLoadFromMetadataAtIndex(IRGenFunction &IGF,
36763711
///
36773712
/// The load is marked invariant. This function should not be called
36783713
/// on metadata objects that are in the process of being initialized.
3679-
static llvm::LoadInst *emitInvariantLoadFromMetadataAtIndex(IRGenFunction &IGF,
3680-
llvm::Value *metadata,
3681-
int index,
3682-
llvm::Type *objectTy,
3683-
const llvm::Twine &suffix = ""){
3684-
3714+
static llvm::LoadInst *
3715+
emitInvariantLoadFromMetadataAtIndex(IRGenFunction &IGF,
3716+
llvm::Value *metadata,
3717+
int index,
3718+
llvm::Type *objectTy,
3719+
const llvm::Twine &suffix = "") {
36853720
auto result = emitLoadFromMetadataAtIndex(IGF, metadata, index, objectTy,
36863721
suffix);
36873722
IGF.setInvariantLoad(result);

test/IRGen/class_resilience.swift

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -I %S/../Inputs -enable-source-import -emit-ir -enable-resilience %s | FileCheck %s
1+
// RUN: %target-swift-frontend -I %S/../Inputs -enable-source-import -emit-ir -enable-resilience %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
22
// RUN: %target-swift-frontend -I %S/../Inputs -enable-source-import -emit-ir -enable-resilience -O %s
33

44
// CHECK: %swift.type = type { [[INT:i32|i64]] }
@@ -226,21 +226,34 @@ public class MyResilientChild : MyResilientParent {
226226

227227
// ClassWithResilientProperty metadata instantiation function
228228

229-
// FIXME: This is bogus since we don't emit code to initialize the
230-
// global ivar offsets yet.
231-
232229

233230
// CHECK-LABEL: define private %swift.type* @create_generic_metadata_ClassWithResilientProperty(%swift.type_pattern*, i8**)
234-
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(
235-
// CHECK: [[SIZE_METADATA:%.*]] = call %swift.type* @_TMaV16resilient_struct4Size()
236-
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(
237-
// CHECK: ret %swift.type* [[METADATA]]
231+
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(
232+
// CHECK: [[SIZE_METADATA:%.*]] = call %swift.type* @_TMaV16resilient_struct4Size()
233+
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(
234+
// CHECK-native: [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
235+
// CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] 12
236+
// CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
237+
// CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_TWvdvC16class_resilience26ClassWithResilientProperty1sV16resilient_struct4Size
238+
// CHECK-native-NEXT: [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
239+
// CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] 13
240+
// CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
241+
// CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_TWvdvC16class_resilience26ClassWithResilientProperty5colorVs5Int32
242+
// CHECK-NEXT: ret %swift.type* [[METADATA]]
238243

239244

240245
// ClassWithResilientlySizedProperty metadata instantiation function
241246

242247
// CHECK-LABEL: define private %swift.type* @create_generic_metadata_ClassWithResilientlySizedProperty(%swift.type_pattern*, i8**)
243-
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(
244-
// CHECK: [[RECTANGLE_METADATA:%.*]] = call %swift.type* @_TMaV16resilient_struct9Rectangle()
245-
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(
246-
// CHECK: ret %swift.type* [[METADATA]]
248+
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(
249+
// CHECK: [[RECTANGLE_METADATA:%.*]] = call %swift.type* @_TMaV16resilient_struct9Rectangle()
250+
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(
251+
// CHECK-native: [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
252+
// CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] 11
253+
// CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
254+
// CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_TWvdvC16class_resilience33ClassWithResilientlySizedProperty1rV16resilient_struct9Rectangle
255+
// CHECK-native-NEXT: [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
256+
// CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] 12
257+
// CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
258+
// CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_TWvdvC16class_resilience33ClassWithResilientlySizedProperty5colorVs5Int32
259+
// CHECK-NEXT: ret %swift.type* [[METADATA]]

test/Interpreter/class_resilience.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
// RUN: %target-run %t/main
1212

13-
// XFAIL: linux
14-
1513
import StdlibUnittest
1614
import resilient_class
1715
import resilient_struct

0 commit comments

Comments
 (0)