diff options
author | Timur Iskhodzhanov <timurrrr@google.com> | 2013-11-06 06:24:31 +0000 |
---|---|---|
committer | Timur Iskhodzhanov <timurrrr@google.com> | 2013-11-06 06:24:31 +0000 |
commit | 053142a90d700c21e491444d6996bb1ff80fa0e2 (patch) | |
tree | 2e96d9574c342b5d807cbb69c39b23e6df2f9bb8 /clang/lib/CodeGen/MicrosoftCXXABI.cpp | |
parent | 67b277c34fc517ea9f17e5505d9c420485224239 (diff) | |
download | bcm5719-llvm-053142a90d700c21e491444d6996bb1ff80fa0e2.tar.gz bcm5719-llvm-053142a90d700c21e491444d6996bb1ff80fa0e2.zip |
Fix PR17738 - add support for vtordisp thunks when using -cxx-abi microsoft
llvm-svn: 194132
Diffstat (limited to 'clang/lib/CodeGen/MicrosoftCXXABI.cpp')
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 7e3a47d9131..6415749e2df 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -988,8 +988,29 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, llvm::Value *V = CGF.Builder.CreateBitCast(This, CGF.Int8PtrTy); - assert(TA.VCallOffsetOffset == 0 && - "VtorDisp adjustment is not supported yet"); + if (!TA.Virtual.isEmpty()) { + assert(TA.Virtual.Microsoft.VtordispOffset < 0); + // Adjust the this argument based on the vtordisp value. + llvm::Value *VtorDispPtr = + CGF.Builder.CreateConstGEP1_32(V, TA.Virtual.Microsoft.VtordispOffset); + VtorDispPtr = + CGF.Builder.CreateBitCast(VtorDispPtr, CGF.Int32Ty->getPointerTo()); + llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); + V = CGF.Builder.CreateGEP(V, CGF.Builder.CreateNeg(VtorDisp)); + + if (TA.Virtual.Microsoft.VBPtrOffset) { + // If the final overrider is defined in a virtual base other than the one + // that holds the vfptr, we have to use a vtordispex thunk which looks up + // the vbtable of the derived class. + assert(TA.Virtual.Microsoft.VBPtrOffset > 0); + assert(TA.Virtual.Microsoft.VBOffsetOffset >= 0); + llvm::Value *VBPtr; + llvm::Value *VBaseOffset = + GetVBaseOffsetFromVBPtr(CGF, V, -TA.Virtual.Microsoft.VBPtrOffset, + TA.Virtual.Microsoft.VBOffsetOffset, &VBPtr); + V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset); + } + } if (TA.NonVirtual) { // Non-virtual adjustment might result in a pointer outside the allocated |