1 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s
2 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s
3 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s
4
5 struct Empty {};
6
7 struct EmptyWithCtor {
EmptyWithCtorEmptyWithCtor8 EmptyWithCtor() {}
9 };
10
11 struct Small {
12 int x;
13 };
14
15 // This is a C++11 trivial and standard-layout struct but not a C++03 POD.
16 struct SmallCpp11NotCpp03Pod : Empty {
17 int x;
18 };
19
20 struct SmallWithCtor {
SmallWithCtorSmallWithCtor21 SmallWithCtor() {}
22 int x;
23 };
24
25 struct Multibyte {
26 char a, b, c, d;
27 };
28
29 struct Packed {
30 short a;
31 int b;
32 short c;
33 };
34
35 struct SmallWithDtor {
36 SmallWithDtor();
37 ~SmallWithDtor();
38 int x;
39 };
40
41 struct SmallWithVftable {
42 int x;
43 virtual void foo();
44 };
45
46 struct Medium {
47 int x, y;
48 };
49
50 struct MediumWithCopyCtor {
51 MediumWithCopyCtor();
52 MediumWithCopyCtor(const struct MediumWithCopyCtor &);
53 int x, y;
54 };
55
56 struct Big {
57 int a, b, c, d, e, f;
58 };
59
60 struct BigWithDtor {
61 BigWithDtor();
62 ~BigWithDtor();
63 int a, b, c, d, e, f;
64 };
65
66 // WIN32: declare void @"{{.*take_bools_and_chars.*}}"
67 // WIN32: (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
68 // WIN32: i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
69 void take_bools_and_chars(char a, char b, SmallWithDtor c, char d, bool e, int f, bool g);
call_bools_and_chars()70 void call_bools_and_chars() {
71 take_bools_and_chars('A', 'B', SmallWithDtor(), 'D', true, 13, false);
72 }
73
74 // Returning structs that fit into a register.
small_return()75 Small small_return() { return Small(); }
76 // LINUX-LABEL: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
77 // WIN32: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
78 // WIN64: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
79
medium_return()80 Medium medium_return() { return Medium(); }
81 // LINUX-LABEL: define void @_Z13medium_returnv(%struct.Medium* noalias sret %agg.result)
82 // WIN32: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
83 // WIN64: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
84
85 // Returning structs that fit into a register but are not POD.
small_non_pod_return()86 SmallCpp11NotCpp03Pod small_non_pod_return() { return SmallCpp11NotCpp03Pod(); }
87 // LINUX-LABEL: define void @_Z20small_non_pod_returnv(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
88 // WIN32: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
89 // WIN64: define void @"\01?small_non_pod_return@@YA?AUSmallCpp11NotCpp03Pod@@XZ"(%struct.SmallCpp11NotCpp03Pod* noalias sret %agg.result)
90
small_with_ctor_return()91 SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); }
92 // LINUX-LABEL: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret %agg.result)
93 // WIN32: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
94 // WIN64: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
95
small_with_vftable_return()96 SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
97 // LINUX-LABEL: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result)
98 // WIN32: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
99 // WIN64: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
100
medium_with_copy_ctor_return()101 MediumWithCopyCtor medium_with_copy_ctor_return() { return MediumWithCopyCtor(); }
102 // LINUX-LABEL: define void @_Z28medium_with_copy_ctor_returnv(%struct.MediumWithCopyCtor* noalias sret %agg.result)
103 // WIN32: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
104 // WIN64: define void @"\01?medium_with_copy_ctor_return@@YA?AUMediumWithCopyCtor@@XZ"(%struct.MediumWithCopyCtor* noalias sret %agg.result)
105
106 // Returning a large struct that doesn't fit into a register.
big_return()107 Big big_return() { return Big(); }
108 // LINUX-LABEL: define void @_Z10big_returnv(%struct.Big* noalias sret %agg.result)
109 // WIN32: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
110 // WIN64: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
111
112
small_arg(Small s)113 void small_arg(Small s) {}
114 // LINUX-LABEL: define void @_Z9small_arg5Small(i32 %s.0)
115 // WIN32: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.0)
116 // WIN64: define void @"\01?small_arg@@YAXUSmall@@@Z"(i32 %s.coerce)
117
medium_arg(Medium s)118 void medium_arg(Medium s) {}
119 // LINUX-LABEL: define void @_Z10medium_arg6Medium(i32 %s.0, i32 %s.1)
120 // WIN32: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i32 %s.0, i32 %s.1)
121 // WIN64: define void @"\01?medium_arg@@YAXUMedium@@@Z"(i64 %s.coerce)
122
small_arg_with_ctor(SmallWithCtor s)123 void small_arg_with_ctor(SmallWithCtor s) {}
124 // LINUX-LABEL: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s)
125 // WIN32: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.0)
126 // WIN64: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(i32 %s.coerce)
127
128 // FIXME: We could coerce to a series of i32s here if we wanted to.
multibyte_arg(Multibyte s)129 void multibyte_arg(Multibyte s) {}
130 // LINUX-LABEL: define void @_Z13multibyte_arg9Multibyte(%struct.Multibyte* byval align 4 %s)
131 // WIN32: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(%struct.Multibyte* byval align 4 %s)
132 // WIN64: define void @"\01?multibyte_arg@@YAXUMultibyte@@@Z"(i32 %s.coerce)
133
packed_arg(Packed s)134 void packed_arg(Packed s) {}
135 // LINUX-LABEL: define void @_Z10packed_arg6Packed(%struct.Packed* byval align 4 %s)
136 // WIN32: define void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* byval align 4 %s)
137 // WIN64: define void @"\01?packed_arg@@YAXUPacked@@@Z"(%struct.Packed* %s)
138
139 // Test that dtors are invoked in the callee.
small_arg_with_dtor(SmallWithDtor s)140 void small_arg_with_dtor(SmallWithDtor s) {}
141 // WIN32: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca) {{.*}} {
142 // WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
143 // WIN32: }
144 // WIN64: define void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
145 // WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
146 // WIN64: }
147
call_small_arg_with_dtor()148 void call_small_arg_with_dtor() {
149 small_arg_with_dtor(SmallWithDtor());
150 }
151 // The temporary is copied, so it's destroyed in the caller as well as the
152 // callee.
153 // WIN64-LABEL: define void @"\01?call_small_arg_with_dtor@@YAXXZ"()
154 // WIN64: call %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QEAA@XZ"
155 // WIN64: call void @"\01?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %{{.*}})
156 // WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
157 // WIN64: ret void
158
159 // Test that references aren't destroyed in the callee.
ref_small_arg_with_dtor(const SmallWithDtor & s)160 void ref_small_arg_with_dtor(const SmallWithDtor &s) { }
161 // WIN32: define void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s) {{.*}} {
162 // WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
163 // WIN32: }
164 // WIN64-LABEL: define void @"\01?ref_small_arg_with_dtor@@YAXAEBUSmallWithDtor@@@Z"(%struct.SmallWithDtor* dereferenceable({{[0-9]+}}) %s)
165
big_arg_with_dtor(BigWithDtor s)166 void big_arg_with_dtor(BigWithDtor s) {}
167 // WIN64-LABEL: define void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %s)
168 // WIN64: call void @"\01??1BigWithDtor@@QEAA@XZ"
169 // WIN64: }
170
call_big_arg_with_dtor()171 void call_big_arg_with_dtor() {
172 big_arg_with_dtor(BigWithDtor());
173 }
174 // We can elide the copy of the temporary in the caller, because this object is
175 // larger than 8 bytes and is passed indirectly.
176 // WIN64-LABEL: define void @"\01?call_big_arg_with_dtor@@YAXXZ"()
177 // WIN64: call %struct.BigWithDtor* @"\01??0BigWithDtor@@QEAA@XZ"
178 // WIN64: call void @"\01?big_arg_with_dtor@@YAXUBigWithDtor@@@Z"(%struct.BigWithDtor* %{{.*}})
179 // WIN64-NOT: call void @"\01??1BigWithDtor@@QEAA@XZ"
180 // WIN64: ret void
181
182 // Test that temporaries passed by reference are destroyed in the caller.
temporary_ref_with_dtor()183 void temporary_ref_with_dtor() {
184 ref_small_arg_with_dtor(SmallWithDtor());
185 }
186 // WIN32: define void @"\01?temporary_ref_with_dtor@@YAXXZ"() {{.*}} {
187 // WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
188 // WIN32: call void @"\01?ref_small_arg_with_dtor@@YAXABUSmallWithDtor@@@Z"
189 // WIN32: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
190 // WIN32: }
191
192 void takes_two_by_val_with_dtor(SmallWithDtor a, SmallWithDtor b);
eh_cleanup_arg_with_dtor()193 void eh_cleanup_arg_with_dtor() {
194 takes_two_by_val_with_dtor(SmallWithDtor(), SmallWithDtor());
195 }
196 // When exceptions are off, we don't have any cleanups. See
197 // microsoft-abi-exceptions.cpp for these cleanups.
198 // WIN32: define void @"\01?eh_cleanup_arg_with_dtor@@YAXXZ"() {{.*}} {
199 // WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
200 // WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ"
201 // WIN32: call void @"\01?takes_two_by_val_with_dtor@@YAXUSmallWithDtor@@0@Z"
202 // WIN32-NOT: call x86_thiscallcc void @"\01??1SmallWithDtor@@QAE@XZ"
203 // WIN32: }
204
small_arg_with_vftable(SmallWithVftable s)205 void small_arg_with_vftable(SmallWithVftable s) {}
206 // LINUX-LABEL: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
207 // WIN32: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca)
208 // WIN64: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
209
medium_arg_with_copy_ctor(MediumWithCopyCtor s)210 void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
211 // LINUX-LABEL: define void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
212 // WIN32: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca)
213 // WIN64: define void @"\01?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
214
big_arg(Big s)215 void big_arg(Big s) {}
216 // LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
217 // WIN32: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s)
218 // WIN64: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* %s)
219
220 // PR27607: We would attempt to load i32 value out of the reference instead of
221 // just loading the pointer from the struct during argument expansion.
222 struct RefField {
223 RefField(int &x);
224 int &x;
225 };
takes_ref_field(RefField s)226 void takes_ref_field(RefField s) {}
227 // LINUX-LABEL: define void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %s)
228 // WIN32: define void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %s.0)
229 // WIN64: define void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %s.coerce)
230
pass_ref_field()231 void pass_ref_field() {
232 int x;
233 takes_ref_field(RefField(x));
234 }
235 // LINUX-LABEL: define void @_Z14pass_ref_fieldv()
236 // LINUX: call void @_Z15takes_ref_field8RefField(%struct.RefField* byval align 4 %{{.*}})
237 // WIN32-LABEL: define void @"\01?pass_ref_field@@YAXXZ"()
238 // WIN32: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i32* %{{.*}})
239 // WIN64-LABEL: define void @"\01?pass_ref_field@@YAXXZ"()
240 // WIN64: call void @"\01?takes_ref_field@@YAXURefField@@@Z"(i64 %{{.*}})
241
242 class Class {
243 public:
thiscall_method_small()244 Small thiscall_method_small() { return Small(); }
245 // LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
246 // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
247 // WIN64: define linkonce_odr void @"\01?thiscall_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
248
thiscall_method_small_with_ctor()249 SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); }
250 // LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
251 // WIN32: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
252 // WIN64: define linkonce_odr void @"\01?thiscall_method_small_with_ctor@Class@@QEAA?AUSmallWithCtor@@XZ"(%class.Class* %this, %struct.SmallWithCtor* noalias sret %agg.result)
253
cdecl_method_small()254 Small __cdecl cdecl_method_small() { return Small(); }
255 // LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
256 // WIN32: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
257 // WIN64: define linkonce_odr void @"\01?cdecl_method_small@Class@@QEAA?AUSmall@@XZ"(%class.Class* %this, %struct.Small* noalias sret %agg.result)
258
cdecl_method_big()259 Big __cdecl cdecl_method_big() { return Big(); }
260 // LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret %agg.result, %class.Class* %this)
261 // WIN32: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
262 // WIN64: define linkonce_odr void @"\01?cdecl_method_big@Class@@QEAA?AUBig@@XZ"(%class.Class* %this, %struct.Big* noalias sret %agg.result)
263
thiscall_method_arg(Empty s)264 void thiscall_method_arg(Empty s) {}
265 // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* %this)
266 // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s)
267 // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmpty@@@Z"(%class.Class* %this, i8 %s.coerce)
268
thiscall_method_arg(EmptyWithCtor s)269 void thiscall_method_arg(EmptyWithCtor s) {}
270 // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(%class.Class* %this)
271 // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s)
272 // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUEmptyWithCtor@@@Z"(%class.Class* %this, i8 %s.coerce)
273
thiscall_method_arg(Small s)274 void thiscall_method_arg(Small s) {}
275 // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* %this, i32 %s.0)
276 // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, i32 %s.0)
277 // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmall@@@Z"(%class.Class* %this, i32 %s.coerce)
278
thiscall_method_arg(SmallWithCtor s)279 void thiscall_method_arg(SmallWithCtor s) {}
280 // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
281 // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.0)
282 // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUSmallWithCtor@@@Z"(%class.Class* %this, i32 %s.coerce)
283
thiscall_method_arg(Big s)284 void thiscall_method_arg(Big s) {}
285 // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(%class.Class* %this, %struct.Big* byval align 4 %s)
286 // WIN32: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s)
287 // WIN64: define linkonce_odr void @"\01?thiscall_method_arg@Class@@QEAAXUBig@@@Z"(%class.Class* %this, %struct.Big* %s)
288 };
289
use_class()290 void use_class() {
291 Class c;
292 c.thiscall_method_small();
293 c.thiscall_method_small_with_ctor();
294
295 c.cdecl_method_small();
296 c.cdecl_method_big();
297
298 c.thiscall_method_arg(Empty());
299 c.thiscall_method_arg(EmptyWithCtor());
300 c.thiscall_method_arg(Small());
301 c.thiscall_method_arg(SmallWithCtor());
302 c.thiscall_method_arg(Big());
303 }
304
305 struct X {
306 X();
307 ~X();
308 };
g(X)309 void g(X) {
310 }
311 // WIN32: define void @"\01?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca) {{.*}} {
312 // WIN32: call x86_thiscallcc void @"\01??1X@@QAE@XZ"(%struct.X* {{.*}})
313 // WIN32: }
f()314 void f() {
315 g(X());
316 }
317 // WIN32: define void @"\01?f@@YAXXZ"() {{.*}} {
318 // WIN32-NOT: call {{.*}} @"\01??1X@@QAE@XZ"
319 // WIN32: }
320
321
322 namespace test2 {
323 // We used to crash on this due to the mixture of POD byval and non-trivial
324 // byval.
325
326 struct NonTrivial {
327 NonTrivial();
328 NonTrivial(const NonTrivial &o);
329 ~NonTrivial();
330 int a;
331 };
332 struct POD { int b; };
333
334 int foo(NonTrivial a, POD b);
bar()335 void bar() {
336 POD b;
337 b.b = 13;
338 int c = foo(NonTrivial(), b);
339 }
340 // WIN32-LABEL: define void @"\01?bar@test2@@YAXXZ"() {{.*}} {
341 // WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty:<{ %"struct.test2::NonTrivial", %"struct.test2::POD" }>]]
342 // WIN32: getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
343 // WIN32: call void @llvm.memcpy
344 // WIN32: getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
345 // WIN32: call x86_thiscallcc %"struct.test2::NonTrivial"* @"\01??0NonTrivial@test2@@QAE@XZ"
346 // WIN32: call i32 @"\01?foo@test2@@YAHUNonTrivial@1@UPOD@1@@Z"([[argmem_ty]]* inalloca %argmem)
347 // WIN32: ret void
348 // WIN32: }
349
350 }
351
352 namespace test3 {
353
354 // Check that we padded the inalloca struct to a multiple of 4.
355 struct NonTrivial {
356 NonTrivial();
357 NonTrivial(const NonTrivial &o);
358 ~NonTrivial();
359 int a;
360 };
foo(NonTrivial a,bool b)361 void foo(NonTrivial a, bool b) { }
362 // WIN32-LABEL: define void @"\01?foo@test3@@YAXUNonTrivial@1@_N@Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca)
363
364 }
365
366 // We would crash here because the later definition of ForwardDeclare1 results
367 // in a different IR type for the value we want to store. However, the alloca's
368 // type will use the argument type selected by fn1.
369 struct ForwardDeclare1;
370
371 typedef void (*FnPtr1)(ForwardDeclare1);
fn1(FnPtr1 a,SmallWithDtor b)372 void fn1(FnPtr1 a, SmallWithDtor b) { }
373
374 struct ForwardDeclare1 {};
375
fn2(FnPtr1 a,SmallWithDtor b)376 void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); };
377 // WIN32-LABEL: define void @"\01?fn2@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"
378 // WIN32: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]], [[argmem_ty:<{ {}\*, %struct.SmallWithDtor }>]]* %{{.*}}, i32 0, i32 0
379 // WIN32: %[[a1:[^ ]*]] = bitcast {}** %[[a]] to void [[dst_ty:\(%struct.ForwardDeclare1\*\)\*]]*
380 // WIN32: %[[argmem:[^ ]*]] = alloca inalloca [[argmem_ty]]
381 // WIN32: %[[gep1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1
382 // WIN32: %[[bc1:[^ ]*]] = bitcast %struct.SmallWithDtor* %[[gep1]] to i8*
383 // WIN32: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %[[bc1]], i8* {{.*}}, i32 4, i32 4, i1 false)
384 // WIN32: %[[a2:[^ ]*]] = load void [[dst_ty]], void [[dst_ty]]* %[[a1]], align 4
385 // WIN32: %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
386 // WIN32: %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]*
387 // WIN32: store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4
388 // WIN32: call void @"\01?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]])
389