From d9878a181f09ffc76b61d430aa3a001102fda5af Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Tue, 13 Oct 2009 10:55:21 +0000 Subject: [PATCH] Refine handling for return value conversions with respect to virtual offsets for covariant thunks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83965 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGVtable.cpp | 34 ++++++++----- test/CodeGenCXX/virt.cpp | 107 +++++++++++++++++++++++++++++++++------ 2 files changed, 114 insertions(+), 27 deletions(-) diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index c3f6074982..2613300459 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -47,7 +47,8 @@ private: typedef llvm::DenseMap Thunks_t; Thunks_t Thunks; typedef llvm::DenseMap > CovariantThunks_t; + std::pair, + CanQualType> > CovariantThunks_t; CovariantThunks_t CovariantThunks; std::vector VCalls; typedef CXXRecordDecl::method_iterator method_iter; @@ -81,7 +82,8 @@ public: } void GenerateVBaseOffsets(std::vector &offsets, - const CXXRecordDecl *RD, uint64_t Offset) { + const CXXRecordDecl *RD, uint64_t Offset, + bool updateVBIndex) { for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { const CXXRecordDecl *Base = @@ -91,11 +93,12 @@ public: int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8; llvm::Constant *m = wrap(BaseOffset); m = wrap((0?700:0) + BaseOffset); - VBIndex[Base] = -(offsets.size()*LLVMPointerWidth/8) - - 3*LLVMPointerWidth/8; + if (updateVBIndex) + VBIndex[Base] = -(offsets.size()*LLVMPointerWidth/8) + - 3*LLVMPointerWidth/8; offsets.push_back(m); } - GenerateVBaseOffsets(offsets, Base, Offset); + GenerateVBaseOffsets(offsets, Base, Offset, updateVBIndex); } } @@ -153,7 +156,12 @@ public: CallOffset ReturnOffset = std::make_pair(0, 0); if (oret != ret) { // FIXME: calculate offsets for covariance - ReturnOffset = std::make_pair(42,getVbaseOffset(oret, ret)); + Index_t nv = 0; + if (CovariantThunks.count(OMD)) { + oret = CovariantThunks[OMD].second; + CovariantThunks.erase(OMD); + } + ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret)); } Index[MD] = i; submethods[i] = m; @@ -174,7 +182,9 @@ public: // FIXME: calculate non-virtual offset ThisOffset = std::make_pair(0, -((idx+extra+2)*LLVMPointerWidth/8)); if (ReturnOffset.first || ReturnOffset.second) - CovariantThunks[MD] = std::make_pair(ThisOffset, ReturnOffset); + CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset, + ReturnOffset), + oret); else Thunks[MD] = ThisOffset; return true; @@ -208,10 +218,10 @@ public: i != e; ++i) { const CXXMethodDecl *MD = i->first; Index_t idx = Index[MD]; - Index_t nv_t = i->second.first.first; - Index_t v_t = i->second.first.second; - Index_t nv_r = i->second.second.first; - Index_t v_r = i->second.second.second; + Index_t nv_t = i->second.first.first.first; + Index_t v_t = i->second.first.first.second; + Index_t nv_r = i->second.first.second.first; + Index_t v_r = i->second.first.second.second; submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, nv_t, v_t, nv_r, v_r); } @@ -385,7 +395,7 @@ public: std::vector offsets; extra = 0; - GenerateVBaseOffsets(offsets, RD, Offset); + GenerateVBaseOffsets(offsets, RD, Offset, !ForVirtualBase); if (ForVirtualBase) extra = offsets.size(); diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index 176009acc4..9ae81e5d3f 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -757,7 +757,7 @@ struct test13_D : test13_NV1, virtual test13_B2 { virtual void Dd() { } virtual void D2() { } virtual void fooNV1() { } -} test13_d; +}; // CHECK-LP64:__ZTV8test13_D: // CHECK-LP64-NEXT: .quad 24 @@ -842,6 +842,95 @@ struct test13_D : test13_NV1, virtual test13_B2 { // CHECK-LP32-NEXT: .long __ZTv0_n32_N9test13_B22B2Ev +class test14 { +public: + virtual void initWithInt(int a); + static test14 *withInt(int a); +}; + +void test14::initWithInt(int a) { } + +test14 *test14::withInt(int a) { + test14 *me = new test14; + me->initWithInt(a); + return me; +} + + +struct test15_B { + virtual test15_B *foo1() { return 0; } + virtual test15_B *foo2() { return 0; } + virtual test15_B *foo3() { return 0; } + int i; +}; + +struct test15_NV1 { + virtual void fooNV1() { } + int i; +}; + +struct test15_B2 : test15_NV1, virtual test15_B { + virtual test15_B2 *foo1() { return 0; } + virtual test15_B2 *foo2() { return 0; } + int i; +}; + +struct test15_D : test15_NV1, virtual test15_B2 { + virtual test15_D *foo1() { return 0; } +}; + +// CHECK-LP64:__ZTV8test15_D: +// CHECK-LP64-NEXT: .quad 32 +// CHECK-LP64-NEXT: .quad 16 +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad __ZTI8test15_D +// CHECK-LP64-NEXT: .quad __ZN10test15_NV16fooNV1Ev +// CHECK-LP64-NEXT: .quad __ZN8test15_D4foo1Ev +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad 18446744073709551600 +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad 16 +// CHECK-LP64-NEXT: .quad 18446744073709551600 +// CHECK-LP64-NEXT: .quad __ZTI8test15_D +// CHECK-LP64-NEXT: .quad __ZN10test15_NV16fooNV1Ev +// CHECK-LP64-NEXT: .quad __ZTcv0_n40_v0_n24_N8test15_D4foo1Ev +// CHECK-LP64-NEXT: .quad __ZN9test15_B24foo2Ev +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad 18446744073709551600 +// CHECK-LP64-NEXT: .quad 18446744073709551584 +// CHECK-LP64-NEXT: .quad 18446744073709551584 +// CHECK-LP64-NEXT: .quad __ZTI8test15_D +// CHECK-LP64-NEXT: .quad __ZTcv0_n24_v0_n32_N8test15_D4foo1Ev +// CHECK-LP64-NEXT: .quad __ZTcv0_n32_v0_n24_N9test15_B24foo2Ev +// CHECK-LP64-NEXT: .quad __ZN8test15_B4foo3Ev + +// CHECK-LP32:__ZTV8test15_D: +// CHECK-LP32-NEXT: .long 20 +// CHECK-LP32-NEXT: .long 8 +// CHECK-LP32-NEXT: .space 4 +// CHECK-LP32-NEXT: .long __ZTI8test15_D +// CHECK-LP32-NEXT: .long __ZN10test15_NV16fooNV1Ev +// CHECK-LP32-NEXT: .long __ZN8test15_D4foo1Ev +// CHECK-LP32-NEXT: .space 4 +// CHECK-LP32-NEXT: .long 4294967288 +// CHECK-LP32-NEXT: .space 4 +// CHECK-LP32-NEXT: .long 12 +// CHECK-LP32-NEXT: .long 4294967288 +// CHECK-LP32-NEXT: .long __ZTI8test15_D +// CHECK-LP32-NEXT: .long __ZN10test15_NV16fooNV1Ev +// CHECK-LP32-NEXT: .long __ZTcv0_n20_v0_n12_N8test15_D4foo1Ev +// CHECK-LP32-NEXT: .long __ZN9test15_B24foo2Ev +// CHECK-LP32-NEXT: .space 4 +// CHECK-LP32-NEXT: .long 4294967284 +// CHECK-LP32-NEXT: .long 4294967276 +// CHECK-LP32-NEXT: .long 4294967276 +// CHECK-LP32-NEXT: .long __ZTI8test15_D +// CHECK-LP32-NEXT: .long __ZTcv0_n12_v0_n16_N8test15_D4foo1Ev +// CHECK-LP32-NEXT: .long __ZTcv0_n16_v0_n12_N9test15_B24foo2Ev +// CHECK-LP32-NEXT: .long __ZN8test15_B4foo3Ev + + + // CHECK-LP64: __ZTV1B: // CHECK-LP64-NEXT: .space 8 // CHECK-LP64-NEXT: .quad __ZTI1B @@ -920,20 +1009,8 @@ struct test13_D : test13_NV1, virtual test13_B2 { // CHECK-LP64-NEXT: .quad __ZN2D14bar4Ev // CHECK-LP64-NEXT: .quad __ZN2D14bar5Ev -class test14 { -public: - virtual void initWithInt(int a); - static test14 *withInt(int a); -}; - -void test14::initWithInt(int a) { } - -test14 *test14::withInt(int a) { - test14 *me = new test14; - me->initWithInt(a); - return me; -} - +test15_D d15; +test13_D d13; test11_D d11; test10_D d10; test9_D d9; -- 2.40.0