From 260594c9654438854931ee23fbbf8c3de8837f06 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 3 Apr 2018 13:13:01 -0700 Subject: [PATCH 1/2] IRGen: Exact casts cannot fail Use initialized metadata in exact checks otherwise we will fail in [exact] checks when we shouldn't. rdar://38885852 --- lib/IRGen/GenCast.cpp | 10 +++---- test/IRGen/exactcast.sil | 59 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/lib/IRGen/GenCast.cpp b/lib/IRGen/GenCast.cpp index 95df8d0c9ef72..a907c09cc74bb 100644 --- a/lib/IRGen/GenCast.cpp +++ b/lib/IRGen/GenCast.cpp @@ -97,7 +97,6 @@ FailableCastResult irgen::emitClassIdenticalCast(IRGenFunction &IGF, toType = IGF.IGM.getLoweredType(metaType.getInstanceType()); } // Emit a reference to the heap metadata for the target type. - const bool allowConservative = true; // If we're allowed to do a conservative check, try to just use the // global class symbol. If the class has been re-allocated, this @@ -105,16 +104,15 @@ FailableCastResult irgen::emitClassIdenticalCast(IRGenFunction &IGF, // test might fail; but it's a much faster check. // TODO: use ObjC class references llvm::Value *targetMetadata; - if (allowConservative && - (targetMetadata = - tryEmitConstantHeapMetadataRef(IGF.IGM, toType.getSwiftRValueType(), - /*allowUninitialized*/ true))) { + if ((targetMetadata = + tryEmitConstantHeapMetadataRef(IGF.IGM, toType.getSwiftRValueType(), + /*allowUninitialized*/ false))) { // ok } else { targetMetadata = emitClassHeapMetadataRef(IGF, toType.getSwiftRValueType(), MetadataValueType::ObjCClass, - /*allowUninitialized*/ allowConservative); + /*allowUninitialized*/ false); } // Handle checking a metatype object's type by directly comparing the address diff --git a/test/IRGen/exactcast.sil b/test/IRGen/exactcast.sil index 0d27078f020af..5cf5bb08f30db 100644 --- a/test/IRGen/exactcast.sil +++ b/test/IRGen/exactcast.sil @@ -23,7 +23,7 @@ class ParentNode : Node { sil @_test_exact_checked_cast_branch : $@convention(method) (@guaranteed Node) -> Int { bb0(%0 : $Node): -//CHECK-LABEL: @_test_exact_checked_cast_branch +//CHECK-LABEL: define{{.*}}@_test_exact_checked_cast_branch //CHECK: = load %swift.type //CHECK-NEXT: = icmp eq %swift.type //CHECK-NEXT: = bitcast @@ -40,6 +40,43 @@ bb3: // Preds: bb0 br bb1 // id: %12 } +class BaseBase { + @inline(never) func foo() + init() + deinit +} + +class Base : BaseBase { + override init() + deinit +} + +final class DerivedInt : Base { + @inline(never) override final func foo() + override init() + deinit +} + +sil @test_exact_checked_cast_branch_dynamic_init : $@convention(thin) (@guaranteed BaseBase) -> Int { +bb0(%0 : $BaseBase): +//CHECK-LABEL: define{{.*}}@test_exact_checked_cast_branch_dynamic_init +//CHECK: call swiftcc {{.*}}@"$S9exactcast10DerivedIntCMa"({{.*}}) +//CHECK: load +//CHECK: bitcast +//CHECK: icmp eq %swift.type +//CHECK: br + checked_cast_br [exact] %0 : $BaseBase to $DerivedInt, bb2, bb3 // id: %2 + +bb1: + return undef : $Int + +bb2(%5 : $DerivedInt): + br bb1 + +bb3: + br bb1 +} + sil @_TFC9pic_crash4NodecfMS0_FT5indexSi_S0_ : $@convention(method) (Int, @owned Node) -> @owned Node sil @_TFC9pic_crash4NodeCfMS0_FT5indexSi_S0_ : $@convention(thin) (Int, @thick Node.Type) -> @owned Node sil [transparent] @_TFC9pic_crash4Nodeg5indexSi : $@convention(method) (@guaranteed Node) -> Int @@ -64,3 +101,23 @@ sil_vtable ParentNode { #ParentNode.init!initializer.1: @_TFC9pic_crash10ParentNodecfMS0_FT4leftCS_4Node5rightS1_5indexSi_S0_ // pic_crash.ParentNode.init (pic_crash.ParentNode.Type)(left : pic_crash.Node, right : pic_crash.Node, index : Swift.Int) -> pic_crash.ParentNode } +sil @$S5test104BaseB0C3fooyyF : $@convention(method) (@guaranteed BaseBase) -> () +sil @$S5test104BaseB0CfD : $@convention(method) (@owned BaseBase) -> () +sil @$S5test14BaseCfD : $@convention(method) (@owned BaseBase) -> () +sil @$S5test110DerivedIntC3fooyyF : $@convention(method) (@guaranteed DerivedInt) -> () +sil @$S5test110DerivedIntCfD : $@convention(method) (@owned DerivedInt) -> () + +sil_vtable BaseBase { + #BaseBase.foo!1: (BaseBase) -> () -> () : @$S5test104BaseB0C3fooyyF + #BaseBase.deinit!deallocator: @$S5test104BaseB0CfD +} + +sil_vtable Base { + #BaseBase.foo!1: (BaseBase) -> () -> () : @$S5test104BaseB0C3fooyyF [inherited] + #Base.deinit!deallocator: @$S5test14BaseCfD +} + +sil_vtable DerivedInt { + #BaseBase.foo!1: (BaseBase) -> () -> () : @$S5test110DerivedIntC3fooyyF [override] + #DerivedInt.deinit!deallocator: @$S5test110DerivedIntCfD +} From ae25c0e104273d872016cb374e350de139a9b115 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 4 Apr 2018 07:30:46 -0700 Subject: [PATCH 2/2] test/IRGen/exactcast.sil fix for branch differences rdar://38885852 --- test/IRGen/exactcast.sil | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IRGen/exactcast.sil b/test/IRGen/exactcast.sil index 5cf5bb08f30db..8e114de929eab 100644 --- a/test/IRGen/exactcast.sil +++ b/test/IRGen/exactcast.sil @@ -60,7 +60,7 @@ final class DerivedInt : Base { sil @test_exact_checked_cast_branch_dynamic_init : $@convention(thin) (@guaranteed BaseBase) -> Int { bb0(%0 : $BaseBase): //CHECK-LABEL: define{{.*}}@test_exact_checked_cast_branch_dynamic_init -//CHECK: call swiftcc {{.*}}@"$S9exactcast10DerivedIntCMa"({{.*}}) +//CHECK: call {{.*}}@"$S9exactcast10DerivedIntCMa"({{.*}}) //CHECK: load //CHECK: bitcast //CHECK: icmp eq %swift.type