Piotr Padlewski via cfe-commits <cfe-commits@lists.llvm.org> writes: > Author: prazek > Date: Mon Aug 17 22:52:00 2015 > New Revision: 245264 > > URL: http://llvm.org/viewvc/llvm-project?rev=245264&view=rev > Log: > Generating assumption loads of vptr after ctor call (fixed) > > Generating call assume(icmp %vtable, %global_vtable) after constructor > call for devirtualization purposes. > > For more info go to: > http://lists.llvm.org/pipermail/cfe-dev/2015-July/044227.html > > Edit: > Fixed version because of PR24479.
(resending since I foolishly sent a very large text file and it got caught in moderation) This was hitting asserts on a couple of bootstrap bots, so I reverted it in r245267. Failing bots: http://lab.llvm.org:8080/green/job/clang-stage2-configure-Rlto_build/6382/ http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/2969 I also managed to grab the crash diagnostics from one of the bots, but the preprocessed source is too large for the list. > http://reviews.llvm.org/D11859 > > Added: > cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp > Modified: > cfe/trunk/lib/CodeGen/CGCXXABI.h > cfe/trunk/lib/CodeGen/CGCall.cpp > cfe/trunk/lib/CodeGen/CGClass.cpp > cfe/trunk/lib/CodeGen/CodeGenFunction.h > cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp > cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp > cfe/trunk/test/CodeGen/available-externally-hidden.cpp > cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp > cfe/trunk/test/CodeGenCXX/template-instantiation.cpp > cfe/trunk/test/CodeGenCXX/thunks.cpp > cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp > cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp > > Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original) > +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Mon Aug 17 22:52:00 2015 > @@ -346,13 +346,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. > > Modified: cfe/trunk/lib/CodeGen/CGCall.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGCall.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGCall.cpp Mon Aug 17 22:52:00 2015 > @@ -1412,7 +1412,8 @@ void CodeGenModule::ConstructAttributeLi > > 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. > > Modified: cfe/trunk/lib/CodeGen/CGClass.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGClass.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGClass.cpp Mon Aug 17 22:52:00 2015 > @@ -1806,12 +1806,14 @@ void CodeGenFunction::EmitCXXConstructor > bool ForVirtualBase, > bool Delegating, llvm::Value > *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, > - getContext().getRecordType(D->getParent())); > + getContext().getRecordType(ClassDecl)); > > if (D->isTrivial() && D->isDefaultConstructor()) { > assert(E->getNumArgs() == 0 && "trivial default ctor with args"); > @@ -1827,7 +1829,7 @@ void CodeGenFunction::EmitCXXConstructor > const Expr *Arg = E->getArg(0); > QualType SrcTy = Arg->getType(); > llvm::Value *Src = EmitLValue(Arg).getAddress(); > - QualType DestTy = getContext().getTypeDeclType(D->getParent()); > + QualType DestTy = getContext().getTypeDeclType(ClassDecl); > EmitAggregateCopyCtor(This, Src, DestTy, SrcTy); > return; > } > @@ -1850,6 +1852,41 @@ void CodeGenFunction::EmitCXXConstructor > 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. > + if (CGM.getCodeGenOpts().OptimizationLevel > 0 && > + ClassDecl->isDynamicClass() && Type != Ctor_Base) > + EmitVTableAssumptionLoads(ClassDecl, This); > +} > + > +void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, > + llvm::Value *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); > + > + 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, > + llvm::Value *This) { > + if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl)) > + for (const VPtr &Vptr : getVTablePointers(ClassDecl)) > + EmitVTableAssumptionLoad(Vptr, This); > } > > void > @@ -2017,24 +2054,12 @@ void CodeGenFunction::PushDestructorClea > 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; > > @@ -2042,17 +2067,15 @@ CodeGenFunction::InitializeVTablePointer > 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, > - LoadCXXThis(), > - VTableClass, > - NearestVBase); > - NonVirtualOffset = OffsetFromNearestVBase; > + VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset( > + *this, LoadCXXThis(), 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. > @@ -2071,23 +2094,36 @@ CodeGenFunction::InitializeVTablePointer > ->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(); > @@ -2125,11 +2161,10 @@ CodeGenFunction::InitializeVTablePointer > 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); > } > } > > @@ -2139,11 +2174,9 @@ void CodeGenFunction::InitializeVTablePo > 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); > > Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Aug 17 22:52:00 2015 > @@ -1309,21 +1309,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); > > @@ -1752,10 +1758,19 @@ 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, > llvm::Value *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, > + llvm::Value *This); > + > + /// Emit assumption that vptr load == global vtable. > + void EmitVTableAssumptionLoad(const VPtr &vptr, llvm::Value *This); > + > void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, > llvm::Value *This, llvm::Value *Src, > const CXXConstructExpr *E); > > Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original) > +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Mon Aug 17 22:52:00 2015 > @@ -190,10 +190,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, > @@ -1376,41 +1390,29 @@ void ItaniumCXXABI::emitVTableDefinition > 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); > + const CXXRecordDecl *NearestVBase) { > > - // And load the address point from the VTT. > - VTableAddressPoint = CGF.Builder.CreateLoad(VTT); > - } 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); > + if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) && > + NeedsVTTParameter(CGF.CurGD)) { > + return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base, > + NearestVBase); > } > - > - return VTableAddressPoint; > + 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() > @@ -1425,6 +1427,30 @@ llvm::Constant *ItaniumCXXABI::getVTable > 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.CreateLoad(VTT); > +} > + > +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"); > > Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original) > +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Mon Aug 17 22:52:00 2015 > @@ -215,10 +215,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, > @@ -1568,14 +1580,15 @@ void MicrosoftCXXABI::emitVTableDefiniti > } > } > > +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()); > @@ -1590,11 +1603,17 @@ static void mangleVFTableName(MicrosoftM > 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; > } > @@ -1604,6 +1623,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::g > // 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; > @@ -1657,10 +1677,11 @@ llvm::GlobalVariable *MicrosoftCXXABI::g > 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 = > > Modified: cfe/trunk/test/CodeGen/available-externally-hidden.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/available-externally-hidden.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGen/available-externally-hidden.cpp (original) > +++ cfe/trunk/test/CodeGen/available-externally-hidden.cpp Mon Aug 17 > 22:52:00 2015 > @@ -27,6 +27,6 @@ class TestSyncMessageFilter : public Syn > }; > > int main() { > -TestSyncMessageFilter* f = new TestSyncMessageFilter; > + TestSyncMessageFilter *f = new TestSyncMessageFilter; > f->Send(new Message); > } > > Modified: cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp Mon Aug 17 22:52:00 2015 > @@ -1,7 +1,7 @@ > // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | > FileCheck %s > -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O1 | > FileCheck %s --check-prefix=O1 > +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O2 | opt > - -S -globalopt -o - | FileCheck %s --check-prefix=O1 > // RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s > -// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O1 | FileCheck > %s --check-prefix=O1 > +// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O2 | opt - -S > -globalopt -o - | FileCheck %s --check-prefix=O1 > > // Check that GlobalOpt can eliminate static constructors for simple implicit > // constructors. This is a targetted integration test to make sure that > LLVM's > > Modified: cfe/trunk/test/CodeGenCXX/template-instantiation.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/template-instantiation.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/template-instantiation.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/template-instantiation.cpp Mon Aug 17 22:52:00 > 2015 > @@ -1,5 +1,7 @@ > // RUN: %clang_cc1 %s -O1 -disable-llvm-optzns -triple=x86_64-apple-darwin10 > -emit-llvm -o - | FileCheck %s > > +// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr > unnamed_addr constant > + > // CHECK: @_ZN7PR100011xE = global > // CHECK-NOT: @_ZN7PR100014kBarE = external global i32 > // > @@ -12,7 +14,6 @@ > // CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32] > // CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A > > -// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr > unnamed_addr constant > > // CHECK-NOT: _ZTVN5test31SIiEE > // CHECK-NOT: _ZTSN5test31SIiEE > > Modified: cfe/trunk/test/CodeGenCXX/thunks.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/thunks.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/thunks.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/thunks.cpp Mon Aug 17 22:52:00 2015 > @@ -1,5 +1,9 @@ > -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm > -o - | FileCheck %s > -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm > -o - -O1 -disable-llvm-optzns | FileCheck %s > +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm > -o %t > +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm > -o %t.opt -O1 -disable-llvm-optzns > +// RUN: FileCheck %s < %t > +// RUN: FileCheck %s < %t.opt > +// RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t > +// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt > > namespace Test1 { > > @@ -380,13 +384,25 @@ D::~D() {} > > /**** The following has to go at the end of the file ****/ > > +// checking without opt > +// CHECK-NONOPT-LABEL: define internal void > @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( > +// CHECK-NONOPT-NOT: comdat > + > // This is from Test5: > -// CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( > -// CHECK-NOT: comdat > -// CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv > +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv > + > +// This is from Test10: > +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv > +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv > + > +// Checking with opt > +// CHECK-OPT-LABEL: define internal void > @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous > namespace)::C"* %this) unnamed_addr #0 align 2 > > // This is from Test10: > -// CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv > -// CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv > +// CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv > +// CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv > + > +// This is from Test5: > +// CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv > > // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} } > > Modified: cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp Mon Aug 17 22:52:00 2015 > @@ -1,4 +1,4 @@ > -// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | > FileCheck %s > +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | opt > - -S -globalopt -o - | FileCheck %s > > struct B; > extern B x; > > Added: cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp?rev=245264&view=auto > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp (added) > +++ cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp Mon Aug 17 22:52:00 2015 > @@ -0,0 +1,172 @@ > +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 > -disable-llvm-optzns -fms-extensions > +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 > -disable-llvm-optzns -fms-extensions > + > +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s > +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s > +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s > +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s > +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s > + > +namespace test1 { > + > +struct A { > + A(); > + virtual void foo(); > +}; > + > +struct B : A { > + virtual void foo(); > +}; > + > +void g(A *a) { a->foo(); } > + > +// CHECK1-LABEL: define void @_ZN5test14fooAEv() > +// CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"* > +// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} > +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds > ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) > +// CHECK1: call void @llvm.assume(i1 %[[CMP]]) > +// CHECK1-LABEL: } > + > +void fooA() { > + A a; > + g(&a); > +} > + > +// CHECK1-LABEL: define void @_ZN5test14fooBEv() > +// CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %{{.*}}) > +// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} > +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds > ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) > +// CHECK1: call void @llvm.assume(i1 %[[CMP]]) > +// CHECK1-LABEL: } > + > +void fooB() { > + B b; > + g(&b); > +} > +// there should not be any assumes in the ctor that calls base ctor > +// CHECK1-LABEL: define linkonce_odr void > @_ZN5test11BC2Ev(%"struct.test1::B"* > +// CHECK1-NOT: @llvm.assume( > +// CHECK1-LABEL: } > +} > +namespace test2 { > +struct A { > + A(); > + virtual void foo(); > +}; > + > +struct B { > + B(); > + virtual void bar(); > +}; > + > +struct C : A, B { > + C(); > + virtual void foo(); > +}; > +void g(A *a) { a->foo(); } > +void h(B *b) { b->bar(); } > + > +// CHECK2-LABEL: define void @_ZN5test24testEv() > +// CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"* > +// CHECK2: %[[VTABLE:.*]] = load i8**, i8*** {{.*}} > +// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds > ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 2) > +// CHECK2: call void @llvm.assume(i1 %[[CMP]]) > + > +// CHECK2: %[[V2:.*]] = bitcast %"struct.test2::C"* %{{.*}} to i8* > +// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8 > +// CHECK2: %[[V3:.*]] = bitcast i8* %[[ADD_PTR]] to i8*** > +// CHECK2: %[[VTABLE2:.*]] = load i8**, i8*** %[[V3]] > +// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds > ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 5) > +// CHECK2: call void @llvm.assume(i1 %[[CMP2]]) > + > +// CHECK2: call void @_ZN5test21gEPNS_1AE( > +// CHECK2-LABEL: } > + > +void test() { > + C c; > + g(&c); > + h(&c); > +} > +} > + > +namespace test3 { > +struct A { > + A(); > +}; > + > +struct B : A { > + B(); > + virtual void foo(); > +}; > + > +struct C : virtual A, B { > + C(); > + virtual void foo(); > +}; > +void g(B *a) { a->foo(); } > + > +// CHECK3-LABEL: define void @_ZN5test34testEv() > +// CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"* > +// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ([4 x > i8*], [4 x i8*]* @_ZTVN5test31CE, i64 0, i64 3) > +// CHECK3: call void @llvm.assume(i1 %[[CMP]]) > +// CHECK3-LABLEL: } > +void test() { > + C c; > + g(&c); > +} > +} // test3 > + > +namespace test4 { > +struct A { > + A(); > + virtual void foo(); > +}; > + > +struct B : virtual A { > + B(); > + virtual void foo(); > +}; > +struct C : B { > + C(); > + virtual void foo(); > +}; > + > +void g(C *c) { c->foo(); } > + > +// CHECK4-LABEL: define void @_ZN5test44testEv() > +// CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"* > +// CHECK4: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} > +// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds > ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4) > +// CHECK4: call void @llvm.assume(i1 %[[CMP]] > + > +// CHECK4: %[[VTABLE2:.*]] = load i8**, i8*** %{{.*}} > +// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds > ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4) > +// CHECK4: call void @llvm.assume(i1 %[[CMP2]]) > +// CHECK4-LABEL: } > + > +void test() { > + C c; > + g(&c); > +} > +} // test4 > + > +namespace test5 { > + > +struct __declspec(novtable) S { > + virtual void foo(); > +}; > + > +void g(S &s) { s.foo(); } > + > +// if struct has novtable specifier, then we can't generate assumes > +// CHECK-MS-LABEL: define void @"\01?test@test5@@YAXXZ"() > +// CHECK-MS: call x86_thiscallcc %"struct.test5::S"* > @"\01??0S@test5@@QAE@XZ"( > +// CHECK-MS-NOT: @llvm.assume > +// CHECK-MS-LABEL: } > + > +void test() { > + S s; > + g(s); > +} > + > +} // test5 > > Modified: cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp?rev=245264&r1=245263&r2=245264&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp Mon Aug 17 > 22:52:00 2015 > @@ -182,8 +182,8 @@ void f() { > namespace Test9 { > // all virtual functions are outline, so we can assume that it will > // be generated in translation unit where foo is defined > -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant > -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant > +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr > constant > +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr > constant > struct A { > virtual void foo(); > virtual void bar(); > @@ -206,7 +206,7 @@ void g() { > namespace Test10 { > > // because A's key function is defined here, vtable is generated in this TU > -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant > +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant > struct A { > virtual void foo(); > virtual void bar(); > @@ -214,14 +214,14 @@ struct A { > void A::foo() {} > > // Because key function is inline we will generate vtable as linkonce_odr > -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant > +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant > struct D : A { > void bar(); > }; > inline void D::bar() {} > > // because B has outline key function then we can refer to > -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr > constant > +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr > constant > struct B : A { > void foo(); > void bar(); > @@ -230,7 +230,7 @@ struct B : A { > // C's key function (car) is outline, but C has inline virtual function so we > // can't guarantee that we will be able to refer to bar from name > // so (at the moment) we can't emit vtable available_externally > -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant > +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant > struct C : A { > void bar() {} // defined in body - not key function > virtual inline void gar(); // inline in body - not key function > @@ -238,7 +238,7 @@ struct C : A { > }; > > // no key function, vtable will be generated everywhere it will be used > -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant > +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant > struct E : A {}; > > void g(A& a) { > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits