IRGen: fix how metadata is loaded for fast class casting

Pass the correct type to `emitHeapMetadataRefForHeapObject()`.
Fixes a runtime crash in case a class protocol is cast to a final swift class, where the actual object is an ObjectiveC class instance.

rdar://99626888
This commit is contained in:
Erik Eckstein
2022-09-21 10:36:14 +02:00
parent d015505090
commit 2527d3765e
3 changed files with 7 additions and 3 deletions

View File

@@ -1108,7 +1108,7 @@ llvm::Value *irgen::emitFastClassCastIfPossible(IRGenFunction &IGF,
// Load the isa pointer.
llvm::Value *objMetadata = emitHeapMetadataRefForHeapObject(IGF, instance,
targetFormalType, GenericSignature(), /*suppress cast*/ true);
sourceFormalType, GenericSignature(), /*suppress cast*/ true);
llvm::Value *rhs = IGF.Builder.CreateBitCast(objMetadata, IGF.IGM.Int8PtrTy);
// return isa_ptr == metadata_ptr ? instance : nullptr

View File

@@ -1917,7 +1917,8 @@ llvm::Value *irgen::emitHeapMetadataRefForHeapObject(IRGenFunction &IGF,
GenericSignature sig,
bool suppressCast) {
ClassDecl *theClass = objectType.getClassOrBoundGenericClass();
if (theClass && isKnownNotTaggedPointer(IGF.IGM, theClass)) {
if ((theClass && isKnownNotTaggedPointer(IGF.IGM, theClass)) ||
!IGF.IGM.ObjCInterop) {
auto isaEncoding = getIsaEncodingForType(IGF.IGM, objectType, sig);
return emitLoadOfHeapMetadataRef(IGF, object,
isaEncoding,

View File

@@ -11,7 +11,7 @@
// 2. check if the generated IR looks like expected:
// RUN: %target-swift-frontend -module-name=Main -I%t %s -emit-ir -g -o - | %FileCheck %s
// RUN: %target-swift-frontend -module-name=Main -I%t %s -emit-ir -g -o - | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-%target-objc-interop
// REQUIRES: executable_test
@@ -48,6 +48,7 @@ func castToFinal(_ b: Classes.Base) -> Classes.Final? {
}
// CHECK-LABEL: define {{.*}} @"$s4Main24unconditionalCastToFinaly7Classes0E0CAC4BaseCF"
// CHECK-NOT: call {{.*}}@object_getClass
// CHECK-NOT: @swift_dynamicCastClass
// CHECK: }
@inline(never)
@@ -64,6 +65,8 @@ func castToResilientFinal(_ b: ResilientClasses.Base) -> ResilientClasses.Final?
}
// CHECK-LABEL: define {{.*}} @"$s4Main19castProtocolToFinaly7Classes0E0CSgAC1P_pF"
// CHECK-objc: call {{.*}}@object_getClass
// CHECK-nonobjc: load
// CHECK-NOT: @swift_dynamicCastClass
// CHECK: }
@inline(never)