File: variadic-generic-reabstraction.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (159 lines) | stat: -rw-r--r-- 12,068 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// RUN: %target-swift-emit-silgen %s | %FileCheck %s

func takesVariadicFunction<each T>(function: (repeat each T) -> Int) {}
func takesVariadicOwnedFunction<each T>(function: (repeat __owned each T) -> Int) {}
func takesFunctionPack<each T, R>(functions: repeat ((each T) -> R)) {}

// CHECK-LABEL: sil{{.*}} @$s4main32forwardAndReabstractFunctionPack9functionsySbxXExQp_tRvzlF :
func forwardAndReabstractFunctionPack<each T>(functions: repeat (each T) -> Bool) {
// CHECK: bb0(%0 : $*Pack{repeat @noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> Bool for <each T>}):
// 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>}
// 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>)
// CHECK-NEXT:    [[ZERO:%.*]] = integer_literal $Builtin.Word, 0
// CHECK-NEXT:    [[ONE:%.*]] = integer_literal $Builtin.Word, 1
// CHECK-NEXT:    [[LEN:%.*]] = pack_length $Pack{repeat each T}
// CHECK-NEXT:    br bb1([[ZERO]] : $Builtin.Word)
// CHECK:       bb1([[IDX:%.*]] : $Builtin.Word)
// CHECK-NEXT:    [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1
// CHECK-NEXT:     cond_br [[IDX_EQ_LEN]], bb3, bb2
// CHECK:       bb2:
// CHECK-NEXT:    [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat (each T) -> Bool}
// CHECK-NEXT:    open_pack_element [[INDEX]] of <each T> at <Pack{repeat each T}>, shape $each T, uuid [[UUID:".*"]]
// CHECK-NEXT:    [[ARG_TUPLE_ELT_ADDR:%.*]] = tuple_pack_element_addr [[INDEX]] of [[ARG_TUPLE]] :
//   Load the parameter function from the parameter pack.
// 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]]) each T>
// CHECK-NEXT:    [[COPY:%.*]] = load [copy] [[PARAM_ELT_ADDR]] :
//   Convert that to an unsubstituted type
// CHECK-NEXT:    [[COPY_CONVERT:%.*]] = convert_function [[COPY]] : $@noescape @callee_guaranteed @substituted <τ_0_0> (@in_guaranteed τ_0_0) -> Bool for <@pack_element([[UUID]]) each T> to $@noescape @callee_guaranteed (@in_guaranteed @pack_element([[UUID]]) each T) -> Bool
//   Wrap in the conversion thunk.
// CHECK-NEXT:    // function_ref
// 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
// CHECK-NEXT:    [[THUNKED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<@pack_element([[UUID]]) each T>([[COPY_CONVERT]])
//   Convert to a substituted type.
// CHECK-NEXT:    [[THUNKED_CONVERT:%.*]] = convert_function [[THUNKED]] : $@callee_guaranteed (@in_guaranteed @pack_element([[UUID]]) each T) -> @out Bool to $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <@pack_element([[UUID]]) each T, Bool>
//   Convert to noescape.
// 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]]) each T, Bool> to $@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <@pack_element([[UUID]]) each T, Bool>
//   Store into the tuple and put the tuple address into the argument pack.
// CHECK-NEXT:    store [[NOESCAPE]] to [init] [[ARG_TUPLE_ELT_ADDR]] :
// 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]]) each 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>}
//   Destroy the thunked escaping function
//   FIXME: does this leave the noescape function dangling??
// CHECK-NEXT:    destroy_value [[THUNKED_CONVERT]] :
// CHECK-NEXT:    [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word
// CHECK-NEXT:    br bb1([[NEXT_IDX]] : $Builtin.Word)
// CHECK:       bb3:
// CHECK-NEXT:    // function_ref
// 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>}) -> ()
// CHECK-NEXT:    apply [[FN]]<Pack{repeat each T}, Bool>([[ARG_PACK]])
// CHECK-NEXT:    destroy_addr [[ARG_TUPLE]] :
// CHECK-NEXT:    dealloc_stack [[ARG_TUPLE]] :
// CHECK-NEXT:    dealloc_pack [[ARG_PACK]] :
  takesFunctionPack(functions: repeat each functions)
}

// CHECK-LABEL: sil{{.*}} @$s4main22passConcreteToVariadic2fnyS2i_SStXE_tF :
// CHECK:         [[COPY:%.*]] = copy_value %0 : $@noescape @callee_guaranteed (Int, @guaranteed String) -> Int
// CHECK:         [[THUNK:%.*]] = function_ref @$sSiSSSiIgygd_Si_SSQSiSiIegpd_TR
// CHECK:         partial_apply [callee_guaranteed] [[THUNK]]([[COPY]])
func passConcreteToVariadic(fn: (Int, String) -> Int) {
  takesVariadicFunction(function: fn)
}

