mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
194 lines
8.5 KiB
Plaintext
194 lines
8.5 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(ptr %0, ptr %1, ptr %2, ptr %3)
|
|
// CHECK-native-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkRefcounting(ptr %0, ptr %1, ptr %2, ptr %3)
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-objc-NEXT: call void @swift_unknownObjectRelease(ptr %2)
|
|
// CHECK-native-NEXT: call void @swift_release(ptr %2)
|
|
// CHECK-NEXT: call void @swift_release(ptr %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(ptr [[TYPE]], ptr [[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 { ptr, ptr } @eraseToExistential(ptr %0)
|
|
// CHECK: [[RESULT1:%.*]] = insertvalue { ptr, ptr } undef, ptr %0, 0
|
|
// CHECK-NEXT: [[RESULT2:%.*]] = insertvalue { ptr, ptr } [[RESULT1]], ptr @"$s21subclass_existentials1DCAA1PAAWP", 1
|
|
// CHECK-NEXT: ret { ptr, ptr } [[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 { ptr, ptr } @eraseToExistentialWithGeneric(ptr %0)
|
|
// CHECK: [[RESULT1:%.*]] = insertvalue { ptr, ptr } undef, ptr %0, 0
|
|
// CHECK-NEXT: [[RESULT2:%.*]] = insertvalue { ptr, ptr } [[RESULT1]], ptr @"$s21subclass_existentials1ECyxGAA1PAAWP", 1
|
|
// CHECK-NEXT: ret { ptr, ptr } [[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(ptr %0, ptr %1, ptr %2)
|
|
sil [ossa] @checkExistentialDowncast : $@convention(thin) (@owned C, @owned C & P) -> () {
|
|
bb0(%0 : @owned $C, %1 : @owned $C & P):
|
|
|
|
// CHECK: [[METATYPE:%.*]] = load ptr, ptr %0, align {{4|8}}
|
|
// 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 { ptr, ptr } @dynamic_cast_existential_1_superclass_unconditional(ptr %0, ptr [[METATYPE]], ptr [[SUPERCLASS]], {{.*}} @"$s21subclass_existentials1RMp"
|
|
// CHECK-NEXT: [[VALUE_ADDR:%.*]] = extractvalue { ptr, ptr } [[RESULT]], 0
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = extractvalue { ptr, ptr } [[RESULT]], 1
|
|
%2 = unconditional_checked_cast %0 : $C to D & R
|
|
|
|
// CHECK-NEXT: call void @swift_release(ptr [[VALUE_ADDR]])
|
|
destroy_value %2 : $D & R
|
|
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call ptr @swift_dynamicCastClassUnconditional(ptr %1, ptr [[SUPERCLASS]], {{.*}})
|
|
%3 = unconditional_checked_cast %1 : $C & P to D
|
|
|
|
// CHECK-NEXT: call void @swift_release(ptr [[RESULT]])
|
|
destroy_value %3 : $D
|
|
|
|
// CHECK-NEXT: ret void
|
|
%result = tuple ()
|
|
return %result : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden { ptr, ptr } @dynamic_cast_existential_1_superclass_unconditional(ptr %0, ptr %1, ptr
|
|
// CHECK: entry:
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call ptr @swift_dynamicCastMetatype(ptr %1, ptr %2)
|
|
// CHECK-NEXT: [[IS_SUBCLASS:%.*]] = icmp ne ptr [[RESULT]], null
|
|
// CHECK-NEXT: br i1 [[IS_SUBCLASS]], label %cont, label %fail
|
|
|
|
// CHECK: cont:
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = call ptr @swift_conformsToProtocol{{(2)?}}(ptr %1, {{.*}} %3)
|
|
// CHECK-NEXT: [[IS_NOT_CONFORMING:%.*]] = icmp eq ptr [[WTABLE]], null
|
|
// CHECK-NEXT: br i1 [[IS_NOT_CONFORMING]], label %fail, label %cont1
|
|
|
|
// CHECK: cont1:
|
|
// CHECK-NEXT: [[RESULT1:%.*]] = insertvalue { ptr, ptr } undef, ptr %0, 0
|
|
// CHECK-NEXT: [[RESULT2:%.*]] = insertvalue { ptr, ptr } [[RESULT1]], ptr [[WTABLE]], 1
|
|
// CHECK-NEXT: ret { ptr, ptr } [[RESULT2]]
|
|
|
|
// CHECK: fail:
|
|
// CHECK-NEXT: call void @llvm.trap()
|
|
// CHECK-NEXT: unreachable
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkExistentialSameClassDowncast(ptr %0)
|
|
sil [ossa] @checkExistentialSameClassDowncast : $@convention(thin) (@owned C) -> () {
|
|
bb0(%0 : @owned $C):
|
|
|
|
// CHECK: [[METATYPE:%.*]] = load ptr, ptr %0, align {{4|8}}
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call { ptr, ptr } @dynamic_cast_existential_1_unconditional(ptr %0, ptr [[METATYPE]], {{.*}} @"$s21subclass_existentials1PMp"
|
|
// CHECK-NEXT: [[VALUE_ADDR:%.*]] = extractvalue { ptr, ptr } [[RESULT]], 0
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = extractvalue { ptr, ptr } [[RESULT]], 1
|
|
%2 = unconditional_checked_cast %0 : $C to C & P
|
|
|
|
// CHECK-NEXT: call void @swift_release(ptr [[VALUE_ADDR]])
|
|
destroy_value %2 : $C & P
|
|
|
|
// CHECK-NEXT: ret void
|
|
%result = tuple ()
|
|
return %result : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden { ptr, ptr } @dynamic_cast_existential_1_unconditional(ptr %0, ptr
|
|
// CHECK: entry:
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = call ptr @swift_conformsToProtocol{{(2)?}}(ptr %1, {{.*}} %2)
|
|
// CHECK-NEXT: [[IS_NOT_CONFORMING:%.*]] = icmp eq ptr [[WTABLE]], null
|
|
// CHECK-NEXT: br i1 [[IS_NOT_CONFORMING]], label %fail, label %cont
|
|
|
|
// CHECK: cont:
|
|
// CHECK-NEXT: [[RESULT1:%.*]] = insertvalue { ptr, ptr } undef, ptr %0, 0
|
|
// CHECK-NEXT: [[RESULT2:%.*]] = insertvalue { ptr, ptr } [[RESULT1]], ptr [[WTABLE]], 1
|
|
// CHECK-NEXT: ret { ptr, ptr } [[RESULT2]]
|
|
|
|
// CHECK: fail:
|
|
// CHECK-NEXT: call void @llvm.trap()
|
|
// CHECK-NEXT: unreachable
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @checkExistentialMetatypeDowncast(ptr %0, ptr %1, ptr %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: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s21subclass_existentials1DCMa"([[INT]] 0)
|
|
// CHECK-NEXT: [[SUPERCLASS:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call { ptr, ptr } @dynamic_cast_existential_1_superclass_unconditional(ptr %0, ptr %0, ptr [[SUPERCLASS]], {{.*}} @"$s21subclass_existentials1RMp"
|
|
// CHECK-NEXT: [[VALUE_ADDR:%.*]] = extractvalue { ptr, ptr } [[RESULT]], 0
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = extractvalue { ptr, ptr } [[RESULT]], 1
|
|
%2 = unconditional_checked_cast %0 : $@thick C.Type to @thick (D & R).Type
|
|
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call ptr @swift_dynamicCastMetatypeUnconditional(ptr %1, ptr [[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(ptr %0)
|
|
sil @checkExistentialSameClassMetatypeDowncast : $@convention(thin) (@owned @thick C.Type) -> () {
|
|
bb0(%0 : $@thick C.Type):
|
|
|
|
// CHECK: [[RESULT:%.*]] = call { ptr, ptr } @dynamic_cast_existential_1_unconditional(ptr %0, ptr %0, {{.*}} @"$s21subclass_existentials1PMp"
|
|
// CHECK-NEXT: [[VALUE_ADDR:%.*]] = extractvalue { ptr, ptr } [[RESULT]], 0
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = extractvalue { ptr, ptr } [[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 {}
|