Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s |
| 2 | |
| 3 | // In each test case, we have two member pointers whose thunks have the same |
| 4 | // vtable offset and same mangling, but their prototypes conflict. The |
| 5 | // arguments and return type may differ. Therefore, we have to bitcast the |
| 6 | // function prototype. Unfortunately, if the return types differ, LLVM's |
| 7 | // optimizers can get upset. |
| 8 | |
| 9 | namespace num_params { |
| 10 | struct A { virtual void a(int); }; |
| 11 | struct B { virtual void b(int, int); }; |
| 12 | struct C : A, B { |
| 13 | virtual void a(int); |
| 14 | virtual void b(int, int); |
| 15 | }; |
| 16 | void f(C *c) { |
| 17 | (c->*(&C::a))(0); |
| 18 | (c->*(&C::b))(0, 0); |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | // CHECK-LABEL: define void @"\01?f@num_params@@YAXPAUC@1@@Z"(%"struct.num_params::C"* %c) |
| 23 | // CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0) |
| 24 | // CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0, i32 0) |
| 25 | |
David Majnemer | 8c9cdb6 | 2015-01-21 01:21:31 +0000 | [diff] [blame] | 26 | // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@num_params@@$BA@AE"(%"struct.num_params::C"* %this, ...) {{.*}} comdat |
David Blaikie | d6c88ec | 2015-04-16 23:25:00 +0000 | [diff] [blame] | 27 | // CHECK: musttail call x86_thiscallcc void (%"struct.num_params::C"*, ...) %{{.*}}(%"struct.num_params::C"* %{{.*}}, ...) |
Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 28 | // CHECK-NEXT: ret void |
| 29 | |
| 30 | namespace i64_return { |
| 31 | struct A { virtual int a(); }; |
| 32 | struct B { virtual long long b(); }; |
| 33 | struct C : A, B { |
| 34 | virtual int a(); |
| 35 | virtual long long b(); |
| 36 | }; |
| 37 | long long f(C *c) { |
| 38 | int x = (c->*(&C::a))(); |
| 39 | long long y = (c->*(&C::b))(); |
| 40 | return x + y; |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | // CHECK-LABEL: define i64 @"\01?f@i64_return@@YA_JPAUC@1@@Z"(%"struct.i64_return::C"* %c) |
| 45 | // CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i32 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}}) |
| 46 | // CHECK: call x86_thiscallcc i64 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i64 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}}) |
| 47 | |
David Majnemer | 8c9cdb6 | 2015-01-21 01:21:31 +0000 | [diff] [blame] | 48 | // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@i64_return@@$BA@AE"(%"struct.i64_return::C"* %this, ...) {{.*}} comdat |
David Blaikie | d6c88ec | 2015-04-16 23:25:00 +0000 | [diff] [blame] | 49 | // CHECK: musttail call x86_thiscallcc void (%"struct.i64_return::C"*, ...) %{{.*}}(%"struct.i64_return::C"* %{{.*}}, ...) |
Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 50 | // CHECK-NEXT: ret void |
| 51 | |
| 52 | namespace sret { |
| 53 | struct Big { int big[32]; }; |
| 54 | struct A { virtual int a(); }; |
| 55 | struct B { virtual Big b(); }; |
| 56 | struct C : A, B { |
| 57 | virtual int a(); |
| 58 | virtual Big b(); |
| 59 | }; |
| 60 | void f(C *c) { |
| 61 | (c->*(&C::a))(); |
| 62 | Big b((c->*(&C::b))()); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | // CHECK-LABEL: define void @"\01?f@sret@@YAXPAUC@1@@Z"(%"struct.sret::C"* %c) |
| 67 | // CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to i32 (%"struct.sret::C"*)*)(%"struct.sret::C"* %{{.*}}) |
| 68 | // CHECK: call x86_thiscallcc void bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to void (%"struct.sret::C"*, %"struct.sret::Big"*)*)(%"struct.sret::C"* %{{.*}}, %"struct.sret::Big"* sret %{{.*}}) |
| 69 | |
David Majnemer | 8c9cdb6 | 2015-01-21 01:21:31 +0000 | [diff] [blame] | 70 | // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@sret@@$BA@AE"(%"struct.sret::C"* %this, ...) {{.*}} comdat |
David Blaikie | d6c88ec | 2015-04-16 23:25:00 +0000 | [diff] [blame] | 71 | // CHECK: musttail call x86_thiscallcc void (%"struct.sret::C"*, ...) %{{.*}}(%"struct.sret::C"* %{{.*}}, ...) |
Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 72 | // CHECK-NEXT: ret void |
| 73 | |
| 74 | namespace cdecl_inalloca { |
| 75 | // Fairly evil, since now we end up doing an inalloca-style call through a |
| 76 | // thunk that doesn't use inalloca. Hopefully the stacks line up? |
| 77 | struct Big { |
| 78 | Big(); |
| 79 | ~Big(); |
| 80 | int big[32]; |
| 81 | }; |
| 82 | struct A { virtual void __cdecl a(); }; |
| 83 | struct B { virtual void __cdecl b(Big); }; |
| 84 | struct C : A, B { |
| 85 | virtual void __cdecl a(); |
| 86 | virtual void __cdecl b(Big); |
| 87 | }; |
| 88 | void f(C *c) { |
| 89 | Big b; |
| 90 | (c->*(&C::a))(); |
| 91 | ((c->*(&C::b))(b)); |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | // CHECK-LABEL: define void @"\01?f@cdecl_inalloca@@YAXPAUC@1@@Z"(%"struct.cdecl_inalloca::C"* %c) |
David Majnemer | bc02d32 | 2015-03-14 06:34:41 +0000 | [diff] [blame] | 96 | // CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}}) |
| 97 | // CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}}) |
Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 98 | |
David Majnemer | bc02d32 | 2015-03-14 06:34:41 +0000 | [diff] [blame] | 99 | // CHECK-LABEL: define linkonce_odr void @"\01??_9C@cdecl_inalloca@@$BA@AA"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat |
David Blaikie | d6c88ec | 2015-04-16 23:25:00 +0000 | [diff] [blame] | 100 | // CHECK: musttail call void (%"struct.cdecl_inalloca::C"*, ...) %{{.*}}(%"struct.cdecl_inalloca::C"* %{{.*}}, ...) |
Reid Kleckner | c347351 | 2014-08-29 21:43:29 +0000 | [diff] [blame] | 101 | // CHECK-NEXT: ret void |