// CHECK-LABEL: sil{{.*}} @$sSiSSSiIgygd_Si_SSQSiSiIegpd_TR :
// CHECK:       bb0(%0 : $*Pack{Int, String}, %1 : @guaranteed $@noescape @callee_guaranteed (Int, @guaranteed String) -> Int):
// CHECK-NEXT:    [[INT_INDEX:%.*]] = scalar_pack_index 0 of $Pack{Int, String}
// CHECK-NEXT:    [[INT_ADDR:%.*]] = pack_element_get [[INT_INDEX]] of %0 : $*Pack{Int, String}
// CHECK-NEXT:    [[INT:%.*]] = load [trivial] [[INT_ADDR]] : $*Int
// CHECK-NEXT:    [[STRING_INDEX:%.*]] = scalar_pack_index 1 of $Pack{Int, String}
// CHECK-NEXT:    [[STRING_ADDR:%.*]] = pack_element_get [[STRING_INDEX]] of %0 : $*Pack{Int, String}
// CHECK-NEXT:    [[STRING:%.*]] = load_borrow [[STRING_ADDR]] : $*String
// CHECK-NEXT:    [[RESULT:%.*]] = apply %1([[INT]], [[STRING]])
// CHECK-NEXT:    end_borrow [[STRING]] : $String
// CHECK-NEXT:    return [[RESULT]] : $Int

//   FIXME: we aren't preserving that the argument is owned
// CHECK-LABEL: sil{{.*}} @$s4main27passConcreteToOwnedVariadic2fnyS2i_SStXE_tF :
// CHECK:         [[COPY:%.*]] = copy_value %0 : $@noescape @callee_guaranteed (Int, @guaranteed String) -> Int
// CHECK:         [[THUNK:%.*]] = function_ref @$sSiSSSiIgygd_Si_SSQSiSiIegpd_TR
// CHECK:         partial_apply [callee_guaranteed] [[THUNK]]([[COPY]])
func passConcreteToOwnedVariadic(fn: (Int, String) -> Int) {
  takesVariadicOwnedFunction(function: fn)
}

// CHECK-LABEL: sil{{.*}} @$s4main29passConcreteClosureToVariadic2fnyS2i_SStXE_tF :
// CHECK:       bb0(%0 : @guaranteed $@noescape @callee_guaranteed (Int, @guaranteed String) -> Int)
// CHECK:         // function_ref
// CHECK-NEXT:   [[CLOSURE:%.*]] = function_ref @$s4main29passConcreteClosureToVariadic2fnyS2i_SStXE_tFS2i_SStXEfU_ : $@convention(thin) @substituted <each τ_0_0> (@pack_guaranteed Pack{repeat each τ_0_0}, @guaranteed @noescape @callee_guaranteed (Int, @guaranteed String) -> Int) -> Int for <Pack{Int, String}>
// CHECK-NEXT:    [[T0:%.*]] = copy_value %0 :
// CHECK-NEXT:    partial_apply [callee_guaranteed] [[CLOSURE]]([[T0]])
func passConcreteClosureToVariadic(fn: (Int, String) -> Int) {
  takesVariadicFunction {x,y in fn(x, y)}
}

// CHECK-LABEL: sil{{.*}} @$s4main29passConcreteClosureToVariadic2fnyS2i_SStXE_tFS2i_SStXEfU_ : 
// CHECK:       bb0(%0 : $*Pack{Int, String}, %1 : @closureCapture @guaranteed $@noescape @callee_guaranteed (Int, @guaranteed String) -> Int):
// CHECK-NEXT:    [[INT_INDEX:%.*]] = scalar_pack_index 0 of $Pack{Int, String}
// CHECK-NEXT:    [[INT_ADDR:%.*]] = pack_element_get [[INT_INDEX]] of %0 : $*Pack{Int, String} as $*Int
// CHECK-NEXT:    [[X:%.*]] = load [trivial] [[INT_ADDR]] : $*Int
// CHECK-NEXT:    debug_value [[X]] : $Int, let, name "x", argno 1
// CHECK-NEXT:    [[STRING_INDEX:%.*]] = scalar_pack_index 1 of $Pack{Int, String}
// CHECK-NEXT:    [[STRING_ADDR:%.*]] = pack_element_get [[STRING_INDEX]] of %0 : $*Pack{Int, String} as $*String
// CHECK-NEXT:    [[Y:%.*]] = load_borrow [[STRING_ADDR]] : $*String
// CHECK-NEXT:    debug_value [[Y]] : $String, let, name "y", argno 2
// CHECK:         apply {{.*}}([[X]], [[Y]])
// CHECK:         end_borrow [[Y]] : $String

/* Doesn't currently type-check
func passConcreteClosureToVariadic2(fn: (Int, String) -> Int, x: Int) {
  takesVariadicFunction {y in fn(x, y)}
}
 */

// rdar://109843932
//   Test that the path where we emit closures naturally at a
//   particular abstraction level correctly handles variadic
//   expansion in the result type.
func takeClosureWithVariadicResult<each Argument, each Result>(_: (repeat each Argument) -> (repeat each Result)) {}

// CHECK-LABEL: sil {{.*}}@$s4main30testResultReabstractedEmissionyyFSb_SitSi_SbtXEfU_ :
// CHECK-SAME: $@convention(thin) @substituted <each τ_0_0, each τ_0_1> (@pack_guaranteed Pack{repeat each τ_0_0}) -> @pack_out Pack{repeat each τ_0_1} for <Pack{Int, Bool}, Pack{Bool, Int}>
// CHECK:       bb0(%0 : $*Pack{Bool, Int}, %1 : $*Pack{Int, Bool}):
// CHECK-NEXT:    [[ARG_INDEX_0:%.*]] = scalar_pack_index 0 of $Pack{Int, Bool}
// CHECK-NEXT:    [[ARG_ADDR_0:%.*]] = pack_element_get [[ARG_INDEX_0]] of %1 : $*Pack{Int, Bool} as $*Int
// CHECK-NEXT:    [[ARG_0:%.*]] = load [trivial] [[ARG_ADDR_0]] : $*Int
// CHECK-NEXT:    debug_value [[ARG_0]] :
// CHECK-NEXT:    [[ARG_INDEX_1:%.*]] = scalar_pack_index 1 of $Pack{Int, Bool}
// CHECK-NEXT:    [[ARG_ADDR_1:%.*]] = pack_element_get [[ARG_INDEX_1]] of %1 : $*Pack{Int, Bool} as $*Bool
// CHECK-NEXT:    [[ARG_1:%.*]] = load [trivial] [[ARG_ADDR_1]] : $*Bool
// CHECK-NEXT:    debug_value [[ARG_1]] :
// CHECK-NEXT:    [[RET_INDEX_0:%.*]] = scalar_pack_index 0 of $Pack{Bool, Int}
// CHECK-NEXT:    [[RET_ADDR_0:%.*]] = pack_element_get [[RET_INDEX_0]] of %0 : $*Pack{Bool, Int} as $*Bool
// CHECK-NEXT:    [[RET_INDEX_1:%.*]] = scalar_pack_index 1 of $Pack{Bool, Int}
// CHECK-NEXT:    [[RET_ADDR_1:%.*]] = pack_element_get [[RET_INDEX_1]] of %0 : $*Pack{Bool, Int} as $*Int
// CHECK-NEXT:    store [[ARG_1]] to [trivial] [[RET_ADDR_0]] : $*Bool
// CHECK-NEXT:    store [[ARG_0]] to [trivial] [[RET_ADDR_1]] : $*Int
func testResultReabstractedEmission() {
  takeClosureWithVariadicResult {
    (a: Int, b: Bool) -> (Bool, Int) in (b, a)
  }
}

// CHECK-LABEL: sil {{.*}}@$s4main40testResultReabstractedEmission_vanishingyyFSbSi_SbtXEfU_ :
// CHECK-SAME: $@convention(thin) @substituted <each τ_0_0, each τ_0_1> (@pack_guaranteed Pack{repeat each τ_0_0}) -> @pack_out Pack{repeat each τ_0_1} for <Pack{Int, Bool}, Pack{Bool}>
// CHECK:       bb0(%0 : $*Pack{Bool}, %1 : $*Pack{Int, Bool}):
// CHECK-NEXT:    [[ARG_INDEX_0:%.*]] = scalar_pack_index 0 of $Pack{Int, Bool}
// CHECK-NEXT:    [[ARG_ADDR_0:%.*]] = pack_element_get [[ARG_INDEX_0]] of %1 : $*Pack{Int, Bool} as $*Int
// CHECK-NEXT:    [[ARG_0:%.*]] = load [trivial] [[ARG_ADDR_0]] : $*Int
// CHECK-NEXT:    debug_value [[ARG_0]] :
// CHECK-NEXT:    [[ARG_INDEX_1:%.*]] = scalar_pack_index 1 of $Pack{Int, Bool}
// CHECK-NEXT:    [[ARG_ADDR_1:%.*]] = pack_element_get [[ARG_INDEX_1]] of %1 : $*Pack{Int, Bool} as $*Bool
// CHECK-NEXT:    [[ARG_1:%.*]] = load [trivial] [[ARG_ADDR_1]] : $*Bool
// CHECK-NEXT:    debug_value [[ARG_1]] :
// CHECK-NEXT:    [[RET_INDEX_0:%.*]] = scalar_pack_index 0 of $Pack{Bool}
// CHECK-NEXT:    [[RET_ADDR_0:%.*]] = pack_element_get [[RET_INDEX_0]] of %0 : $*Pack{Bool} as $*Bool
// CHECK-NEXT:    store [[ARG_1]] to [trivial] [[RET_ADDR_0]] : $*Bool
func testResultReabstractedEmission_vanishing() {
  takeClosureWithVariadicResult {
    (a: Int, b: Bool) -> Bool in b
  }
}