blob: a7fe70c268357983d55bddc68101391e1bb823f6 [file] [log] [blame]
// RUN: %target-sil-opt -O -wmo -enable-sil-verify-all %s | %FileCheck %s
// REQUIRES: objc_interop
sil_stage canonical
import Builtin
import Swift
import SwiftShims
public class A {
@objc deinit
init()
}
public protocol P {
func foo() -> Int64
}
public class B : A, P {
public func foo() -> Int64
@objc deinit
override init()
}
public class C : A, P {
public func foo() -> Int64
@objc deinit
override init()
}
func imp(x: A & P, y: A & P) -> Int64
public func test(x: B, y: C) -> Int64
// protocol witness for P.foo() in conformance B
sil shared [transparent] [serialized] [thunk] @Pfoo : $@convention(witness_method: P) (@in_guaranteed B) -> Int64 {
// %0 // user: %1
bb0(%0 : $*B):
%1 = load %0 : $*B // users: %2, %3
%2 = class_method %1 : $B, #B.foo : (B) -> () -> Int64, $@convention(method) (@guaranteed B) -> Int64 // user: %3
%3 = apply %2(%1) : $@convention(method) (@guaranteed B) -> Int64 // user: %4
return %3 : $Int64 // id: %4
} // end sil function 'Pfoo'
// B.foo()
sil [noinline] @foo : $@convention(method) (@guaranteed B) -> Int64 {
// %0 // user: %1
bb0(%0 : $B):
debug_value %0 : $B, let, name "self", argno 1 // id: %1
%2 = integer_literal $Builtin.Int64, 1 // user: %3
%3 = struct $Int64 (%2 : $Builtin.Int64) // user: %4
return %3 : $Int64 // id: %4
} // end sil function 'foo'
// This function calls @impl. The optimizer generates a specialization of impl
// based on the arguments passed to it here. Even though this function isn't
// directly checked, it is essentail for the optimization.
// test(x:y:)
sil @test :$@convention(thin) (@guaranteed B, @guaranteed C) -> Int64 {
// %0 // users: %5, %4, %2
// %1 // users: %7, %6, %3
bb0(%0 : $B, %1 : $C):
debug_value %0 : $B, let, name "x", argno 1 // id: %2
debug_value %1 : $C, let, name "y", argno 2 // id: %3
strong_retain %0 : $B // id: %4
%5 = init_existential_ref %0 : $B : $B, $A & P // users: %11, %9
strong_retain %1 : $C // id: %6
%7 = init_existential_ref %1 : $C : $C, $A & P // users: %10, %9
// function_ref imp(x:y:)
%8 = function_ref @impl : $@convention(thin) (@guaranteed A & P, @guaranteed A & P) -> Int64 // user: %9
%9 = apply %8(%5, %7) : $@convention(thin) (@guaranteed A & P, @guaranteed A & P) -> Int64 // user: %12
strong_release %7 : $A & P // id: %10
strong_release %5 : $A & P // id: %11
return %9 : $Int64 // id: %12
} // end sil function 'test'
// We're looking of an optimized spcialization of @impl, not @impl itself.
// CHECK-NOT: @impl
// CHECK-LABEL: sil shared [noinline] @{{.*}}impl{{.*}}
// In the optimization pass we look for uses of alloc_stack (aka %5).
// This test makes sure that we look at the correct uses with the
// correct dominance order (store before apply before dealloc).
// This function will be passed arguments of type B and C for arguments
// %0 and %1 respectively. We want to make sure that we call B's foo method
// and not C's foo method.
sil hidden [noinline] @impl : $@convention(thin) (@guaranteed A & P, @guaranteed A & P) -> Int64 {
bb0(%0 : $A & P, %1 : $A & P):
%2 = open_existential_ref %0 : $A & P to $@opened("A1F1B526-1463-11EA-932F-ACBC329C418B") A & P
%3 = unchecked_ref_cast %1 : $A & P to $@opened("A1F1B526-1463-11EA-932F-ACBC329C418B") A & P
%5 = alloc_stack $@opened("A1F1B526-1463-11EA-932F-ACBC329C418B") A & P
store %2 to %5 : $*@opened("A1F1B526-1463-11EA-932F-ACBC329C418B") A & P
// We want to make sure that we picked up on the FIRST store and not the second one.
// class C's foo method is named "bar" whereas class B's foo method is named "foo".
// We want to make sure that we call a function named "foo" not "bar".
// CHECK: [[FN:%[0-9]+]] = function_ref @${{.*}}foo{{.*}} : $@convention(thin) () -> Int64
%7 = witness_method $@opened("A1F1B526-1463-11EA-932F-ACBC329C418B") A & P, #P.foo : <Self where Self : P> (Self) -> () -> Int64, %2 : $@opened("A1F1B526-1463-11EA-932F-ACBC329C418B") A & P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int64
// CHECK: apply [[FN]]
%8 = apply %7<@opened("A1F1B526-1463-11EA-932F-ACBC329C418B") A & P>(%5) : $@convention(witness_method: P) _0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int64
store %3 to %5 : $*@opened("A1F1B526-1463-11EA-932F-ACBC329C418B") A & P
dealloc_stack %5 : $*@opened("A1F1B526-1463-11EA-932F-ACBC329C418B") A & P
return %8 : $Int64
// CHECK-LABEL: end sil function {{.*}}impl{{.*}}
} // end sil function 'impl'
// C.foo()
sil @bar : $@convention(method) (@guaranteed C) -> Int64
sil_vtable [serialized] B {
#B.foo: (B) -> () -> Int64 : @foo // B.foo()
}
sil_vtable [serialized] C {
#C.foo: (C) -> () -> Int64 : @bar
}
sil_witness_table [serialized] B: P module run {
method #P.foo: <Self where Self : P> (Self) -> () -> Int64 : @Pfoo // protocol witness for P.foo() in conformance B
}