Files
swift-mirror/test/IRGen/subclass_existentials.sil
Doug Gregor 55b8698613 [Mangling] Mangle generic signature of a conformance relative to the nominal type.
Conformance manglings, which are used for witness tables and related witness
thunks, mangle the generic signature of the conformance. Since conformances
also describe the conforming type, mangle the conformances's generic signature
relative to the conforming type's generic signature.

In practice, this means that we don't mangle any part of the generic signature
into a conformance mangling now, so we see a decent win: 2.3% smaller
trie and 6.4% smaller strings section in the standard library binary.
When conditional conformances land, we'll see some generic signatures
mangling again (for the additional requirements of the constrained
extension).
2017-10-12 10:15:17 -07:00

217 lines
12 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_rt_swift_release(%swift.refcounted* %2)
// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_rt_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* @_T021subclass_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* @_T021subclass_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* @_T021subclass_existentials1PMp, %swift.protocol** [[PROTOCOL]]
// CHECK-NEXT: [[SUPERCLASS:%.*]] = call %swift.type* @_T021subclass_existentials1CCMa()
// CHECK-NEXT: [[METATYPE:%.*]] = call %swift.type* @swift_rt_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** @_T021subclass_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** @_T021subclass_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* @_T021subclass_existentials1DCMa()
// CHECK-NEXT: [[RESULT:%.*]] = call { i8*, i8** } @dynamic_cast_existential_1_superclass_unconditional(i8* [[VALUE]], %swift.type* [[METATYPE]], %swift.type* [[SUPERCLASS]], %swift.protocol* @_T021subclass_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_rt_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_rt_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* @_T021subclass_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_rt_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* @_T021subclass_existentials1DCMa()
// CHECK-NEXT: [[RESULT:%.*]] = call { i8*, i8** } @dynamic_cast_existential_1_superclass_unconditional(i8* [[METATYPE]], %swift.type* %0, %swift.type* [[SUPERCLASS]], %swift.protocol* @_T021subclass_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* @_T021subclass_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 {}