| // RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s |
| |
| // REQUIRES: CPU=i386 || CPU=x86_64 |
| |
| sil_stage canonical |
| |
| protocol DefCon { |
| init() |
| } |
| |
| |
| // CHECK-LABEL: define{{( 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{{( 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{{( protected)?}} swiftcc void @testGenericWitnessMethod(%swift.opaque* noalias nocapture sret, %T14witness_method6SyncUpV* noalias nocapture, %swift.type* %T) |
| // CHECK: entry: |
| // CHECK: [[METADATA:%.*]] = call %swift.type* @"$S14witness_method6SyncUpVMa"(%swift.type* %T) |
| // CHECK: [[WTABLE:%.*]] = call i8** @"$S14witness_method6SyncUpVyxGAA7SynergyAAWa"(%swift.type* [[METADATA]], i8*** undef, {{i32|i64}} 0) |
| // 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: [[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{{( 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{{( 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{{( 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 {} |