r246213 - Generating assumption loads of vptr after ctor call (fixed)
Piotr Padlewski via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 27 14:35:37 PDT 2015
Author: prazek
Date: Thu Aug 27 16:35:37 2015
New Revision: 246213
URL: http://llvm.org/viewvc/llvm-project?rev=246213&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.
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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Thu Aug 27 16:35:37 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Aug 27 16:35:37 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Thu Aug 27 16:35:37 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Aug 27 16:35:37 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Thu Aug 27 16:35:37 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,
@@ -1374,41 +1388,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()
@@ -1423,6 +1425,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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Thu Aug 27 16:35:37 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/available-externally-hidden.cpp (original)
+++ cfe/trunk/test/CodeGen/available-externally-hidden.cpp Thu Aug 27 16:35:37 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/ctor-globalopt.cpp Thu Aug 27 16:35:37 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 targeted 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/template-instantiation.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/template-instantiation.cpp Thu Aug 27 16:35:37 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/thunks.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/thunks.cpp Thu Aug 27 16:35:37 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/virtual-base-ctor.cpp Thu Aug 27 16:35:37 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=246213&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/vtable-assume-load.cpp Thu Aug 27 16:35:37 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 at test5@@YAXXZ"()
+// CHECK-MS: call x86_thiscallcc %"struct.test5::S"* @"\01??0S at test5@@QAE at 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=246213&r1=246212&r2=246213&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp Thu Aug 27 16:35:37 2015
@@ -186,8 +186,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();
@@ -210,7 +210,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();
@@ -218,14 +218,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();
@@ -234,7 +234,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
@@ -242,7 +242,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) {
More information about the cfe-commits
mailing list