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