114 lines · cpp
1// RUN: %clang_cc1 %s -fno-rtti -triple=i686-pc-win32 -emit-llvm -o - | FileCheck --check-prefix=CHECK32 %s2// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o - | FileCheck --check-prefix=CHECK64 %s3 4namespace byval_thunk {5struct Agg {6 Agg();7 Agg(const Agg &);8 ~Agg();9 int x;10};11 12struct A { virtual void foo(Agg x); };13struct B { virtual void foo(Agg x); };14struct C : A, B { C(); virtual void foo(Agg x); };15C::C() {} // force emission16 17// CHECK32-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?foo@C@byval_thunk@@W3AEXUAgg@2@@Z"18// CHECK32: (ptr noundef %this, ptr inalloca(<{ %"struct.byval_thunk::Agg" }>) %0)19// CHECK32: getelementptr i8, ptr %{{.*}}, i32 -420// CHECK32: musttail call x86_thiscallcc void @"?foo@C@byval_thunk@@UAEXUAgg@2@@Z"21// CHECK32: (ptr noundef %{{.*}}, ptr inalloca(<{ %"struct.byval_thunk::Agg" }>) %0)22// CHECK32-NEXT: ret void23 24// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z"25// CHECK64: (ptr noundef %this, ptr dead_on_return noundef %x)26// CHECK64: getelementptr i8, ptr %{{.*}}, i32 -827// CHECK64: call void @"?foo@C@byval_thunk@@UEAAXUAgg@2@@Z"28// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr dead_on_return noundef %x)29// CHECK64-NOT: call30// CHECK64: ret void31}32 33namespace stdcall_thunk {34struct Agg {35 Agg();36 Agg(const Agg &);37 ~Agg();38 int x;39};40 41struct A { virtual void __stdcall foo(Agg x); };42struct B { virtual void __stdcall foo(Agg x); };43struct C : A, B { C(); virtual void __stdcall foo(Agg x); };44C::C() {} // force emission45 46// CHECK32-LABEL: define linkonce_odr dso_local x86_stdcallcc void @"?foo@C@stdcall_thunk@@W3AGXUAgg@2@@Z"47// CHECK32: (ptr inalloca(<{ ptr, %"struct.stdcall_thunk::Agg" }>) %0)48// CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds nuw <{ ptr, %"struct.stdcall_thunk::Agg" }>, ptr %0, i32 0, i32 049// CHECK32: load ptr, ptr %[[this_slot]]50// CHECK32: getelementptr i8, ptr %{{.*}}, i32 -451// CHECK32: store ptr %{{.*}}, ptr %[[this_slot]]52// CHECK32: musttail call x86_stdcallcc void @"?foo@C@stdcall_thunk@@UAGXUAgg@2@@Z"53// CHECK32: (ptr inalloca(<{ ptr, %"struct.stdcall_thunk::Agg" }>) %0)54// CHECK32-NEXT: ret void55 56// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@stdcall_thunk@@W7EAAXUAgg@2@@Z"57// CHECK64: (ptr noundef %this, ptr dead_on_return noundef %x)58// CHECK64: getelementptr i8, ptr %{{.*}}, i32 -859// CHECK64: call void @"?foo@C@stdcall_thunk@@UEAAXUAgg@2@@Z"60// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr dead_on_return noundef %x)61// CHECK64-NOT: call62// CHECK64: ret void63}64 65namespace sret_thunk {66struct Agg {67 Agg();68 Agg(const Agg &);69 ~Agg();70 int x;71};72 73struct A { virtual Agg __cdecl foo(Agg x); };74struct B { virtual Agg __cdecl foo(Agg x); };75struct C : A, B { C(); virtual Agg __cdecl foo(Agg x); };76C::C() {} // force emission77 78// CHECK32-LABEL: define linkonce_odr dso_local ptr @"?foo@C@sret_thunk@@W3AA?AUAgg@2@U32@@Z"79// CHECK32: (ptr inalloca(<{ ptr, ptr, %"struct.sret_thunk::Agg" }>) %0)80// CHECK32: %[[this_slot:[^ ]*]] = getelementptr inbounds nuw <{ ptr, ptr, %"struct.sret_thunk::Agg" }>, ptr %0, i32 0, i32 081// CHECK32: load ptr, ptr %[[this_slot]]82// CHECK32: getelementptr i8, ptr %{{.*}}, i32 -483// CHECK32: store ptr %{{.*}}, ptr %[[this_slot]]84// CHECK32: %[[rv:[^ ]*]] = musttail call ptr @"?foo@C@sret_thunk@@UAA?AUAgg@2@U32@@Z"85// CHECK32: (ptr inalloca(<{ ptr, ptr, %"struct.sret_thunk::Agg" }>) %0)86// CHECK32-NEXT: ret ptr %[[rv]]87 88// CHECK64-LABEL: define linkonce_odr dso_local void @"?foo@C@sret_thunk@@W7EAA?AUAgg@2@U32@@Z"89// CHECK64: (ptr noundef %this, ptr dead_on_unwind noalias writable sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr dead_on_return noundef %x)90// CHECK64: getelementptr i8, ptr %{{.*}}, i32 -891// CHECK64: call void @"?foo@C@sret_thunk@@UEAA?AUAgg@2@U32@@Z"92// CHECK64: (ptr {{[^,]*}} %{{.*}}, ptr dead_on_unwind writable sret(%"struct.sret_thunk::Agg") align 4 %agg.result, ptr dead_on_return noundef %x)93// CHECK64-NOT: call94// CHECK64: ret void95}96 97#if 098// FIXME: When we extend LLVM IR to allow forwarding of varargs through musttail99// calls, use this test.100namespace variadic_thunk {101struct Agg {102 Agg();103 Agg(const Agg &);104 ~Agg();105 int x;106};107 108struct A { virtual void foo(Agg x, ...); };109struct B { virtual void foo(Agg x, ...); };110struct C : A, B { C(); virtual void foo(Agg x, ...); };111C::C() {} // force emission112}113#endif114