blob: cb2dc81034c9711c94a09df29d63348e9227742f [file] [log] [blame]
// RUN: %target-swift-frontend %s -emit-ir | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s -DINT=i%target-ptrsize
// REQUIRES: CPU=i386 || CPU=x86_64
sil_stage canonical
protocol DefCon {
init()
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @defcon(%swift.opaque* noalias nocapture sret, %swift.type*, %swift.type* %T, i8** %T.DefCon) {{.*}} {
sil @defcon : $@convention(thin) <T: DefCon> (@thick T.Type) -> @out T {
entry(%0: $*T, %1: $@thick T.Type):
// CHECK-x86_64: [[WITNESS_GEP:%.*]] = getelementptr inbounds i8*, i8** %T.DefCon, i32 1
// CHECK-i386: [[WITNESS_GEP:%.*]] = getelementptr inbounds i8*, i8** %T.DefCon, i32 1
// CHECK-i386: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_GEP]], align 4
// CHECK-x86_64: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_GEP]], align 8
// CHECK: [[METHOD:%.*]] = bitcast i8* [[WITNESS]] to void (%swift.opaque*, %swift.type*, %swift.type*, i8**)*
// CHECK: call swiftcc void [[METHOD]]
%m = witness_method $T, #DefCon.init!allocator.1 : $@convention(witness_method: DefCon) <U: DefCon> (@thick U.Type) -> @out U
%z = apply %m<T>(%0, %1) : $@convention(witness_method: DefCon) <V: DefCon> (@thick V.Type) -> @out V
return %z : $()
}
// rdar://24141848
protocol Base {
func foo()
}
protocol Derived : Base {}
struct ImplementsDerived : Derived {
func foo() {}
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @testInheritedConformance
sil @testInheritedConformance : $@convention(thin) (@in ImplementsDerived) -> () {
entry(%0: $*ImplementsDerived):
// CHECK: [[WITNESS:%.*]] = load i8*, i8** getelementptr inbounds (i8*, i8** @"$s14witness_method17ImplementsDerivedVAA4BaseAAWP", i32 1)
// CHECK: [[METHOD:%.*]] = bitcast i8* [[WITNESS]] to void (%swift.opaque*, %swift.type*, i8**)*
// CHECK: call swiftcc void [[METHOD]]
%m = witness_method $ImplementsDerived, #Base.foo!1 : $@convention(witness_method: Base) <U: Base> (@in_guaranteed U) -> ()
%z = apply %m<ImplementsDerived>(%0) : $@convention(witness_method: Base) <V: Base> (@in_guaranteed V) -> ()
return %z : $()
}
// Make sure a witness_method call with a generic Self type uses the correct
// calling convention.
protocol Synergy {
associatedtype LowHangingFruit
func actionItem() -> LowHangingFruit
}
struct SyncUp<Deliverable> : Synergy {
let d: Deliverable
func actionItem() -> Deliverable {
return d
}
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @testGenericWitnessMethod(%swift.opaque* noalias nocapture sret, %T14witness_method6SyncUpV* noalias nocapture, %swift.type* %T)
// CHECK: entry:
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s14witness_method6SyncUpVMa"([[INT]] 255, %swift.type* %T)
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
// CHECK: [[WTABLE:%.*]] = call i8** @swift_getWitnessTable(
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[WTABLE]], i32 2
// CHECK: [[WITNESS_FN:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK: [[WITNESS:%.*]] = bitcast i8* [[WITNESS_FN]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
// CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @swift_checkMetadataState([[INT]] 0, %swift.type* [[METADATA]])
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0
// CHECK: [[ARG:%.*]] = bitcast %T14witness_method6SyncUpV* %1 to %swift.opaque*
// CHECK: call swiftcc void [[WITNESS]](%swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture swiftself [[ARG]], %swift.type* [[METADATA]], i8** [[WTABLE]])
// CHECK: ret void
sil @testGenericWitnessMethod : $@convention(thin) <T> (@in SyncUp<T>) -> @out T {
entry(%ret : $*T, %self : $*SyncUp<T>):
%m = witness_method $SyncUp<T>, #Synergy.actionItem!1 : $@convention(witness_method: Synergy) <U: Synergy> (@in_guaranteed U) -> @out U.LowHangingFruit
%z = apply %m<SyncUp<T>>(%ret, %self) : $@convention(witness_method: Synergy) <U: Synergy> (@in_guaranteed U) -> @out U.LowHangingFruit
return %z : $()
}
protocol Pivot {}
protocol Strategy {
associatedtype GrowthHack : Pivot
func disrupt() -> GrowthHack
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @testArchetypeWitnessMethod(%swift.opaque* noalias nocapture sret, %swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.Strategy)
// CHECK: entry:
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** %T.Strategy, i32 3
// CHECK: [[WITNESS_FN:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK: [[WITNESS:%.*]] = bitcast i8* [[WITNESS_FN]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
// CHECK: call swiftcc void [[WITNESS]](%swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture swiftself %1, %swift.type* %T, i8** %T.Strategy)
// CHECK: ret void
sil @testArchetypeWitnessMethod : $@convention(thin) <T : Strategy> (@in T) -> @out T.GrowthHack {
entry(%ret : $*T.GrowthHack, %self : $*T):
%m = witness_method $T, #Strategy.disrupt!1 : $@convention(witness_method: Strategy) <U: Strategy> (@in_guaranteed U) -> @out U.GrowthHack
%z = apply %m<T>(%ret, %self) : $@convention(witness_method: Strategy) <U: Strategy> (@in_guaranteed U) -> @out U.GrowthHack
return %z : $()
}
// Class-constrained archetype witness method.
struct ToVideo : Pivot {}
class TPSReport<CoverSheet> : Strategy {
typealias GrowthHack = ToVideo
func disrupt() -> GrowthHack
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @classArchetypeWitnessMethod(%T14witness_method9TPSReportC** noalias nocapture swiftself dereferenceable({{4|8}}), %swift.type* %Self, i8** %SelfWitnessTable)
sil @classArchetypeWitnessMethod : $@convention(witness_method: Strategy) <T><CoverSheet where T : TPSReport<CoverSheet>> (@in_guaranteed T) -> () {
entry(%self : $*T):
%z = tuple ()
return %z : $()
}
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @testClassArchetypeWitnessMethod(%T14witness_method7ToVideoV* noalias nocapture sret, %T14witness_method9TPSReportC** noalias nocapture dereferenceable({{4|8}}), %swift.type* %T, %swift.type* %CoverSheet)
// CHECK: entry:
// CHECK: [[WITNESS_FN:%.*]] = load i8*, i8** getelementptr inbounds (i8*, i8** @"$s14witness_method9TPSReportCyxGAA8StrategyAAWP", i32 3)
// CHECK: [[WITNESS:%.*]] = bitcast i8* [[WITNESS_FN]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
// CHECK: call swiftcc void [[WITNESS]](%swift.opaque* noalias nocapture sret %4, %swift.opaque* noalias nocapture swiftself %5, %swift.type* %T, i8** @"$s14witness_method9TPSReportCyxGAA8StrategyAAWP")
// CHECK: ret void
sil @testClassArchetypeWitnessMethod : $@convention(thin) <T><CoverSheet where T : TPSReport<CoverSheet>> (@in_guaranteed T) -> (@out T.GrowthHack) {
entry(%ret : $*T.GrowthHack, %self : $*T):
%m = witness_method $T, #Strategy.disrupt!1 : $@convention(witness_method: Strategy) <U: Strategy> (@in_guaranteed U) -> @out U.GrowthHack
%z = apply %m<T>(%ret, %self) : $@convention(witness_method: Strategy) <U: Strategy> (@in_guaranteed U) -> @out U.GrowthHack
return %z : $()
}
sil_vtable TPSReport {}