Revert r246214 and r246213

These two commits causes llvm LTO bootstrap to hang in ScalarEvolution.

llvm-svn: 246282
This commit is contained in:
Steven Wu
2015-08-28 07:14:10 +00:00
parent 1e5a8c1a5c
commit 5528da76ef
13 changed files with 143 additions and 570 deletions

View File

@@ -218,10 +218,8 @@ public:
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0;
virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; }
/// \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 bool canEmitAvailableExternallyVTable(
const CXXRecordDecl *RD) const = 0;
virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) = 0;
@@ -348,25 +346,13 @@ 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.
virtual llvm::Value *
getVTableAddressPointInStructor(CodeGenFunction &CGF, const CXXRecordDecl *RD,
BaseSubobject Base,
const CXXRecordDecl *NearestVBase) = 0;
/// 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;
/// Get the address point of the vtable for the given base subobject while
/// building a constexpr.

View File

@@ -1412,8 +1412,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>();
if (FPT && !isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
FPT->isNothrow(getContext()))
if (FPT && 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.

View File

@@ -1806,14 +1806,12 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
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(ClassDecl));
getContext().getRecordType(D->getParent()));
if (D->isTrivial() && D->isDefaultConstructor()) {
assert(E->getNumArgs() == 0 && "trivial default ctor with args");
@@ -1829,7 +1827,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
const Expr *Arg = E->getArg(0);
QualType SrcTy = Arg->getType();
llvm::Value *Src = EmitLValue(Arg).getAddress();
QualType DestTy = getContext().getTypeDeclType(ClassDecl);
QualType DestTy = getContext().getTypeDeclType(D->getParent());
EmitAggregateCopyCtor(This, Src, DestTy, SrcTy);
return;
}
@@ -1852,48 +1850,6 @@ 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,
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
@@ -2061,12 +2017,24 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) {
PushDestructorCleanup(D, Addr);
}
void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
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;
// Compute the address point.
bool NeedsVirtualOffset;
llvm::Value *VTableAddressPoint =
CGM.getCXXABI().getVTableAddressPointInStructor(
*this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase);
*this, VTableClass, Base, NearestVBase, NeedsVirtualOffset);
if (!VTableAddressPoint)
return;
@@ -2074,15 +2042,17 @@ void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
llvm::Value *VirtualOffset = nullptr;
CharUnits NonVirtualOffset = CharUnits::Zero();
if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr)) {
if (NeedsVirtualOffset) {
// 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(), Vptr.VTableClass, Vptr.NearestVBase);
NonVirtualOffset = Vptr.OffsetFromNearestVBase;
VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(*this,
LoadCXXThis(),
VTableClass,
NearestVBase);
NonVirtualOffset = OffsetFromNearestVBase;
} else {
// We can just use the base offset in the complete class.
NonVirtualOffset = Vptr.Base.getBaseOffset();
NonVirtualOffset = Base.getBaseOffset();
}
// Apply the offsets.
@@ -2101,36 +2071,23 @@ void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
->getPointerTo();
VTableField = Builder.CreateBitCast(VTableField, VTablePtrTy->getPointerTo());
VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy);
llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField);
CGM.DecorateInstruction(Store, CGM.getTBAAInfoForVTablePtr());
}
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) {
void
CodeGenFunction::InitializeVTablePointers(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
bool BaseIsNonVirtualPrimaryBase,
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy& VBases) {
// 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.
VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase, VTableClass};
Vptrs.push_back(Vptr);
InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase,
VTableClass);
}
const CXXRecordDecl *RD = Base.getBase();
@@ -2168,10 +2125,11 @@ void CodeGenFunction::getVTablePointers(BaseSubobject Base,
BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;
}
getVTablePointers(
BaseSubobject(BaseDecl, BaseOffset),
I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase,
BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs);
InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset),
I.isVirtual() ? BaseDecl : NearestVBase,
BaseOffsetFromNearestVBase,
BaseDeclIsNonVirtualPrimaryBase,
VTableClass, VBases);
}
}
@@ -2181,9 +2139,11 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
return;
// Initialize the vtable pointers for this class and all of its bases.
if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD))
for (const VPtr &Vptr : getVTablePointers(RD))
InitializeVTablePointer(Vptr);
VisitedVirtualBasesSetTy VBases;
InitializeVTablePointers(BaseSubobject(RD, CharUnits::Zero()),
/*NearestVBase=*/nullptr,
/*OffsetFromNearestVBase=*/CharUnits::Zero(),
/*BaseIsNonVirtualPrimaryBase=*/false, RD, VBases);
if (RD->getNumVBases())
CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD);

