OLD | NEW |
1 ; RUN: opt < %s -expand-varargs -S | FileCheck %s | 1 ; RUN: opt < %s -expand-varargs -S | FileCheck %s |
2 | 2 |
3 %va_list = type i8* | 3 %va_list = type i8* |
4 | 4 |
5 declare void @llvm.va_start(i8*) | 5 declare void @llvm.va_start(i8*) |
6 declare void @llvm.va_end(i8*) | 6 declare void @llvm.va_end(i8*) |
7 declare void @llvm.va_copy(i8*, i8*) | 7 declare void @llvm.va_copy(i8*, i8*) |
8 | 8 |
9 declare i32 @outside_func(i32 %arg, %va_list* %args) | 9 declare i32 @outside_func(i32 %arg, %va_list* %args) |
10 | 10 |
11 | |
12 ; Produced by the expansion of @varargs_call1(): | |
13 ; CHECK: %vararg_call = type <{ i64, i32 }> | |
14 | |
15 ; Produced by the expansion of @call_with_zero_varargs(). | |
16 ; We have a dummy field to deal with buggy programs: | |
17 ; CHECK: %vararg_call.0 = type <{ i32 }> | |
18 | |
19 | |
20 define i32 @varargs_func(i32 %arg, ...) { | 11 define i32 @varargs_func(i32 %arg, ...) { |
21 %arglist_alloc = alloca %va_list | 12 %arglist_alloc = alloca %va_list |
22 %arglist = bitcast %va_list* %arglist_alloc to i8* | 13 %arglist = bitcast %va_list* %arglist_alloc to i8* |
23 | 14 |
24 call void @llvm.va_start(i8* %arglist) | 15 call void @llvm.va_start(i8* %arglist) |
25 %result = call i32 @outside_func(i32 %arg, %va_list* %arglist_alloc) | 16 %result = call i32 @outside_func(i32 %arg, %va_list* %arglist_alloc) |
26 call void @llvm.va_end(i8* %arglist) | 17 call void @llvm.va_end(i8* %arglist) |
27 ret i32 %result | 18 ret i32 %result |
28 } | 19 } |
29 ; CHECK: define i32 @varargs_func(i32 %arg, i8* %varargs) { | 20 ; CHECK: define i32 @varargs_func(i32 %arg, i8* %varargs) { |
30 ; CHECK-NEXT: %arglist_alloc = alloca i8* | 21 ; CHECK-NEXT: %arglist_alloc = alloca i8* |
31 ; CHECK-NEXT: %arglist = bitcast i8** %arglist_alloc to i8* | 22 ; CHECK-NEXT: %arglist = bitcast i8** %arglist_alloc to i8* |
32 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i8** | 23 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i8** |
33 ; CHECK-NEXT: store i8* %varargs, i8** %arglist1 | 24 ; CHECK-NEXT: store i8* %varargs, i8** %arglist1 |
34 ; CHECK-NEXT: %result = call i32 @outside_func(i32 %arg, i8** %arglist_alloc) | 25 ; CHECK-NEXT: %result = call i32 @outside_func(i32 %arg, i8** %arglist_alloc) |
35 ; CHECK-NEXT: ret i32 %result | 26 ; CHECK-NEXT: ret i32 %result |
36 | 27 |
37 | 28 |
38 define i32 @varargs_call1() { | 29 define i32 @varargs_call1() { |
39 %result = call i32 (i32, ...)* @varargs_func(i32 111, i64 222, i32 333) | 30 %result = call i32 (i32, ...)* @varargs_func(i32 111, i64 222, i32 333) |
40 ret i32 %result | 31 ret i32 %result |
41 } | 32 } |
42 ; CHECK: define i32 @varargs_call1() { | 33 ; CHECK: define i32 @varargs_call1() { |
43 ; CHECK-NEXT: %vararg_buffer = alloca %vararg_call | 34 ; CHECK-NEXT: %vararg_buffer = alloca <{ i64, i32 }> |
44 ; CHECK-NEXT: %vararg_lifetime_bitcast = bitcast %vararg_call* %vararg_buffer to
i8* | 35 ; CHECK-NEXT: %vararg_lifetime_bitcast = bitcast <{ i64, i32 }>* %vararg_buffer
to i8* |
45 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 12, i8* %vararg_lifetime_bitcas
t) | 36 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 12, i8* %vararg_lifetime_bitcas
t) |
46 ; CHECK-NEXT: %vararg_ptr = getelementptr %vararg_call* %vararg_buffer, i32 0, i
32 0 | 37 ; CHECK-NEXT: %vararg_ptr = getelementptr <{ i64, i32 }>* %vararg_buffer, i32 0,
i32 0 |
47 ; CHECK-NEXT: store i64 222, i64* %vararg_ptr | 38 ; CHECK-NEXT: store i64 222, i64* %vararg_ptr |
48 ; CHECK-NEXT: %vararg_ptr1 = getelementptr %vararg_call* %vararg_buffer, i32 0,
i32 1 | 39 ; CHECK-NEXT: %vararg_ptr1 = getelementptr <{ i64, i32 }>* %vararg_buffer, i32 0
, i32 1 |
49 ; CHECK-NEXT: store i32 333, i32* %vararg_ptr1 | 40 ; CHECK-NEXT: store i32 333, i32* %vararg_ptr1 |
50 ; CHECK-NEXT: %vararg_func = bitcast i32 (i32, ...)* bitcast (i32 (i32, i8*)* @v
arargs_func to i32 (i32, ...)*) to i32 (i32, %vararg_call*)* | 41 ; CHECK-NEXT: %vararg_func = bitcast i32 (i32, ...)* bitcast (i32 (i32, i8*)* @v
arargs_func to i32 (i32, ...)*) to i32 (i32, <{ i64, i32 }>*)* |
51 ; CHECK-NEXT: %result = call i32 %vararg_func(i32 111, %vararg_call* %vararg_buf
fer) | 42 ; CHECK-NEXT: %result = call i32 %vararg_func(i32 111, <{ i64, i32 }>* %vararg_b
uffer) |
52 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 12, i8* %vararg_lifetime_bitcast) | 43 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 12, i8* %vararg_lifetime_bitcast) |
53 ; CHECK-NEXT: ret i32 %result | 44 ; CHECK-NEXT: ret i32 %result |
54 | 45 |
55 | 46 |
56 ; Check that the pass works when there are no variable arguments. | 47 ; Check that the pass works when there are no variable arguments. |
57 define i32 @call_with_zero_varargs() { | 48 define i32 @call_with_zero_varargs() { |
58 %result = call i32 (i32, ...)* @varargs_func(i32 111) | 49 %result = call i32 (i32, ...)* @varargs_func(i32 111) |
59 ret i32 %result | 50 ret i32 %result |
60 } | 51 } |
61 ; CHECK: define i32 @call_with_zero_varargs() { | 52 ; CHECK: define i32 @call_with_zero_varargs() { |
62 ; CHECK-NEXT: %vararg_buffer = alloca %vararg_call.0 | 53 ; We have a dummy i32 field to deal with buggy programs: |
63 ; CHECK: %vararg_func = bitcast i32 (i32, ...)* bitcast (i32 (i32, i8*)* @vararg
s_func to i32 (i32, ...)*) to i32 (i32, %vararg_call.0*)* | 54 ; CHECK-NEXT: %vararg_buffer = alloca <{ i32 }> |
64 ; CHECK-NEXT: %result = call i32 %vararg_func(i32 111, %vararg_call.0* %vararg_b
uffer) | 55 ; CHECK: %vararg_func = bitcast i32 (i32, ...)* bitcast (i32 (i32, i8*)* @vararg
s_func to i32 (i32, ...)*) to i32 (i32, <{ i32 }>*)* |
| 56 ; CHECK-NEXT: %result = call i32 %vararg_func(i32 111, <{ i32 }>* %vararg_buffer
) |
65 | 57 |
66 | 58 |
67 ; Check that "invoke" instructions are expanded out too. | 59 ; Check that "invoke" instructions are expanded out too. |
68 define i32 @varargs_invoke() { | 60 define i32 @varargs_invoke() { |
69 %result = invoke i32 (i32, ...)* @varargs_func(i32 111, i64 222) | 61 %result = invoke i32 (i32, ...)* @varargs_func(i32 111, i64 222) |
70 to label %cont unwind label %lpad | 62 to label %cont unwind label %lpad |
71 cont: | 63 cont: |
72 ret i32 %result | 64 ret i32 %result |
73 lpad: | 65 lpad: |
74 %lp = landingpad { i8*, i32 } personality i8* null cleanup | 66 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
75 ret i32 0 | 67 ret i32 0 |
76 } | 68 } |
77 ; CHECK: @varargs_invoke | 69 ; CHECK: @varargs_invoke |
78 ; CHECK: %result = invoke i32 %vararg_func(i32 111, %vararg_call.1* %vararg_buff
er) | 70 ; CHECK: %result = invoke i32 %vararg_func(i32 111, <{ i64 }>* %vararg_buffer) |
79 ; CHECK-NEXT: to label %cont unwind label %lpad | 71 ; CHECK-NEXT: to label %cont unwind label %lpad |
80 ; CHECK: cont: | 72 ; CHECK: cont: |
81 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) | 73 ; CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) |
82 ; CHECK: lpad: | 74 ; CHECK: lpad: |
83 ; CHECK: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) | 75 ; CHECK: call void @llvm.lifetime.end(i64 8, i8* %vararg_lifetime_bitcast) |
84 | 76 |
85 | 77 |
86 define void @varargs_multiple_calls() { | 78 define void @varargs_multiple_calls() { |
87 %call1 = call i32 (i32, ...)* @varargs_func(i32 11, i64 22, i32 33) | 79 %call1 = call i32 (i32, ...)* @varargs_func(i32 11, i64 22, i32 33) |
88 %call2 = call i32 (i32, ...)* @varargs_func(i32 44, i64 55, i32 66) | 80 %call2 = call i32 (i32, ...)* @varargs_func(i32 44, i64 55, i32 66) |
89 ret void | 81 ret void |
90 } | 82 } |
91 ; CHECK: @varargs_multiple_calls() | 83 ; CHECK: @varargs_multiple_calls() |
92 ; The added allocas should appear at the start of the function. | 84 ; The added allocas should appear at the start of the function. |
93 ; CHECK: %vararg_buffer{{.*}} = alloca %vararg_call{{.*}} | 85 ; CHECK: %vararg_buffer{{.*}} = alloca <{ i64, i32 }> |
94 ; CHECK: %vararg_buffer{{.*}} = alloca %vararg_call{{.*}} | 86 ; CHECK: %vararg_buffer{{.*}} = alloca <{ i64, i32 }> |
95 ; CHECK: %call1 = call i32 %vararg_func{{.*}}(i32 11, %vararg_call{{.*}}* %varar
g_buffer{{.*}}) | 87 ; CHECK: %call1 = call i32 %vararg_func{{.*}}(i32 11, <{ i64, i32 }>* %vararg_bu
ffer{{.*}}) |
96 ; CHECK: %call2 = call i32 %vararg_func{{.*}}(i32 44, %vararg_call{{.*}}* %varar
g_buffer{{.*}}) | 88 ; CHECK: %call2 = call i32 %vararg_func{{.*}}(i32 44, <{ i64, i32 }>* %vararg_bu
ffer{{.*}}) |
97 | 89 |
98 | 90 |
99 define i32 @va_arg_i32(i8* %arglist) { | 91 define i32 @va_arg_i32(i8* %arglist) { |
100 %result = va_arg i8* %arglist, i32 | 92 %result = va_arg i8* %arglist, i32 |
101 ret i32 %result | 93 ret i32 %result |
102 } | 94 } |
103 ; CHECK: define i32 @va_arg_i32(i8* %arglist) { | 95 ; CHECK: define i32 @va_arg_i32(i8* %arglist) { |
104 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i32** | 96 ; CHECK-NEXT: %arglist1 = bitcast i8* %arglist to i32** |
105 ; CHECK-NEXT: %arglist_current = load i32** %arglist1 | 97 ; CHECK-NEXT: %arglist_current = load i32** %arglist1 |
106 ; CHECK-NEXT: %result = load i32* %arglist_current | 98 ; CHECK-NEXT: %result = load i32* %arglist_current |
(...skipping 18 matching lines...) Expand all Loading... |
125 define void @do_va_copy(i8* %dest, i8* %src) { | 117 define void @do_va_copy(i8* %dest, i8* %src) { |
126 call void @llvm.va_copy(i8* %dest, i8* %src) | 118 call void @llvm.va_copy(i8* %dest, i8* %src) |
127 ret void | 119 ret void |
128 } | 120 } |
129 ; CHECK: define void @do_va_copy(i8* %dest, i8* %src) { | 121 ; CHECK: define void @do_va_copy(i8* %dest, i8* %src) { |
130 ; CHECK-NEXT: %vacopy_src = bitcast i8* %src to i8** | 122 ; CHECK-NEXT: %vacopy_src = bitcast i8* %src to i8** |
131 ; CHECK-NEXT: %vacopy_dest = bitcast i8* %dest to i8** | 123 ; CHECK-NEXT: %vacopy_dest = bitcast i8* %dest to i8** |
132 ; CHECK-NEXT: %vacopy_currentptr = load i8** %vacopy_src | 124 ; CHECK-NEXT: %vacopy_currentptr = load i8** %vacopy_src |
133 ; CHECK-NEXT: store i8* %vacopy_currentptr, i8** %vacopy_dest | 125 ; CHECK-NEXT: store i8* %vacopy_currentptr, i8** %vacopy_dest |
134 ; CHECK-NEXT: ret void | 126 ; CHECK-NEXT: ret void |
OLD | NEW |