Skip to content

Commit 7097fac

Browse files
committed
Fix the code pattern with which we access ObjC classes to correctly
use classrefs instead of accessing the symbol directly. This might be a very nasty bug to work around.
1 parent 737155b commit 7097fac

File tree

10 files changed

+68
-9
lines changed

10 files changed

+68
-9
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,9 @@ SILLinkage LinkEntity::getLinkage(IRGenModule &IGM,
11021102
}
11031103
llvm_unreachable("bad metadata access kind");
11041104

1105+
case Kind::ObjCClassRef:
1106+
return SILLinkage::Private;
1107+
11051108
case Kind::WitnessTableOffset:
11061109
case Kind::Function:
11071110
case Kind::Other:
@@ -1183,6 +1186,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
11831186
case Kind::DirectProtocolWitnessTable:
11841187
return ::isAvailableExternally(IGM, getProtocolConformance()->getDeclContext());
11851188

1189+
case Kind::ObjCClassRef:
11861190
case Kind::TypeMangling:
11871191
case Kind::ValueWitness:
11881192
case Kind::WitnessTableOffset:
@@ -2210,6 +2214,33 @@ llvm::Constant *IRGenModule::emitTypeMetadataRecords() {
22102214
return var;
22112215
}
22122216

2217+
/// Fetch a global reference to a reference to the given Objective-C class.
2218+
/// The result is of type ObjCClassPtrTy->getPointerTo().
2219+
Address IRGenModule::getAddrOfObjCClassRef(ClassDecl *theClass) {
2220+
assert(ObjCInterop && "getting address of ObjC class ref in no-interop mode");
2221+
2222+
Alignment alignment = getPointerAlignment();
2223+
2224+
LinkEntity entity = LinkEntity::forObjCClassRef(theClass);
2225+
DebugTypeInfo DbgTy(theClass, ObjCClassPtrTy->getPointerTo(),
2226+
getPointerSize(), alignment);
2227+
auto addr = getAddrOfLLVMVariable(entity, alignment, NotForDefinition,
2228+
ObjCClassPtrTy, DbgTy);
2229+
2230+
// Define it lazily.
2231+
if (auto global = dyn_cast<llvm::GlobalVariable>(addr)) {
2232+
if (global->isDeclaration()) {
2233+
global->setSection("__DATA,__objc_classrefs,regular,no_dead_strip");
2234+
global->setLinkage(llvm::GlobalVariable::PrivateLinkage);
2235+
global->setExternallyInitialized(true);
2236+
global->setInitializer(getAddrOfObjCClass(theClass, NotForDefinition));
2237+
addCompilerUsedGlobal(global);
2238+
}
2239+
}
2240+
2241+
return Address(addr, alignment);
2242+
}
2243+
22132244
/// Fetch a global reference to the given Objective-C class. The
22142245
/// result is of type ObjCClassPtrTy.
22152246
llvm::Constant *IRGenModule::getAddrOfObjCClass(ClassDecl *theClass,

lib/IRGen/GenMeta.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ llvm::Value *irgen::emitObjCHeapMetadataRef(IRGenFunction &IGF,
301301
return IGF.Builder.CreateCall(IGF.IGM.getLookUpClassFn(), className);
302302
}
303303

304-
auto classObject = IGF.IGM.getAddrOfObjCClass(theClass, NotForDefinition);
304+
Address classRef = IGF.IGM.getAddrOfObjCClassRef(theClass);
305+
auto classObject = IGF.Builder.CreateLoad(classRef);
305306
if (allowUninitialized) return classObject;
306307

307308
// TODO: memoize this the same way that we memoize Swift type metadata?

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ private: \
839839
llvm::Type *definitionType);
840840
llvm::Constant *getAddrOfObjCClass(ClassDecl *D,
841841
ForDefinition_t forDefinition);
842+
Address getAddrOfObjCClassRef(ClassDecl *D);
842843
llvm::Constant *getAddrOfObjCMetaclass(ClassDecl *D,
843844
ForDefinition_t forDefinition);
844845
llvm::Constant *getAddrOfSwiftMetaclassStub(ClassDecl *D,

lib/IRGen/Linking.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,16 @@ void LinkEntity::mangle(raw_ostream &buffer) const {
274274
}
275275
return mangler.finalize(buffer);
276276

277+
// An Objective-C class reference reference. The symbol is private, so
278+
// the mangling is unimportant; it should just be readable in LLVM IR.
279+
case Kind::ObjCClassRef: {
280+
mangler.append("OBJC_CLASS_REF_$_");
281+
llvm::SmallString<64> tempBuffer;
282+
StringRef name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(tempBuffer);
283+
mangler.append(name);
284+
return mangler.finalize(buffer);
285+
}
286+
277287
// An Objective-C class reference; not a swift mangling.
278288
case Kind::ObjCClass: {
279289
llvm::SmallString<64> TempBuffer;

lib/IRGen/Linking.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ class LinkEntity {
104104
/// An Objective-C class reference. The pointer is a ClassDecl*.
105105
ObjCClass,
106106

107+
/// An Objective-C class reference reference. The pointer is a ClassDecl*.
108+
ObjCClassRef,
109+
107110
/// An Objective-C metaclass reference. The pointer is a ClassDecl*.
108111
ObjCMetaclass,
109112

@@ -320,6 +323,12 @@ class LinkEntity {
320323
return entity;
321324
}
322325

326+
static LinkEntity forObjCClassRef(ClassDecl *decl) {
327+
LinkEntity entity;
328+
entity.setForDecl(Kind::ObjCClassRef, decl, 0);
329+
return entity;
330+
}
331+
323332
static LinkEntity forObjCClass(ClassDecl *decl) {
324333
LinkEntity entity;
325334
entity.setForDecl(Kind::ObjCClass, decl, 0);

test/ClangModules/attr-swift_private.swift

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

9191
// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_TMaCSo12__PrivFooSub{{.*}} {
92-
// CHECK: %objc_class* @"OBJC_CLASS_$_PrivFooSub"
92+
// CHECK: %objc_class** @"OBJC_CLASS_REF_$_PrivFooSub"
9393
// CHECK: }
9494

9595
// CHECK-LABEL: define linkonce_odr hidden {{.+}} @_TTOFCSo3BarcfT2__Vs5Int32_GSQS__

test/ClangModules/objc_ir.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ func propertyAccess(b b: B) {
8080

8181
// CHECK: define hidden [[B]]* @_TF7objc_ir8downcastFT1aCSo1A_CSo1B(
8282
func downcast(a a: A) -> B {
83-
// CHECK: [[T0:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* @"OBJC_CLASS_$_B")
83+
// CHECK: [[CLASS:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_B"
84+
// CHECK: [[T0:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* [[CLASS]])
8485
// CHECK: [[T1:%.*]] = bitcast %objc_class* [[T0]] to i8*
8586
// CHECK: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[A:%.*]], i8* [[T1]]) [[NOUNWIND:#[0-9]+]]
8687
return a as! B

test/IRGen/generic_types.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ import Swift
8787
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
8888
// CHECK: %T = load %swift.type*, %swift.type** [[T0]],
8989
// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* null)
90-
// CHECK-objc: [[SUPER:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* @"OBJC_CLASS_$_SwiftObject")
90+
// CHECK-objc: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_SwiftObject"
91+
// CHECK-objc: [[SUPER:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* [[T0]])
9192
// CHECK-objc: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[SUPER]])
9293
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
9394
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 10
@@ -100,7 +101,8 @@ import Swift
100101
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
101102
// CHECK: %T = load %swift.type*, %swift.type** [[T0]],
102103
// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* null)
103-
// CHECK-objc: [[SUPER:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* @"OBJC_CLASS_$_SwiftObject")
104+
// CHECK-objc: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_SwiftObject"
105+
// CHECK-objc: [[SUPER:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* [[T0]])
104106
// CHECK-objc: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[SUPER]])
105107
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
106108
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 10

test/IRGen/objc_casts.sil

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ 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: [[T2:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* @"OBJC_CLASS_$_Foo")
31+
// CHECK-NEXT: [[T2a:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_Foo"
32+
// CHECK-NEXT: [[T2:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* [[T2a]])
3233
// CHECK-NEXT: [[T3:%.*]] = bitcast %objc_class* [[T2]] to i8*
3334
// CHECK-NEXT: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[T1]], i8* [[T3]])
3435
sil hidden @metatype_to_objc_class : $@convention(thin) <T> (@thick T.Type) -> () {
@@ -43,7 +44,8 @@ bb0(%metatype : $@thick T.Type):
4344
// CHECK: [[T0:%.*]] = call %objc_object* @swift_dynamicCastMetatypeToObjectUnconditional(%swift.type* [[ARG]])
4445
// TODO: is this really necessary? also, this really shouldn't use a direct reference
4546
// CHECK-NEXT: [[T1:%.*]] = bitcast %objc_object* [[T0]] to i8*
46-
// CHECK-NEXT: [[T2:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* @"OBJC_CLASS_$_Foo")
47+
// CHECK-NEXT: [[T2a:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_Foo"
48+
// CHECK-NEXT: [[T2:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* [[T2a]])
4749
// CHECK-NEXT: [[T3:%.*]] = bitcast %objc_class* [[T2]] to i8*
4850
// CHECK-NEXT: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[T1]], i8* [[T3]])
4951
sil hidden @opt_metatype_to_objc_class : $@convention(thin) <T> (Optional<T.Type>) -> () {

test/IRGen/objc_generic_class_metadata.sil

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ entry:
2828
%b = metatype $@thick GenericClass<NSObject>.Type
2929
apply %z<GenericClass<NSObject>>(%b) : $@convention(thin) <T> (@thick T.Type) -> ()
3030

31-
// CHECK: [[OBJC_CLASS:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* @"OBJC_CLASS_$_GenericClass")
31+
// CHECK: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_GenericClass",
32+
// CHECK: [[OBJC_CLASS:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* [[T0]])
3233
// CHECK: call void @objc_class_sink(%objc_class* [[OBJC_CLASS]], %swift.type* [[METADATA]])
3334
%c = metatype $@objc_metatype GenericClass<NSString>.Type
3435
apply %y<GenericClass<NSString>>(%c) : $@convention(thin) <T: AnyObject> (@objc_metatype T.Type) -> ()
@@ -46,7 +47,8 @@ entry:
4647
}
4748

4849
// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_TMaCSo12GenericClass()
49-
// CHECK: call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* @"OBJC_CLASS_$_GenericClass")
50+
// CHECK: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_GenericClass",
51+
// CHECK: call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* [[T0]])
5052

5153
// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_TMaGSaTCSo12GenericClassSi__()
5254
// CHECK: [[TUPLE:%.*]] = call %swift.type* @_TMaTCSo12GenericClassSi_()

0 commit comments

Comments
 (0)