View File

@@ -682,7 +682,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM,
const CXXRecordDecl *RD) {
return CGM.getCodeGenOpts().OptimizationLevel > 0 &&
CGM.getCXXABI().canSpeculativelyEmitVTable(RD);
CGM.getCXXABI().canEmitAvailableExternallyVTable(RD);
}
/// Compute the required linkage of the v-table for the given class.
@@ -832,11 +832,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);
}

View File

@@ -1310,27 +1310,21 @@ public:
void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init,
ArrayRef<VarDecl *> ArrayIndexes);
/// 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;
/// InitializeVTablePointer - Initialize the vtable pointer of the given
/// subobject.
///
void InitializeVTablePointer(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
const CXXRecordDecl *VTableClass);
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
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(BaseSubobject Base,
const CXXRecordDecl *NearestVBase,
CharUnits OffsetFromNearestVBase,
bool BaseIsNonVirtualPrimaryBase,
const CXXRecordDecl *VTableClass,
VisitedVirtualBasesSetTy& VBases);
void InitializeVTablePointers(const CXXRecordDecl *ClassDecl);
@@ -1759,19 +1753,10 @@ 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);

View File

@@ -190,24 +190,10 @@ 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) override;
llvm::Value *getVTableAddressPointInStructorWithVTT(
CodeGenFunction &CGF, const CXXRecordDecl *VTableClass,
BaseSubobject Base, const CXXRecordDecl *NearestVBase);
BaseSubobject Base, const CXXRecordDecl *NearestVBase,
bool &NeedsVirtualOffset) override;
llvm::Constant *
getVTableAddressPointForConstExpr(BaseSubobject Base,
@@ -229,7 +215,7 @@ public:
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;
bool canEmitAvailableExternallyVTable(const CXXRecordDecl *RD) const override;
void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
bool ReturnAdjustment) override {
@@ -1388,29 +1374,41 @@ 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) {
const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
bool NeedsVTTParam = CGM.getCXXABI().NeedsVTTParameter(CGF.CurGD);
NeedsVirtualOffset = (NeedsVTTParam && NearestVBase);
if ((Base.getBase()->getNumVBases() || NearestVBase != nullptr) &&
NeedsVTTParameter(CGF.CurGD)) {
return getVTableAddressPointInStructorWithVTT(CGF, VTableClass, Base,
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.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);
}
return getVTableAddressPoint(Base, VTableClass);
return VTableAddressPoint;
}
llvm::Constant *
ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
const CXXRecordDecl *VTableClass) {
llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());
llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
BaseSubobject Base, const CXXRecordDecl *VTableClass) {
auto *VTable = getAddrOfVTable(VTableClass, CharUnits());
// Find the appropriate vtable within the vtable group.
uint64_t AddressPoint = CGM.getItaniumVTableContext()
@@ -1425,30 +1423,6 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
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");
@@ -1523,7 +1497,8 @@ void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
}
bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
bool ItaniumCXXABI::canEmitAvailableExternallyVTable(
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)

View File

