diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 30 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 134 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 40 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 95 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 54 |
7 files changed, 238 insertions, 124 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index 828c9ecfc6a..fb878e753f1 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -228,8 +228,10 @@ public: virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0; virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; } - virtual bool canEmitAvailableExternallyVTable( - const CXXRecordDecl *RD) const = 0; + /// \brief Determine whether it's possible to emit a vtable for \p RD, even + /// though we do not know that the vtable has been marked as used by semantic + /// analysis. + virtual bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const = 0; virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) = 0; @@ -355,13 +357,25 @@ public: virtual void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD) = 0; + /// Checks if ABI requires extra virtual offset for vtable field. + virtual bool + isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, + CodeGenFunction::VPtr Vptr) = 0; + + /// Checks if ABI requires to initilize vptrs for given dynamic class. + virtual bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) = 0; + + /// Get the address point of the vtable for the given base subobject. + virtual llvm::Constant * + getVTableAddressPoint(BaseSubobject Base, + const CXXRecordDecl *VTableClass) = 0; + /// Get the address point of the vtable for the given base subobject while - /// building a constructor or a destructor. On return, NeedsVirtualOffset - /// tells if a virtual base adjustment is needed in order to get the offset - /// of the base subobject. - virtual llvm::Value *getVTableAddressPointInStructor( - CodeGenFunction &CGF, const CXXRecordDecl *RD, BaseSubobject Base, - const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) = 0; + /// building a constructor or a destructor. + virtual llvm::Value * + getVTableAddressPointInStructor(CodeGenFunction &CGF, const CXXRecordDecl *RD, + BaseSubobject Base, + const CXXRecordDecl *NearestVBase) = 0; /// Get the address point of the vtable for the given base subobject while /// building a constexpr. diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index b54264b5054..344d06ba668 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1417,7 +1417,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>(); - if (FPT && FPT->isNothrow(getContext())) + if (FPT && !isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) && + FPT->isNothrow(getContext())) FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); // Don't use [[noreturn]] or _Noreturn for a call to a virtual function. // These attributes are not inherited by overloads. diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 45ef0f52b01..dc65b14a91f 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1984,12 +1984,14 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, bool ForVirtualBase, bool Delegating, Address This, const CXXConstructExpr *E) { + const CXXRecordDecl *ClassDecl = D->getParent(); + // C++11 [class.mfct.non-static]p2: // If a non-static member function of a class X is called for an object that // is not of type X, or of a type derived from X, the behavior is undefined. // FIXME: Provide a source location here. EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, SourceLocation(), - This.getPointer(), getContext().getRecordType(D->getParent())); + This.getPointer(), getContext().getRecordType(ClassDecl)); if (D->isTrivial() && D->isDefaultConstructor()) { assert(E->getNumArgs() == 0 && "trivial default ctor with args"); @@ -2005,7 +2007,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const Expr *Arg = E->getArg(0); QualType SrcTy = Arg->getType(); Address Src = EmitLValue(Arg).getAddress(); - QualType DestTy = getContext().getTypeDeclType(D->getParent()); + QualType DestTy = getContext().getTypeDeclType(ClassDecl); EmitAggregateCopyCtor(This, Src, DestTy, SrcTy); return; } @@ -2028,6 +2030,48 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(Args, D, Type, ExtraArgs); EmitCall(Info, Callee, ReturnValueSlot(), Args, D); + + // Generate vtable assumptions if we're constructing a complete object + // with a vtable. We don't do this for base subobjects for two reasons: + // first, it's incorrect for classes with virtual bases, and second, we're + // about to overwrite the vptrs anyway. + // We also have to make sure if we can refer to vtable: + // - If vtable is external then it's safe to use it (for available_externally + // CGVTables will make sure if it can emit it). + // - Otherwise we can refer to vtable if it's safe to speculatively emit. + // FIXME: If vtable is used by ctor/dtor, we are always safe to refer to it. + if (CGM.getCodeGenOpts().OptimizationLevel > 0 && + ClassDecl->isDynamicClass() && Type != Ctor_Base && + (CGM.getVTables().isVTableExternal(ClassDecl) || + CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl))) + EmitVTableAssumptionLoads(ClassDecl, This); +} + +void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, Address This) { + llvm::Value *VTableGlobal = + CGM.getCXXABI().getVTableAddressPoint(Vptr.Base, Vptr.VTableClass); + if (!VTableGlobal) + return; + + // We can just use the base offset in the complete class. + CharUnits NonVirtualOffset = Vptr.Base.getBaseOffset(); + + if (!NonVirtualOffset.isZero()) + This = + ApplyNonVirtualAndVirtualOffset(*this, This, NonVirtualOffset, nullptr, + Vptr.VTableClass, Vptr.NearestVBase); + + llvm::Value *VPtrValue = GetVTablePtr(This, VTableGlobal->getType()); + llvm::Value *Cmp = + Builder.CreateICmpEQ(VPtrValue, VTableGlobal, "cmp.vtables"); + Builder.CreateAssumption(Cmp); +} + +void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, + Address This) { + if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl)) + for (const VPtr &Vptr : getVTablePointers(ClassDecl)) + EmitVTableAssumptionLoad(Vptr, This); } void @@ -2193,24 +2237,12 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) { PushDestructorCleanup(D, Addr); } -void -CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, - const CXXRecordDecl *NearestVBase, - CharUnits OffsetFromNearestVBase, - const CXXRecordDecl *VTableClass) { - const CXXRecordDecl *RD = Base.getBase(); - - // Don't initialize the vtable pointer if the class is marked with the - // 'novtable' attribute. - if ((RD == VTableClass || RD == NearestVBase) && - VTableClass->hasAttr<MSNoVTableAttr>()) - return; - +void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) { // Compute the address point. - bool NeedsVirtualOffset; llvm::Value *VTableAddressPoint = CGM.getCXXABI().getVTableAddressPointInStructor( - *this, VTableClass, Base, NearestVBase, NeedsVirtualOffset); + *this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase); + if (!VTableAddressPoint) return; @@ -2218,27 +2250,25 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, llvm::Value *VirtualOffset = nullptr; CharUnits NonVirtualOffset = CharUnits::Zero(); - if (NeedsVirtualOffset) { + if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr)) { // We need to use the virtual base offset offset because the virtual base // might have a different offset in the most derived class. - VirtualOffset = - CGM.getCXXABI().GetVirtualBaseClassOffset(*this, LoadCXXThisAddress(), - VTableClass, NearestVBase); - NonVirtualOffset = OffsetFromNearestVBase; + + VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset( + *this, LoadCXXThisAddress(), Vptr.VTableClass, Vptr.NearestVBase); + NonVirtualOffset = Vptr.OffsetFromNearestVBase; } else { // We can just use the base offset in the complete class. - NonVirtualOffset = Base.getBaseOffset(); + NonVirtualOffset = Vptr.Base.getBaseOffset(); } // Apply the offsets. Address VTableField = LoadCXXThisAddress(); if (!NonVirtualOffset.isZero() || VirtualOffset) - VTableField = ApplyNonVirtualAndVirtualOffset(*this, VTableField, - NonVirtualOffset, - VirtualOffset, - VTableClass, - NearestVBase); + VTableField = ApplyNonVirtualAndVirtualOffset( + *this, VTableField, NonVirtualOffset, VirtualOffset, Vptr.VTableClass, + Vptr.NearestVBase); // Finally, store the address point. Use the same LLVM types as the field to // support optimization. @@ -2248,23 +2278,36 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, ->getPointerTo(); VTableField = Builder.CreateBitCast(VTableField, VTablePtrTy->getPointerTo()); VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy); + llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField); CGM.DecorateInstruction(Store, CGM.getTBAAInfoForVTablePtr()); } -void -CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, - const CXXRecordDecl *NearestVBase, - CharUnits OffsetFromNearestVBase, - bool BaseIsNonVirtualPrimaryBase, - const CXXRecordDecl *VTableClass, - VisitedVirtualBasesSetTy& VBases) { +CodeGenFunction::VPtrsVector +CodeGenFunction::getVTablePointers(const CXXRecordDecl *VTableClass) { + CodeGenFunction::VPtrsVector VPtrsResult; + VisitedVirtualBasesSetTy VBases; + getVTablePointers(BaseSubobject(VTableClass, CharUnits::Zero()), + /*NearestVBase=*/nullptr, + /*OffsetFromNearestVBase=*/CharUnits::Zero(), + /*BaseIsNonVirtualPrimaryBase=*/false, VTableClass, VBases, + VPtrsResult); + return VPtrsResult; +} + +void CodeGenFunction::getVTablePointers(BaseSubobject Base, + const CXXRecordDecl *NearestVBase, + CharUnits OffsetFromNearestVBase, + bool BaseIsNonVirtualPrimaryBase, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy &VBases, + VPtrsVector &Vptrs) { // If this base is a non-virtual primary base the address point has already // been set. if (!BaseIsNonVirtualPrimaryBase) { // Initialize the vtable pointer for this base. - InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase, - VTableClass); + VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase, VTableClass}; + Vptrs.push_back(Vptr); } const CXXRecordDecl *RD = Base.getBase(); @@ -2302,11 +2345,10 @@ CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl; } - InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset), - I.isVirtual() ? BaseDecl : NearestVBase, - BaseOffsetFromNearestVBase, - BaseDeclIsNonVirtualPrimaryBase, - VTableClass, VBases); + getVTablePointers( + BaseSubobject(BaseDecl, BaseOffset), + I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase, + BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs); } } @@ -2316,11 +2358,9 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) { return; // Initialize the vtable pointers for this class and all of its bases. - VisitedVirtualBasesSetTy VBases; - InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()), - /*NearestVBase=*/nullptr, - /*OffsetFromNearestVBase=*/CharUnits::Zero(), - /*BaseIsNonVirtualPrimaryBase=*/false, RD, VBases); + if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD)) + for (const VPtr &Vptr : getVTablePointers(RD)) + InitializeVTablePointer(Vptr); if (RD->getNumVBases()) CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 48e06a3879d..6aa624ec060 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -696,7 +696,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM, const CXXRecordDecl *RD) { return CGM.getCodeGenOpts().OptimizationLevel > 0 && - CGM.getCXXABI().canEmitAvailableExternallyVTable(RD); + CGM.getCXXABI().canSpeculativelyEmitVTable(RD); } /// Compute the required linkage of the v-table for the given class. @@ -846,11 +846,11 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) { /// we define that v-table? static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM, const CXXRecordDecl *RD) { - // If vtable is internal then it has to be done + // If vtable is internal then it has to be done. if (!CGM.getVTables().isVTableExternal(RD)) return true; - // If it's external then maybe we will need it as available_externally + // If it's external then maybe we will need it as available_externally. return shouldEmitAvailableExternallyVTable(CGM, RD); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 39259329832..34112727a11 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1354,21 +1354,27 @@ public: void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init, ArrayRef<VarDecl *> ArrayIndexes); - /// InitializeVTablePointer - Initialize the vtable pointer of the given - /// subobject. - /// - void InitializeVTablePointer(BaseSubobject Base, - const CXXRecordDecl *NearestVBase, - CharUnits OffsetFromNearestVBase, - const CXXRecordDecl *VTableClass); + /// Struct with all informations about dynamic [sub]class needed to set vptr. + struct VPtr { + BaseSubobject Base; + const CXXRecordDecl *NearestVBase; + CharUnits OffsetFromNearestVBase; + const CXXRecordDecl *VTableClass; + }; + + /// Initialize the vtable pointer of the given subobject. + void InitializeVTablePointer(const VPtr &vptr); + + typedef llvm::SmallVector<VPtr, 4> VPtrsVector; typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; - void InitializeVTablePointers(BaseSubobject Base, - const CXXRecordDecl *NearestVBase, - CharUnits OffsetFromNearestVBase, - bool BaseIsNonVirtualPrimaryBase, - const CXXRecordDecl *VTableClass, - VisitedVirtualBasesSetTy& VBases); + VPtrsVector getVTablePointers(const CXXRecordDecl *VTableClass); + + void getVTablePointers(BaseSubobject Base, const CXXRecordDecl *NearestVBase, + CharUnits OffsetFromNearestVBase, + bool BaseIsNonVirtualPrimaryBase, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy &VBases, VPtrsVector &vptrs); void InitializeVTablePointers(const CXXRecordDecl *ClassDecl); @@ -1836,10 +1842,18 @@ public: // they are substantially the same. void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, const FunctionArgList &Args); + void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, Address This, const CXXConstructExpr *E); + /// Emit assumption load for all bases. Requires to be be called only on + /// most-derived class and not under construction of the object. + void EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, Address This); + + /// Emit assumption that vptr load == global vtable. + void EmitVTableAssumptionLoad(const VPtr &vptr, Address This); + void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, Address This, Address Src, const CXXConstructExpr *E); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 0c6a6d751c7..e0add8fa6a1 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -243,10 +243,24 @@ public: void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD) override; + bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, + CodeGenFunction::VPtr Vptr) override; + + bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override { + return true; + } + + llvm::Constant * + getVTableAddressPoint(BaseSubobject Base, + const CXXRecordDecl *VTableClass) override; + llvm::Value *getVTableAddressPointInStructor( CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, - BaseSubobject Base, const CXXRecordDecl *NearestVBase, - bool &NeedsVirtualOffset) override; + BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; + + llvm::Value *getVTableAddressPointInStructorWithVTT( + CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, + BaseSubobject Base, const CXXRecordDecl *NearestVBase); llvm::Constant * getVTableAddressPointForConstExpr(BaseSubobject Base, @@ -267,7 +281,7 @@ public: void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; - bool canEmitAvailableExternallyVTable(const CXXRecordDecl *RD) const override; + bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override; void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD, bool ReturnAdjustment) override { @@ -1459,41 +1473,29 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, CGM.EmitVTableBitSetEntries(VTable, VTLayout); } +bool ItaniumCXXABI::isVirtualOffsetNeededForVTableField( + CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) { + if (Vptr.NearestVBase == nullptr) + return false; + return NeedsVTTParameter(CGF.CurGD); +} + llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor( CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, - const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) { - bool NeedsVTTParam = CGM.getCXXABI().NeedsVTTParameter(CGF.CurGD); - NeedsVirtualOffset = (NeedsVTTParam && NearestVBase); - - llvm::Value *VTableAddressPoint; - if (NeedsVTTParam && (Base.getBase()->getNumVBases() || NearestVBase)) { - // Get the secondary vpointer index. - uint64_t VirtualPointerIndex = - CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base); - - /// Load the VTT. - llvm::Value *VTT = CGF.LoadCXXVTT(); - if (VirtualPointerIndex) - VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex); - - // And load the address point from the VTT. - VTableAddressPoint = CGF.Builder.CreateAlignedLoad(VTT, CGF.getPointerAlign()); - } else { - llvm::Constant *VTable = - CGM.getCXXABI().getAddrOfVTable(VTableClass, CharUnits()); - uint64_t AddressPoint = CGM.getItaniumVTableContext() - .getVTableLayout(VTableClass) - .getAddressPoint(Base); - VTableAddressPoint = - CGF.Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint); - } + const CXXRecordDecl *NearestVBase) { - return VTableAddressPoint; + if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) && + NeedsVTTParameter(CGF.CurGD)) { + return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base, + NearestVBase); + } + return getVTableAddressPoint(Base, VTableClass); } -llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - auto *VTable = getAddrOfVTable(VTableClass, CharUnits()); +llvm::Constant * +ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base, + const CXXRecordDecl *VTableClass) { + llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits()); // Find the appropriate vtable within the vtable group. uint64_t AddressPoint = CGM.getItaniumVTableContext() @@ -1508,6 +1510,30 @@ llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( VTable, Indices); } +llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( + CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, + const CXXRecordDecl *NearestVBase) { + assert((Base.getBase()->getNumVBases() || NearestVBase != nullptr) && + NeedsVTTParameter(CGF.CurGD) && "This class doesn't have VTT"); + + // Get the secondary vpointer index. + uint64_t VirtualPointerIndex = + CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base); + + /// Load the VTT. + llvm::Value *VTT = CGF.LoadCXXVTT(); + if (VirtualPointerIndex) + VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex); + + // And load the address point from the VTT. + return CGF.Builder.CreateAlignedLoad(VTT, CGF.getPointerAlign()); +} + +llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( + BaseSubobject Base, const CXXRecordDecl *VTableClass) { + return getVTableAddressPoint(Base, VTableClass); +} + llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets"); @@ -1583,8 +1609,7 @@ void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) { VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD); } -bool ItaniumCXXABI::canEmitAvailableExternallyVTable( - const CXXRecordDecl *RD) const { +bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const { // We don't emit available_externally vtables if we are in -fapple-kext mode // because kext mode does not permit devirtualization. if (CGM.getLangOpts().AppleKext) diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 5cefc72ed0c..74c8774ba21 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -127,8 +127,7 @@ public: QualType DestTy) override; bool EmitBadCastCall(CodeGenFunction &CGF) override; - bool canEmitAvailableExternallyVTable( - const CXXRecordDecl *RD) const override { + bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override { return false; } @@ -236,10 +235,22 @@ public: void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD) override; + bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF, + CodeGenFunction::VPtr Vptr) override; + + /// Don't initialize vptrs if dynamic class + /// is marked with with the 'novtable' attribute. + bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override { + return !VTableClass->hasAttr<MSNoVTableAttr>(); + } + + llvm::Constant * + getVTableAddressPoint(BaseSubobject Base, + const CXXRecordDecl *VTableClass) override; + llvm::Value *getVTableAddressPointInStructor( CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, - BaseSubobject Base, const CXXRecordDecl *NearestVBase, - bool &NeedsVirtualOffset) override; + BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; llvm::Constant * getVTableAddressPointForConstExpr(BaseSubobject Base, @@ -1608,14 +1619,15 @@ void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, } } +bool MicrosoftCXXABI::isVirtualOffsetNeededForVTableField( + CodeGenFunction &CGF, CodeGenFunction::VPtr Vptr) { + return Vptr.NearestVBase != nullptr; +} + llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor( CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, - const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) { - NeedsVirtualOffset = (NearestVBase != nullptr); - - (void)getAddrOfVTable(VTableClass, Base.getBaseOffset()); - VFTableIdTy ID(VTableClass, Base.getBaseOffset()); - llvm::GlobalValue *VTableAddressPoint = VFTablesMap[ID]; + const CXXRecordDecl *NearestVBase) { + llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass); if (!VTableAddressPoint) { assert(Base.getBase()->getNumVBases() && !getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr()); @@ -1630,11 +1642,17 @@ static void mangleVFTableName(MicrosoftMangleContext &MangleContext, MangleContext.mangleCXXVFTable(RD, VFPtr->MangledPath, Out); } -llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { +llvm::Constant * +MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base, + const CXXRecordDecl *VTableClass) { (void)getAddrOfVTable(VTableClass, Base.getBaseOffset()); VFTableIdTy ID(VTableClass, Base.getBaseOffset()); - llvm::GlobalValue *VFTable = VFTablesMap[ID]; + return VFTablesMap[ID]; +} + +llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( + BaseSubobject Base, const CXXRecordDecl *VTableClass) { + llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass); assert(VFTable && "Couldn't find a vftable for the given base?"); return VFTable; } @@ -1644,6 +1662,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, // getAddrOfVTable may return 0 if asked to get an address of a vtable which // shouldn't be used in the given record type. We want to cache this result in // VFTablesMap, thus a simple zero check is not sufficient. + VFTableIdTy ID(RD, VPtrOffset); VTablesMapTy::iterator I; bool Inserted; @@ -1697,10 +1716,11 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, if (llvm::GlobalValue *VFTable = CGM.getModule().getNamedGlobal(VFTableName)) { VFTablesMap[ID] = VFTable; - return VTableAliasIsRequred - ? cast<llvm::GlobalVariable>( - cast<llvm::GlobalAlias>(VFTable)->getBaseObject()) - : cast<llvm::GlobalVariable>(VFTable); + VTable = VTableAliasIsRequred + ? cast<llvm::GlobalVariable>( + cast<llvm::GlobalAlias>(VFTable)->getBaseObject()) + : cast<llvm::GlobalVariable>(VFTable); + return VTable; } uint64_t NumVTableSlots = |