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