Files
swift-mirror/test/IRGen/subclass_existentials.sil
John McCall 03d94b44a6 Add default IR attributes to helper functions and convert
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.
2020-08-08 16:57:02 -04:00

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 {}