mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
several more places to use getOrCreateHelperFunction. This means that several of these places are now emitting shared functions rather than private ones, which I've verified is okay. There are some other places where privacy is still unfortunately necessary. I've also fixed the name of the store-extra-inhabitants helper function to say "store" instead of "get", which is longstanding (but harmless because it's private). Fixes rdar://66707994.
209 lines
11 KiB
Plaintext
209 lines
11 KiB
Plaintext
// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK-%target-runtime --check-prefix=CHECK -DINT=i%target-ptrsize
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
class C {}
|
|
class G<T> {}
|
|
|
|
protocol P {}
|
|
|
|
class D : C, P {}
|
|
class E<T> : G<T>, P {}
|
|
|
|
protocol R {}
|
|
|
|
// Make sure we use native reference counting when the existential has a Swift
|
|
// class bound.
|
|
|
|
// CHECK-objc-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkRefcounting(%T21subclass_existentials1CC* %0, i8** %1, %objc_object* %2, i8** %3)
|
|
// CHECK-native-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkRefcounting(%T21subclass_existentials1CC* %0, i8** %1, %swift.refcounted* %2, i8** %3)
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-objc-NEXT: call void @swift_unknownObjectRelease(%objc_object* %2)
|
|
// CHECK-native-NEXT: call void @swift_release(%swift.refcounted* %2)
|
|
// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T21subclass_existentials1CC*)*)(%T21subclass_existentials1CC* %0)
|
|
// CHECK-NEXT: ret void
|
|
|
|
sil [ossa] @checkRefcounting : $@convention(thin) (@owned C & P, @owned AnyObject & P) -> () {
|
|
bb0(%0 : @owned $C & P, %1 : @owned $AnyObject & P):
|
|
destroy_value %1 : $AnyObject & P
|
|
destroy_value %0 : $C & P
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// Make sure we call the runtime function with the right arguments when we
|
|
// instantiate metadata for a subclass existential.
|
|
|
|
sil @takesMetadata : $@convention(thin) <T> (@thick T.Type) -> ()
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkMetadata()
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[TYPE:%.*]] = call {{.*}}@"$s21subclass_existentials1P_AA1CCXcMD"
|
|
// CHECK-NEXT: call swiftcc void @takesMetadata(%swift.type* [[TYPE]], %swift.type* [[TYPE]])
|
|
// CHECK-NEXT: ret void
|
|
|
|
sil [ossa] @checkMetadata : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @takesMetadata : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> ()
|
|
%1 = metatype $@thin (C & P).Protocol
|
|
%2 = metatype $@thick (C & P).Protocol
|
|
%3 = apply %0<(C & P)>(%2) : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> ()
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %T21subclass_existentials1CC*, i8** } @eraseToExistential(%T21subclass_existentials1DC* %0)
|
|
// CHECK: [[INSTANCE:%.*]] = bitcast %T21subclass_existentials1DC* %0 to %T21subclass_existentials1CC*
|
|
// CHECK-NEXT: [[RESULT1:%.*]] = insertvalue { %T21subclass_existentials1CC*, i8** } undef, %T21subclass_existentials1CC* [[INSTANCE]], 0
|
|
// CHECK-NEXT: [[RESULT2:%.*]] = insertvalue { %T21subclass_existentials1CC*, i8** } [[RESULT1]], i8** @"$s21subclass_existentials1DCAA1PAAWP", 1
|
|
// CHECK-NEXT: ret { %T21subclass_existentials1CC*, i8** } [[RESULT2]]
|
|
sil @eraseToExistential : $@convention(thin) (@owned D) -> @owned C & P {
|
|
bb0(%0 : $D):
|
|
%2 = init_existential_ref %0 : $D : $D, $C & P
|
|
return %2 : $C & P
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { %T21subclass_existentials1GC*, i8** } @eraseToExistentialWithGeneric(%T21subclass_existentials1EC* %0)
|
|
// CHECK: [[INSTANCE:%.*]] = bitcast %T21subclass_existentials1EC* %0 to %T21subclass_existentials1GC*
|
|
// CHECK-NEXT: [[RESULT1:%.*]] = insertvalue { %T21subclass_existentials1GC*, i8** } undef, %T21subclass_existentials1GC* [[INSTANCE]], 0
|
|
// CHECK-NEXT: [[RESULT2:%.*]] = insertvalue { %T21subclass_existentials1GC*, i8** } [[RESULT1]], i8** @"$s21subclass_existentials1ECyxGAA1PAAWP", 1
|
|
// CHECK-NEXT: ret { %T21subclass_existentials1GC*, i8** } [[RESULT2]]
|
|
sil @eraseToExistentialWithGeneric : $@convention(thin) <τ_0_0> (@owned E<τ_0_0>) -> @owned G<τ_0_0> & P {
|
|
bb0(%0 : $E<τ_0_0>):
|
|
%2 = init_existential_ref %0 : $E<τ_0_0> : $E<τ_0_0>, $G<τ_0_0> & P
|
|
return %2 : $G<τ_0_0> & P
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkExistentialDowncast(%T21subclass_existentials1CC* %0, %T21subclass_existentials1CC* %1, i8** %2)
|
|
sil [ossa] @checkExistentialDowncast : $@convention(thin) (@owned C, @owned C & P) -> () {
|
|
bb0(%0 : @owned $C, %1 : @owned $C & P):
|
|
|
|
// CHECK: [[METATYPE_PTR:%.*]] = bitcast %T21subclass_existentials1CC* %0 to %swift.type**
|
|
// CHECK-NEXT: [[METATYPE:%.*]] = load %swift.type*, %swift.type** [[METATYPE_PTR]], align {{4|8}}
|
|
// CHECK-NEXT: [[VALUE:%.*]] = bitcast %T21subclass_existentials1CC* %0 to i8*
|
|
// CHECK-NEXT: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s21subclass_existentials1DCMa"([[INT]] 0)
|
|
// CHECK-NEXT: [[SUPERCLASS:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call { i8*, i8** } @dynamic_cast_existential_1_superclass_unconditional(i8* [[VALUE]], %swift.type* [[METATYPE]], %swift.type* [[SUPERCLASS]], {{.*}} @"$s21subclass_existentials1RMp"
|
|
// CHECK-NEXT: [[VALUE_ADDR:%.*]] = extractvalue { i8*, i8** } [[RESULT]], 0
|
|
// CHECK-NEXT: [[VALUE:%.*]] = bitcast i8* [[VALUE_ADDR]] to %T21subclass_existentials1DC*
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = extractvalue { i8*, i8** } [[RESULT]], 1
|
|
%2 = unconditional_checked_cast %0 : $C to D & R
|
|
|
|
// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T21subclass_existentials1DC*)*)(%T21subclass_existentials1DC* [[VALUE]])
|
|
destroy_value %2 : $D & R
|
|
|
|
// CHECK-NEXT: [[VALUE:%.*]] = bitcast %T21subclass_existentials1CC* %1 to i8*
|
|
// CHECK-NEXT: [[CLASS_ADDR:%.*]] = bitcast %swift.type* [[SUPERCLASS]] to i8*
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call i8* @swift_dynamicCastClassUnconditional(i8* [[VALUE]], i8* [[CLASS_ADDR]], {{.*}})
|
|
// CHECK-NEXT: [[VALUE:%.*]] = bitcast i8* [[RESULT]] to %T21subclass_existentials1DC*
|
|
%3 = unconditional_checked_cast %1 : $C & P to D
|
|
|
|
// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T21subclass_existentials1DC*)*)(%T21subclass_existentials1DC* [[VALUE]])
|
|
destroy_value %3 : $D
|
|
|
|
// CHECK-NEXT: ret void
|
|
%result = tuple ()
|
|
return %result : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden { i8*, i8** } @dynamic_cast_existential_1_superclass_unconditional(i8* %0, %swift.type* %1, %swift.type*
|
|
// CHECK: entry:
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call %swift.type* @swift_dynamicCastMetatype(%swift.type* %1, %swift.type* %2)
|
|
// CHECK-NEXT: [[IS_SUBCLASS:%.*]] = icmp ne %swift.type* [[RESULT]], null
|
|
// CHECK-NEXT: br i1 [[IS_SUBCLASS]], label %cont, label %fail
|
|
|
|
// CHECK: cont:
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = call i8** @swift_conformsToProtocol(%swift.type* %1, {{.*}} %3)
|
|
// CHECK-NEXT: [[IS_NOT_CONFORMING:%.*]] = icmp eq i8** [[WTABLE]], null
|
|
// CHECK-NEXT: br i1 [[IS_NOT_CONFORMING]], label %fail, label %cont1
|
|
|
|
// CHECK: cont1:
|
|
// CHECK-NEXT: [[RESULT1:%.*]] = insertvalue { i8*, i8** } undef, i8* %0, 0
|
|
// CHECK-NEXT: [[RESULT2:%.*]] = insertvalue { i8*, i8** } [[RESULT1]], i8** [[WTABLE]], 1
|
|
// CHECK-NEXT: ret { i8*, i8** } [[RESULT2]]
|
|
|
|
// CHECK: fail:
|
|
// CHECK-NEXT: call void @llvm.trap()
|
|
// CHECK-NEXT: unreachable
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkExistentialSameClassDowncast(%T21subclass_existentials1CC* %0)
|
|
sil [ossa] @checkExistentialSameClassDowncast : $@convention(thin) (@owned C) -> () {
|
|
bb0(%0 : @owned $C):
|
|
|
|
// CHECK: [[METATYPE_PTR:%.*]] = bitcast %T21subclass_existentials1CC* %0 to %swift.type**
|
|
// CHECK-NEXT: [[METATYPE:%.*]] = load %swift.type*, %swift.type** [[METATYPE_PTR]], align {{4|8}}
|
|
// CHECK-NEXT: [[VALUE:%.*]] = bitcast %T21subclass_existentials1CC* %0 to i8*
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call { i8*, i8** } @dynamic_cast_existential_1_unconditional(i8* [[VALUE]], %swift.type* [[METATYPE]], {{.*}} @"$s21subclass_existentials1PMp"
|
|
// CHECK-NEXT: [[VALUE_ADDR:%.*]] = extractvalue { i8*, i8** } [[RESULT]], 0
|
|
// CHECK-NEXT: [[VALUE:%.*]] = bitcast i8* [[VALUE_ADDR]] to %T21subclass_existentials1CC*
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = extractvalue { i8*, i8** } [[RESULT]], 1
|
|
%2 = unconditional_checked_cast %0 : $C to C & P
|
|
|
|
// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T21subclass_existentials1CC*)*)(%T21subclass_existentials1CC* [[VALUE]])
|
|
destroy_value %2 : $C & P
|
|
|
|
// CHECK-NEXT: ret void
|
|
%result = tuple ()
|
|
return %result : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden { i8*, i8** } @dynamic_cast_existential_1_unconditional(i8* %0, %swift.type*
|
|
// CHECK: entry:
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = call i8** @swift_conformsToProtocol(%swift.type* %1, {{.*}} %2)
|
|
// CHECK-NEXT: [[IS_NOT_CONFORMING:%.*]] = icmp eq i8** [[WTABLE]], null
|
|
// CHECK-NEXT: br i1 [[IS_NOT_CONFORMING]], label %fail, label %cont
|
|
|
|
// CHECK: cont:
|
|
// CHECK-NEXT: [[RESULT1:%.*]] = insertvalue { i8*, i8** } undef, i8* %0, 0
|
|
// CHECK-NEXT: [[RESULT2:%.*]] = insertvalue { i8*, i8** } [[RESULT1]], i8** [[WTABLE]], 1
|
|
// CHECK-NEXT: ret { i8*, i8** } [[RESULT2]]
|
|
|
|
// CHECK: fail:
|
|
// CHECK-NEXT: call void @llvm.trap()
|
|
// CHECK-NEXT: unreachable
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkExistentialMetatypeDowncast(%swift.type* %0, %swift.type* %1, i8** %2)
|
|
sil @checkExistentialMetatypeDowncast : $@convention(thin) (@owned @thick C.Type, @owned @thick (C & P).Type) -> () {
|
|
bb0(%0 : $@thick C.Type, %1 : $@thick (C & P).Type):
|
|
|
|
// CHECK: [[METATYPE:%.*]] = bitcast %swift.type* %0 to i8*
|
|
// CHECK-NEXT: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s21subclass_existentials1DCMa"([[INT]] 0)
|
|
// CHECK-NEXT: [[SUPERCLASS:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call { i8*, i8** } @dynamic_cast_existential_1_superclass_unconditional(i8* [[METATYPE]], %swift.type* %0, %swift.type* [[SUPERCLASS]], {{.*}} @"$s21subclass_existentials1RMp"
|
|
// CHECK-NEXT: [[VALUE_ADDR:%.*]] = extractvalue { i8*, i8** } [[RESULT]], 0
|
|
// CHECK-NEXT: [[VALUE:%.*]] = bitcast i8* [[VALUE_ADDR]] to %swift.type*
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = extractvalue { i8*, i8** } [[RESULT]], 1
|
|
%2 = unconditional_checked_cast %0 : $@thick C.Type to @thick (D & R).Type
|
|
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call %swift.type* @swift_dynamicCastMetatypeUnconditional(%swift.type* %1, %swift.type* [[SUPERCLASS]], {{.*}})
|
|
%3 = unconditional_checked_cast %1 : $@thick (C & P).Type to @thick D.Type
|
|
|
|
// CHECK-NEXT: ret void
|
|
%result = tuple ()
|
|
return %result : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkExistentialSameClassMetatypeDowncast(%swift.type* %0)
|
|
sil @checkExistentialSameClassMetatypeDowncast : $@convention(thin) (@owned @thick C.Type) -> () {
|
|
bb0(%0 : $@thick C.Type):
|
|
|
|
// CHECK: [[METATYPE:%.*]] = bitcast %swift.type* %0 to i8*
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call { i8*, i8** } @dynamic_cast_existential_1_unconditional(i8* [[METATYPE]], %swift.type* %0, {{.*}} @"$s21subclass_existentials1PMp"
|
|
// CHECK-NEXT: [[VALUE_ADDR:%.*]] = extractvalue { i8*, i8** } [[RESULT]], 0
|
|
// CHECK-NEXT: [[VALUE:%.*]] = bitcast i8* [[VALUE_ADDR]] to %swift.type*
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = extractvalue { i8*, i8** } [[RESULT]], 1
|
|
%2 = unconditional_checked_cast %0 : $@thick C.Type to @thick (C & P).Type
|
|
|
|
// CHECK-NEXT: ret void
|
|
%result = tuple ()
|
|
return %result : $()
|
|
}
|
|
|
|
sil_vtable C {}
|
|
sil_vtable D {}
|
|
sil_vtable G {}
|
|
sil_vtable E {}
|