1- // RUN: not %clang_cc1 %s -fno-rtti -triple=i686-pc-win32 -emit-llvm -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK32 %s
1+ // RUN: %clang_cc1 %s -fno-rtti -triple=i686-pc-win32 -emit-llvm -o - | FileCheck --check-prefix=CHECK32 %s
22// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o - | FileCheck --check-prefix=CHECK64 %s
33
44namespace byval_thunk {
@@ -11,15 +11,103 @@ struct Agg {
1111
1212struct A { virtual void foo (Agg x); };
1313struct B { virtual void foo (Agg x); };
14- struct C : A, B { virtual void foo (Agg x); };
15- C c;
14+ struct C : A, B { C(); virtual void foo (Agg x); };
15+ C::C () {} // force emission
1616
17- // CHECK32: cannot compile this non-trivial argument copy for thunk yet
17+ // CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01?foo@C@byval_thunk@@W3AEXUAgg@2@@Z"
18+ // CHECK32: (%"struct.byval_thunk::C"* %this, <{ %"struct.byval_thunk::Agg" }>* inalloca)
19+ // CHECK32: %2 = getelementptr i8* %{{.*}}, i32 -4
20+ // CHECK32: musttail call x86_thiscallcc void @"\01?foo@C@byval_thunk@@UAEXUAgg@2@@Z"
21+ // CHECK32: (%"struct.byval_thunk::C"* %{{.*}}, <{ %"struct.byval_thunk::Agg" }>* inalloca %0)
22+ // CHECK32-NEXT: ret void
1823
1924// CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z"
2025// CHECK64: (%"struct.byval_thunk::C"* %this, %"struct.byval_thunk::Agg"* %x)
2126// CHECK64: getelementptr i8* %{{.*}}, i32 -8
22- // CHECK64: call void @"\01?foo@C@byval_thunk@@UEAAXUAgg@2@@Z"(%"struct.byval_thunk::C"* %{{.*}}, %"struct.byval_thunk::Agg"* %x)
27+ // CHECK64: call void @"\01?foo@C@byval_thunk@@UEAAXUAgg@2@@Z"
28+ // CHECK64: (%"struct.byval_thunk::C"* %{{.*}}, %"struct.byval_thunk::Agg"* %x)
2329// CHECK64-NOT: call
2430// CHECK64: ret void
2531}
32+
33+ namespace stdcall_thunk {
34+ struct Agg {
35+ Agg ();
36+ Agg (const Agg &);
37+ ~Agg ();
38+ int x;
39+ };
40+
41+ struct A { virtual void __stdcall foo (Agg x); };
42+ struct B { virtual void __stdcall foo (Agg x); };
43+ struct C : A, B { C(); virtual void __stdcall foo (Agg x); };
44+ C::C () {} // force emission
45+
46+ // CHECK32-LABEL: define linkonce_odr x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@W3AGXUAgg@2@@Z"
47+ // CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca)
48+ // CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* %0, i32 0, i32 0
49+ // CHECK32: load %"struct.stdcall_thunk::C"** %[[this_slot]]
50+ // CHECK32: getelementptr i8* %{{.*}}, i32 -4
51+ // CHECK32: store %"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::C"** %[[this_slot]]
52+ // CHECK32: musttail call x86_stdcallcc void @"\01?foo@C@stdcall_thunk@@UAGXUAgg@2@@Z"
53+ // CHECK32: (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca %0)
54+ // CHECK32-NEXT: ret void
55+
56+ // CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z"
57+ // CHECK64: (%"struct.stdcall_thunk::C"* %this, %"struct.stdcall_thunk::Agg"* %x)
58+ // CHECK64: getelementptr i8* %{{.*}}, i32 -8
59+ // CHECK64: call void @"\01?foo@C@stdcall_thunk@@UEAAXUAgg@2@@Z"
60+ // CHECK64: (%"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::Agg"* %x)
61+ // CHECK64-NOT: call
62+ // CHECK64: ret void
63+ }
64+
65+ namespace sret_thunk {
66+ struct Agg {
67+ Agg ();
68+ Agg (const Agg &);
69+ ~Agg ();
70+ int x;
71+ };
72+
73+ struct A { virtual Agg __cdecl foo (Agg x); };
74+ struct B { virtual Agg __cdecl foo (Agg x); };
75+ struct C : A, B { C(); virtual Agg __cdecl foo (Agg x); };
76+ C::C () {} // force emission
77+
78+ // CHECK32-LABEL: define linkonce_odr %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@W3AA?AUAgg@2@U32@@Z"
79+ // CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca)
80+ // CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* %0, i32 0, i32 0
81+ // CHECK32: load %"struct.sret_thunk::C"** %[[this_slot]]
82+ // CHECK32: getelementptr i8* %{{.*}}, i32 -4
83+ // CHECK32: store %"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::C"** %[[this_slot]]
84+ // CHECK32: %[[rv:[^ ]*]] = musttail call %"struct.sret_thunk::Agg"* @"\01?foo@C@sret_thunk@@UAA?AUAgg@2@U32@@Z"
85+ // CHECK32: (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca %0)
86+ // CHECK32-NEXT: ret %"struct.sret_thunk::Agg"* %[[rv]]
87+
88+ // CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z"
89+ // CHECK64: (%"struct.sret_thunk::C"* %this, %"struct.sret_thunk::Agg"* noalias sret %agg.result, %"struct.sret_thunk::Agg"* %x)
90+ // CHECK64: getelementptr i8* %{{.*}}, i32 -8
91+ // CHECK64: call void @"\01?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z"
92+ // CHECK64: (%"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::Agg"* sret %agg.result, %"struct.sret_thunk::Agg"* %x)
93+ // CHECK64-NOT: call
94+ // CHECK64: ret void
95+ }
96+
97+ #if 0
98+ // FIXME: When we extend LLVM IR to allow forwarding of varargs through musttail
99+ // calls, use this test.
100+ namespace variadic_thunk {
101+ struct Agg {
102+ Agg();
103+ Agg(const Agg &);
104+ ~Agg();
105+ int x;
106+ };
107+
108+ struct A { virtual void foo(Agg x, ...); };
109+ struct B { virtual void foo(Agg x, ...); };
110+ struct C : A, B { C(); virtual void foo(Agg x, ...); };
111+ C::C() {} // force emission
112+ }
113+ #endif
0 commit comments