1 | // RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32 |
2 | // RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64 |
3 | |
4 | struct S { |
5 | int x, y, z; |
6 | }; |
7 | |
8 | // U is not trivially copyable, and requires inalloca to pass by value. |
9 | struct U { |
10 | int u; |
11 | U(); |
12 | ~U(); |
13 | U(const U &); |
14 | }; |
15 | |
16 | struct B; |
17 | |
18 | struct C { |
19 | virtual void foo(); |
20 | virtual int bar(int, double); |
21 | virtual S baz(int); |
22 | virtual S qux(U); |
23 | virtual void thud(...); |
24 | virtual void (B::*plugh())(); |
25 | }; |
26 | |
27 | namespace { |
28 | struct D { |
29 | virtual void foo(); |
30 | }; |
31 | } |
32 | |
33 | void f() { |
34 | void (C::*ptr)(); |
35 | ptr = &C::foo; |
36 | ptr = &C::foo; // Don't crash trying to define the thunk twice :) |
37 | |
38 | int (C::*ptr2)(int, double); |
39 | ptr2 = &C::bar; |
40 | |
41 | S (C::*ptr3)(int); |
42 | ptr3 = &C::baz; |
43 | |
44 | void (D::*ptr4)(); |
45 | ptr4 = &D::foo; |
46 | |
47 | S (C::*ptr5)(U); |
48 | ptr5 = &C::qux; |
49 | |
50 | void (C::*ptr6)(...); |
51 | ptr6 = &C::thud; |
52 | |
53 | auto ptr7 = &C::plugh; |
54 | |
55 | |
56 | // CHECK32-LABEL: define dso_local void @"?f@@YAXXZ"() |
57 | // CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AE" to i8*), i8** %ptr |
58 | // CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B3AE" to i8*), i8** %ptr2 |
59 | // CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AE" to i8*), i8** %ptr3 |
60 | // CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A0x{{[^@]*}}@@$BA@AE" to i8*), i8** %ptr4 |
61 | // CHECK32: } |
62 | // |
63 | // CHECK64-LABEL: define dso_local void @"?f@@YAXXZ"() |
64 | // CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BA@AA" to i8*), i8** %ptr |
65 | // CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$B7AA" to i8*), i8** %ptr2 |
66 | // CHECK64: store i8* bitcast (void (%struct.C*, ...)* @"??_9C@@$BBA@AA" to i8*), i8** %ptr3 |
67 | // CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*, ...)* @"??_9D@?A0x{{[^@]*}}@@$BA@AA" to i8*), i8** %ptr |
68 | // CHECK64: } |
69 | } |
70 | |
71 | |
72 | // Thunk for calling the 1st virtual function in C with no parameters. |
73 | // CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$BA@AE"(%struct.C* %this, ...) |
74 | // CHECK32: #[[ATTR:[0-9]+]] |
75 | // CHECK32-NOT: unnamed_addr |
76 | // CHECK32: comdat |
77 | // CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 0 |
78 | // CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
79 | // CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
80 | // CHECK32-NEXT: ret void |
81 | // CHECK32: } |
82 | // |
83 | // CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BA@AA"(%struct.C* %this, ...) |
84 | // CHECK64: #[[ATTR:[0-9]+]] |
85 | // CHECK64-NOT: unnamed_addr |
86 | // CHECK64: comdat |
87 | // CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 0 |
88 | // CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
89 | // CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
90 | // CHECK64-NEXT: ret void |
91 | // CHECK64: } |
92 | |
93 | // Thunk for calling the 2nd virtual function in C, taking int and double as parameters, returning int. |
94 | // CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$B3AE"(%struct.C* %this, ...) |
95 | // CHECK32: #[[ATTR]] comdat |
96 | // CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 1 |
97 | // CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
98 | // CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
99 | // CHECK32-NEXT: ret void |
100 | // CHECK32: } |
101 | // |
102 | // CHECK64-LABEL: define linkonce_odr void @"??_9C@@$B7AA"(%struct.C* %this, ...) |
103 | // CHECK64: #[[ATTR]] comdat |
104 | // CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 1 |
105 | // CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
106 | // CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
107 | // CHECK64-NEXT: ret void |
108 | // CHECK64: } |
109 | |
110 | // Thunk for calling the 3rd virtual function in C, taking an int parameter, returning a struct. |
111 | // CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$B7AE"(%struct.C* %this, ...) |
112 | // CHECK32: #[[ATTR]] comdat |
113 | // CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 2 |
114 | // CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
115 | // CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
116 | // CHECK32-NEXT: ret void |
117 | // CHECK32: } |
118 | // |
119 | // CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BBA@AA"(%struct.C* %this, ...) |
120 | // CHECK64: #[[ATTR]] comdat |
121 | // CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 2 |
122 | // CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
123 | // CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
124 | // CHECK64-NEXT: ret void |
125 | // CHECK64: } |
126 | |
127 | // Thunk for calling the virtual function in internal class D. |
128 | // CHECK32-LABEL: define internal x86_thiscallcc void @"??_9D@?A0x{{[^@]*}}@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this, ...) |
129 | // CHECK32: #[[ATTR]] |
130 | // CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0 |
131 | // CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]] |
132 | // CHECK32: musttail call x86_thiscallcc void (%"struct.(anonymous namespace)::D"*, ...) [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}}, ...) |
133 | // CHECK32-NEXT: ret void |
134 | // CHECK32: } |
135 | // |
136 | // CHECK64-LABEL: define internal void @"??_9D@?A0x{{[^@]*}}@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this, ...) |
137 | // CHECK64: #[[ATTR]] |
138 | // CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** %{{.*}}, i64 0 |
139 | // CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*, ...)*, void (%"struct.(anonymous namespace)::D"*, ...)** [[VPTR]] |
140 | // CHECK64: musttail call void (%"struct.(anonymous namespace)::D"*, ...) [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}}, ...) |
141 | // CHECK64-NEXT: ret void |
142 | // CHECK64: } |
143 | |
144 | // Thunk for calling the fourth virtual function in C, taking a struct parameter |
145 | // and returning a struct. |
146 | // CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"??_9C@@$BM@AE"(%struct.C* %this, ...) {{.*}} comdat |
147 | // CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 3 |
148 | // CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
149 | // CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
150 | // CHECK32-NEXT: ret void |
151 | // CHECK32: } |
152 | // |
153 | // CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BBI@AA"(%struct.C* %this, ...) {{.*}} comdat |
154 | // CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 3 |
155 | // CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
156 | // CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
157 | // CHECK64: ret void |
158 | // CHECK64: } |
159 | |
160 | // Thunk for calling the fifth virtual function in C which uses the __cdecl calling convention. |
161 | // CHECK32-LABEL: define linkonce_odr void @"??_9C@@$BBA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 { |
162 | // CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 4 |
163 | // CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
164 | // CHECK32: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
165 | // CHECK32: ret void |
166 | // CHECK32: } |
167 | // |
168 | // CHECK64-LABEL: define linkonce_odr void @"??_9C@@$BCA@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 { |
169 | // CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 4 |
170 | // CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
171 | // CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
172 | // CHECK64: ret void |
173 | // CHECK64: } |
174 | |
175 | // CHECK32: define linkonce_odr x86_thiscallcc void @"??_9C@@$BBE@AE"(%struct.C* %this, ...) {{.*}} comdat align 2 { |
176 | // CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 5 |
177 | // CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
178 | // CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
179 | // CHECK32: ret void |
180 | // CHECK32: } |
181 | |
182 | // CHECK64: define linkonce_odr void @"??_9C@@$BCI@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 { |
183 | // CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %{{.*}}, i64 5 |
184 | // CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]] |
185 | // CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...) |
186 | // CHECK64: ret void |
187 | // CHECK64: } |
188 | |
189 | // CHECK32: #[[ATTR]] = {{{.*}}"thunk"{{.*}}} |
190 | |