blob: bd35163ce3d7eebfb8804ffdbf12fe98fdbe8ce0 [file] [log] [blame]
// RUN: %target-swift-frontend %s -emit-ir | FileCheck %s
// REQUIRES: CPU=x86_64
sil_stage canonical
struct Foo {}
class Bar<T, U, V> {}
sil_vtable Bar {}
sil @_TFC19sil_witness_methods3BarD : $@convention(method) <T, U, V> (Bar<T, U, V>) -> ()
struct X {}
struct Y {}
struct Z {}
protocol P {
func concrete_method()
static func concrete_static_method()
func generic_method<Z>(x: Z)
}
// CHECK-LABEL: define{{( protected)?}} %swift.type* @concrete_type_concrete_method_witness(%V19sil_witness_methods3Foo* noalias nocapture, %swift.type* %Self, i8** %SelfWitnessTable)
sil @concrete_type_concrete_method_witness : $@convention(witness_method) (@in Foo) -> @thick Foo.Type {
entry(%x : $*Foo):
%m = metatype $@thick Foo.Type
return %m : $@thick Foo.Type
}
// CHECK-LABEL: define{{( protected)?}} %swift.type* @generic_type_concrete_method_witness(%C19sil_witness_methods3Bar** noalias nocapture dereferenceable({{.*}}), %swift.type* %Self, i8** %SelfWitnessTable)
// CHECK: [[T0:%.*]] = bitcast %swift.type* %Self to %swift.type**
// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 10
// CHECK: %T = load %swift.type*, %swift.type** [[T1]], align 8
// CHECK: [[U0:%.*]] = bitcast %swift.type* %Self to %swift.type**
// CHECK: [[U1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[U0]], i64 11
// CHECK: %U = load %swift.type*, %swift.type** [[U1]], align 8
// CHECK: [[V0:%.*]] = bitcast %swift.type* %Self to %swift.type**
// CHECK: [[V1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[V0]], i64 12
// CHECK: %V = load %swift.type*, %swift.type** [[V1]], align 8
sil @generic_type_concrete_method_witness : $@convention(witness_method) <T, U, V> (@in Bar<T, U, V>) -> @thick Bar<T, U, V>.Type {
entry(%x : $*Bar<T, U, V>):
%t = metatype $@thick T.Type
%u = metatype $@thick U.Type
%v = metatype $@thick V.Type
%m = metatype $@thick Bar<T, U, V>.Type
return %m : $@thick Bar<T, U, V>.Type
}
// TODO: %Self Type arg is redundant for static method witness
// CHECK-LABEL: define{{( protected)?}} %swift.type* @concrete_type_concrete_static_method_witness(%swift.type*, %swift.type* %Self, i8** %SelfWitnessTable)
sil @concrete_type_concrete_static_method_witness : $@convention(witness_method) (@thick Foo.Type) -> @thick Foo.Type {
entry(%x : $@thick Foo.Type):
%m = metatype $@thick Foo.Type
return %m : $@thick Foo.Type
}
// The use of %0 or %Self here is irrelevant.
// CHECK-LABEL: define{{( protected)?}} %swift.type* @generic_type_concrete_static_method_witness(%swift.type*, %swift.type* %Self, i8** %SelfWitnessTable)
// CHECK: [[T0:%.*]] = bitcast %swift.type* %Self to %swift.type**
// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 10
// CHECK: %T = load %swift.type*, %swift.type** [[T1]], align 8
// CHECK: [[U0:%.*]] = bitcast %swift.type* %Self to %swift.type**
// CHECK: [[U1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[U0]], i64 11
// CHECK: %U = load %swift.type*, %swift.type** [[U1]], align 8
// CHECK: [[V0:%.*]] = bitcast %swift.type* %Self to %swift.type**
// CHECK: [[V1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[V0]], i64 12
// CHECK: %V = load %swift.type*, %swift.type** [[V1]], align 8
sil @generic_type_concrete_static_method_witness : $@convention(witness_method) <T, U, V> (@thick Bar<T, U, V>.Type) -> @thick Bar<T, U, V>.Type {
entry(%x : $@thick Bar<T, U, V>.Type):
%t = metatype $@thick T.Type
%u = metatype $@thick U.Type
%v = metatype $@thick V.Type
%m = metatype $@thick Bar<T, U, V>.Type
return %m : $@thick Bar<T, U, V>.Type
}
// TODO: %Self Type arg is redundant for class method witness
// CHECK-LABEL: define{{( protected)?}} %swift.type* @concrete_type_generic_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %V19sil_witness_methods3Foo* noalias nocapture, %swift.type* %Self, i8** %SelfWitnessTable)
sil @concrete_type_generic_method_witness : $@convention(witness_method) <Z> (@in Z, @in Foo) -> @thick Foo.Type {
entry(%z : $*Z, %x : $*Foo):
%m = metatype $@thick Foo.Type
return %m : $@thick Foo.Type
}
// CHECK-LABEL: define{{( protected)?}} %swift.type* @generic_type_generic_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %C19sil_witness_methods3Bar** noalias nocapture dereferenceable({{.*}}), %swift.type* %Self, i8** %SelfWitnessTable)
sil @generic_type_generic_method_witness : $@convention(witness_method) <T, U, V, Z> (@in Z, @in Bar<T, U, V>) -> @thick Bar<T, U, V>.Type {
entry(%z : $*Z, %x : $*Bar<T, U, V>):
%t = metatype $@thick T.Type
%u = metatype $@thick U.Type
%v = metatype $@thick V.Type
%m = metatype $@thick Bar<T, U, V>.Type
return %m : $@thick Bar<T, U, V>.Type
}
// CHECK-LABEL: define{{( protected)?}} %swift.type* @concrete_type_generic_static_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %swift.type*, %swift.type* %Self, i8** %SelfWitnessTable)
sil @concrete_type_generic_static_method_witness : $@convention(witness_method) <Z> (@in Z, @thick Foo.Type) -> @thick Foo.Type {
entry(%z : $*Z, %x : $@thick Foo.Type):
%m = metatype $@thick Foo.Type
return %m : $@thick Foo.Type
}
// CHECK-LABEL: define{{( protected)?}} %swift.type* @generic_type_generic_static_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %swift.type*, %swift.type* %Self, i8** %SelfWitnessTable)
sil @generic_type_generic_static_method_witness : $@convention(witness_method) <T, U, V, Z> (@in Z, @thick Bar<T, U, V>.Type) -> @thick Bar<T, U, V>.Type {
entry(%z : $*Z, %x : $@thick Bar<T, U, V>.Type):
%t = metatype $@thick T.Type
%u = metatype $@thick U.Type
%v = metatype $@thick V.Type
%m = metatype $@thick Bar<T, U, V>.Type
return %m : $@thick Bar<T, U, V>.Type
}
// CHECK-LABEL: define{{( protected)?}} void @call_concrete_witness() {{.*}} {
// CHECK: call %swift.type* @concrete_type_concrete_method_witness(%V19sil_witness_methods3Foo* {{.*}}, %swift.type* {{.*}} @_TMfV19sil_witness_methods3Foo, {{.*}})
sil @call_concrete_witness : $(Foo) -> () {
entry(%x : $Foo):
%m = alloc_stack $Foo
store %x to %m : $*Foo
%w = function_ref @concrete_type_concrete_method_witness : $@convention(witness_method) (@in Foo) -> @thick Foo.Type
%z = apply %w(%m) : $@convention(witness_method) (@in Foo) -> @thick Foo.Type
dealloc_stack %m : $*Foo
return undef : $()
}
// CHECK-LABEL: define{{( protected)?}} void @call_concrete_static_witness() {{.*}} {
// CHECK: call %swift.type* @concrete_type_concrete_static_method_witness(%swift.type* {{.*}} @_TMfV19sil_witness_methods3Foo, {{.*}} %swift.type* {{.*}} @_TMfV19sil_witness_methods3Foo, {{.*}})
sil @call_concrete_static_witness : $() -> () {
entry:
%m = metatype $@thick Foo.Type
%w = function_ref @concrete_type_concrete_static_method_witness : $@convention(witness_method) (@thick Foo.Type) -> @thick Foo.Type
%z = apply %w(%m) : $@convention(witness_method) (@thick Foo.Type) -> @thick Foo.Type
return undef : $()
}
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @partial_apply_concrete_witness() {{.*}} {
// CHECK: [[CONTEXT:%.*]] = call noalias %swift.refcounted* @rt_swift_allocObject({{.*}})
// CHECK: [[LAYOUT:%.*]] = bitcast %swift.refcounted* [[CONTEXT]] to <{ %swift.refcounted, i8* }>*
// CHECK: [[WTABLE:%.*]] = getelementptr inbounds <{ %swift.refcounted, i8* }>, <{ %swift.refcounted, i8* }>* [[LAYOUT]], i32 0, i32 1
// CHECK: store i8* null, i8** [[WTABLE]]
// CHECK: [[RESULT:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (%swift.type* (%GC19sil_witness_methods3BarVS_3FooS1_S1__**, %swift.refcounted*)* @_TPA_generic_type_concrete_method_witness to i8*), %swift.refcounted* undef }, %swift.refcounted* [[CONTEXT]], 1
// CHECK: ret { i8*, %swift.refcounted* } [[RESULT]]
sil @partial_apply_concrete_witness : $() -> @callee_owned (@in Bar<Foo, Foo, Foo>) -> @thick Bar<Foo, Foo, Foo>.Type {
entry:
%w = function_ref @generic_type_concrete_method_witness : $@convention(witness_method) <T, U, V> (@in Bar<T, U, V>) -> @thick Bar<T, U, V>.Type
%z = partial_apply %w<Foo, Foo, Foo>() : $@convention(witness_method) <T, U, V> (@in Bar<T, U, V>) -> @thick Bar<T, U, V>.Type
return %z : $@callee_owned (@in Bar<Foo, Foo, Foo>) -> @thick Bar<Foo, Foo, Foo>.Type
}