@@ -106,7 +106,8 @@ public:
QualType DestTy) override;
bool EmitBadCastCall(CodeGenFunction &CGF) override;
bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override {
bool canEmitAvailableExternallyVTable(
const CXXRecordDecl *RD) const override {
return false;
}
@@ -214,22 +215,10 @@ 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) override;
BaseSubobject Base, const CXXRecordDecl *NearestVBase,
bool &NeedsVirtualOffset) override;
llvm::Constant *
getVTableAddressPointForConstExpr(BaseSubobject Base,
@@ -1579,15 +1568,14 @@ 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) {
llvm::Constant *VTableAddressPoint = getVTableAddressPoint(Base, VTableClass);
const CXXRecordDecl *NearestVBase, bool &NeedsVirtualOffset) {
NeedsVirtualOffset = (NearestVBase != nullptr);
(void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
VFTableIdTy ID(VTableClass, Base.getBaseOffset());
llvm::GlobalValue *VTableAddressPoint = VFTablesMap[ID];
if (!VTableAddressPoint) {
assert(Base.getBase()->getNumVBases() &&
!getContext().getASTRecordLayout(Base.getBase()).hasOwnVFPtr());
@@ -1602,17 +1590,11 @@ static void mangleVFTableName(MicrosoftMangleContext &MangleContext,
MangleContext.mangleCXXVFTable(RD, VFPtr->MangledPath, Out);
}
llvm::Constant *
MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base,
const CXXRecordDecl *VTableClass) {
(void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
VFTableIdTy ID(VTableClass, Base.getBaseOffset());
return VFTablesMap[ID];
}
llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr(
BaseSubobject Base, const CXXRecordDecl *VTableClass) {
llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass);
(void)getAddrOfVTable(VTableClass, Base.getBaseOffset());
VFTableIdTy ID(VTableClass, Base.getBaseOffset());
llvm::GlobalValue *VFTable = VFTablesMap[ID];
assert(VFTable && "Couldn't find a vftable for the given base?");
return VFTable;
}
@@ -1622,7 +1604,6 @@ 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;
@@ -1676,11 +1657,10 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
if (llvm::GlobalValue *VFTable =
CGM.getModule().getNamedGlobal(VFTableName)) {
VFTablesMap[ID] = VFTable;
VTable = VTableAliasIsRequred
? cast<llvm::GlobalVariable>(
cast<llvm::GlobalAlias>(VFTable)->getBaseObject())
: cast<llvm::GlobalVariable>(VFTable);
return VTable;
return VTableAliasIsRequred
? cast<llvm::GlobalVariable>(
cast<llvm::GlobalAlias>(VFTable)->getBaseObject())
: cast<llvm::GlobalVariable>(VFTable);
}
uint64_t NumVTableSlots =

View File

@@ -27,6 +27,6 @@ class TestSyncMessageFilter : public SyncMessageFilter {
};
int main() {
TestSyncMessageFilter *f = new TestSyncMessageFilter;
TestSyncMessageFilter* f = new TestSyncMessageFilter;
f->Send(new Message);
}

View File

@@ -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 -O2 | opt - -S -globalopt -o - | FileCheck %s --check-prefix=O1
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O1 | 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 -O2 | opt - -S -globalopt -o - | FileCheck %s --check-prefix=O1
// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O1 | 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

View File

@@ -1,9 +1,5 @@
// 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
// 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
namespace Test1 {
@@ -384,27 +380,13 @@ 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-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
// CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(
// CHECK-NOT: comdat
// CHECK-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 Test5:
// CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
// This is from Test10:
// CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
// CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
// CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
// CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
// CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }

View File

@@ -1,4 +1,4 @@
// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | opt - -S -globalopt -o - | FileCheck %s
// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | FileCheck %s
struct B;
extern B x;

View File

@@ -1,295 +0,0 @@
// 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
// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t.ll %s
// RUN: FileCheck --check-prefix=CHECK7 --input-file=%t.ll %s
// RUN: FileCheck --check-prefix=CHECK8 --input-file=%t.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 testMS {
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@testMS@@YAXXZ"()
// CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"\01??0S@testMS@@QAE@XZ"(
// CHECK-MS-NOT: @llvm.assume
// CHECK-MS-LABEL: }
void test() {
S s;
g(s);
}
} // testMS
namespace test6 {
// CHECK6: @_ZTVN5test61AE = external
struct A {
A();
virtual void foo();
virtual ~A() {}
};
struct B : A {
B();
};
// Because A's vtable is external, it's safe to generate assumption loads.
// CHECK6-LABEL: define void @_ZN5test61gEv()
// CHECK6: call void @_ZN5test61AC1Ev(
// CHECK6: call void @llvm.assume(
// We can't emit assumption loads for B, because if we would refer to vtable
// it would refer to functions that will not be able to find (like implicit
// inline destructor).
// CHECK6-LABEL: call void @_ZN5test61BC1Ev(
// CHECK6-NOT: call void @llvm.assume(
// CHECK6-LABEL: }
void g() {
A *a = new A;
B *b = new B;
}
}
namespace test7 {
// Because A's key function is defined here, vtable is generated in this TU
// CHECK7: @_ZTVN5test71AE = unnamed_addr constant
struct A {
A();
virtual void foo();
virtual void bar();
};
void A::foo() {}
// CHECK7-LABEL: define void @_ZN5test71gEv()
// CHECK7: call void @_ZN5test71AC1Ev(
// CHECK7: call void @llvm.assume(
// CHECK7-LABEL: }
void g() {
A *a = new A();
a->bar();
}
}
namespace test8 {
struct A {
virtual void foo();
virtual void bar();
};
// CHECK8-DAG: @_ZTVN5test81BE = available_externally unnamed_addr constant
struct B : A {
B();
void foo();
void bar();
};
// CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr constant
struct C : A {
C();
void bar();
void foo() {}
};
inline void C::bar() {}
// CHECK8-DAG: @_ZTVN5test81DE = external unnamed_addr constant
struct D : A {
D();
void foo();
void inline bar();
};
void D::bar() {}
// CHECK8-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr constant
struct E : A {
E();
};
// CHECK8-LABEL: define void @_ZN5test81bEv()
// CHECK8: call void @llvm.assume(
// CHECK8-LABEL: }
void b() {
B b;
b.bar();
}
// FIXME: C has inline virtual functions which prohibits as from generating
// assumption loads, but because vtable is generated in this TU (key function
// defined here) it would be correct to refer to it.
// CHECK8-LABEL: define void @_ZN5test81cEv()
// CHECK8-NOT: call void @llvm.assume(
// CHECK8-LABEL: }
void c() {
C c;
c.bar();
}
// CHECK8-LABEL: define void @_ZN5test81dEv()
// CHECK8: call void @llvm.assume(
// CHECK8-LABEL: }
void d() {
D d;
d.bar();
}
// CHECK8-LABEL: define void @_ZN5test81eEv()
// CHECK8: call void @llvm.assume(
// CHECK8-LABEL: }
void e() {
E e;
e.bar();
}
}

View File

@@ -184,10 +184,10 @@ void f() {
} // Test8
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-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant
// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant
// 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
struct A {
virtual void foo();
virtual void bar();
@@ -210,22 +210,22 @@ void g() {
namespace Test10 {
// because A's key function is defined here, vtable is generated in this TU
// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant
// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant
struct A {
virtual void foo();
virtual void bar();
};
void A::foo() {}
// Because key function is inline we will generate vtable as linkonce_odr.
// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
// Because key function is inline we will generate vtable as linkonce_odr
// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant
struct D : A {
void bar();
};
inline void D::bar() {}
// Because B has outline all virtual functions, we can refer to them.
// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant
// because B has outline key function then we can refer to
// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant
struct B : A {
void foo();
void bar();
@@ -233,8 +233,8 @@ 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-DAG: @_ZTVN6Test101CE = external unnamed_addr constant
// so (at the moment) we can't emit vtable available_externally
// CHECK-TEST10: @_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-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant
struct E : A {};
void g(A& a) {
@@ -365,3 +365,4 @@ void test() {
}
}