diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-09-14 01:45:09 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-09-14 01:45:09 +0000 |
commit | 82bad6bbb6c04ec6e34562988d0d1f9e450a7279 (patch) | |
tree | 902554287ad4c129ecaf7ea0dd36ebf58e471e63 /lib/CodeGen/CGVTables.cpp | |
parent | cf15f17f04995766883f5c5c76cb82bb25617e6d (diff) |
Fix thunk emission for covariant virtual functions in cases which require
both a virtual and a non-virtual offset. PR13832.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163866 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVTables.cpp')
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index afd58e8ae2..43708ff160 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -79,15 +79,16 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD, static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF, llvm::Value *Ptr, int64_t NonVirtualAdjustment, - int64_t VirtualAdjustment) { + int64_t VirtualAdjustment, + bool IsReturnAdjustment) { if (!NonVirtualAdjustment && !VirtualAdjustment) return Ptr; llvm::Type *Int8PtrTy = CGF.Int8PtrTy; llvm::Value *V = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy); - if (NonVirtualAdjustment) { - // Do the non-virtual adjustment. + if (NonVirtualAdjustment && !IsReturnAdjustment) { + // Perform the non-virtual adjustment for a base-to-derived cast. V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment); } @@ -95,7 +96,7 @@ static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF, llvm::Type *PtrDiffTy = CGF.ConvertType(CGF.getContext().getPointerDiffType()); - // Do the virtual adjustment. + // Perform the virtual adjustment. llvm::Value *VTablePtrPtr = CGF.Builder.CreateBitCast(V, Int8PtrTy->getPointerTo()); @@ -113,6 +114,11 @@ static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF, V = CGF.Builder.CreateInBoundsGEP(V, Offset); } + if (NonVirtualAdjustment && IsReturnAdjustment) { + // Perform the non-virtual adjustment for a derived-to-base cast. + V = CGF.Builder.CreateConstInBoundsGEP1_64(V, NonVirtualAdjustment); + } + // Cast back to the original type. return CGF.Builder.CreateBitCast(V, Ptr->getType()); } @@ -199,7 +205,8 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF, ReturnValue = PerformTypeAdjustment(CGF, ReturnValue, Thunk.Return.NonVirtual, - Thunk.Return.VBaseOffsetOffset); + Thunk.Return.VBaseOffsetOffset, + /*IsReturnAdjustment*/true); if (NullCheckValue) { CGF.Builder.CreateBr(AdjustEnd); @@ -281,7 +288,8 @@ void CodeGenFunction::GenerateVarArgsThunk( llvm::Value *AdjustedThisPtr = PerformTypeAdjustment(*this, ThisPtr, Thunk.This.NonVirtual, - Thunk.This.VCallOffsetOffset); + Thunk.This.VCallOffsetOffset, + /*IsReturnAdjustment*/false); ThisStore->setOperand(0, AdjustedThisPtr); if (!Thunk.Return.isEmpty()) { @@ -335,7 +343,8 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, llvm::Value *AdjustedThisPtr = PerformTypeAdjustment(*this, LoadCXXThis(), Thunk.This.NonVirtual, - Thunk.This.VCallOffsetOffset); + Thunk.This.VCallOffsetOffset, + /*IsReturnAdjustment*/false); CallArgList CallArgs; |