| // RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s |
| |
| // REQUIRES: CPU=x86_64 |
| |
| sil_stage canonical |
| |
| protocol P { |
| func concrete_method() |
| static func concrete_static_method() |
| func generic_method<Z>(x: Z) |
| } |
| |
| struct Foo: P { |
| func concrete_method() |
| static func concrete_static_method() |
| func generic_method<Z>(x: Z) |
| } |
| class Bar<T, U, V>: P { |
| func concrete_method() |
| static func concrete_static_method() |
| func generic_method<Z>(x: Z) |
| } |
| sil_vtable Bar {} |
| sil @$s19sil_witness_methods3BarCfD : $@convention(method) <T, U, V> (Bar<T, U, V>) -> () |
| |
| struct X {} |
| struct Y {} |
| struct Z {} |
| |
| // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @concrete_type_concrete_method_witness(%T19sil_witness_methods3FooV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) |
| sil @concrete_type_concrete_method_witness : $@convention(witness_method: P) (@in Foo) -> @thick Foo.Type { |
| entry(%x : $*Foo): |
| %m = metatype $@thick Foo.Type |
| return %m : $@thick Foo.Type |
| } |
| |
| // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @generic_type_concrete_method_witness(%T19sil_witness_methods3BarC** noalias nocapture swiftself 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: P) <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{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @concrete_type_concrete_static_method_witness(%swift.type* swiftself, %swift.type* %Self, i8** %SelfWitnessTable) |
| sil @concrete_type_concrete_static_method_witness : $@convention(witness_method: P) (@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{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @generic_type_concrete_static_method_witness(%swift.type* swiftself, %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: P) <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{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @concrete_type_generic_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %T19sil_witness_methods3FooV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) |
| sil @concrete_type_generic_method_witness : $@convention(witness_method: P) <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{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @generic_type_generic_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %T19sil_witness_methods3BarC{{.*}}** noalias nocapture swiftself dereferenceable(8), %swift.type* %Self, i8** %SelfWitnessTable) |
| sil @generic_type_generic_method_witness : $@convention(witness_method: P) <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{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @concrete_type_generic_static_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %swift.type* swiftself, %swift.type* %Self, i8** %SelfWitnessTable) |
| sil @concrete_type_generic_static_method_witness : $@convention(witness_method: P) <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{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @generic_type_generic_static_method_witness(%swift.opaque* noalias nocapture, %swift.type* %Z, %swift.type* swiftself, %swift.type* %Self, i8** %SelfWitnessTable) |
| sil @generic_type_generic_static_method_witness : $@convention(witness_method: P) <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{{( dllexport)?}}{{( protected)?}} swiftcc void @call_concrete_witness() {{.*}} { |
| // CHECK: call swiftcc %swift.type* @concrete_type_concrete_method_witness(%T19sil_witness_methods3FooV* {{.*}}, %swift.type* {{.*}} @"$s19sil_witness_methods3FooVMf", {{.*}}) |
| 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: P) (@in Foo) -> @thick Foo.Type |
| %z = apply %w(%m) : $@convention(witness_method: P) (@in Foo) -> @thick Foo.Type |
| dealloc_stack %m : $*Foo |
| return undef : $() |
| } |
| |
| // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @call_concrete_static_witness() {{.*}} { |
| // CHECK: call swiftcc %swift.type* @concrete_type_concrete_static_method_witness(%swift.type* {{.*}} @"$s19sil_witness_methods3FooVMf", {{.*}} %swift.type* {{.*}} @"$s19sil_witness_methods3FooVMf", {{.*}}) |
| sil @call_concrete_static_witness : $() -> () { |
| entry: |
| %m = metatype $@thick Foo.Type |
| %w = function_ref @concrete_type_concrete_static_method_witness : $@convention(witness_method: P) (@thick Foo.Type) -> @thick Foo.Type |
| %z = apply %w(%m) : $@convention(witness_method: P) (@thick Foo.Type) -> @thick Foo.Type |
| return undef : $() |
| } |
| |
| // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_concrete_witness() {{.*}} { |
| // CHECK: [[CONTEXT:%.*]] = call noalias %swift.refcounted* @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* bitcast (i8** @"$s19sil_witness_methods3BarCyxq_q0_GAA1PAAWP" to i8*), i8** [[WTABLE]] |
| // CHECK: [[RESULT:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (%swift.type* (%T19sil_witness_methods3BarCyAA3FooVA2EG**, %swift.refcounted*)* @"$s36generic_type_concrete_method_witnessTA" 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: P) <T, U, V> (@in Bar<T, U, V>) -> @thick Bar<T, U, V>.Type |
| %z = partial_apply %w<Foo, Foo, Foo>() : $@convention(witness_method: P) <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 |
| } |