Files
swift-mirror/test/IRGen/subclass_existentials.sil
T
Greg Parker e223f1fc9b [IRGen][runtime] Simplify runtime CCs and entry point ABIs (#14175)
* 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.
2018-01-29 13:22:30 -08:00

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