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:
parent
48a3291675
commit
00755e9554
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue