File: yield_once_big.sil

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 (238 lines) | stat: -rw-r--r-- 11,291 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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// RUN: %target-swift-frontend -emit-irgen %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-ptrsize-%target-ptrauth -DINT=i%target-ptrsize
// UNSUPPORTED: CPU=arm64_32

import Builtin
import Swift

sil @marker : $(Builtin.Int32) -> ()

class SomeClass {}
sil_vtable SomeClass {}

class SomeSubclass : SomeClass {}
sil_vtable SomeSubclass {}

// This is designed to be loadable, but large enough that we want to
// pass it indirectly.  This triggers a bunch of special handling in
// some of the IRGen preparation passes, too.
struct Big<T: SomeClass> {
  var a: T
  var b: T
  var c: T
  var d: T
  var e: T
  var f: T
  var g: T
  var h: T
}

struct BigWrapper<T : SomeClass> {
  var big: Big<T>
}

sil @make_big : $<T: SomeClass> () -> (@owned Big<T>)
sil @use_some_class : $<T : SomeClass> (@guaranteed T) -> ()

// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { ptr, ptr } @test_simple
// CHECK-32-SAME:  (ptr noalias dereferenceable([[BUFFER_SIZE:16]]) %0, ptr %C)
// CHECK-64-SAME:  (ptr noalias dereferenceable([[BUFFER_SIZE:32]]) %0, ptr %C)
sil [ossa] @test_simple : $@yield_once <C: SomeClass> () -> (@yields @owned Big<C>) {
entry:
  //   Allocate space for the return value of make_big.
  // CHECK:         [[TEMP:%.*]] = alloca [[BIG:%T14yield_once_big3BigV]]
  // CHECK-32-SAME: , align 4
  // CHECK-64-SAME: , align 8

  //   Coroutine setup.
  // CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free)
  // CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free)
  // CHECK-NEXT:    [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null)
  // CHECK-NEXT:    store ptr

  //   Create the return temporary.  We could give this a tighter bound.
  // CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 {{.*}}, ptr [[TEMP]])

  // CHECK-NEXT:    call swiftcc void @marker(i32 1000)
  %marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
  %1000 = integer_literal $Builtin.Int32, 1000
  apply %marker(%1000) : $@convention(thin) (Builtin.Int32) -> ()

  // CHECK-NEXT:    call swiftcc void @make_big(ptr noalias nocapture sret({{.*}}) [[TEMP]], ptr %C)
  %make = function_ref @make_big : $@convention(thin) <T: SomeClass> () -> (@owned Big<T>)
  %value = apply %make<C>() : $@convention(thin) <T: SomeClass> () -> (@owned Big<T>)

  //   Suspend.
  // CHECK-NEXT:    [[IS_UNWIND:%.*]] = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr [[TEMP]])

  // CHECK-NEXT:    br i1 [[IS_UNWIND]]
  yield %value : $Big<C>, resume resume, unwind unwind

resume:
  // CHECK:         call swiftcc void @marker(i32 2000)
  %2000 = integer_literal $Builtin.Int32, 2000
  apply %marker(%2000) : $@convention(thin) (Builtin.Int32) -> ()
  // CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 {{.*}}, ptr [[TEMP]])
  // CHECK-NEXT:    br label %coro.end
  %ret = tuple ()
  return %ret : $()

unwind:
  // CHECK:         call swiftcc void @marker(i32 3000)
  %3000 = integer_literal $Builtin.Int32, 3000
  apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
  // CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 {{.*}}, ptr [[TEMP]])
  // CHECK-NEXT:    br label %coro.end
  unwind

  // CHECK:       coro.end:
  // CHECK:         call i1 @llvm.coro.end(ptr [[BEGIN]], i1 false)
  // CHECK-NEXT:    unreachable
}

// CHECK-LABEL:     declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC"
// CHECK-SAME:      (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1)

// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_simple_call(i1 %0)
sil [ossa] @test_simple_call : $(Builtin.Int1) -> () {
entry(%flag : $Builtin.Int1):
  //   Allocate the buffer.
  // CHECK:         [[T0:%.*]] = alloca {{\[}}[[BUFFER_SIZE]] x i8], align [[BUFFER_ALIGN]]
  // CHECK-NEXT:    [[BUFFER:%.*]] = getelementptr inbounds {{\[}}[[BUFFER_SIZE]] x i8], ptr [[T0]], i32 0, i32 0
  // CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr [[BUFFER]])

  // CHECK-NEXT:    [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s14yield_once_big12SomeSubclassCMa"([[INT]] 0)
  // CHECK-NEXT:    [[SUBCLASS:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0

  //   Prepare the continuation function pointer to block analysis.
  // CHECK-NEXT:    [[T0:%.*]] = call ptr @llvm.coro.prepare.retcon(ptr @test_simple
  //   Call the function pointer.
  // CHECK-NEXT:    [[RAMP_RESULT:%.*]] = call swiftcc [[RAMP_RESULT_T:{ ptr, ptr }]] [[T0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]], ptr [[SUBCLASS]])
  // CHECK-NEXT:    [[CONTINUATION:%.*]] = extractvalue [[RAMP_RESULT_T]] [[RAMP_RESULT]], 0
  // CHECK-NEXT:    [[PTR:%.*]] = extractvalue [[RAMP_RESULT_T]] [[RAMP_RESULT]], 1
  %0 = function_ref @test_simple : $@convention(thin) @yield_once <T: SomeClass> () -> (@yields @owned Big<T>)
  (%value, %token) = begin_apply %0<SomeSubclass>() : $@convention(thin) @yield_once <T: SomeClass> () -> (@yields @owned Big<T>)

  //   Load.  This is spurious.
  // CHECK-NEXT:    [[T0:%.*]] = getelementptr inbounds [[BIGSUB:%T14yield_once_big3BigVyAA12SomeSubclassCG]], ptr [[PTR]], i32 0, i32 0
  // CHECK-NEXT:    [[R0:%.*]] = load ptr, ptr [[T0]], align
  // CHECK-NEXT:    [[T0:%.*]] = getelementptr inbounds [[BIGSUB]], ptr [[PTR]], i32 0, i32 1
  // CHECK-NEXT:    [[R1:%.*]] = load ptr, ptr [[T0]], align
  // CHECK-NEXT:    [[T0:%.*]] = getelementptr inbounds [[BIGSUB]], ptr [[PTR]], i32 0, i32 2
  // CHECK-NEXT:    [[R2:%.*]] = load ptr, ptr [[T0]], align
  // CHECK-NEXT:    [[T0:%.*]] = getelementptr inbounds [[BIGSUB]], ptr [[PTR]], i32 0, i32 3
  // CHECK-NEXT:    [[R3:%.*]] = load ptr, ptr [[T0]], align
  // CHECK-NEXT:    [[T0:%.*]] = getelementptr inbounds [[BIGSUB]], ptr [[PTR]], i32 0, i32 4
  // CHECK-NEXT:    [[R4:%.*]] = load ptr, ptr [[T0]], align
  // CHECK-NEXT:    [[T0:%.*]] = getelementptr inbounds [[BIGSUB]], ptr [[PTR]], i32 0, i32 5
  // CHECK-NEXT:    [[R5:%.*]] = load ptr, ptr [[T0]], align
  // CHECK-NEXT:    [[T0:%.*]] = getelementptr inbounds [[BIGSUB]], ptr [[PTR]], i32 0, i32 6
  // CHECK-NEXT:    [[R6:%.*]] = load ptr, ptr [[T0]], align
  // CHECK-NEXT:    [[T0:%.*]] = getelementptr inbounds [[BIGSUB]], ptr [[PTR]], i32 0, i32 7
  // CHECK-NEXT:    [[R7:%.*]] = load ptr, ptr [[T0]], align

  //   Branch.
  // CHECK-NEXT:    br i1 %0,
  cond_br %flag, yes, no

yes:
  // CHECK-64-ptrauth: ptrtoint
  // CHECK-64-ptrauth-NEXT: ptrauth.blend
  // CHECK:    call swiftcc void [[CONTINUATION]](ptr noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]], i1 false)
  // CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr [[BUFFER]])
  end_apply %token

  // CHECK-NEXT:    br label
  br cont

no:
  // CHECK-64-ptrauth: ptrtoint
  // CHECK-64-ptrauth-NEXT: ptrauth.blend
  // CHECK:    call swiftcc void [[CONTINUATION]](ptr noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]], i1 true)
  // CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr [[BUFFER]])
  abort_apply %token

  // CHECK-NEXT:    br label
  br cont

cont:
  // CHECK:         call void @swift_release(ptr [[R0]])
  // CHECK-NEXT:    call void @swift_release(ptr [[R1]])
  // CHECK-NEXT:    call void @swift_release(ptr [[R2]])
  // CHECK-NEXT:    call void @swift_release(ptr [[R3]])
  // CHECK:         call void @swift_release(ptr [[R4]])
  // CHECK-NEXT:    call void @swift_release(ptr [[R5]])
  // CHECK-NEXT:    call void @swift_release(ptr [[R6]])
  // CHECK-NEXT:    call void @swift_release(ptr [[R7]])
  destroy_value %value : $Big<SomeSubclass>

  // CHECK-NEXT:    ret void
  %ret = tuple ()
  return %ret : $()
}

// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { ptr, ptr } @test_simple_guaranteed
// CHECK-32-SAME:  (ptr noalias dereferenceable([[BUFFER_SIZE:16]]) %0, ptr noalias nocapture dereferenceable(32) %1, ptr %C)
// CHECK-64-SAME:  (ptr noalias dereferenceable([[BUFFER_SIZE:32]]) %0, ptr noalias nocapture dereferenceable(64) %1, ptr %C)
sil [ossa] @test_simple_guaranteed : $@yield_once <C: SomeClass> (@in_guaranteed BigWrapper<C>) -> (@yields @guaranteed Big<C>) {
entry(%arg : $*BigWrapper<C>):
  //   Allocate space for the return value of make_big.
  // CHECK:         [[TEMP:%.*]] = alloca [[BIG:%T14yield_once_big3BigV]]
  // CHECK-32-SAME: , align 4
  // CHECK-64-SAME: , align 8

  //   Coroutine setup.
  // CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free)
  // CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free)
  // CHECK-NEXT:    [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null)
  // CHECK-NEXT:    store ptr

  //   Create the return temporary.  We could give this a tighter bound.
  // CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 {{.*}}, ptr [[TEMP]])

  // CHECK-NEXT:    call swiftcc void @marker(i32 1000)
  %marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
  %1000 = integer_literal $Builtin.Int32, 1000
  apply %marker(%1000) : $@convention(thin) (Builtin.Int32) -> ()

  %value = load_borrow %arg : $*BigWrapper<C>
  %field = struct_extract %value : $BigWrapper<C>, #BigWrapper.big

  // Make sure that we properly convert these struct_extract to
  // struct_element_addr while rewriting.
  //
  // CHECK: call swiftcc void @use_some_class(
  %field2 = struct_extract %value : $BigWrapper<C>, #BigWrapper.big
  %field3 = struct_extract %field2 : $Big<C>, #Big.a
  %f = function_ref @use_some_class : $@convention(thin) <T : SomeClass> (@guaranteed T) -> ()
  apply %f<C>(%field3) : $@convention(thin) <T : SomeClass>(@guaranteed T) -> ()

  //   Suspend.
  // CHECK-NEXT:    [[IS_UNWIND:%.*]] = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr [[TEMP]])

  // CHECK-NEXT:    br i1 [[IS_UNWIND]]
  yield %field : $Big<C>, resume resume, unwind unwind

resume:
  end_borrow %value : $BigWrapper<C>

  // CHECK:         call swiftcc void @marker(i32 2000)
  %2000 = integer_literal $Builtin.Int32, 2000
  apply %marker(%2000) : $@convention(thin) (Builtin.Int32) -> ()
  // CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 {{.*}}, ptr [[TEMP]])
  // CHECK-NEXT:    br label %coro.end
  %ret = tuple ()
  return %ret : $()

unwind:
  end_borrow %value : $BigWrapper<C>
  // CHECK:         call swiftcc void @marker(i32 3000)
  %3000 = integer_literal $Builtin.Int32, 3000
  apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
  // CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 {{.*}}, ptr [[TEMP]])
  // CHECK-NEXT:    br label %coro.end
  unwind

  // CHECK:       coro.end:
  // CHECK:         call i1 @llvm.coro.end(ptr [[BEGIN]], i1 false)
  // CHECK-NEXT:    unreachable
}