microsoft-abi-virtual-member-pointers.cpp revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
1651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32
2651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64
393b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
493b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborgstruct S {
593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  int x, y, z;
693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg};
793b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
86bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// U is not trivially copyable, and requires inalloca to pass by value.
96bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstruct U {
106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  int u;
116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  U();
126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ~U();
136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  U(const U &);
146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborgstruct C {
1793b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  virtual void foo();
1893b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  virtual int bar(int, double);
1993b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  virtual S baz(int);
206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  virtual S qux(U);
2193b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg};
2293b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
2393b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborgnamespace {
2493b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborgstruct D {
2593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  virtual void foo();
2693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg};
2793b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg}
2893b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
2993b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborgvoid f() {
3093b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  void (C::*ptr)();
3193b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  ptr = &C::foo;
3293b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  ptr = &C::foo; // Don't crash trying to define the thunk twice :)
3393b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
3493b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  int (C::*ptr2)(int, double);
3593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  ptr2 = &C::bar;
3693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
3793b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  S (C::*ptr3)(int);
3893b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  ptr3 = &C::baz;
3993b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
4093b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  void (D::*ptr4)();
4193b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg  ptr4 = &D::foo;
4293b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  S (C::*ptr5)(U);
446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ptr5 = &C::qux;
456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
4793b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32-LABEL: define void @"\01?f@@YAXXZ"()
4893b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: store i8* bitcast (void (%struct.C*)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr
4993b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: store i8* bitcast (i32 (%struct.C*, i32, double)* @"\01??_9C@@$B3AE" to i8*), i8** %ptr2
506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: store i8* bitcast (void (%struct.C*, %struct.S*, i32)* @"\01??_9C@@$B7AE" to i8*), i8** %ptr3
51651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// CHECK32: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*)* @"\01??_9D@?A@@$BA@AE" to i8*), i8** %ptr4
5293b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: }
5393b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg//
5493b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64-LABEL: define void @"\01?f@@YAXXZ"()
5593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: store i8* bitcast (void (%struct.C*)* @"\01??_9C@@$BA@AA" to i8*), i8** %ptr
5693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: store i8* bitcast (i32 (%struct.C*, i32, double)* @"\01??_9C@@$B7AA" to i8*), i8** %ptr2
576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: store i8* bitcast (void (%struct.C*, %struct.S*, i32)* @"\01??_9C@@$BBA@AA" to i8*), i8** %ptr3
58651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// CHECK64: store i8* bitcast (void (%"struct.(anonymous namespace)::D"*)* @"\01??_9D@?A@@$BA@AA" to i8*), i8** %ptr
5993b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: }
6093b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg}
6193b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
6293b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
6393b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// Thunk for calling the 1st virtual function in C with no parameters.
6493b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BA@AE"(%struct.C* %this) unnamed_addr
6593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*)** %{{.*}}, i64 0
6693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*)** [[VPTR]]
676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%struct.C* %{{.*}})
6893b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: ret void
6993b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: }
7093b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg//
7193b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BA@AA"(%struct.C* %this) unnamed_addr
7293b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*)** %{{.*}}, i64 0
7393b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*)** [[VPTR]]
746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: musttail call void [[CALLEE]](%struct.C* %{{.*}})
7593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: ret void
7693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: }
7793b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
7893b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// Thunk for calling the 2nd virtual function in C, taking int and double as parameters, returning int.
7993b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32-LABEL: define linkonce_odr x86_thiscallcc i32 @"\01??_9C@@$B3AE"(%struct.C* %this, i32, double) unnamed_addr
8093b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: [[VPTR:%.*]] = getelementptr inbounds i32 (%struct.C*, i32, double)** %{{.*}}, i64 1
8193b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: [[CALLEE:%.*]] = load i32 (%struct.C*, i32, double)** [[VPTR]]
826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: [[CALL:%.*]] = musttail call x86_thiscallcc i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}})
8393b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: ret i32 [[CALL]]
8493b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: }
8593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg//
8693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64-LABEL: define linkonce_odr i32 @"\01??_9C@@$B7AA"(%struct.C* %this, i32, double) unnamed_addr
8793b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: [[VPTR:%.*]] = getelementptr inbounds i32 (%struct.C*, i32, double)** %{{.*}}, i64 1
8893b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: [[CALLEE:%.*]] = load i32 (%struct.C*, i32, double)** [[VPTR]]
896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: [[CALL:%.*]] = musttail call i32 [[CALLEE]](%struct.C* %{{.*}}, i32 %{{.*}}, double %{{.*}})
9093b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: ret i32 [[CALL]]
9193b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: }
9293b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
9393b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// Thunk for calling the 3rd virtual function in C, taking an int parameter, returning a struct.
946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$B7AE"(%struct.C* %this, %struct.S* noalias sret %agg.result, i32) unnamed_addr
956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, i32)** %{{.*}}, i64 2
966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, i32)** [[VPTR]]
976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%struct.C* %{{.*}}, %struct.S* sret %agg.result, i32 %{{.*}})
9893b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: ret void
9993b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: }
10093b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg//
1016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBA@AA"(%struct.C* %this, %struct.S* noalias sret %agg.result, i32) unnamed_addr
1026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, i32)** %{{.*}}, i64 2
1036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, i32)** [[VPTR]]
1046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: musttail call void [[CALLEE]](%struct.C* %{{.*}}, %struct.S* sret %agg.result, i32 %{{.*}})
10593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: ret void
10693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: }
10793b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg
10893b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// Thunk for calling the virtual function in internal class D.
109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// CHECK32-LABEL: define internal x86_thiscallcc void @"\01??_9D@?A@@$BA@AE"(%"struct.(anonymous namespace)::D"* %this) unnamed_addr
110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*)** %{{.*}}, i64 0
111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// CHECK32: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*)** [[VPTR]]
1126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: musttail call x86_thiscallcc void [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}})
11393b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: ret void
11493b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK32: }
11593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg//
116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// CHECK64-LABEL: define internal void @"\01??_9D@?A@@$BA@AA"(%"struct.(anonymous namespace)::D"* %this) unnamed_addr
117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%"struct.(anonymous namespace)::D"*)** %{{.*}}, i64 0
118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// CHECK64: [[CALLEE:%.*]] = load void (%"struct.(anonymous namespace)::D"*)** [[VPTR]]
1196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: musttail call void [[CALLEE]](%"struct.(anonymous namespace)::D"* %{{.*}})
1206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: ret void
1216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: }
1226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// Thunk for calling the fourth virtual function in C, taking a struct parameter and returning a struct.
1246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32-LABEL: define linkonce_odr x86_thiscallcc %struct.S* @"\01??_9C@@$BM@AE"(%struct.C* %this, <{ %struct.S*, %struct.U }>* inalloca) unnamed_addr
1256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: [[VPTR:%.*]] = getelementptr inbounds %struct.S* (%struct.C*, <{ %struct.S*, %struct.U }>*)** %{{.*}}, i64 3
1266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: [[CALLEE:%.*]] = load %struct.S* (%struct.C*, <{ %struct.S*, %struct.U }>*)** [[VPTR]]
1276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: [[CALL:%.*]] = musttail call x86_thiscallcc %struct.S* [[CALLEE]](%struct.C* %this, <{ %struct.S*, %struct.U }>* inalloca %{{.*}})
1286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: ret %struct.S* [[CALL]]
1296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK32: }
1306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
1316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64-LABEL: define linkonce_odr void @"\01??_9C@@$BBI@AA"(%struct.C* %this, %struct.S* noalias sret %agg.result, %struct.U*) unnamed_addr
1326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, %struct.S*, %struct.U*)** %{{.*}}, i64 3
1336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, %struct.S*, %struct.U*)** [[VPTR]]
1346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// CHECK64: musttail call void [[CALLEE]](%struct.C* %this, %struct.S* sret %agg.result, %struct.U* %{{.*}})
13593b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: ret void
13693b717ac956f5c82f7895ed8874cbd514c6d0a4eHans Wennborg// CHECK64: }
137