OLD | NEW |
---|---|
(Empty) | |
1 ; RUN: opt < %s -expand-varargs -S | FileCheck %s | |
eliben
2013/03/21 16:10:11
Add a test with more than one call/invoke to a var
Mark Seaborn
2013/03/21 18:07:55
Done.
| |
2 | |
3 %va_list = type i8* | |
4 | |
5 declare void @llvm.va_start(i8*) | |
6 declare void @llvm.va_end(i8*) | |
7 declare void @llvm.va_copy(i8*, i8*) | |
8 | |
9 declare i32 @outside_func(i32 %arg, %va_list* %args) | |
10 | |
11 | |
12 ; Produced by the expansion of @varargs_call1(): | |
13 ; CHECK: %vararg_call = type <{ i64, i32 }> | |
14 | |
15 | |
16 define i32 @varargs_func(i32 %arg, ...) { | |
17 %arglist_alloc = alloca %va_list | |
18 %arglist = bitcast %va_list* %arglist_alloc to i8* | |
19 | |
20 call void @llvm.va_start(i8* %arglist) | |
21 %result = call i32 @outside_func(i32 %arg, %va_list* %arglist_alloc) | |
22 call void @llvm.va_end(i8* %arglist) | |
23 ret i32 %result | |
24 } | |
25 ; CHECK: define i32 @varargs_func(i32 %arg, i8* %varargs) { | |
26 ; CHECK-NEXT: %arglist_alloc = alloca i8* | |
27 ; CHECK-NEXT: %arglist = bitcast i8** %arglist_alloc to i8* | |
28 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i8** | |
29 ; CHECK-NEXT: store i8* %varargs, i8** %arglist1 | |
30 ; CHECK-NEXT: %result = call i32 @outside_func(i32 %arg, i8** %arglist_alloc) | |
31 ; CHECK-NEXT: ret i32 %result | |
32 | |
33 | |
34 define i32 @varargs_call1() { | |
35 %result = call i32 (i32, ...)* @varargs_func(i32 111, i64 222, i32 333) | |
36 ret i32 %result | |
37 } | |
38 ; CHECK: define i32 @varargs_call1() { | |
39 ; CHECK-NEXT: %vararg_buffer = alloca %vararg_call | |
40 ; CHECK-NEXT: %vararg_lifetime_bitcast = bitcast %vararg_call* %vararg_buffer to i8* | |
41 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 12, i8* %vararg_lifetime_bitcas t) | |
42 ; CHECK-NEXT: %vararg_ptr = getelementptr %vararg_call* %vararg_buffer, i32 0, i 32 0 | |
43 ; CHECK-NEXT: store i64 222, i64* %vararg_ptr | |
44 ; CHECK-NEXT: %vararg_ptr1 = getelementptr %vararg_call* %vararg_buffer, i32 0, i32 1 | |
45 ; CHECK-NEXT: store i32 333, i32* %vararg_ptr1 | |
46 ; CHECK-NEXT: %vararg_func = bitcast i32 (i32, ...)* bitcast (i32 (i32, i8*)* @v arargs_func to i32 (i32, ...)*) to i32 (i32, %vararg_call*)* | |
47 ; CHECK-NEXT: %result = call i32 %vararg_func(i32 111, %vararg_call* %vararg_buf fer) | |
48 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 12, i8* %vararg_lifetime_bitcast) | |
49 ; CHECK-NEXT: ret i32 %result | |
50 | |
51 | |
52 define i32 @varargs_call2() { | |
53 %result = call i32 (i32, ...)* @varargs_func(i32 111) | |
54 ret i32 %result | |
55 } | |
56 ; CHECK: define i32 @varargs_call2() { | |
57 ; CHECK-NEXT: %vararg_func = bitcast i32 (i32, ...)* bitcast (i32 (i32, i8*)* @v arargs_func to i32 (i32, ...)*) to i32 (i32, {}*)* | |
58 ; CHECK-NEXT: %result = call i32 %vararg_func(i32 111, {}* undef) | |
59 | |
60 | |
61 define i32 @varargs_invoke() { | |
62 %result = invoke i32 (i32, ...)* @varargs_func(i32 111, i64 222) | |
63 to label %cont unwind label %lpad | |
64 cont: | |
65 ret i32 %result | |
66 lpad: | |
67 %lp = landingpad { i8*, i32 } personality i8* null cleanup | |
68 ret i32 0 | |
69 } | |
70 ; CHECK: @varargs_invoke | |
71 ; CHECK: %result = invoke i32 %vararg_func(i32 111, %vararg_call.0* %vararg_buff er) | |
72 ; CHECK-NEXT: to label %cont unwind label %lpad | |
73 ; CHECK: cont: | |
74 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) | |
75 ; CHECK: lpad: | |
76 ; CHECK: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) | |
77 | |
78 | |
79 define i32 @va_arg_i32(i8* %arglist) { | |
80 %result = va_arg i8* %arglist, i32 | |
81 ret i32 %result | |
82 } | |
83 ; CHECK: define i32 @va_arg_i32(i8* %arglist) { | |
84 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i32** | |
85 ; CHECK-NEXT: %arglist_current = load i32** %arglist1 | |
86 ; CHECK-NEXT: %result = load i32* %arglist_current | |
87 ; CHECK-NEXT: %arglist_next = getelementptr i32* %arglist_current, i32 1 | |
88 ; CHECK-NEXT: store i32* %arglist_next, i32** %arglist1 | |
89 ; CHECK-NEXT: ret i32 %result | |
90 | |
91 | |
92 define i64 @va_arg_i64(i8* %arglist) { | |
93 %result = va_arg i8* %arglist, i64 | |
94 ret i64 %result | |
95 } | |
96 ; CHECK: define i64 @va_arg_i64(i8* %arglist) { | |
97 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i64** | |
98 ; CHECK-NEXT: %arglist_current = load i64** %arglist1 | |
99 ; CHECK-NEXT: %result = load i64* %arglist_current | |
100 ; CHECK-NEXT: %arglist_next = getelementptr i64* %arglist_current, i32 1 | |
101 ; CHECK-NEXT: store i64* %arglist_next, i64** %arglist1 | |
102 ; CHECK-NEXT: ret i64 %result | |
103 | |
104 | |
105 define void @do_va_copy(i8* %dest, i8* %src) { | |
106 call void @llvm.va_copy(i8* %dest, i8* %src) | |
107 ret void | |
108 } | |
109 ; CHECK: define void @do_va_copy(i8* %dest, i8* %src) { | |
110 ; CHECK-NEXT: %vacopy_src = bitcast i8* %src to i8** | |
111 ; CHECK-NEXT: %vacopy_dest = bitcast i8* %dest to i8** | |
112 ; CHECK-NEXT: %vacopy_currentptr = load i8** %vacopy_src | |
113 ; CHECK-NEXT: store i8* %vacopy_currentptr, i8** %vacopy_dest | |
114 ; CHECK-NEXT: ret void | |
OLD | NEW |