mirror of
https://github.com/apple/swift.git
synced 2026-06-27 12:25:55 +02:00
e223f1fc9b
* Remove RegisterPreservingCC. It was unused. * Remove DefaultCC from the runtime. The distinction between C_CC and DefaultCC was unused and inconsistently applied. Separate C_CC and DefaultCC are still present in the compiler. * Remove function pointer indirection from runtime functions except those that are used by Instruments. The remaining Instruments interface is expected to change later due to function pointer liability. * Remove swift_rt_ wrappers. Function pointers are an ABI liability that we don't want, and there are better ways to get nonlazy binding if we need it. The fully custom wrappers were only needed for RegisterPreservingCC and for optimizing the Instruments function pointers.
217 lines
11 KiB
Plaintext
217 lines
11 KiB
Plaintext
// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK-%target-runtime --check-prefix=CHECK
|
|
|
|
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{{( protected)?}} swiftcc void @checkRefcounting(%T21subclass_existentials1CC*, i8**, %objc_object*, i8**)
|
|
// CHECK-native-LABEL: define{{( protected)?}} swiftcc void @checkRefcounting(%T21subclass_existentials1CC*, i8**, %swift.refcounted*, i8**)
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-objc-NEXT: call void @swift_unknownRelease(%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 @checkRefcounting : $@convention(thin) (@owned C & P, @owned AnyObject & P) -> () {
|
|
bb0(%0 : $C & P, %1 : $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{{( protected)?}} swiftcc void @checkMetadata()
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: %0 = call %swift.type* @"$S21subclass_existentials1P_AA1CCXcMa"()
|
|
// CHECK-NEXT: call swiftcc void @takesMetadata(%swift.type* %0, %swift.type* %0)
|
|
// CHECK-NEXT: ret void
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden %swift.type* @"$S21subclass_existentials1P_AA1CCXcMa"()
|
|
// CHECK: entry:
|
|
// CHECK-NEXT: [[PROTOCOL_ARRAY:%.*]] = alloca [1 x %swift.protocol*]
|
|
// CHECK: cacheIsNull:
|
|
// CHECK: [[PROTOCOLS:%.*]] = bitcast [1 x %swift.protocol*]* [[PROTOCOL_ARRAY]] to %swift.protocol**
|
|
// CHECK-NEXT: [[PROTOCOL:%.*]] = getelementptr inbounds %swift.protocol*, %swift.protocol** [[PROTOCOLS]], i32 0
|
|
// CHECK-NEXT: store %swift.protocol* @"$S21subclass_existentials1PMp", %swift.protocol** [[PROTOCOL]]
|
|
// CHECK-NEXT: [[SUPERCLASS:%.*]] = call %swift.type* @"$S21subclass_existentials1CCMa"()
|
|
// CHECK-NEXT: [[METATYPE:%.*]] = call %swift.type* @swift_getExistentialTypeMetadata(i1 false, %swift.type* [[SUPERCLASS]], {{i32|i64}} 1, %swift.protocol** [[PROTOCOLS]])
|
|
// CHECK: ret
|
|
|
|
sil @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{{( protected)?}} swiftcc { %T21subclass_existentials1CC*, i8** } @eraseToExistential(%T21subclass_existentials1DC*)
|
|
// 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{{( protected)?}} swiftcc { %T21subclass_existentials1GC*, i8** } @eraseToExistentialWithGeneric(%T21subclass_existentials1EC*)
|
|
// 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{{( protected)?}} swiftcc void @checkExistentialDowncast(%T21subclass_existentials1CC*, %T21subclass_existentials1CC*, i8**)
|
|
sil @checkExistentialDowncast : $@convention(thin) (@owned C, @owned C & P) -> () {
|
|
bb0(%0 : $C, %1 : $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: [[SUPERCLASS:%.*]] = call %swift.type* @"$S21subclass_existentials1DCMa"()
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call { i8*, i8** } @dynamic_cast_existential_1_superclass_unconditional(i8* [[VALUE]], %swift.type* [[METATYPE]], %swift.type* [[SUPERCLASS]], %swift.protocol* @"$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 private { i8*, i8** } @dynamic_cast_existential_1_superclass_unconditional(i8*, %swift.type*, %swift.type*, %swift.protocol*)
|
|
// 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, %swift.protocol* %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{{( protected)?}} swiftcc void @checkExistentialSameClassDowncast(%T21subclass_existentials1CC*)
|
|
sil @checkExistentialSameClassDowncast : $@convention(thin) (@owned C) -> () {
|
|
bb0(%0 : $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]], %swift.protocol* @"$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 private { i8*, i8** } @dynamic_cast_existential_1_unconditional(i8*, %swift.type*, %swift.protocol*)
|
|
// CHECK: entry:
|
|
// CHECK-NEXT: [[WTABLE:%.*]] = call i8** @swift_conformsToProtocol(%swift.type* %1, %swift.protocol* %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{{( protected)?}} swiftcc void @checkExistentialMetatypeDowncast(%swift.type*, %swift.type*, i8**)
|
|
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: [[SUPERCLASS:%.*]] = call %swift.type* @"$S21subclass_existentials1DCMa"()
|
|
// CHECK-NEXT: [[RESULT:%.*]] = call { i8*, i8** } @dynamic_cast_existential_1_superclass_unconditional(i8* [[METATYPE]], %swift.type* %0, %swift.type* [[SUPERCLASS]], %swift.protocol* @"$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{{( protected)?}} swiftcc void @checkExistentialSameClassMetatypeDowncast(%swift.type*)
|
|
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, %swift.protocol* @"$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 {} |