xref: /llvm-project/llvm/test/Transforms/SafeStack/X86/coloring2.ll (revision 3bd517205799a152689434ceddf9493765f1e883)
1; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
2; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
3; RUN: opt -passes=safe-stack -safe-stack-coloring=1 -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
4; RUN: opt -passes=safe-stack -safe-stack-coloring=1 -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
5
6; x and y share the stack slot.
7define void @f() safestack {
8; CHECK-LABEL: define void @f
9entry:
10; CHECK:  %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
11; CHECK:   getelementptr i8, ptr %[[USP]], i32 -16
12
13  %x = alloca i32, align 4
14  %y = alloca i32, align 4
15  %z = alloca i32, align 4
16
17  call void @llvm.lifetime.start.p0(i64 -1, ptr %z)
18  call void @llvm.lifetime.start.p0(i64 -1, ptr %x)
19
20; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
21  call void @capture32(ptr %x)
22  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
23  call void @llvm.lifetime.start.p0(i64 -1, ptr %y)
24
25; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
26  call void @capture32(ptr %y)
27  call void @llvm.lifetime.end.p0(i64 -1, ptr %y)
28
29; CHECK:   getelementptr i8, ptr %[[USP]], i32 -8
30  call void @capture32(ptr %z)
31  call void @llvm.lifetime.end.p0(i64 -1, ptr %z)
32
33  ret void
34}
35
36define void @no_markers() safestack {
37; CHECK-LABEL: define void @no_markers(
38entry:
39; CHECK:  %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
40; CHECK:   getelementptr i8, ptr %[[USP]], i32 -16
41
42  %x = alloca i32, align 4
43  %y = alloca i32, align 4
44
45  call void @llvm.lifetime.start.p0(i64 -1, ptr %x)
46
47; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
48  call void @capture32(ptr %x)
49  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
50
51; CHECK:   getelementptr i8, ptr %[[USP]], i32 -8
52  call void @capture32(ptr %y)
53
54  ret void
55}
56
57; x and y can't share memory, but they can split z's storage.
58define void @g() safestack {
59; CHECK-LABEL: define void @g
60entry:
61; CHECK:  %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
62; CHECK:   getelementptr i8, ptr %[[USP]], i32 -16
63
64  %x = alloca i32, align 4
65  %y = alloca i32, align 4
66  %z = alloca i64, align 4
67
68  call void @llvm.lifetime.start.p0(i64 -1, ptr %x)
69  call void @llvm.lifetime.start.p0(i64 -1, ptr %y)
70
71; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
72  call void @capture32(ptr %x)
73  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
74
75; CHECK:   getelementptr i8, ptr %[[USP]], i32 -8
76  call void @capture32(ptr %y)
77  call void @llvm.lifetime.end.p0(i64 -1, ptr %y)
78  call void @llvm.lifetime.start.p0(i64 -1, ptr %z)
79
80; CHECK:   getelementptr i8, ptr %[[USP]], i32 -8
81  call void @capture64(ptr %z)
82  call void @llvm.lifetime.end.p0(i64 -1, ptr %z)
83
84  ret void
85}
86
87; Both y and z fit in x's alignment gap.
88define void @h() safestack {
89; CHECK-LABEL: define void @h
90entry:
91; CHECK:  %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
92; CHECK:   getelementptr i8, ptr %[[USP]], i32 -16
93
94  %x = alloca i32, align 16
95  %z = alloca i64, align 4
96  %y = alloca i32, align 4
97
98  call void @llvm.lifetime.start.p0(i64 -1, ptr %x)
99  call void @llvm.lifetime.start.p0(i64 -1, ptr %y)
100  call void @llvm.lifetime.start.p0(i64 -1, ptr %z)
101
102; CHECK:   getelementptr i8, ptr %[[USP]], i32 -16
103  call void @capture32(ptr %x)
104
105; CHECK:   getelementptr i8, ptr %[[USP]], i32 -12
106  call void @capture32(ptr %y)
107
108; CHECK:   getelementptr i8, ptr %[[USP]], i32 -8
109  call void @capture64(ptr %z)
110
111  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
112  call void @llvm.lifetime.end.p0(i64 -1, ptr %y)
113  call void @llvm.lifetime.end.p0(i64 -1, ptr %z)
114
115  ret void
116}
117
118; void f(bool a, bool b) {
119;   long x1, x2; capture64(&x1); capture64(&x2);
120;   if (a) {
121;     long y; capture64(&y);
122;     if (b) {
123;       long y1; capture64(&y1);
124;     } else {
125;       long y2; capture64(&y2);
126;     }
127;   } else {
128;     long z; capture64(&z);
129;     if (b) {
130;       long z1; capture64(&z1);
131;     } else {
132;       long z2; capture64(&z2);
133;     }
134;   }
135; }
136; Everything fits in 4 x 64-bit slots.
137define void @i(i1 zeroext %a, i1 zeroext %b) safestack {
138; CHECK-LABEL: define void @i
139entry:
140; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
141; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -32
142  %x1 = alloca i64, align 8
143  %x2 = alloca i64, align 8
144  %y = alloca i64, align 8
145  %y1 = alloca i64, align 8
146  %y2 = alloca i64, align 8
147  %z = alloca i64, align 8
148  %z1 = alloca i64, align 8
149  %z2 = alloca i64, align 8
150  call void @llvm.lifetime.start.p0(i64 -1, ptr %x1)
151  call void @llvm.lifetime.start.p0(i64 -1, ptr %x2)
152; CHECK:   getelementptr i8, ptr %[[USP]], i32 -8
153; CHECK:   call void @capture64(
154  call void @capture64(ptr nonnull %x1)
155; CHECK:   getelementptr i8, ptr %[[USP]], i32 -16
156; CHECK:   call void @capture64(
157  call void @capture64(ptr nonnull %x2)
158  br i1 %a, label %if.then, label %if.else4
159
160if.then:                                          ; preds = %entry
161  call void @llvm.lifetime.start.p0(i64 -1, ptr %y)
162; CHECK:   getelementptr i8, ptr %[[USP]], i32 -24
163; CHECK:   call void @capture64(
164  call void @capture64(ptr nonnull %y)
165  br i1 %b, label %if.then3, label %if.else
166
167if.then3:                                         ; preds = %if.then
168  call void @llvm.lifetime.start.p0(i64 -1, ptr %y1)
169; CHECK:   getelementptr i8, ptr %[[USP]], i32 -32
170; CHECK:   call void @capture64(
171  call void @capture64(ptr nonnull %y1)
172  call void @llvm.lifetime.end.p0(i64 -1, ptr %y1)
173  br label %if.end
174
175if.else:                                          ; preds = %if.then
176  call void @llvm.lifetime.start.p0(i64 -1, ptr %y2)
177; CHECK:   getelementptr i8, ptr %[[USP]], i32 -32
178; CHECK:   call void @capture64(
179  call void @capture64(ptr nonnull %y2)
180  call void @llvm.lifetime.end.p0(i64 -1, ptr %y2)
181  br label %if.end
182
183if.end:                                           ; preds = %if.else, %if.then3
184  call void @llvm.lifetime.end.p0(i64 -1, ptr %y)
185  br label %if.end9
186
187if.else4:                                         ; preds = %entry
188  call void @llvm.lifetime.start.p0(i64 -1, ptr %z)
189; CHECK:   getelementptr i8, ptr %[[USP]], i32 -24
190; CHECK:   call void @capture64(
191  call void @capture64(ptr nonnull %z)
192  br i1 %b, label %if.then6, label %if.else7
193
194if.then6:                                         ; preds = %if.else4
195  call void @llvm.lifetime.start.p0(i64 -1, ptr %z1)
196; CHECK:   getelementptr i8, ptr %[[USP]], i32 -32
197; CHECK:   call void @capture64(
198  call void @capture64(ptr nonnull %z1)
199  call void @llvm.lifetime.end.p0(i64 -1, ptr %z1)
200  br label %if.end8
201
202if.else7:                                         ; preds = %if.else4
203  call void @llvm.lifetime.start.p0(i64 -1, ptr %z2)
204; CHECK:   getelementptr i8, ptr %[[USP]], i32 -32
205; CHECK:   call void @capture64(
206  call void @capture64(ptr nonnull %z2)
207  call void @llvm.lifetime.end.p0(i64 -1, ptr %z2)
208  br label %if.end8
209
210if.end8:                                          ; preds = %if.else7, %if.then6
211  call void @llvm.lifetime.end.p0(i64 -1, ptr %z)
212  br label %if.end9
213
214if.end9:                                          ; preds = %if.end8, %if.end
215  call void @llvm.lifetime.end.p0(i64 -1, ptr %x2)
216  call void @llvm.lifetime.end.p0(i64 -1, ptr %x1)
217  ret void
218}
219
220; lifetime for x ends in 2 different BBs
221define void @no_merge1(i1 %d) safestack {
222; CHECK-LABEL: define void @no_merge1(
223entry:
224; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
225; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -16
226  %x = alloca i32, align 4
227  %y = alloca i32, align 4
228  call void @llvm.lifetime.start.p0(i64 -1, ptr %x)
229; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
230; CHECK:   call void @capture32(
231  call void @capture32(ptr %x)
232  br i1 %d, label %bb2, label %bb3
233bb2:
234  call void @llvm.lifetime.start.p0(i64 -1, ptr %y)
235; CHECK:   getelementptr i8, ptr %[[USP]], i32 -8
236; CHECK:   call void @capture32(
237  call void @capture32(ptr %y)
238  call void @llvm.lifetime.end.p0(i64 -1, ptr %y)
239  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
240  ret void
241bb3:
242  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
243  ret void
244}
245
246define void @merge1(i1 %d) safestack {
247; CHECK-LABEL: define void @merge1(
248entry:
249; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
250; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -16
251  %x = alloca i32, align 4
252  %y = alloca i32, align 4
253  call void @llvm.lifetime.start.p0(i64 -1, ptr %x)
254; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
255; CHECK:   call void @capture32(
256  call void @capture32(ptr %x)
257  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
258  br i1 %d, label %bb2, label %bb3
259bb2:
260  call void @llvm.lifetime.start.p0(i64 -1, ptr %y)
261; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
262; CHECK:   call void @capture32(
263  call void @capture32(ptr %y)
264  call void @llvm.lifetime.end.p0(i64 -1, ptr %y)
265  ret void
266bb3:
267  ret void
268}
269
270; Missing lifetime.end
271define void @merge2_noend(i1 %d) safestack {
272; CHECK-LABEL: define void @merge2_noend(
273entry:
274; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
275; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -16
276  %x = alloca i32, align 4
277  %y = alloca i32, align 4
278  call void @llvm.lifetime.start.p0(i64 -1, ptr %x)
279; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
280; CHECK:   call void @capture32(
281  call void @capture32(ptr %x)
282  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
283  br i1 %d, label %bb2, label %bb3
284bb2:
285  call void @llvm.lifetime.start.p0(i64 -1, ptr %y)
286; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
287; CHECK:   call void @capture32(
288  call void @capture32(ptr %y)
289  ret void
290bb3:
291  ret void
292}
293
294; Missing lifetime.end
295define void @merge3_noend(i1 %d) safestack {
296; CHECK-LABEL: define void @merge3_noend(
297entry:
298; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
299; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -16
300  %x = alloca i32, align 4
301  %y = alloca i32, align 4
302  call void @llvm.lifetime.start.p0(i64 -1, ptr %x)
303; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
304; CHECK:   call void @capture32(
305  call void @capture32(ptr %x)
306  br i1 %d, label %bb2, label %bb3
307bb2:
308  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
309  call void @llvm.lifetime.start.p0(i64 -1, ptr %y)
310; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
311; CHECK:   call void @capture32(
312  call void @capture32(ptr %y)
313  ret void
314bb3:
315  ret void
316}
317
318; Missing lifetime.start
319define void @nomerge4_nostart(i1 %d) safestack {
320; CHECK-LABEL: define void @nomerge4_nostart(
321entry:
322; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
323; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -16
324  %x = alloca i32, align 4
325  %y = alloca i32, align 4
326; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
327; CHECK:   call void @capture32(
328  call void @capture32(ptr %x)
329  call void @llvm.lifetime.end.p0(i64 -1, ptr %x)
330  br i1 %d, label %bb2, label %bb3
331bb2:
332  call void @llvm.lifetime.start.p0(i64 -1, ptr %y)
333; CHECK:   getelementptr i8, ptr %[[USP]], i32 -8
334; CHECK:   call void @capture32(
335  call void @capture32(ptr %y)
336  ret void
337bb3:
338  ret void
339}
340
341define void @array_merge() safestack {
342; CHECK-LABEL: define void @array_merge(
343entry:
344; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
345; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -800
346  %A.i1 = alloca [100 x i32], align 4
347  %B.i2 = alloca [100 x i32], align 4
348  %A.i = alloca [100 x i32], align 4
349  %B.i = alloca [100 x i32], align 4
350  call void @llvm.lifetime.start.p0(i64 -1, ptr %A.i)
351  call void @llvm.lifetime.start.p0(i64 -1, ptr %B.i)
352; CHECK:   getelementptr i8, ptr %[[USP]], i32 -400
353; CHECK:   call void @capture100x32(
354  call void @capture100x32(ptr %A.i)
355; CHECK:   getelementptr i8, ptr %[[USP]], i32 -800
356; CHECK:   call void @capture100x32(
357  call void @capture100x32(ptr %B.i)
358  call void @llvm.lifetime.end.p0(i64 -1, ptr %A.i)
359  call void @llvm.lifetime.end.p0(i64 -1, ptr %B.i)
360  call void @llvm.lifetime.start.p0(i64 -1, ptr %A.i1)
361  call void @llvm.lifetime.start.p0(i64 -1, ptr %B.i2)
362; CHECK:   getelementptr i8, ptr %[[USP]], i32 -400
363; CHECK:   call void @capture100x32(
364  call void @capture100x32(ptr %A.i1)
365; CHECK:   getelementptr i8, ptr %[[USP]], i32 -800
366; CHECK:   call void @capture100x32(
367  call void @capture100x32(ptr %B.i2)
368  call void @llvm.lifetime.end.p0(i64 -1, ptr %A.i1)
369  call void @llvm.lifetime.end.p0(i64 -1, ptr %B.i2)
370  ret void
371}
372
373define void @myCall_pr15707() safestack {
374; CHECK-LABEL: define void @myCall_pr15707(
375entry:
376; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
377; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -200000
378  %buf1 = alloca i8, i32 100000, align 16
379  %buf2 = alloca i8, i32 100000, align 16
380
381  call void @llvm.lifetime.start.p0(i64 -1, ptr %buf1)
382  call void @llvm.lifetime.end.p0(i64 -1, ptr %buf1)
383
384  call void @llvm.lifetime.start.p0(i64 -1, ptr %buf1)
385  call void @llvm.lifetime.start.p0(i64 -1, ptr %buf2)
386  call void @capture8(ptr %buf1)
387  call void @capture8(ptr %buf2)
388  ret void
389}
390
391; Check that we don't assert and crash even when there are allocas
392; outside the declared lifetime regions.
393define void @bad_range() safestack {
394; CHECK-LABEL: define void @bad_range(
395entry:
396; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
397; A.i and B.i unsafe, not merged
398; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -800
399; A.i1 and B.i2 safe
400; CHECK: = alloca [100 x i32], align 4
401; CHECK: = alloca [100 x i32], align 4
402
403  %A.i1 = alloca [100 x i32], align 4
404  %B.i2 = alloca [100 x i32], align 4
405  %A.i = alloca [100 x i32], align 4
406  %B.i = alloca [100 x i32], align 4
407  call void @llvm.lifetime.start.p0(i64 -1, ptr %A.i) nounwind
408  call void @llvm.lifetime.start.p0(i64 -1, ptr %B.i) nounwind
409  call void @capture100x32(ptr %A.i)
410  call void @capture100x32(ptr %B.i)
411  call void @llvm.lifetime.end.p0(i64 -1, ptr %A.i) nounwind
412  call void @llvm.lifetime.end.p0(i64 -1, ptr %B.i) nounwind
413  br label %block2
414
415block2:
416  ; I am used outside the marked lifetime.
417  call void @capture100x32(ptr %A.i)
418  call void @capture100x32(ptr %B.i)
419  ret void
420}
421
422%struct.Klass = type { i32, i32 }
423
424define i32 @shady_range(i32 %argc, ptr nocapture %argv) safestack {
425; CHECK-LABEL: define i32 @shady_range(
426entry:
427; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
428; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -64
429  %a.i = alloca [4 x %struct.Klass], align 16
430  %b.i = alloca [4 x %struct.Klass], align 16
431  ; I am used outside the lifetime zone below:
432  call void @llvm.lifetime.start.p0(i64 -1, ptr %a.i)
433  call void @llvm.lifetime.start.p0(i64 -1, ptr %b.i)
434  call void @capture8(ptr %a.i)
435  call void @capture8(ptr %b.i)
436  %z3 = load i32, ptr %a.i, align 16
437  call void @llvm.lifetime.end.p0(i64 -1, ptr %a.i)
438  call void @llvm.lifetime.end.p0(i64 -1, ptr %b.i)
439  ret i32 %z3
440}
441
442define void @end_loop() safestack {
443; CHECK-LABEL: define void @end_loop()
444entry:
445; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
446; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -16
447  %x = alloca i8, align 4
448  call void @llvm.lifetime.start.p0(i64 4, ptr %x) nounwind
449  br label %l2
450
451l2:
452  call void @capture8(ptr %x)
453  call void @llvm.lifetime.end.p0(i64 4, ptr %x) nounwind
454  br label %l2
455}
456
457; Check that @x and @y get distinct stack slots => @x lifetime does not break
458; when control re-enters l2.
459define void @start_loop() safestack {
460; CHECK-LABEL: define void @start_loop()
461entry:
462; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
463; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -16
464  %x = alloca i8, align 4
465  %y = alloca i8, align 4
466  call void @llvm.lifetime.start.p0(i64 4, ptr %x) nounwind
467  br label %l2
468
469l2:
470; CHECK:   getelementptr i8, ptr %[[USP]], i32 -8
471  call void @llvm.lifetime.start.p0(i64 4, ptr %y) nounwind
472  call void @capture8(ptr %y)
473  call void @llvm.lifetime.end.p0(i64 4, ptr %y) nounwind
474
475; CHECK:   getelementptr i8, ptr %[[USP]], i32 -4
476  call void @llvm.lifetime.start.p0(i64 4, ptr %x) nounwind
477  call void @capture8(ptr %x)
478  br label %l2
479}
480
481; This test checks for a bug where the stack coloring algorithm was not tracking
482; the live range of allocas through phi instructions, so it did not consider
483; alloca and alloca2 to be live at the same time.  As a result it was using
484; the same stack slot for both allocas.  To ensure this bug isn't present, we
485; check that there are 64 bytes allocated for the unsafe stack which is enough
486; space for both allocas.
487; CHECK-LABEL: @stack_coloring_liveness_bug
488define void @stack_coloring_liveness_bug(i32 %arg0) #0 {
489entry:
490; CHECK:        %[[USP:.*]] = load ptr, ptr @__safestack_unsafe_stack_ptr
491; CHECK-NEXT:   getelementptr i8, ptr %[[USP]], i32 -64
492  %alloca = alloca [32 x i8], align 16
493  %alloca2 = alloca [32 x i8], align 16
494  %cond = icmp eq i32 %arg0, 0
495  br i1 %cond, label %if, label %else
496
497if:
498  br label %end
499
500else:
501; CHECK:   getelementptr i8, ptr %[[USP]], i32 -32
502  call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloca)
503  call void @capture8(ptr %alloca)
504  call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloca)
505  br label %end
506
507end:
508; CHECK:   getelementptr i8, ptr %[[USP]], i32 -64
509  %alloca.end = phi ptr [ %alloca, %if], [%alloca, %else]
510  call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloca2)
511  call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %alloca.end)
512  call void @capture2_8(ptr %alloca2, ptr %alloca.end)
513  call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloca2)
514  call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %alloca.end)
515  ret void
516}
517
518attributes #0 = { safestack }
519
520declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
521declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
522declare void @capture8(ptr)
523declare void @capture32(ptr)
524declare void @capture64(ptr)
525declare void @capture100x32(ptr)
526declare void @capture2_8(ptr, ptr)
527