summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp262
1 files changed, 159 insertions, 103 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
index bed4670..891697f 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
@@ -240,7 +240,7 @@ static BaseOffset ComputeBaseOffset(ASTContext &Context,
const RecordType *BaseType = Element.Base->getType()->getAs<RecordType>();
const CXXRecordDecl *Base = cast<CXXRecordDecl>(BaseType->getDecl());
- NonVirtualOffset += Layout.getBaseClassOffset(Base);
+ NonVirtualOffset += Layout.getBaseClassOffsetInBits(Base);
}
// FIXME: This should probably use CharUnits or something. Maybe we should
@@ -358,12 +358,12 @@ FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual,
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
- BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl);
BaseOffsetInLayoutClass =
- LayoutClassLayout.getVBaseClassOffset(BaseDecl);
+ LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl);
} else {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- uint64_t Offset = Layout.getBaseClassOffset(BaseDecl);
+ uint64_t Offset = Layout.getBaseClassOffsetInBits(BaseDecl);
BaseOffset = Base.getBaseOffset() + Offset;
BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset;
@@ -396,9 +396,9 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base,
continue;
}
- BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
+ BaseOffset = MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl);
} else {
- BaseOffset = Layout.getBaseClassOffset(BaseDecl) +
+ BaseOffset = Layout.getBaseClassOffsetInBits(BaseDecl) +
Base.getBaseOffset();
}
@@ -793,22 +793,22 @@ VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
// (Since we're emitting the vcall and vbase offsets in reverse order, we'll
// emit them for the primary base first).
if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
- bool PrimaryBaseIsVirtual = Layout.getPrimaryBaseWasVirtual();
+ bool PrimaryBaseIsVirtual = Layout.isPrimaryBaseVirtual();
uint64_t PrimaryBaseOffset;
// Get the base offset of the primary base.
if (PrimaryBaseIsVirtual) {
- assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
+ assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 &&
"Primary vbase should have a zero offset!");
const ASTRecordLayout &MostDerivedClassLayout =
Context.getASTRecordLayout(MostDerivedClass);
PrimaryBaseOffset =
- MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
+ MostDerivedClassLayout.getVBaseClassOffsetInBits(PrimaryBase);
} else {
- assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
"Primary base should have a zero offset!");
PrimaryBaseOffset = Base.getBaseOffset();
@@ -849,9 +849,9 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
// Handle the primary base first.
// We only want to add vcall offsets if the base is non-virtual; a virtual
// primary base will have its vcall and vbase offsets emitted already.
- if (PrimaryBase && !Layout.getPrimaryBaseWasVirtual()) {
+ if (PrimaryBase && !Layout.isPrimaryBaseVirtual()) {
// Get the base offset of the primary base.
- assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
"Primary base should have a zero offset!");
AddVCallOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
@@ -903,7 +903,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
// Get the base offset of this base.
uint64_t BaseOffset = Base.getBaseOffset() +
- Layout.getBaseClassOffset(BaseDecl);
+ Layout.getBaseClassOffsetInBits(BaseDecl);
AddVCallOffsets(BaseSubobject(BaseDecl, BaseOffset), VBaseOffset);
}
@@ -924,7 +924,7 @@ void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
if (I->isVirtual() && VisitedVirtualBases.insert(BaseDecl)) {
// FIXME: We shouldn't use / 8 here.
int64_t Offset =
- (int64_t)(LayoutClassLayout.getVBaseClassOffset(BaseDecl) -
+ (int64_t)(LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl) -
OffsetInLayoutClass) / 8;
// Add the vbase offset offset.
@@ -1372,7 +1372,7 @@ VTableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
/// Get the virtual base offset, relative to the most derived class
/// layout.
OffsetToBaseSubobject +=
- LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase);
+ LayoutClassLayout.getVBaseClassOffsetInBits(Offset.VirtualBase);
} else {
// Otherwise, the non-virtual offset is relative to the derived class
// offset.
@@ -1520,8 +1520,8 @@ VTableBuilder::IsOverriderUsed(const CXXMethodDecl *Overrider,
if (!PrimaryBase)
break;
- if (Layout.getPrimaryBaseWasVirtual()) {
- assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
+ if (Layout.isPrimaryBaseVirtual()) {
+ assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 &&
"Primary base should always be at offset 0!");
const ASTRecordLayout &LayoutClassLayout =
@@ -1529,13 +1529,13 @@ VTableBuilder::IsOverriderUsed(const CXXMethodDecl *Overrider,
// Now check if this is the primary base that is not a primary base in the
// most derived class.
- if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
+ if (LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase) !=
FirstBaseOffsetInLayoutClass) {
// We found it, stop walking the chain.
break;
}
} else {
- assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
"Primary base should always be at offset 0!");
}
@@ -1586,23 +1586,23 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
uint64_t PrimaryBaseOffset;
uint64_t PrimaryBaseOffsetInLayoutClass;
- if (Layout.getPrimaryBaseWasVirtual()) {
- assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
+ if (Layout.isPrimaryBaseVirtual()) {
+ assert(Layout.getVBaseClassOffsetInBits(PrimaryBase) == 0 &&
"Primary vbase should have a zero offset!");
const ASTRecordLayout &MostDerivedClassLayout =
Context.getASTRecordLayout(MostDerivedClass);
PrimaryBaseOffset =
- MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
+ MostDerivedClassLayout.getVBaseClassOffsetInBits(PrimaryBase);
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
PrimaryBaseOffsetInLayoutClass =
- LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
+ LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase);
} else {
- assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
+ assert(Layout.getBaseClassOffsetInBits(PrimaryBase) == 0 &&
"Primary base should have a zero offset!");
PrimaryBaseOffset = Base.getBaseOffset();
@@ -1664,9 +1664,18 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
if (ThisAdjustment.VCallOffsetOffset &&
Overrider.Method->getParent() == MostDerivedClass) {
+
+ // There's no return adjustment from OverriddenMD and MD,
+ // but that doesn't mean there isn't one between MD and
+ // the final overrider.
+ BaseOffset ReturnAdjustmentOffset =
+ ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD);
+ ReturnAdjustment ReturnAdjustment =
+ ComputeReturnAdjustment(ReturnAdjustmentOffset);
+
// This is a virtual thunk for the most derived class, add it.
AddThunk(Overrider.Method,
- ThunkInfo(ThisAdjustment, ReturnAdjustment()));
+ ThunkInfo(ThisAdjustment, ReturnAdjustment));
}
}
@@ -1779,13 +1788,13 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
if (!PrimaryBase)
break;
- if (Layout.getPrimaryBaseWasVirtual()) {
+ if (Layout.isPrimaryBaseVirtual()) {
// Check if this virtual primary base is a primary base in the layout
// class. If it's not, we don't want to add it.
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
- if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) !=
+ if (LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase) !=
OffsetInLayoutClass) {
// We don't want to add this class (or any of its primary bases).
break;
@@ -1835,7 +1844,7 @@ void VTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
}
// Get the base offset of this base.
- uint64_t RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
+ uint64_t RelativeBaseOffset = Layout.getBaseClassOffsetInBits(BaseDecl);
uint64_t BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
uint64_t BaseOffsetInLayoutClass = OffsetInLayoutClass + RelativeBaseOffset;
@@ -1866,7 +1875,7 @@ VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
// Check if it's virtual.
- if (Layout.getPrimaryBaseWasVirtual()) {
+ if (Layout.isPrimaryBaseVirtual()) {
bool IsPrimaryVirtualBase = true;
if (isBuildingConstructorVTable()) {
@@ -1876,7 +1885,7 @@ VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
Context.getASTRecordLayout(LayoutClass);
uint64_t PrimaryBaseOffsetInLayoutClass =
- LayoutClassLayout.getVBaseClassOffset(PrimaryBase);
+ LayoutClassLayout.getVBaseClassOffsetInBits(PrimaryBase);
// We know that the base is not a primary base in the layout class if
// the base offsets are different.
@@ -1904,10 +1913,11 @@ VTableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
- BaseOffsetInLayoutClass = LayoutClassLayout.getVBaseClassOffset(BaseDecl);
+ BaseOffsetInLayoutClass =
+ LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl);
} else {
BaseOffsetInLayoutClass =
- OffsetInLayoutClass + Layout.getBaseClassOffset(BaseDecl);
+ OffsetInLayoutClass + Layout.getBaseClassOffsetInBits(BaseDecl);
}
DeterminePrimaryVirtualBases(BaseDecl, BaseOffsetInLayoutClass, VBases);
@@ -1933,12 +1943,12 @@ VTableBuilder::LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
const ASTRecordLayout &MostDerivedClassLayout =
Context.getASTRecordLayout(MostDerivedClass);
uint64_t BaseOffset =
- MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
+ MostDerivedClassLayout.getVBaseClassOffsetInBits(BaseDecl);
const ASTRecordLayout &LayoutClassLayout =
Context.getASTRecordLayout(LayoutClass);
uint64_t BaseOffsetInLayoutClass =
- LayoutClassLayout.getVBaseClassOffset(BaseDecl);
+ LayoutClassLayout.getVBaseClassOffsetInBits(BaseDecl);
LayoutPrimaryAndSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
/*BaseIsMorallyVirtual=*/true,
@@ -2230,6 +2240,19 @@ void VTableBuilder::dumpLayout(llvm::raw_ostream& Out) {
}
+static void
+CollectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context,
+ VTableBuilder::PrimaryBasesSetVectorTy &PrimaryBases) {
+ while (RD) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
+ if (PrimaryBase)
+ PrimaryBases.insert(PrimaryBase);
+
+ RD = PrimaryBase;
+ }
+}
+
void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
// Itanium C++ ABI 2.5.2:
@@ -2258,10 +2281,7 @@ void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
// Collect all the primary bases, so we can check whether methods override
// a method from the base.
VTableBuilder::PrimaryBasesSetVectorTy PrimaryBases;
- for (ASTRecordLayout::primary_base_info_iterator
- I = Layout.primary_base_begin(), E = Layout.primary_base_end();
- I != E; ++I)
- PrimaryBases.insert((*I).getBase());
+ CollectPrimaryBases(RD, CGM.getContext(), PrimaryBases);
const CXXDestructorDecl *ImplicitVirtualDtor = 0;
@@ -2336,6 +2356,33 @@ void CodeGenVTables::ComputeMethodVTableIndices(const CXXRecordDecl *RD) {
NumVirtualFunctionPointers[RD] = CurrentIndex;
}
+bool CodeGenVTables::ShouldEmitVTableInThisTU(const CXXRecordDecl *RD) {
+ assert(RD->isDynamicClass() && "Non dynamic classes have no VTable.");
+
+ TemplateSpecializationKind TSK = RD->getTemplateSpecializationKind();
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ return false;
+
+ const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD);
+ if (!KeyFunction)
+ return true;
+
+ // Itanium C++ ABI, 5.2.6 Instantiated Templates:
+ // An instantiation of a class template requires:
+ // - In the object where instantiated, the virtual table...
+ if (TSK == TSK_ImplicitInstantiation ||
+ TSK == TSK_ExplicitInstantiationDefinition)
+ return true;
+
+ // If we're building with optimization, we always emit VTables since that
+ // allows for virtual function calls to be devirtualized.
+ // (We don't want to do this in -fapple-kext mode however).
+ if (CGM.getCodeGenOpts().OptimizationLevel && !CGM.getLangOptions().AppleKext)
+ return true;
+
+ return KeyFunction->hasBody();
+}
+
uint64_t CodeGenVTables::getNumVirtualFunctionPointers(const CXXRecordDecl *RD) {
llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
NumVirtualFunctionPointers.find(RD);
@@ -2409,14 +2456,16 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
// Compute the mangled name.
llvm::SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
getCXXABI().getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(),
- Thunk.This, Name);
+ Thunk.This, Out);
else
- getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Name);
-
+ getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Out);
+ Out.flush();
+
const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD);
- return GetOrCreateLLVMFunction(Name, Ty, GD);
+ return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/true);
}
static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF,
@@ -2563,7 +2612,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
const llvm::Type *Ty =
CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(GD),
FPT->isVariadic());
- llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);
+ llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
const CGFunctionInfo &FnInfo =
CGM.getTypes().getFunctionInfo(ResultType, CallArgs,
@@ -2621,7 +2670,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
}
if (!ResultType->isVoidType() && Slot.isNull())
- CGM.getCXXABI().EmitReturnFromThunk(CGF, RV, ResultType);
+ CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType);
FinishFunction();
@@ -2632,7 +2681,8 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
setThunkVisibility(CGM, MD, Thunk, Fn);
}
-void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
+void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
+ bool UseAvailableExternallyLinkage)
{
llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk);
@@ -2667,9 +2717,42 @@ void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
OldThunkFn->eraseFromParent();
}
- // Actually generate the thunk body.
llvm::Function *ThunkFn = cast<llvm::Function>(Entry);
+
+ if (!ThunkFn->isDeclaration()) {
+ if (UseAvailableExternallyLinkage) {
+ // There is already a thunk emitted for this function, do nothing.
+ return;
+ }
+
+ // If a function has a body, it should have available_externally linkage.
+ assert(ThunkFn->hasAvailableExternallyLinkage() &&
+ "Function should have available_externally linkage!");
+
+ // Change the linkage.
+ CGM.setFunctionLinkage(cast<CXXMethodDecl>(GD.getDecl()), ThunkFn);
+ return;
+ }
+
+ // Actually generate the thunk body.
CodeGenFunction(CGM).GenerateThunk(ThunkFn, GD, Thunk);
+
+ if (UseAvailableExternallyLinkage)
+ ThunkFn->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
+}
+
+void CodeGenVTables::MaybeEmitThunkAvailableExternally(GlobalDecl GD,
+ const ThunkInfo &Thunk) {
+ // We only want to do this when building with optimizations.
+ if (!CGM.getCodeGenOpts().OptimizationLevel)
+ return;
+
+ // We can't emit thunks for member functions with incomplete types.
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ if (CGM.getTypes().VerifyFuncTypeComplete(MD->getType().getTypePtr()))
+ return;
+
+ EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true);
}
void CodeGenVTables::EmitThunks(GlobalDecl GD)
@@ -2694,7 +2777,7 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
const ThunkInfoVectorTy &ThunkInfoVector = I->second;
for (unsigned I = 0, E = ThunkInfoVector.size(); I != E; ++I)
- EmitThunk(GD, ThunkInfoVector[I]);
+ EmitThunk(GD, ThunkInfoVector[I], /*UseAvailableExternallyLinkage=*/false);
}
void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
@@ -2703,9 +2786,7 @@ void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
// We may need to generate a definition for this vtable.
if (RequireVTable && !Entry.getInt()) {
- if (!isKeyFunctionInAnotherTU(CGM.getContext(), RD) &&
- RD->getTemplateSpecializationKind()
- != TSK_ExplicitInstantiationDeclaration)
+ if (ShouldEmitVTableInThisTU(RD))
CGM.DeferredVTables.push_back(RD);
Entry.setInt(true);
@@ -2719,7 +2800,14 @@ void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD,
// Add the VTable layout.
uint64_t NumVTableComponents = Builder.getNumVTableComponents();
+ // -fapple-kext adds an extra entry at end of vtbl.
+ bool IsAppleKext = CGM.getContext().getLangOptions().AppleKext;
+ if (IsAppleKext)
+ NumVTableComponents += 1;
+
uint64_t *LayoutData = new uint64_t[NumVTableComponents + 1];
+ if (IsAppleKext)
+ LayoutData[NumVTableComponents] = 0;
Entry.setPointer(LayoutData);
// Store the number of components.
@@ -2861,12 +2949,13 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second;
Init = CGM.GetAddrOfThunk(GD, Thunk);
-
+ MaybeEmitThunkAvailableExternally(GD, Thunk);
+
NextVTableThunkIndex++;
} else {
const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);
- Init = CGM.GetAddrOfFunction(GD, Ty);
+ Init = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
}
Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
@@ -2886,52 +2975,11 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
return llvm::ConstantArray::get(ArrayType, Inits.data(), Inits.size());
}
-/// GetGlobalVariable - Will return a global variable of the given type.
-/// If a variable with a different type already exists then a new variable
-/// with the right type will be created.
-/// FIXME: We should move this to CodeGenModule and rename it to something
-/// better and then use it in CGVTT and CGRTTI.
-static llvm::GlobalVariable *
-GetGlobalVariable(llvm::Module &Module, llvm::StringRef Name,
- const llvm::Type *Ty,
- llvm::GlobalValue::LinkageTypes Linkage) {
-
- llvm::GlobalVariable *GV = Module.getNamedGlobal(Name);
- llvm::GlobalVariable *OldGV = 0;
-
- if (GV) {
- // Check if the variable has the right type.
- if (GV->getType()->getElementType() == Ty)
- return GV;
-
- assert(GV->isDeclaration() && "Declaration has wrong type!");
-
- OldGV = GV;
- }
-
- // Create a new variable.
- GV = new llvm::GlobalVariable(Module, Ty, /*isConstant=*/true,
- Linkage, 0, Name);
-
- if (OldGV) {
- // Replace occurrences of the old variable if needed.
- GV->takeName(OldGV);
-
- if (!OldGV->use_empty()) {
- llvm::Constant *NewPtrForOldDecl =
- llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
- OldGV->replaceAllUsesWith(NewPtrForOldDecl);
- }
-
- OldGV->eraseFromParent();
- }
-
- return GV;
-}
-
llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
llvm::SmallString<256> OutName;
- CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, OutName);
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, Out);
+ Out.flush();
llvm::StringRef Name = OutName.str();
ComputeVTableRelatedInformation(RD, true);
@@ -2940,8 +2988,11 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
llvm::ArrayType *ArrayType =
llvm::ArrayType::get(Int8PtrTy, getNumVTableComponents(RD));
- return GetGlobalVariable(CGM.getModule(), Name, ArrayType,
- llvm::GlobalValue::ExternalLinkage);
+ llvm::GlobalVariable *GV =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
+ llvm::GlobalValue::ExternalLinkage);
+ GV->setUnnamedAddr(true);
+ return GV;
}
void
@@ -2970,7 +3021,7 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
VTable->setLinkage(Linkage);
// Set the right visibility.
- CGM.setTypeVisibility(VTable, RD, /*ForRTTI*/ false);
+ CGM.setTypeVisibility(VTable, RD, CodeGenModule::TVK_ForVTable);
}
llvm::GlobalVariable *
@@ -2991,8 +3042,10 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
// Get the mangled construction vtable name.
llvm::SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
CGM.getCXXABI().getMangleContext().
- mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8, Base.getBase(), OutName);
+ mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8, Base.getBase(), Out);
+ Out.flush();
llvm::StringRef Name = OutName.str();
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
@@ -3001,8 +3054,8 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
// Create the variable that will hold the construction vtable.
llvm::GlobalVariable *VTable =
- GetGlobalVariable(CGM.getModule(), Name, ArrayType,
- llvm::GlobalValue::InternalLinkage);
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
+ llvm::GlobalValue::InternalLinkage);
// Add the thunks.
VTableThunksTy VTableThunks;
@@ -3034,7 +3087,10 @@ CodeGenVTables::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
VTable = GetAddrOfVTable(RD);
EmitVTableDefinition(VTable, Linkage, RD);
- GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
+ if (RD->getNumVBases()) {
+ llvm::GlobalVariable *VTT = GetAddrOfVTT(RD);
+ EmitVTTDefinition(VTT, Linkage, RD);
+ }
// If this is the magic class __cxxabiv1::__fundamental_type_info,
// we will emit the typeinfo for the fundamental types. This is the
OpenPOWER on IntegriCloud