Fix thunk emission for covariant virtual functions in cases which require

both a virtual and a non-virtual offset. PR13832.

llvm-svn: 163866
This commit is contained in:
Eli Friedman 2012-09-14 01:45:09 +00:00
parent 48a3291675
commit 00755e9554
2 changed files with 42 additions and 7 deletions

View File

@ -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;

View File

@ -301,6 +301,32 @@ namespace Test12 {
// CHECK: getelementptr inbounds i8* {{.*}}, i64 8
}
// PR13832
namespace Test13 {
struct B1 {
virtual B1 &foo1();
};
struct Pad1 {
virtual ~Pad1();
};
struct Proxy1 : Pad1, B1 {
virtual ~Proxy1();
};
struct D : virtual Proxy1 {
virtual ~D();
virtual D &foo1();
};
D& D::foo1() {
return *this;
}
// CHECK: define {{.*}} @_ZTcvn8_n32_v8_n24_N6Test131D4foo1Ev
// CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
// CHECK: getelementptr inbounds i8* {{.*}}, i64 -32
// CHECK: getelementptr inbounds i8* {{.*}}, i64 -24
// CHECK: getelementptr inbounds i8* {{.*}}, i64 8
// CHECK: ret %"struct.Test13::D"*
}
/**** The following has to go at the end of the file ****/
// This is from Test5: