|
| 1 | +// RUN: %target-swift-emit-silgen -enable-experimental-feature VariadicGenerics %s | %FileCheck %s |
| 2 | +// REQUIRES: asserts |
| 3 | + |
| 4 | +func takesVariadicFunction<each T>(function: (repeat each T) -> Int) {} |
| 5 | +func takesFunctionPack<each T, R>(functions: repeat ((each T) -> R)) {} |
| 6 | + |
| 7 | +// CHECK-LABEL: sil{{.*}} @$s4main32forwardAndReabstractFunctionPack9functionsySbxXExQp_tRvzlF : |
| 8 | +func forwardAndReabstractFunctionPack<each T>(functions: repeat (each T) -> Bool) { |
| 9 | +// CHECK: bb0(%0 : $*Pack{repeat @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> Bool for <each T>}): |
| 10 | +// CHECK: [[ARG_PACK:%.*]] = alloc_pack $Pack{repeat @noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <each T, Bool>} |
| 11 | +// CHECK-NEXT: [[ARG_TUPLE:%.*]] = alloc_stack $(repeat @noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <each T, Bool>) |
| 12 | +// CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0 |
| 13 | +// CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1 |
| 14 | +// CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T} |
| 15 | +// CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word) |
| 16 | +// CHECK: bb1([[IDX:%.*]] : $Builtin.Word) |
| 17 | +// CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1 |
| 18 | +// CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb3, bb2 |
| 19 | +// CHECK: bb2: |
| 20 | +// CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat (each T) -> Bool} |
| 21 | +// CHECK-NEXT: open_pack_element [[INDEX]] of <each T> at <Pack{repeat each T}>, shape $T, uuid [[UUID:".*"]] |
| 22 | +// CHECK-NEXT: [[ARG_TUPLE_ELT_ADDR:%.*]] = tuple_pack_element_addr [[INDEX]] of [[ARG_TUPLE]] : |
| 23 | +// Load the parameter function from the parameter pack. |
| 24 | +// CHECK-NEXT: [[PARAM_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %0 : $*Pack{repeat @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> Bool for <each T>} as $*@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> Bool for <@pack_element([[UUID]]) T> |
| 25 | +// CHECK-NEXT: [[COPY:%.*]] = load [copy] [[PARAM_ELT_ADDR]] : |
| 26 | +// Convert that to an unsubstituted type |
| 27 | +// CHECK-NEXT: [[COPY_CONVERT:%.*]] = convert_function [[COPY]] : $@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> Bool for <@pack_element([[UUID]]) T> to $@noescape @callee_guaranteed (@in_guaranteed @pack_element([[UUID]]) T) -> Bool |
| 28 | +// Wrap in the conversion thunk. |
| 29 | +// CHECK-NEXT: // function_ref |
| 30 | +// CHECK-NEXT: [[THUNK:%.*]] = function_ref @$sxSbIgnd_xSbIegnr_lTR : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0, @guaranteed @noescape @callee_guaranteed (@in_guaranteed τ_0_0) -> Bool) -> @out Bool |
| 31 | +// CHECK-NEXT: [[THUNKED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<@pack_element([[UUID]]) T>([[COPY_CONVERT]]) |
| 32 | +// Convert to a substituted type. |
| 33 | +// CHECK-NEXT: [[THUNKED_CONVERT:%.*]] = convert_function [[THUNKED]] : $@callee_guaranteed (@in_guaranteed @pack_element([[UUID]]) T) -> @out Bool to $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <@pack_element([[UUID]]) T, Bool> |
| 34 | +// Convert to noescape. |
| 35 | +// CHECK-NEXT: [[NOESCAPE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[THUNKED_CONVERT]] : $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <@pack_element([[UUID]]) T, Bool> to $@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <@pack_element([[UUID]]) T, Bool> |
| 36 | +// Store into the tuple and put the tuple address into the argument pack. |
| 37 | +// CHECK-NEXT: store [[NOESCAPE]] to [init] [[ARG_TUPLE_ELT_ADDR]] : |
| 38 | +// CHECK-NEXT: pack_element_set [[ARG_TUPLE_ELT_ADDR]] : $*@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <@pack_element([[UUID]]) T, Bool> into %11 of [[ARG_PACK]] : $*Pack{repeat @noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <each T, Bool>} |
| 39 | +// Destroy the thunked escaping function |
| 40 | +// FIXME: does this leave the noescape function dangling?? |
| 41 | +// CHECK-NEXT: destroy_value [[THUNKED_CONVERT]] : |
| 42 | +// CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word |
| 43 | +// CHECK-NEXT: br bb1([[NEXT_IDX]] : $Builtin.Word) |
| 44 | +// CHECK: bb3: |
| 45 | +// CHECK-NEXT: // function_ref |
| 46 | +// CHECK-NEXT: [[FN:%.*]] = function_ref @$s4main17takesFunctionPack9functionsyq_xXExQp_tRvzr0_lF : $@convention(thin) <each τ_0_0, τ_0_1> (@pack_guaranteed Pack{repeat @noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <each τ_0_0, τ_0_1>}) -> () |
| 47 | +// CHECK-NEXT: apply [[FN]]<Pack{repeat each T}, Bool>([[ARG_PACK]]) |
| 48 | +// CHECK-NEXT: destroy_addr [[ARG_TUPLE]] : |
| 49 | +// CHECK-NEXT: dealloc_stack [[ARG_TUPLE]] : |
| 50 | +// CHECK-NEXT: dealloc_pack [[ARG_PACK]] : |
| 51 | + takesFunctionPack(functions: repeat each functions) |
| 52 | +} |
0 commit comments