| // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -devirtualizer -generic-specializer -inline -dce | %FileCheck %s |
| |
| sil_stage canonical |
| |
| import Builtin |
| |
| protocol P { |
| func foo() -> Builtin.Int1 |
| } |
| |
| struct S : P { |
| func foo() -> Builtin.Int1 |
| } |
| |
| private class C : P { |
| func foo() -> Builtin.Int1 |
| } |
| |
| // CHECK-LABEL: struct_target |
| sil [always_inline] @struct_target : $@convention(method) (S) -> Builtin.Int1 { |
| // CHECK: bb0 |
| bb0(%0 : $S): |
| %2 = integer_literal $Builtin.Int1, 0 |
| return %2 : $Builtin.Int1 |
| } |
| |
| // CHECK-LABEL: struct_witness |
| sil [always_inline] [thunk] @struct_witness : $@convention(witness_method: P) (@in_guaranteed S) -> Builtin.Int1 { |
| // CHECK: bb0 |
| bb0(%0 : $*S): |
| // CHECK-NOT: load |
| %1 = load %0 : $*S |
| // CHECK-NOT: function_ref |
| %2 = function_ref @struct_target : $@convention(method) (S) -> Builtin.Int1 |
| // CHECK-NOT: apply |
| %3 = apply %2(%1) : $@convention(method) (S) -> Builtin.Int1 |
| // CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Int1, 0 |
| // CHECK: return [[ZERO]] |
| return %3 : $Builtin.Int1 |
| } |
| |
| // CHECK-LABEL: struct_caller |
| sil shared @struct_caller : $@convention(thin) (@in S) -> Builtin.Int1 { |
| // CHECK: bb0 |
| bb0(%0 : $*S): |
| // CHECK-NOT: witness_method |
| %2 = witness_method $S, #P.foo!1 : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Builtin.Int1 |
| // CHECK-NOT: apply |
| %3 = apply %2<S>(%0) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Builtin.Int1 |
| // CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Int1, 0 |
| // CHECK: return [[ZERO]] |
| destroy_addr %0 : $*S |
| return %3 : $Builtin.Int1 |
| } |
| |
| // CHECK-LABEL: class_target |
| sil [always_inline] @class_target : $@convention(method) (@guaranteed C) -> Builtin.Int1 { |
| bb0(%0 : $C): |
| %1 = integer_literal $Builtin.Int1, -1 |
| return %1 : $Builtin.Int1 |
| } |
| |
| // CHECK-LABEL: class_witness |
| sil [always_inline] [thunk] @class_witness : $@convention(witness_method: P) (@in_guaranteed C) -> Builtin.Int1 { |
| // CHECK: bb0 |
| bb0(%0 : $*C): |
| // CHECK-NOT: load |
| %1 = load %0 : $*C |
| // CHECK-NOT: class_method |
| %3 = class_method %1 : $C, #C.foo!1 : (C) -> () -> Builtin.Int1, $@convention(method) (@guaranteed C) -> Builtin.Int1 |
| // CHECK-NOT: apply |
| %4 = apply %3(%1) : $@convention(method) (@guaranteed C) -> Builtin.Int1 |
| // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int1, -1 |
| // CHECK: return [[ONE]] |
| return %4 : $Builtin.Int1 |
| } |
| |
| // CHECK-LABEL: class_caller |
| sil shared @class_caller : $@convention(thin) (@in C) -> Builtin.Int1 { |
| // CHECK: bb0 |
| bb0(%0 : $*C): |
| // CHECK-NOT: witness_method |
| %1 = witness_method $C, #P.foo!1 : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Builtin.Int1 |
| // CHECK-NOT: apply |
| %2 = apply %1<C>(%0) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Builtin.Int1 |
| destroy_addr %0 : $*C |
| // CHECK: [[ONE:%.*]] = integer_literal $Builtin.Int1, -1 |
| // CHECK: return [[ONE]] |
| return %2 : $Builtin.Int1 |
| } |
| |
| sil_vtable C { |
| #C.foo!1: @class_target |
| } |
| |
| sil_witness_table C: P module main { |
| method #P.foo!1: @class_witness |
| } |
| |
| sil_witness_table S: P module main { |
| method #P.foo!1: @struct_witness |
| } |