Skip to content

Commit e178d8b

Browse files
authored
Merge pull request #15358 from DougGregor/objc-class-ref-runtime
[Runtime] Reference ObjC class objects indirectly in conformance records
2 parents 0d93b39 + ecf55f5 commit e178d8b

11 files changed

+27
-15
lines changed

include/swift/IRGen/Linking.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,9 @@ class LinkEntity {
766766
bool isForeignTypeMetadataCandidate() const {
767767
return getKind() == Kind::ForeignTypeMetadataCandidate;
768768
}
769+
bool isObjCClassRef() const {
770+
return getKind() == Kind::ObjCClassRef;
771+
}
769772

770773
/// Determine whether this entity will be weak-imported.
771774
bool isWeakImported(ModuleDecl *module) const {

lib/IRGen/GenDecl.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,6 +2445,15 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
24452445
Alignment alignment,
24462446
llvm::Type *defaultType,
24472447
ConstantReference::Directness forceIndirectness) {
2448+
// ObjC class references can always be directly referenced, even in
2449+
// the weird cases where we don't see a definition.
2450+
if (entity.isObjCClassRef()) {
2451+
auto value = getAddrOfObjCClassRef(
2452+
const_cast<ClassDecl *>(cast<ClassDecl>(entity.getDecl())));
2453+
return { cast<llvm::Constant>(value.getAddress()),
2454+
ConstantReference::Direct };
2455+
}
2456+
24482457
// Ensure the variable is at least forward-declared.
24492458
if (entity.isForeignTypeMetadataCandidate()) {
24502459
auto foreignCandidate
@@ -2522,7 +2531,7 @@ IRGenModule::getTypeEntityReference(NominalTypeDecl *decl) {
25222531

25232532
kind = TypeMetadataRecordKind::IndirectObjCClass;
25242533
defaultTy = TypeMetadataPtrTy;
2525-
entity = LinkEntity::forObjCClass(clas);
2534+
entity = LinkEntity::forObjCClassRef(clas);
25262535
} else {
25272536
// A reference to a concrete type.
25282537
// TODO: consider using a symbolic reference (i.e. a symbol string
@@ -2537,8 +2546,8 @@ IRGenModule::getTypeEntityReference(NominalTypeDecl *decl) {
25372546

25382547
// Adjust the flags now that we know whether the reference to this
25392548
// entity will be indirect.
2540-
if (ref.isIndirect() &&
2541-
kind == TypeMetadataRecordKind::DirectNominalTypeDescriptor) {
2549+
if (ref.isIndirect()) {
2550+
assert(kind == TypeMetadataRecordKind::DirectNominalTypeDescriptor);
25422551
kind = TypeMetadataRecordKind::IndirectNominalTypeDescriptor;
25432552
}
25442553

lib/IRGen/Linking.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ std::string LinkEntity::mangleAsString() const {
191191
case Kind::ObjCClassRef: {
192192
llvm::SmallString<64> tempBuffer;
193193
StringRef name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(tempBuffer);
194-
std::string Result("OBJC_CLASS_REF_$_");
194+
std::string Result("\01l_OBJC_CLASS_REF_$_");
195195
Result.append(name.data(), name.size());
196196
return Result;
197197
}

test/ClangImporter/attr-swift_private.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public func testTopLevel() {
9292
}
9393

9494
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo10PrivFooSubCMa{{.*}} {
95-
// CHECK: %objc_class** @"OBJC_CLASS_REF_$_PrivFooSub"
95+
// CHECK: %objc_class** @"\01l_OBJC_CLASS_REF_$_PrivFooSub"
9696
// CHECK: }
9797

9898
// CHECK-LABEL: define linkonce_odr hidden {{.+}} @"$SSo3BarC8__noArgsABSgyt_tcfcTO"

test/ClangImporter/objc_ir.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ func propertyAccess(b b: B) {
7474
// CHECK: load i8*, i8** @"\01L_selector(setCounter:)"
7575
b.counter = b.counter + 1
7676

77-
// CHECK: load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_B"
77+
// CHECK: load %objc_class*, %objc_class** @"\01l_OBJC_CLASS_REF_$_B"
7878
// CHECK: load i8*, i8** @"\01L_selector(sharedCounter)"
7979
// CHECK: load i8*, i8** @"\01L_selector(setSharedCounter:)"
8080
B.sharedCounter = B.sharedCounter + 1
8181
}
8282

8383
// CHECK-LABEL: define hidden swiftcc %TSo1BC* @"$S7objc_ir8downcast1aSo1BCSo1AC_tF"(
8484
func downcast(a a: A) -> B {
85-
// CHECK: [[CLASS:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_B"
85+
// CHECK: [[CLASS:%.*]] = load %objc_class*, %objc_class** @"\01l_OBJC_CLASS_REF_$_B"
8686
// CHECK: [[T0:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[CLASS]])
8787
// CHECK: [[T1:%.*]] = bitcast %objc_class* [[T0]] to i8*
8888
// CHECK: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[A:%.*]], i8* [[T1]]) [[NOUNWIND:#[0-9]+]]

test/IRGen/COFF-objc-sections.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class D {
2121
// CHECK-COFF-NOT: @"$S4main1CCMf" = {{.*}}, section "__DATA,__objc_data, regular"
2222
// CHECK-COFF: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, section ".objc_protolist$B"
2323
// CHECK-COFF: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P" = {{.*}}, section ".objc_protorefs$B"
24-
// CHECK-COFF: @"OBJC_CLASS_REF_$_I" = {{.*}}, section ".objc_classrefs$B"
24+
// CHECK-COFF: @"\01l_OBJC_CLASS_REF_$_I" = {{.*}}, section ".objc_classrefs$B"
2525
// CHECK-COFF: @"\01L_selector(init)" = {{.*}}, section ".objc_selrefs$B"
2626
// CHECK-COFF: @objc_classes = {{.*}}, section ".objc_classlist$B"
2727
// CHECK-COFF: @objc_categories = {{.*}}, section ".objc_catlist$B"

test/IRGen/ELF-objc-sections.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class D {
2121
// CHECK-ELF-NOT: @"$S4main1CCMf" = {{.*}}, section "__DATA,__objc_data, regular"
2222
// CHECK-ELF: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, section "objc_protolist"
2323
// CHECK-ELF: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P" = {{.*}}, section "objc_protorefs", align 8
24-
// CHECK-ELF: @"OBJC_CLASS_REF_$_I" = {{.*}}, section "objc_classrefs", align 8
24+
// CHECK-ELF: @"\01l_OBJC_CLASS_REF_$_I" = {{.*}}, section "objc_classrefs", align 8
2525
// CHECK-ELF: @"\01L_selector(init)" = {{.*}}, section "objc_selrefs"
2626
// CHECK-ELF: @objc_classes = {{.*}}, section "objc_classlist"
2727
// CHECK-ELF: @objc_categories = {{.*}}, section "objc_catlist"

test/IRGen/objc_bridged_generic_conformance.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
// CHECK-NOT: _TMnCSo
55

6-
// CHECK: @"$SSo6ThingyCyxG32objc_bridged_generic_conformance1PADMc" = hidden constant %swift.protocol_conformance_descriptor {{.*}} @"got.OBJC_CLASS_$_Thingy"
6+
// CHECK: @"$SSo6ThingyCyxG32objc_bridged_generic_conformance1PADMc" = hidden constant %swift.protocol_conformance_descriptor {{.*}} @"\01l_OBJC_CLASS_REF_$_Thingy"
77

88
// CHECK-NOT: _TMnCSo
99

test/IRGen/objc_casts.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ bb0(%unused : $@thick T.Type, %obj : $NSObject):
2828
// CHECK: [[T0:%.*]] = call %objc_object* @swift_dynamicCastMetatypeToObjectUnconditional(%swift.type* %0)
2929
// TODO: is this really necessary? also, this really shouldn't use a direct reference
3030
// CHECK-NEXT: [[T1:%.*]] = bitcast %objc_object* [[T0]] to i8*
31-
// CHECK-NEXT: [[T2a:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_Foo"
31+
// CHECK-NEXT: [[T2a:%.*]] = load %objc_class*, %objc_class** @"\01l_OBJC_CLASS_REF_$_Foo"
3232
// CHECK-NEXT: [[T2:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T2a]])
3333
// CHECK-NEXT: [[T3:%.*]] = bitcast %objc_class* [[T2]] to i8*
3434
// CHECK-NEXT: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[T1]], i8* [[T3]])
@@ -44,7 +44,7 @@ bb0(%metatype : $@thick T.Type):
4444
// CHECK: [[T0:%.*]] = call %objc_object* @swift_dynamicCastMetatypeToObjectUnconditional(%swift.type* [[ARG]])
4545
// TODO: is this really necessary? also, this really shouldn't use a direct reference
4646
// CHECK-NEXT: [[T1:%.*]] = bitcast %objc_object* [[T0]] to i8*
47-
// CHECK-NEXT: [[T2a:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_Foo"
47+
// CHECK-NEXT: [[T2a:%.*]] = load %objc_class*, %objc_class** @"\01l_OBJC_CLASS_REF_$_Foo"
4848
// CHECK-NEXT: [[T2:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T2a]])
4949
// CHECK-NEXT: [[T3:%.*]] = bitcast %objc_class* [[T2]] to i8*
5050
// CHECK-NEXT: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[T1]], i8* [[T3]])

test/IRGen/objc_generic_class_metadata.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ entry:
3939
%b = metatype $@thick GenericClass<NSObject>.Type
4040
apply %z<GenericClass<NSObject>>(%b) : $@convention(thin) <T> (@thick T.Type) -> ()
4141

42-
// CHECK: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_GenericClass",
42+
// CHECK: [[T0:%.*]] = load %objc_class*, %objc_class** @"\01l_OBJC_CLASS_REF_$_GenericClass",
4343
// CHECK: [[OBJC_CLASS:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T0]])
4444
// CHECK: call swiftcc void @objc_class_sink(%objc_class* [[OBJC_CLASS]], %swift.type* [[METADATA]])
4545
%c = metatype $@objc_metatype GenericClass<NSString>.Type
@@ -79,7 +79,7 @@ entry(%0: $Subclass, %1: $NSDictionary):
7979
}
8080

8181
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo12GenericClassCMa"(
82-
// CHECK: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_GenericClass",
82+
// CHECK: [[T0:%.*]] = load %objc_class*, %objc_class** @"\01l_OBJC_CLASS_REF_$_GenericClass",
8383
// CHECK: call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T0]])
8484

8585
// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSaySo12GenericClassC_SitGMa"

test/IRGen/protocol_conformance_records_objc.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extension NSRect: Runcible {
3030
// -- protocol descriptor
3131
// CHECK-SAME: [[RUNCIBLE]]
3232
// -- class object reference
33-
// CHECK-SAME: @"got.OBJC_CLASS_$_Gizmo"
33+
// CHECK-SAME: @"\01l_OBJC_CLASS_REF_$_Gizmo"
3434
// -- witness table
3535
// CHECK-SAME: @"$SSo5GizmoC33protocol_conformance_records_objc8RuncibleACWP"
3636
// -- flags

0 commit comments

Comments
 (0)