summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGVTables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGVTables.cpp')
-rw-r--r--lib/CodeGen/CGVTables.cpp427
1 files changed, 151 insertions, 276 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 0f023e6..6abac26 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -87,112 +87,61 @@ private:
/// MostDerivedClassLayout - the AST record layout of the most derived class.
const ASTRecordLayout &MostDerivedClassLayout;
- /// BaseSubobjectMethodPairTy - Uniquely identifies a member function
+ /// MethodBaseOffsetPairTy - Uniquely identifies a member function
/// in a base subobject.
- typedef std::pair<BaseSubobject, const CXXMethodDecl *>
- BaseSubobjectMethodPairTy;
-
- typedef llvm::DenseMap<BaseSubobjectMethodPairTy,
+ typedef std::pair<const CXXMethodDecl *, uint64_t> MethodBaseOffsetPairTy;
+
+ typedef llvm::DenseMap<MethodBaseOffsetPairTy,
OverriderInfo> OverridersMapTy;
/// OverridersMap - The final overriders for all virtual member functions of
/// all the base subobjects of the most derived class.
OverridersMapTy OverridersMap;
- /// VisitedVirtualBases - A set of all the visited virtual bases, used to
- /// avoid visiting virtual bases more than once.
- llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBases;
+ /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented
+ /// as a record decl and a subobject number) and its offsets in the most
+ /// derived class as well as the layout class.
+ typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>,
+ uint64_t> SubobjectOffsetMapTy;
- typedef llvm::DenseMap<BaseSubobjectMethodPairTy, BaseOffset>
- AdjustmentOffsetsMapTy;
-
- /// ReturnAdjustments - Holds return adjustments for all the overriders that
- /// need to perform return value adjustments.
- AdjustmentOffsetsMapTy ReturnAdjustments;
-
- // FIXME: We might be able to get away with making this a SmallSet.
- typedef llvm::SmallSetVector<uint64_t, 2> OffsetSetVectorTy;
-
- /// SubobjectOffsetsMapTy - This map is used for keeping track of all the
- /// base subobject offsets that a single class declaration might refer to.
- ///
- /// For example, in:
- ///
- /// struct A { virtual void f(); };
- /// struct B1 : A { };
- /// struct B2 : A { };
- /// struct C : B1, B2 { virtual void f(); };
- ///
- /// when we determine that C::f() overrides A::f(), we need to update the
- /// overriders map for both A-in-B1 and A-in-B2 and the subobject offsets map
- /// will have the subobject offsets for both A copies.
- typedef llvm::DenseMap<const CXXRecordDecl *, OffsetSetVectorTy>
- SubobjectOffsetsMapTy;
-
- /// ComputeFinalOverriders - Compute the final overriders for a given base
- /// subobject (and all its direct and indirect bases).
- void ComputeFinalOverriders(BaseSubobject Base,
- bool BaseSubobjectIsVisitedVBase,
- uint64_t OffsetInLayoutClass,
- SubobjectOffsetsMapTy &Offsets);
+ typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy;
- /// AddOverriders - Add the final overriders for this base subobject to the
- /// map of final overriders.
- void AddOverriders(BaseSubobject Base, uint64_t OffsetInLayoutClass,
- SubobjectOffsetsMapTy &Offsets);
+ /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the
+ /// given base.
+ void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
+ uint64_t OffsetInLayoutClass,
+ SubobjectOffsetMapTy &SubobjectOffsets,
+ SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
+ SubobjectCountMapTy &SubobjectCounts);
- /// PropagateOverrider - Propagate the NewMD overrider to all the functions
- /// that OldMD overrides. For example, if we have:
- ///
- /// struct A { virtual void f(); };
- /// struct B : A { virtual void f(); };
- /// struct C : B { virtual void f(); };
- ///
- /// and we want to override B::f with C::f, we also need to override A::f with
- /// C::f.
- void PropagateOverrider(const CXXMethodDecl *OldMD,
- BaseSubobject NewBase,
- uint64_t OverriderOffsetInLayoutClass,
- const CXXMethodDecl *NewMD,
- SubobjectOffsetsMapTy &Offsets);
+ typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy;
+
+ /// dump - dump the final overriders for a base subobject, and all its direct
+ /// and indirect base subobjects.
+ void dump(llvm::raw_ostream &Out, BaseSubobject Base,
+ VisitedVirtualBasesSetTy& VisitedVirtualBases);
- static void MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
- SubobjectOffsetsMapTy &Offsets);
-
public:
FinalOverriders(const CXXRecordDecl *MostDerivedClass,
uint64_t MostDerivedClassOffset,
const CXXRecordDecl *LayoutClass);
/// getOverrider - Get the final overrider for the given method declaration in
- /// the given base subobject.
- OverriderInfo getOverrider(BaseSubobject Base,
- const CXXMethodDecl *MD) const {
- assert(OverridersMap.count(std::make_pair(Base, MD)) &&
+ /// the subobject with the given base offset.
+ OverriderInfo getOverrider(const CXXMethodDecl *MD,
+ uint64_t BaseOffset) const {
+ assert(OverridersMap.count(std::make_pair(MD, BaseOffset)) &&
"Did not find overrider!");
- return OverridersMap.lookup(std::make_pair(Base, MD));
+ return OverridersMap.lookup(std::make_pair(MD, BaseOffset));
}
- /// getReturnAdjustmentOffset - Get the return adjustment offset for the
- /// method decl in the given base subobject. Returns an empty base offset if
- /// no adjustment is needed.
- BaseOffset getReturnAdjustmentOffset(BaseSubobject Base,
- const CXXMethodDecl *MD) const {
- return ReturnAdjustments.lookup(std::make_pair(Base, MD));
- }
-
/// dump - dump the final overriders.
void dump() {
- assert(VisitedVirtualBases.empty() &&
- "Visited virtual bases aren't empty!");
- dump(llvm::errs(), BaseSubobject(MostDerivedClass, 0));
- VisitedVirtualBases.clear();
+ VisitedVirtualBasesSetTy VisitedVirtualBases;
+ dump(llvm::errs(), BaseSubobject(MostDerivedClass, 0), VisitedVirtualBases);
}
- /// dump - dump the final overriders for a base subobject, and all its direct
- /// and indirect base subobjects.
- void dump(llvm::raw_ostream &Out, BaseSubobject Base);
};
#define DUMP_OVERRIDERS 0
@@ -204,54 +153,57 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
Context(MostDerivedClass->getASTContext()),
MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) {
-
- // Compute the final overriders.
- SubobjectOffsetsMapTy Offsets;
- ComputeFinalOverriders(BaseSubobject(MostDerivedClass, 0),
- /*BaseSubobjectIsVisitedVBase=*/false,
- MostDerivedClassOffset, Offsets);
- VisitedVirtualBases.clear();
-#if DUMP_OVERRIDERS
- // And dump them (for now).
- dump();
-
- // Also dump the base offsets (for now).
- for (SubobjectOffsetsMapTy::const_iterator I = Offsets.begin(),
- E = Offsets.end(); I != E; ++I) {
- const OffsetSetVectorTy& OffsetSetVector = I->second;
+ // Compute base offsets.
+ SubobjectOffsetMapTy SubobjectOffsets;
+ SubobjectOffsetMapTy SubobjectLayoutClassOffsets;
+ SubobjectCountMapTy SubobjectCounts;
+ ComputeBaseOffsets(BaseSubobject(MostDerivedClass, 0), /*IsVirtual=*/false,
+ MostDerivedClassOffset, SubobjectOffsets,
+ SubobjectLayoutClassOffsets, SubobjectCounts);
- llvm::errs() << "Base offsets for ";
- llvm::errs() << I->first->getQualifiedNameAsString() << '\n';
+ // Get the the final overriders.
+ CXXFinalOverriderMap FinalOverriders;
+ MostDerivedClass->getFinalOverriders(FinalOverriders);
- for (unsigned I = 0, E = OffsetSetVector.size(); I != E; ++I)
- llvm::errs() << " " << I << " - " << OffsetSetVector[I] / 8 << '\n';
+ for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(),
+ E = FinalOverriders.end(); I != E; ++I) {
+ const CXXMethodDecl *MD = I->first;
+ const OverridingMethods& Methods = I->second;
+
+ for (OverridingMethods::const_iterator I = Methods.begin(),
+ E = Methods.end(); I != E; ++I) {
+ unsigned SubobjectNumber = I->first;
+ assert(SubobjectOffsets.count(std::make_pair(MD->getParent(),
+ SubobjectNumber)) &&
+ "Did not find subobject offset!");
+
+ uint64_t BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(),
+ SubobjectNumber)];
+
+ assert(I->second.size() == 1 && "Final overrider is not unique!");
+ const UniqueVirtualMethod &Method = I->second.front();
+
+ const CXXRecordDecl *OverriderRD = Method.Method->getParent();
+ assert(SubobjectLayoutClassOffsets.count(
+ std::make_pair(OverriderRD, Method.Subobject))
+ && "Did not find subobject offset!");
+ uint64_t OverriderOffset =
+ SubobjectLayoutClassOffsets[std::make_pair(OverriderRD,
+ Method.Subobject)];
+
+ OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)];
+ assert(!Overrider.Method && "Overrider should not exist yet!");
+
+ Overrider.Offset = OverriderOffset;
+ Overrider.Method = Method.Method;
+ }
}
-#endif
-}
-
-void FinalOverriders::AddOverriders(BaseSubobject Base,
- uint64_t OffsetInLayoutClass,
- SubobjectOffsetsMapTy &Offsets) {
- const CXXRecordDecl *RD = Base.getBase();
-
- for (CXXRecordDecl::method_iterator I = RD->method_begin(),
- E = RD->method_end(); I != E; ++I) {
- const CXXMethodDecl *MD = *I;
-
- if (!MD->isVirtual())
- continue;
- // First, propagate the overrider.
- PropagateOverrider(MD, Base, OffsetInLayoutClass, MD, Offsets);
-
- // Add the overrider as the final overrider of itself.
- OverriderInfo& Overrider = OverridersMap[std::make_pair(Base, MD)];
- assert(!Overrider.Method && "Overrider should not exist yet!");
-
- Overrider.Offset = OffsetInLayoutClass;
- Overrider.Method = MD;
- }
+#if DUMP_OVERRIDERS
+ // And dump them (for now).
+ dump();
+#endif
}
static BaseOffset ComputeBaseOffset(ASTContext &Context,
@@ -365,153 +317,64 @@ ComputeReturnAdjustmentBaseOffset(ASTContext &Context,
return ComputeBaseOffset(Context, BaseRD, DerivedRD);
}
-void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD,
- BaseSubobject NewBase,
- uint64_t OverriderOffsetInLayoutClass,
- const CXXMethodDecl *NewMD,
- SubobjectOffsetsMapTy &Offsets) {
- for (CXXMethodDecl::method_iterator I = OldMD->begin_overridden_methods(),
- E = OldMD->end_overridden_methods(); I != E; ++I) {
- const CXXMethodDecl *OverriddenMD = *I;
- const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent();
-
- // We want to override OverriddenMD in all subobjects, for example:
- //
- /// struct A { virtual void f(); };
- /// struct B1 : A { };
- /// struct B2 : A { };
- /// struct C : B1, B2 { virtual void f(); };
- ///
- /// When overriding A::f with C::f we need to do so in both A subobjects.
- const OffsetSetVectorTy &OffsetVector = Offsets[OverriddenRD];
-
- // Go through all the subobjects.
- for (unsigned I = 0, E = OffsetVector.size(); I != E; ++I) {
- uint64_t Offset = OffsetVector[I];
-
- BaseSubobject OverriddenSubobject = BaseSubobject(OverriddenRD, Offset);
- BaseSubobjectMethodPairTy SubobjectAndMethod =
- std::make_pair(OverriddenSubobject, OverriddenMD);
-
- OverriderInfo &Overrider = OverridersMap[SubobjectAndMethod];
-
- assert(Overrider.Method && "Did not find existing overrider!");
-
- // Check if we need return adjustments or base adjustments.
- // (We don't want to do this for pure virtual member functions).
- if (!NewMD->isPure()) {
- // Get the return adjustment base offset.
- BaseOffset ReturnBaseOffset =
- ComputeReturnAdjustmentBaseOffset(Context, NewMD, OverriddenMD);
-
- if (!ReturnBaseOffset.isEmpty()) {
- // Store the return adjustment base offset.
- ReturnAdjustments[SubobjectAndMethod] = ReturnBaseOffset;
- }
- }
-
- // Set the new overrider.
- Overrider.Offset = OverriderOffsetInLayoutClass;
- Overrider.Method = NewMD;
-
- // And propagate it further.
- PropagateOverrider(OverriddenMD, NewBase, OverriderOffsetInLayoutClass,
- NewMD, Offsets);
- }
- }
-}
-
void
-FinalOverriders::MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
- SubobjectOffsetsMapTy &Offsets) {
- // Iterate over the new offsets.
- for (SubobjectOffsetsMapTy::const_iterator I = NewOffsets.begin(),
- E = NewOffsets.end(); I != E; ++I) {
- const CXXRecordDecl *NewRD = I->first;
- const OffsetSetVectorTy& NewOffsetVector = I->second;
-
- OffsetSetVectorTy &OffsetVector = Offsets[NewRD];
-
- // Merge the new offsets set vector into the old.
- OffsetVector.insert(NewOffsetVector.begin(), NewOffsetVector.end());
- }
-}
-
-void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base,
- bool BaseSubobjectIsVisitedVBase,
- uint64_t OffsetInLayoutClass,
- SubobjectOffsetsMapTy &Offsets) {
+FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
+ uint64_t OffsetInLayoutClass,
+ SubobjectOffsetMapTy &SubobjectOffsets,
+ SubobjectOffsetMapTy &SubobjectLayoutClassOffsets,
+ SubobjectCountMapTy &SubobjectCounts) {
const CXXRecordDecl *RD = Base.getBase();
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- SubobjectOffsetsMapTy NewOffsets;
+ unsigned SubobjectNumber = 0;
+ if (!IsVirtual)
+ SubobjectNumber = ++SubobjectCounts[RD];
+
+ // Set up the subobject to offset mapping.
+ assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber))
+ && "Subobject offset already exists!");
+ assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber))
+ && "Subobject offset already exists!");
+
+ SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] =
+ Base.getBaseOffset();
+ SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] =
+ OffsetInLayoutClass;
+ // Traverse our bases.
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
- // Ignore bases that don't have any virtual member functions.
- if (!BaseDecl->isPolymorphic())
- continue;
-
- bool IsVisitedVirtualBase = BaseSubobjectIsVisitedVBase;
+
uint64_t BaseOffset;
uint64_t BaseOffsetInLayoutClass;
if (I->isVirtual()) {
- if (!VisitedVirtualBases.insert(BaseDecl))
- IsVisitedVirtualBase = true;
- BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
-
+ // Check if we've visited this virtual base before.
+ if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0)))
+ continue;
+
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
+
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
BaseOffsetInLayoutClass =
LayoutClassLayout.getVBaseClassOffset(BaseDecl);
} else {
- BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset();
- BaseOffsetInLayoutClass = Layout.getBaseClassOffset(BaseDecl) +
- OffsetInLayoutClass;
- }
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ uint64_t Offset = Layout.getBaseClassOffset(BaseDecl);
- // Compute the final overriders for this base.
- // We always want to compute the final overriders, even if the base is a
- // visited virtual base. Consider:
- //
- // struct A {
- // virtual void f();
- // virtual void g();
- // };
- //
- // struct B : virtual A {
- // void f();
- // };
- //
- // struct C : virtual A {
- // void g ();
- // };
- //
- // struct D : B, C { };
- //
- // Here, we still want to compute the overriders for A as a base of C,
- // because otherwise we'll miss that C::g overrides A::f.
- ComputeFinalOverriders(BaseSubobject(BaseDecl, BaseOffset),
- IsVisitedVirtualBase, BaseOffsetInLayoutClass,
- NewOffsets);
- }
-
- /// Now add the overriders for this particular subobject.
- /// (We don't want to do this more than once for a virtual base).
- if (!BaseSubobjectIsVisitedVBase)
- AddOverriders(Base, OffsetInLayoutClass, NewOffsets);
-
- // And merge the newly discovered subobject offsets.
- MergeSubobjectOffsets(NewOffsets, Offsets);
-
- /// Finally, add the offset for our own subobject.
- Offsets[RD].insert(Base.getBaseOffset());
+ BaseOffset = Base.getBaseOffset() + Offset;
+ BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
+ }
+
+ ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset), I->isVirtual(),
+ BaseOffsetInLayoutClass, SubobjectOffsets,
+ SubobjectLayoutClassOffsets, SubobjectCounts);
+ }
}
-void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) {
+void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base,
+ VisitedVirtualBasesSetTy &VisitedVirtualBases) {
const CXXRecordDecl *RD = Base.getBase();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
@@ -537,7 +400,7 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) {
Base.getBaseOffset();
}
- dump(Out, BaseSubobject(BaseDecl, BaseOffset));
+ dump(Out, BaseSubobject(BaseDecl, BaseOffset), VisitedVirtualBases);
}
Out << "Final overriders for (" << RD->getQualifiedNameAsString() << ", ";
@@ -551,17 +414,17 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) {
if (!MD->isVirtual())
continue;
- OverriderInfo Overrider = getOverrider(Base, MD);
+ OverriderInfo Overrider = getOverrider(MD, Base.getBaseOffset());
Out << " " << MD->getQualifiedNameAsString() << " - (";
Out << Overrider.Method->getQualifiedNameAsString();
Out << ", " << ", " << Overrider.Offset / 8 << ')';
- AdjustmentOffsetsMapTy::const_iterator AI =
- ReturnAdjustments.find(std::make_pair(Base, MD));
- if (AI != ReturnAdjustments.end()) {
- const BaseOffset &Offset = AI->second;
+ BaseOffset Offset;
+ if (!Overrider.Method->isPure())
+ Offset = ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
+ if (!Offset.isEmpty()) {
Out << " [ret-adj: ";
if (Offset.VirtualBase)
Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, ";
@@ -1013,7 +876,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
if (Overriders) {
// Get the final overrider.
FinalOverriders::OverriderInfo Overrider =
- Overriders->getOverrider(Base, MD);
+ Overriders->getOverrider(MD, Base.getBaseOffset());
/// The vcall offset is the offset from the virtual base to the object
/// where the function was overridden.
@@ -1390,8 +1253,7 @@ void VTableBuilder::ComputeThisAdjustments() {
// Get the final overrider for this method.
FinalOverriders::OverriderInfo Overrider =
- Overriders.getOverrider(BaseSubobject(MD->getParent(),
- MethodInfo.BaseOffset), MD);
+ Overriders.getOverrider(MD, MethodInfo.BaseOffset);
// Check if we need an adjustment at all.
if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) {
@@ -1763,7 +1625,7 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
// Get the final overrider.
FinalOverriders::OverriderInfo Overrider =
- Overriders.getOverrider(Base, MD);
+ Overriders.getOverrider(MD, Base.getBaseOffset());
// Check if this virtual member function overrides a method in a primary
// base. If this is the case, and the return type doesn't require adjustment
@@ -1828,8 +1690,12 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
}
// Check if this overrider needs a return adjustment.
- BaseOffset ReturnAdjustmentOffset =
- Overriders.getReturnAdjustmentOffset(Base, MD);
+ // We don't want to do this for pure virtual member functions.
+ BaseOffset ReturnAdjustmentOffset;
+ if (!OverriderMD->isPure()) {
+ ReturnAdjustmentOffset =
+ ComputeReturnAdjustmentBaseOffset(Context, OverriderMD, MD);
+ }
ReturnAdjustment ReturnAdjustment =
ComputeReturnAdjustment(ReturnAdjustmentOffset);
@@ -2775,7 +2641,7 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
const CXXRecordDecl *RD = MD->getParent();
// Compute VTable related info for this class.
- ComputeVTableRelatedInformation(RD);
+ ComputeVTableRelatedInformation(RD, false);
ThunksMapTy::const_iterator I = Thunks.find(MD);
if (I == Thunks.end()) {
@@ -2788,24 +2654,30 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
EmitThunk(GD, ThunkInfoVector[I]);
}
-void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
- uint64_t *&LayoutData = VTableLayoutMap[RD];
+void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
+ bool RequireVTable) {
+ VTableLayoutData &Entry = VTableLayoutMap[RD];
+
+ // We may need to generate a definition for this vtable.
+ if (RequireVTable && !Entry.getInt()) {
+ if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) &&
+ RD->getTemplateSpecializationKind()
+ != TSK_ExplicitInstantiationDeclaration)
+ CGM.DeferredVTables.push_back(RD);
+
+ Entry.setInt(true);
+ }
// Check if we've computed this information before.
- if (LayoutData)
+ if (Entry.getPointer())
return;
- // We may need to generate a definition for this vtable.
- if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) &&
- RD->getTemplateSpecializationKind()
- != TSK_ExplicitInstantiationDeclaration)
- CGM.DeferredVTables.push_back(RD);
-
VTableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD);
// Add the VTable layout.
uint64_t NumVTableComponents = Builder.getNumVTableComponents();
- LayoutData = new uint64_t[NumVTableComponents + 1];
+ uint64_t *LayoutData = new uint64_t[NumVTableComponents + 1];
+ Entry.setPointer(LayoutData);
// Store the number of components.
LayoutData[0] = NumVTableComponents;
@@ -3020,7 +2892,7 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
CGM.getMangleContext().mangleCXXVTable(RD, OutName);
llvm::StringRef Name = OutName.str();
- ComputeVTableRelatedInformation(RD);
+ ComputeVTableRelatedInformation(RD, true);
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
llvm::ArrayType *ArrayType =
@@ -3054,6 +2926,9 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
// Set the correct linkage.
VTable->setLinkage(Linkage);
+
+ // Set the right visibility.
+ CGM.setGlobalVisibility(VTable, RD);
}
llvm::GlobalVariable *
OpenPOWER on IntegriCloud