// RUN: %target-swift-frontend %s -emit-ir -enable-objc-interop -disable-objc-attr-requires-foundation-module | %FileCheck %s -DINT=i%target-ptrsize // REQUIRES: CPU=i386 || CPU=x86_64 sil_stage canonical import Builtin import Swift struct NotClass {} class A {} class B: A {} sil_vtable A {} sil_vtable B {} // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %T5casts1BC* @unchecked_addr_cast(%T5casts1AC** noalias nocapture dereferenceable({{.*}}) %0) {{.*}} { // CHECK: bitcast %T5casts1AC** %0 to %T5casts1BC** sil @unchecked_addr_cast : $(@in A) -> B { entry(%a : $*A): %b = unchecked_addr_cast %a : $*A to $*B %x = load %b : $*B return %x : $B } protocol CP: class {} protocol CP2: class {} @objc protocol OP: class {} // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc i8* @ref_to_raw_pointer_existential(%objc_object* %0, i8** %1) {{.*}} { // CHECK: [[CAST:%.*]] = bitcast %objc_object* %0 to i8* // CHECK: ret i8* [[CAST]] sil @ref_to_raw_pointer_existential : $@convention(thin) (@owned CP) -> Builtin.RawPointer { entry(%p : $CP): %r = ref_to_raw_pointer %p : $CP to $Builtin.RawPointer return %r : $Builtin.RawPointer } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %objc_object* @raw_pointer_to_ref_existential(i8* %0) {{.*}} { // CHECK: [[CAST:%.*]] = bitcast i8* %0 to %objc_object* // CHECK: ret %objc_object* [[CAST]] sil @raw_pointer_to_ref_existential : $@convention(thin) (@owned Builtin.RawPointer) -> AnyObject { entry(%p : $Builtin.RawPointer): %r = raw_pointer_to_ref %p : $Builtin.RawPointer to $AnyObject return %r : $AnyObject } sil @unchecked_ref_cast_to_existential : $@convention(thin) (@owned Builtin.NativeObject) -> @owned AnyObject { entry(%n : $Builtin.NativeObject): %r = unchecked_ref_cast %n : $Builtin.NativeObject to $AnyObject return %r : $AnyObject } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %objc_object*, i8** } @u_cast_to_class_existential(%objc_object* %0) // CHECK: call { i8*, i8** } @dynamic_cast_existential_1_unconditional(i8* {{%.*}}, %swift.type* {{%.*}}, {{.*}} @"$s5casts2CPMp" // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} private { i8*, i8** } @dynamic_cast_existential_1_unconditional(i8* %0, %swift.type* %1, %swift.protocol* %2) {{.*}} { // CHECK: [[WITNESS:%.*]] = call i8** @swift_conformsToProtocol(%swift.type* %1, %swift.protocol* %2) // CHECK: [[IS_NULL:%.*]] = icmp eq i8** [[WITNESS]], null // CHECK: br i1 [[IS_NULL]], label %fail, label %cont // CHECK: cont: // CHECK: [[FIRST:%.*]] = insertvalue { i8*, i8** } undef, i8* %0, 0 // CHECK: [[SECOND:%.*]] = insertvalue { i8*, i8** } [[FIRST]], i8** [[WITNESS]], 1 // CHECK: ret { i8*, i8** } [[SECOND]] // CHECK: fail: // CHECK: call void @llvm.trap() sil @u_cast_to_class_existential : $@convention(thin) (@owned AnyObject) -> @owned CP { entry(%a : $AnyObject): %p = unconditional_checked_cast %a : $AnyObject to CP return %p : $CP } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %swift.type*, i8** } @u_cast_to_existential_metatype(%swift.type* %0) // CHECK: call { i8*, i8** } @dynamic_cast_existential_1_unconditional(i8* %1, %swift.type* %0, {{.*}} @"$s5casts2CPMp" sil @u_cast_to_existential_metatype : $@convention(thin) (@owned @thick Any.Type) -> @owned @thick CP.Type { entry(%a : $@thick Any.Type): %p = unconditional_checked_cast %a : $@thick Any.Type to @thick CP.Type return %p : $@thick CP.Type } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %objc_object*, i8**, i8** } @u_cast_to_class_existential_2(%objc_object* %0) // CHECK: call { i8*, i8**, i8** } @dynamic_cast_existential_2_unconditional(i8* {{%.*}}, %swift.type* {{%.*}}, {{.*}} @"$s5casts2CPMp"{{[^,]*}}, {{.*}} @"$s5casts3CP2Mp" // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} private { i8*, i8**, i8** } @dynamic_cast_existential_2_unconditional(i8* %0, %swift.type* %1, %swift.protocol* %2, %swift.protocol* %3) // CHECK: [[WITNESS:%.*]] = call i8** @swift_conformsToProtocol(%swift.type* %1, %swift.protocol* %2) // CHECK: [[IS_NULL:%.*]] = icmp eq i8** [[WITNESS]], null // CHECK: br i1 [[IS_NULL]], label %fail, label %cont // CHECK: cont: // CHECK: [[WITNESS:%.*]] = call i8** @swift_conformsToProtocol(%swift.type* %1, %swift.protocol* %3) // CHECK: [[IS_NULL:%.*]] = icmp eq i8** [[WITNESS]], null // CHECK: br i1 [[IS_NULL]], label %fail, label %cont1 // CHECK: cont1: // CHECK: ret { i8*, i8**, i8** } // CHECK: fail: // CHECK: call void @llvm.trap() sil @u_cast_to_class_existential_2 : $@convention(thin) (@owned AnyObject) -> @owned CP & CP2 { entry(%a : $AnyObject): %p = unconditional_checked_cast %a : $AnyObject to CP & CP2 return %p : $CP & CP2 } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %objc_object*, i8**, i8** } @u_cast_to_class_existential_mixed(%objc_object* %0) // CHECK: call %objc_object* @swift_dynamicCastObjCProtocolUnconditional // CHECK: call { i8*, i8**, i8** } @dynamic_cast_existential_2_unconditional(i8* {{%.*}}, %swift.type* {{%.*}}, {{.*}} @"$s5casts2CPMp" {{[^,]*}}, {{.*}} @"$s5casts3CP2Mp" sil @u_cast_to_class_existential_mixed : $@convention(thin) (@owned AnyObject) -> @owned CP & OP & CP2 { entry(%a : $AnyObject): %p = unconditional_checked_cast %a : $AnyObject to CP & OP & CP2 return %p : $CP & OP & CP2 } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %swift.type*, i8**, i8** } @u_cast_to_existential_metatype_mixed(%swift.type* %0) // CHECK: call %swift.type* @swift_dynamicCastTypeToObjCProtocolUnconditional(%swift.type* %0, {{(i32|i64)}} 1, i8** {{%.*}}) // CHECK: [[CAST:%.*]] = call { i8*, i8**, i8** } @dynamic_cast_existential_2_unconditional(i8* {{.*}}, %swift.type* %0, {{.*}} @"$s5casts2CPMp" {{[^,]*}}, {{.*}} @"$s5casts3CP2Mp" // CHECK: [[OBJPTR:%.*]] = extractvalue { i8*, i8**, i8** } [[CAST]], 0 // CHECK: [[OBJ:%.*]] = bitcast i8* [[OBJPTR]] to %swift.type* // CHECK: insertvalue {{.*}} [[OBJ]] sil @u_cast_to_existential_metatype_mixed : $@convention(thin) (@owned @thick Any.Type) -> @owned @thick (CP & OP & CP2).Type { entry(%a : $@thick Any.Type): %p = unconditional_checked_cast %a : $@thick Any.Type to @thick (CP & OP & CP2).Type return %p : $@thick (CP & OP & CP2).Type } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %objc_object*, i8** } @c_cast_to_class_existential(%objc_object* %0) // CHECK: call { i8*, i8** } @dynamic_cast_existential_1_conditional(i8* {{.*}}, %swift.type* %.Type, {{.*}} @"$s5casts2CPMp" // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} private { i8*, i8** } @dynamic_cast_existential_1_conditional(i8* %0, %swift.type* %1, %swift.protocol* %2) // CHECK: [[WITNESS:%.*]] = call i8** @swift_conformsToProtocol(%swift.type* %1, %swift.protocol* %2) // CHECK: [[IS_NULL:%.*]] = icmp eq i8** [[WITNESS]], null // CHECK: br i1 [[IS_NULL]], label %fail, label %cont // CHECK: cont: // CHECK: ret { i8*, i8** } // CHECK: fail: // CHECK: ret { i8*, i8** } zeroinitializer sil @c_cast_to_class_existential : $@convention(thin) (@owned AnyObject) -> @owned CP { entry(%a : $AnyObject): checked_cast_br %a : $AnyObject to CP, yea, nay yea(%p : $CP): return %p : $CP nay: unreachable } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %swift.type*, i8** } @c_cast_to_existential_metatype(%swift.type* %0) {{.*}} { // CHECK: call { i8*, i8** } @dynamic_cast_existential_1_conditional(i8* %1, %swift.type* %0, {{.*}} @"$s5casts2CPMp" sil @c_cast_to_existential_metatype : $@convention(thin) (@owned @thick Any.Type) -> @owned @thick CP.Type { entry(%a : $@thick Any.Type): checked_cast_br %a : $@thick Any.Type to @thick CP.Type, yea, nay yea(%p : $@thick CP.Type): return %p : $@thick CP.Type nay: unreachable } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %objc_object*, i8**, i8** } @c_cast_to_class_existential_2(%objc_object* %0) // CHECK: call { i8*, i8**, i8** } @dynamic_cast_existential_2_conditional(i8* {{%.*}}, %swift.type* {{%.*}}, {{.*}} @"$s5casts2CPMp" {{[^,]*}}, {{.*}} @"$s5casts3CP2Mp" // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} private { i8*, i8**, i8** } @dynamic_cast_existential_2_conditional(i8* %0, %swift.type* %1, %swift.protocol* %2, %swift.protocol* %3) // CHECK: [[WITNESS:%.*]] = call i8** @swift_conformsToProtocol(%swift.type* %1, %swift.protocol* %2) // CHECK: [[IS_NULL:%.*]] = icmp eq i8** [[WITNESS]], null // CHECK: br i1 [[IS_NULL]], label %fail, label %cont // CHECK: cont: // CHECK: [[WITNESS:%.*]] = call i8** @swift_conformsToProtocol(%swift.type* %1, %swift.protocol* %3) // CHECK: [[IS_NULL:%.*]] = icmp eq i8** [[WITNESS]], null // CHECK: br i1 [[IS_NULL]], label %fail, label %cont1 // CHECK: cont1: // CHECK: ret { i8*, i8**, i8** } // CHECK: fail: // CHECK: ret { i8*, i8**, i8** } zeroinitializer sil @c_cast_to_class_existential_2 : $@convention(thin) (@owned AnyObject) -> @owned CP & CP2 { entry(%a : $AnyObject): checked_cast_br %a : $AnyObject to CP & CP2, yea, nay yea(%p : $CP & CP2): return %p : $CP & CP2 nay: unreachable } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %objc_object*, i8**, i8** } @c_cast_to_class_existential_mixed(%objc_object* %0) // CHECK: [[CAST:%.*]] = call %objc_object* @swift_dynamicCastObjCProtocolConditional // CHECK: [[IS_NULL:%.*]] = icmp eq %objc_object* [[CAST]], null // CHECK: br i1 [[IS_NULL]], label %cont, label %success // CHECK: success: // CHECK: call { i8*, i8**, i8** } @dynamic_cast_existential_2_conditional(i8* {{%.*}}, %swift.type* {{%.*}}, {{.*}} @"$s5casts2CPMp" {{[^,]*}}, {{.*}} @"$s5casts3CP2Mp" // CHECK: br label %cont // CHECK: cont: // CHECK: phi %objc_object* [ [[CAST:%.*]], %success ], [ null, %entry ] sil @c_cast_to_class_existential_mixed : $@convention(thin) (@owned AnyObject) -> @owned CP & OP & CP2 { entry(%a : $AnyObject): checked_cast_br %a : $AnyObject to CP & OP & CP2, yea, nay yea(%p : $CP & OP & CP2): return %p : $CP & OP & CP2 nay: unreachable } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %swift.type*, i8**, i8** } @c_cast_to_existential_metatype_mixed(%swift.type* %0) // CHECK: [[OBJC_CAST:%.*]] = call %swift.type* @swift_dynamicCastTypeToObjCProtocolConditional(%swift.type* %0, {{(i32|i64)}} 1, i8** {{%.*}}) // CHECK: [[IS_NULL:%.*]] = icmp eq %swift.type* [[OBJC_CAST]], null // CHECK: br i1 [[IS_NULL]], label %cont, label %success // CHECK: success: // CHECK: call { i8*, i8**, i8** } @dynamic_cast_existential_2_conditional(i8* {{.*}}, %swift.type* %0, {{.*}} @"$s5casts2CPMp" {{[^,]*}}, {{.*}} @"$s5casts3CP2Mp" sil @c_cast_to_existential_metatype_mixed : $@convention(thin) (@owned @thick Any.Type) -> @owned @thick (CP & OP & CP2).Type { entry(%a : $@thick Any.Type): checked_cast_br %a : $@thick Any.Type to @thick (CP & OP & CP2).Type, yea, nay yea(%p : $@thick (CP & OP & CP2).Type): return %p : $@thick (CP & OP & CP2).Type nay: unreachable } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %objc_object* @checked_upcast(%T5casts1AC* %0) {{.*}} { // -- Don't need to check conformance of an object to AnyObject. // CHECK-NOT: call %objc_object* @swift_dynamicCastObjCProtocolConditional // CHECK: phi %objc_object* sil @checked_upcast : $@convention(thin) (@owned A) -> @owned AnyObject { entry(%a : $A): checked_cast_br %a : $A to AnyObject, yea, nay yea(%o : $AnyObject): return %o : $AnyObject nay: unreachable } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %T5casts1AC* @checked_downcast_optional({{(i32|i64)}} %0) {{.*}} { // CHECK: [[T0:%.*]] = inttoptr {{(i32|i64)}} %0 to %T5casts1AC* // CHECK: [[OBJ_PTR:%.*]] = bitcast %T5casts1AC* [[T0]] to i8* // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s5casts1ACMa"([[INT]] 0) // CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK: [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to i8* // CHECK: [[RESULT_PTR:%.*]] = call i8* @swift_dynamicCastClass(i8* [[OBJ_PTR]], i8* [[METADATA_PTR]]) // CHECK: [[RESULT:%.*]] = bitcast i8* [[RESULT_PTR]] to %T5casts1AC* // CHECK: [[COND:%.*]] = icmp ne %T5casts1AC* [[RESULT]], null // CHECK: br i1 [[COND]] sil @checked_downcast_optional : $@convention(thin) (Optional) -> @owned A { entry(%a : $Optional): checked_cast_br %a : $Optional to A, yea, nay yea(%aa : $A): return %aa : $A nay: unreachable } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @checked_downcast_optional_metatype({{(i32|i64)}} %0) {{.*}} { // CHECK: [[VALUE:%.*]] = inttoptr {{(i32|i64)}} %0 to %swift.type* // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s5casts1BCMa"([[INT]] 0) // CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK: [[RESULT:%.*]] = call %swift.type* @swift_dynamicCastMetatype(%swift.type* [[VALUE]], %swift.type* [[METADATA]]) // CHECK: [[COND:%.*]] = icmp ne %swift.type* [[RESULT]], null // CHECK: br i1 [[COND]] sil @checked_downcast_optional_metatype : $@convention(thin) (Optional<@thick A.Type>) -> @thick B.Type { entry(%a : $Optional<@thick A.Type>): checked_cast_br %a : $Optional<@thick A.Type> to @thick B.Type, yea, nay yea(%b : $@thick B.Type): return %b : $@thick B.Type nay: unreachable } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @checked_downcast_optional_exmetatype({{(i32 %0, i32 %1|i64 %0, i64 %1)}}) {{.*}} { // CHECK: [[VALUE:%.*]] = inttoptr {{(i32|i64)}} %0 to %swift.type* // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s5casts1BCMa"([[INT]] 0) // CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 // CHECK: [[RESULT:%.*]] = call %swift.type* @swift_dynamicCastMetatype(%swift.type* [[VALUE]], %swift.type* [[METADATA]]) // CHECK: [[COND:%.*]] = icmp ne %swift.type* [[RESULT]], null // CHECK: br i1 [[COND]] sil @checked_downcast_optional_exmetatype : $@convention(thin) (Optional<@thick CP.Type>) -> @thick B.Type { entry(%a : $Optional<@thick CP.Type>): checked_cast_br %a : $Optional<@thick CP.Type> to @thick B.Type, yea, nay yea(%b : $@thick B.Type): return %b : $@thick B.Type nay: unreachable } // CHECK: define {{(dllexport )?}}{{(protected )?}}swiftcc {{.*}} @checked_downcast_optional_class_to_ex([[INT]] %0) // CHECK: entry: // CHECK: [[V1:%.*]] = inttoptr [[INT]] %0 to %T5casts1AC* // CHECK: [[V2:%.*]] = icmp ne %T5casts1AC* [[V1]], null // CHECK: br i1 [[V2]], label %[[LBL:.*]], label // CHECK: [[LBL]]: // CHECK: [[V4:%.*]] = getelementptr inbounds %T5casts1AC, %T5casts1AC* [[V1]] // CHECK: load %swift.type*, %swift.type** [[V4]] sil @checked_downcast_optional_class_to_ex : $@convention(thin) (@guaranteed Optional) -> @owned Optional { bb0(%0 : $Optional): checked_cast_br %0 : $Optional to CP, bb1, bb2 bb1(%3 : $CP): %4 = enum $Optional, #Optional.some!enumelt, %3 : $CP retain_value %0 : $Optional br bb3(%4 : $Optional) bb2: %7 = enum $Optional, #Optional.none!enumelt br bb3(%7 : $Optional) bb3(%9 : $Optional): return %9 : $Optional } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checked_metatype_to_object_casts sil @checked_metatype_to_object_casts : $@convention(thin) (@thick Any.Type) -> () { entry(%e : $@thick Any.Type): %a = metatype $@thin NotClass.Type // CHECK: br i1 false checked_cast_br %a : $@thin NotClass.Type to AnyObject, a_yea, a_nay a_yea(%1 : $AnyObject): %b = metatype $@thick A.Type // CHECK: bitcast %swift.type* {{%.*}} to %objc_object* checked_cast_br %b : $@thick A.Type to AnyObject, b_yea, b_nay b_yea(%2 : $AnyObject): %c = metatype $@objc_metatype A.Type // CHECK: bitcast %objc_class* {{%.*}} to %objc_object* checked_cast_br %c : $@objc_metatype A.Type to AnyObject, c_yea, c_nay c_yea(%3 : $AnyObject): %d = metatype $@thick T.Type // CHECK: call %objc_object* @swift_dynamicCastMetatypeToObjectConditional(%swift.type* %T) checked_cast_br %d : $@thick T.Type to AnyObject, d_yea, d_nay d_yea(%4 : $AnyObject): // CHECK: call %objc_object* @swift_dynamicCastMetatypeToObjectConditional(%swift.type* %0) checked_cast_br %e : $@thick Any.Type to AnyObject, e_yea, e_nay e_yea(%5 : $AnyObject): return undef : $() a_nay: unreachable b_nay: unreachable c_nay: unreachable d_nay: unreachable e_nay: unreachable } @objc class OA {} sil_vtable OA {} sil hidden @$s5casts2OACACycfcTo : $@convention(thin) (OA) -> OA { entry(%x : $OA): return %x : $OA } @objc class OB {} sil_vtable OB {} sil hidden_external @$s5casts2OBCACycfcTo : $@convention(thin) (OB) -> OB { entry(%x : $OB): return %x : $OB } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %T5casts1BC* @checked_object_to_object_casts(%T5casts1AC* %0) // CHECK: @swift_dynamicCastClassUnconditional sil @checked_object_to_object_casts : $@convention(thin) (A) -> B { entry(%a : $A): %b = unconditional_checked_cast %a : $A to B return %b : $B } // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %T5casts2OBC* @checked_objc_object_to_object_casts(%T5casts2OAC* %0) // CHECK: @swift_dynamicCastClassUnconditional sil @checked_objc_object_to_object_casts : $@convention(thin) (OA) -> OB { entry(%a : $OA): %b = unconditional_checked_cast %a : $OA to OB return %b : $OB } protocol P {} protocol PAnyObject: AnyObject {} class C {} sil_vtable C {} // CHECK-LABEL: define{{.*}} @cast_protocol_composition_with_anyobject // CHECK: [[C:%.*]] = call swiftcc %swift.metadata_response @"$s5casts1CCMa" // CHECK: [[C_META:%.*]] = extractvalue %swift.metadata_response [[C]], 0 // CHECK: call { i8*, i8** } @dynamic_cast_existential_1_superclass_conditional({{.*}}, %swift.type* [[C_META]], %swift.protocol* {{.*}}@"$s5casts1PMp" sil @cast_protocol_composition_with_anyobject : $@convention(thin) (@owned P & AnyObject ) -> @owned Optional { bb0(%0: $P & AnyObject): checked_cast_br %0 : $P & AnyObject to C & P, bb1, bb2 bb1(%2 : $C & P): %3 = enum $Optional, #Optional.some!enumelt, %2 : $C & P br bb3(%3 : $Optional) bb2: strong_release %0 : $P & AnyObject %6 = enum $Optional, #Optional.none!enumelt br bb3(%6 : $Optional) bb3(%11 : $Optional): return %11 : $Optional } // CHECK-LABEL: define{{.*}} @cast_protocol_with_anyobject // CHECK: [[C:%.*]] = call swiftcc %swift.metadata_response @"$s5casts1CCMa" // CHECK: [[C_META:%.*]] = extractvalue %swift.metadata_response [[C]], 0 // CHECK: call { i8*, i8** } @dynamic_cast_existential_1_superclass_conditional({{.*}}, %swift.type* [[C_META]], %swift.protocol* {{.*}}@"$s5casts10PAnyObjectMp" sil @cast_protocol_with_anyobject : $@convention(thin) (@owned PAnyObject ) -> @owned Optional { bb0(%0: $PAnyObject): checked_cast_br %0 : $PAnyObject to C & PAnyObject, bb1, bb2 bb1(%2 : $C & PAnyObject): %3 = enum $Optional, #Optional.some!enumelt, %2 : $C & PAnyObject br bb3(%3 : $Optional) bb2: strong_release %0 : $PAnyObject %6 = enum $Optional, #Optional.none!enumelt br bb3(%6 : $Optional) bb3(%11 : $Optional): return %11 : $Optional }