r182870 - [ms-cxxabi] Implement MSVC virtual base adjustment
John McCall
rjmccall at apple.com
Tue Jun 4 10:45:10 PDT 2013
On May 29, 2013, at 11:02 AM, Reid Kleckner <reid at kleckner.net> wrote:
> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=182870&r1=182869&r2=182870&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Wed May 29 13:02:47 2013
> @@ -48,6 +48,11 @@ public:
> llvm::Value *ptr,
> QualType type);
>
> + llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
> + llvm::Value *This,
> + const CXXRecordDecl *ClassDecl,
> + const CXXRecordDecl *BaseClassDecl);
> +
> void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
> CXXCtorType Type,
> CanQualType &ResTy,
> @@ -142,6 +147,22 @@ private:
> GetNullMemberPointerFields(const MemberPointerType *MPT,
> llvm::SmallVectorImpl<llvm::Constant *> &fields);
>
> + /// \brief Finds the offset from the base of RD to the vbptr it uses, even if
> + /// it is reusing a vbptr from a non-virtual base. RD must have morally
> + /// virtual bases.
> + CharUnits GetVBPtrOffsetFromBases(const CXXRecordDecl *RD);
> +
> + /// \brief Shared code for virtual base adjustment. Returns the offset from
> + /// the vbptr to the virtual base. Optionally returns the address of the
> + /// vbptr itself.
> + llvm::Value *GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
> + llvm::Value *Base,
> + llvm::Value *VBPtrOffset,
> + llvm::Value *VBTableOffset,
> + llvm::Value **VBPtr = 0);
> +
> + /// \brief Performs a full virtual base adjustment. Used to dereference
> + /// pointers to members of virtual bases.
> llvm::Value *AdjustVirtualBase(CodeGenFunction &CGF, const CXXRecordDecl *RD,
> llvm::Value *Base,
> llvm::Value *VirtualBaseAdjustmentOffset,
> @@ -212,6 +233,68 @@ llvm::Value *MicrosoftCXXABI::adjustToCo
> return ptr;
> }
>
> +CharUnits MicrosoftCXXABI::GetVBPtrOffsetFromBases(const CXXRecordDecl *RD) {
> + assert(RD->getNumVBases());
> + CharUnits Total = CharUnits::Zero();
> + while (RD) {
> + const ASTRecordLayout &RDLayout = getContext().getASTRecordLayout(RD);
> + CharUnits VBPtrOffset = RDLayout.getVBPtrOffset();
> + // -1 is the sentinel for no vbptr.
> + if (VBPtrOffset != CharUnits::fromQuantity(-1)) {
> + Total += VBPtrOffset;
> + break;
> + }
> +
> + // RD is reusing the vbptr of a non-virtual base. Find it and continue.
> + const CXXRecordDecl *FirstNVBaseWithVBases = 0;
> + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
> + E = RD->bases_end(); I != E; ++I) {
> + const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
> + if (!I->isVirtual() && Base->getNumVBases() > 0) {
> + FirstNVBaseWithVBases = Base;
> + break;
> + }
> + }
> + assert(FirstNVBaseWithVBases);
Please break this out into a function and use llvm_unreachable in the
fall-out case.
> + Total += RDLayout.getBaseClassOffset(FirstNVBaseWithVBases);
> + RD = FirstNVBaseWithVBases;
> + }
> + return Total;
> +}
> +
> +llvm::Value *
> +MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
> + llvm::Value *This,
> + const CXXRecordDecl *ClassDecl,
> + const CXXRecordDecl *BaseClassDecl) {
> + int64_t VBPtrChars = GetVBPtrOffsetFromBases(ClassDecl).getQuantity();
> + llvm::Value *VBPtrOffset = llvm::ConstantInt::get(CGM.PtrDiffTy, VBPtrChars);
> +
> + // The vbtable is an array of i32 offsets. The first entry is a self entry,
> + // and the rest are offsets from the vbptr to virtual bases. The bases are
> + // ordered the same way our vbases are ordered: as they appear in a
> + // left-to-right depth-first search of the hierarchy.
> + unsigned VBTableIndex = 1; // Start with one to skip the self entry.
> + for (CXXRecordDecl::base_class_const_iterator I = ClassDecl->vbases_begin(),
> + E = ClassDecl->vbases_end(); I != E; ++I) {
> + if (I->getType()->getAsCXXRecordDecl() == BaseClassDecl)
> + break;
> + VBTableIndex++;
> + }
> + assert(VBTableIndex != 1 + ClassDecl->getNumVBases() &&
> + "BaseClassDecl must be a vbase of ClassDecl");
Same.
Otherwise looks fine.
John.
More information about the cfe-commits
mailing list