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.cpp328
1 files changed, 167 insertions, 161 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
index 9570550..1a09830 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp
@@ -11,16 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#include "CodeGenFunction.h"
#include "CGCXXABI.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantBuilder.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/SetVector.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <algorithm>
@@ -32,7 +30,7 @@ using namespace CodeGen;
CodeGenVTables::CodeGenVTables(CodeGenModule &CGM)
: CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {}
-llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
+llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
const ThunkInfo &Thunk) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
@@ -96,7 +94,7 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,
AdjustNull = CGF.createBasicBlock("adjust.null");
AdjustNotNull = CGF.createBasicBlock("adjust.notnull");
AdjustEnd = CGF.createBasicBlock("adjust.end");
-
+
llvm::Value *IsNull = CGF.Builder.CreateIsNull(ReturnValue);
CGF.Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull);
CGF.EmitBlock(AdjustNotNull);
@@ -113,14 +111,14 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,
CGF.EmitBlock(AdjustNull);
CGF.Builder.CreateBr(AdjustEnd);
CGF.EmitBlock(AdjustEnd);
-
+
llvm::PHINode *PHI = CGF.Builder.CreatePHI(ReturnValue->getType(), 2);
PHI->addIncoming(ReturnValue, AdjustNotNull);
- PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()),
+ PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()),
AdjustNull);
ReturnValue = PHI;
}
-
+
return RValue::get(ReturnValue);
}
@@ -232,8 +230,11 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, FunctionArgs);
// Start defining the function.
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs,
- MD->getLocation(), MD->getLocation());
+ MD->getLocation());
+ // Create a scope with an artificial location for the body of this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(*this);
// Since we didn't pass a GlobalDecl to StartFunction, do this ourselves.
CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
@@ -251,7 +252,7 @@ void CodeGenFunction::FinishThunk() {
FinishFunction();
}
-void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
+void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr,
const ThunkInfo *Thunk) {
assert(isa<CXXMethodDecl>(CurGD.getDecl()) &&
"Please use a new CGF for this thunk");
@@ -271,7 +272,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
CGM.ErrorUnsupported(
MD, "non-trivial argument copy for return-adjusting thunk");
}
- EmitMustTailThunk(MD, AdjustedThisPtr, Callee);
+ EmitMustTailThunk(MD, AdjustedThisPtr, CalleePtr);
return;
}
@@ -285,7 +286,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
// Add the rest of the arguments.
for (const ParmVarDecl *PD : MD->parameters())
- EmitDelegateCallArg(CallArgs, PD, PD->getLocStart());
+ EmitDelegateCallArg(CallArgs, PD, SourceLocation());
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
@@ -317,10 +318,11 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
!hasScalarEvaluationKind(CurFnInfo->getReturnType()))
Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
-
+
// Now emit our call.
llvm::Instruction *CallOrInvoke;
- RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, MD, &CallOrInvoke);
+ CGCallee Callee = CGCallee::forDirect(CalleePtr, MD);
+ RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, &CallOrInvoke);
// Consider return adjustment if we have ThunkInfo.
if (Thunk && !Thunk->Return.isEmpty())
@@ -340,7 +342,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
llvm::Value *AdjustedThisPtr,
- llvm::Value *Callee) {
+ llvm::Value *CalleePtr) {
// Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery
// to translate AST arguments into LLVM IR arguments. For thunks, we know
// that the caller prototype more or less matches the callee prototype with
@@ -369,13 +371,14 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
// Emit the musttail call manually. Even if the prologue pushed cleanups, we
// don't actually want to run them.
- llvm::CallInst *Call = Builder.CreateCall(Callee, Args);
+ llvm::CallInst *Call = Builder.CreateCall(CalleePtr, Args);
Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
// Apply the standard set of call attributes.
unsigned CallingConv;
CodeGen::AttributeListType AttributeList;
- CGM.ConstructAttributeList(Callee->getName(), *CurFnInfo, MD, AttributeList,
+ CGM.ConstructAttributeList(CalleePtr->getName(),
+ *CurFnInfo, MD, AttributeList,
CallingConv, /*AttrOnCallSite=*/true);
llvm::AttributeSet Attrs =
llvm::AttributeSet::get(getLLVMContext(), AttributeList);
@@ -397,11 +400,13 @@ void CodeGenFunction::generateThunk(llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk) {
StartThunk(Fn, GD, FnInfo);
+ // Create a scope with an artificial location for the body of this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(*this);
// Get our callee.
llvm::Type *Ty =
CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeGlobalDeclaration(GD));
- llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+ llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
// Make the call and return the result.
EmitCallAndReturnForThunk(Callee, &Thunk);
@@ -436,14 +441,14 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
// Remove the name from the old thunk function and get a new thunk.
OldThunkFn->setName(StringRef());
Entry = cast<llvm::GlobalValue>(CGM.GetAddrOfThunk(GD, Thunk));
-
+
// If needed, replace the old thunk with a bitcast.
if (!OldThunkFn->use_empty()) {
llvm::Constant *NewPtrForOldDecl =
llvm::ConstantExpr::getBitCast(Entry, OldThunkFn->getType());
OldThunkFn->replaceAllUsesWith(NewPtrForOldDecl);
}
-
+
// Remove the old thunk.
OldThunkFn->eraseFromParent();
}
@@ -503,7 +508,7 @@ void CodeGenVTables::maybeEmitThunkForVTable(GlobalDecl GD,
void CodeGenVTables::EmitThunks(GlobalDecl GD)
{
- const CXXMethodDecl *MD =
+ const CXXMethodDecl *MD =
cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl();
// We don't need to generate thunks for the base destructor.
@@ -520,146 +525,146 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
emitThunk(GD, Thunk, /*ForVTable=*/false);
}
-llvm::Constant *CodeGenVTables::CreateVTableInitializer(
- const CXXRecordDecl *RD, const VTableComponent *Components,
- unsigned NumComponents, const VTableLayout::VTableThunkTy *VTableThunks,
- unsigned NumVTableThunks, llvm::Constant *RTTI) {
- SmallVector<llvm::Constant *, 64> Inits;
+void CodeGenVTables::addVTableComponent(
+ ConstantArrayBuilder &builder, const VTableLayout &layout,
+ unsigned idx, llvm::Constant *rtti, unsigned &nextVTableThunkIndex) {
+ auto &component = layout.vtable_components()[idx];
- llvm::Type *Int8PtrTy = CGM.Int8PtrTy;
-
- llvm::Type *PtrDiffTy =
- CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+ auto addOffsetConstant = [&](CharUnits offset) {
+ builder.add(llvm::ConstantExpr::getIntToPtr(
+ llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()),
+ CGM.Int8PtrTy));
+ };
- unsigned NextVTableThunkIndex = 0;
+ switch (component.getKind()) {
+ case VTableComponent::CK_VCallOffset:
+ return addOffsetConstant(component.getVCallOffset());
- llvm::Constant *PureVirtualFn = nullptr, *DeletedVirtualFn = nullptr;
+ case VTableComponent::CK_VBaseOffset:
+ return addOffsetConstant(component.getVBaseOffset());
- for (unsigned I = 0; I != NumComponents; ++I) {
- VTableComponent Component = Components[I];
+ case VTableComponent::CK_OffsetToTop:
+ return addOffsetConstant(component.getOffsetToTop());
- llvm::Constant *Init = nullptr;
+ case VTableComponent::CK_RTTI:
+ return builder.add(llvm::ConstantExpr::getBitCast(rtti, CGM.Int8PtrTy));
- switch (Component.getKind()) {
- case VTableComponent::CK_VCallOffset:
- Init = llvm::ConstantInt::get(PtrDiffTy,
- Component.getVCallOffset().getQuantity());
- Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy);
- break;
- case VTableComponent::CK_VBaseOffset:
- Init = llvm::ConstantInt::get(PtrDiffTy,
- Component.getVBaseOffset().getQuantity());
- Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy);
+ case VTableComponent::CK_FunctionPointer:
+ case VTableComponent::CK_CompleteDtorPointer:
+ case VTableComponent::CK_DeletingDtorPointer: {
+ GlobalDecl GD;
+
+ // Get the right global decl.
+ switch (component.getKind()) {
+ default:
+ llvm_unreachable("Unexpected vtable component kind");
+ case VTableComponent::CK_FunctionPointer:
+ GD = component.getFunctionDecl();
break;
- case VTableComponent::CK_OffsetToTop:
- Init = llvm::ConstantInt::get(PtrDiffTy,
- Component.getOffsetToTop().getQuantity());
- Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy);
+ case VTableComponent::CK_CompleteDtorPointer:
+ GD = GlobalDecl(component.getDestructorDecl(), Dtor_Complete);
break;
- case VTableComponent::CK_RTTI:
- Init = llvm::ConstantExpr::getBitCast(RTTI, Int8PtrTy);
+ case VTableComponent::CK_DeletingDtorPointer:
+ GD = GlobalDecl(component.getDestructorDecl(), Dtor_Deleting);
break;
- case VTableComponent::CK_FunctionPointer:
- case VTableComponent::CK_CompleteDtorPointer:
- case VTableComponent::CK_DeletingDtorPointer: {
- GlobalDecl GD;
-
- // Get the right global decl.
- switch (Component.getKind()) {
- default:
- llvm_unreachable("Unexpected vtable component kind");
- case VTableComponent::CK_FunctionPointer:
- GD = Component.getFunctionDecl();
- break;
- case VTableComponent::CK_CompleteDtorPointer:
- GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Complete);
- break;
- case VTableComponent::CK_DeletingDtorPointer:
- GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Deleting);
- break;
- }
-
- if (CGM.getLangOpts().CUDA) {
- // Emit NULL for methods we can't codegen on this
- // side. Otherwise we'd end up with vtable with unresolved
- // references.
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- // OK on device side: functions w/ __device__ attribute
- // OK on host side: anything except __device__-only functions.
- bool CanEmitMethod = CGM.getLangOpts().CUDAIsDevice
- ? MD->hasAttr<CUDADeviceAttr>()
- : (MD->hasAttr<CUDAHostAttr>() ||
- !MD->hasAttr<CUDADeviceAttr>());
- if (!CanEmitMethod) {
- Init = llvm::ConstantExpr::getNullValue(Int8PtrTy);
- break;
- }
- // Method is acceptable, continue processing as usual.
- }
+ }
- if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) {
- // We have a pure virtual member function.
- if (!PureVirtualFn) {
- llvm::FunctionType *Ty =
- llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
- StringRef PureCallName = CGM.getCXXABI().GetPureVirtualCallName();
- PureVirtualFn = CGM.CreateRuntimeFunction(Ty, PureCallName);
- if (auto *F = dyn_cast<llvm::Function>(PureVirtualFn))
- F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- PureVirtualFn = llvm::ConstantExpr::getBitCast(PureVirtualFn,
- CGM.Int8PtrTy);
- }
- Init = PureVirtualFn;
- } else if (cast<CXXMethodDecl>(GD.getDecl())->isDeleted()) {
- if (!DeletedVirtualFn) {
- llvm::FunctionType *Ty =
- llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
- StringRef DeletedCallName =
- CGM.getCXXABI().GetDeletedVirtualCallName();
- DeletedVirtualFn = CGM.CreateRuntimeFunction(Ty, DeletedCallName);
- if (auto *F = dyn_cast<llvm::Function>(DeletedVirtualFn))
- F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- DeletedVirtualFn = llvm::ConstantExpr::getBitCast(DeletedVirtualFn,
- CGM.Int8PtrTy);
- }
- Init = DeletedVirtualFn;
- } else {
- // Check if we should use a thunk.
- if (NextVTableThunkIndex < NumVTableThunks &&
- VTableThunks[NextVTableThunkIndex].first == I) {
- const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second;
-
- maybeEmitThunkForVTable(GD, Thunk);
- Init = CGM.GetAddrOfThunk(GD, Thunk);
-
- NextVTableThunkIndex++;
- } else {
- llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);
-
- Init = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
- }
-
- Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
- }
- break;
+ if (CGM.getLangOpts().CUDA) {
+ // Emit NULL for methods we can't codegen on this
+ // side. Otherwise we'd end up with vtable with unresolved
+ // references.
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ // OK on device side: functions w/ __device__ attribute
+ // OK on host side: anything except __device__-only functions.
+ bool CanEmitMethod =
+ CGM.getLangOpts().CUDAIsDevice
+ ? MD->hasAttr<CUDADeviceAttr>()
+ : (MD->hasAttr<CUDAHostAttr>() || !MD->hasAttr<CUDADeviceAttr>());
+ if (!CanEmitMethod)
+ return builder.addNullPointer(CGM.Int8PtrTy);
+ // Method is acceptable, continue processing as usual.
}
- case VTableComponent::CK_UnusedFunctionPointer:
- Init = llvm::ConstantExpr::getNullValue(Int8PtrTy);
- break;
+ auto getSpecialVirtualFn = [&](StringRef name) {
+ llvm::FunctionType *fnTy =
+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ llvm::Constant *fn = CGM.CreateRuntimeFunction(fnTy, name);
+ if (auto f = dyn_cast<llvm::Function>(fn))
+ f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ return llvm::ConstantExpr::getBitCast(fn, CGM.Int8PtrTy);
};
-
- Inits.push_back(Init);
+
+ llvm::Constant *fnPtr;
+
+ // Pure virtual member functions.
+ if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) {
+ if (!PureVirtualFn)
+ PureVirtualFn =
+ getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName());
+ fnPtr = PureVirtualFn;
+
+ // Deleted virtual member functions.
+ } else if (cast<CXXMethodDecl>(GD.getDecl())->isDeleted()) {
+ if (!DeletedVirtualFn)
+ DeletedVirtualFn =
+ getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName());
+ fnPtr = DeletedVirtualFn;
+
+ // Thunks.
+ } else if (nextVTableThunkIndex < layout.vtable_thunks().size() &&
+ layout.vtable_thunks()[nextVTableThunkIndex].first == idx) {
+ auto &thunkInfo = layout.vtable_thunks()[nextVTableThunkIndex].second;
+
+ maybeEmitThunkForVTable(GD, thunkInfo);
+ nextVTableThunkIndex++;
+ fnPtr = CGM.GetAddrOfThunk(GD, thunkInfo);
+
+ // Otherwise we can use the method definition directly.
+ } else {
+ llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
+ fnPtr = CGM.GetAddrOfFunction(GD, fnTy, /*ForVTable=*/true);
+ }
+
+ fnPtr = llvm::ConstantExpr::getBitCast(fnPtr, CGM.Int8PtrTy);
+ builder.add(fnPtr);
+ return;
+ }
+
+ case VTableComponent::CK_UnusedFunctionPointer:
+ return builder.addNullPointer(CGM.Int8PtrTy);
+ }
+
+ llvm_unreachable("Unexpected vtable component kind");
+}
+
+llvm::Type *CodeGenVTables::getVTableType(const VTableLayout &layout) {
+ SmallVector<llvm::Type *, 4> tys;
+ for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) {
+ tys.push_back(llvm::ArrayType::get(CGM.Int8PtrTy, layout.getVTableSize(i)));
+ }
+
+ return llvm::StructType::get(CGM.getLLVMContext(), tys);
+}
+
+void CodeGenVTables::createVTableInitializer(ConstantStructBuilder &builder,
+ const VTableLayout &layout,
+ llvm::Constant *rtti) {
+ unsigned nextVTableThunkIndex = 0;
+ for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) {
+ auto vtableElem = builder.beginArray(CGM.Int8PtrTy);
+ size_t thisIndex = layout.getVTableOffset(i);
+ size_t nextIndex = thisIndex + layout.getVTableSize(i);
+ for (unsigned i = thisIndex; i != nextIndex; ++i) {
+ addVTableComponent(vtableElem, layout, i, rtti, nextVTableThunkIndex);
+ }
+ vtableElem.finishAndAddTo(builder);
}
-
- llvm::ArrayType *ArrayType = llvm::ArrayType::get(Int8PtrTy, NumComponents);
- return llvm::ConstantArray::get(ArrayType, Inits);
}
llvm::GlobalVariable *
-CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
- const BaseSubobject &Base,
- bool BaseIsVirtual,
+CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
+ const BaseSubobject &Base,
+ bool BaseIsVirtual,
llvm::GlobalVariable::LinkageTypes Linkage,
VTableAddressPointsMapTy& AddressPoints) {
if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
@@ -680,8 +685,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
Base.getBase(), Out);
StringRef Name = OutName.str();
- llvm::ArrayType *ArrayType =
- llvm::ArrayType::get(CGM.Int8PtrTy, VTLayout->getNumVTableComponents());
+ llvm::Type *VTType = getVTableType(*VTLayout);
// Construction vtable symbols are not part of the Itanium ABI, so we cannot
// guarantee that they actually will be available externally. Instead, when
@@ -692,8 +696,8 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
Linkage = llvm::GlobalVariable::InternalLinkage;
// Create the variable that will hold the construction vtable.
- llvm::GlobalVariable *VTable =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, Linkage);
+ llvm::GlobalVariable *VTable =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage);
CGM.setGlobalVisibility(VTable, RD);
// V-tables are always unnamed_addr.
@@ -703,12 +707,11 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
CGM.getContext().getTagDeclType(Base.getBase()));
// Create and set the initializer.
- llvm::Constant *Init = CreateVTableInitializer(
- Base.getBase(), VTLayout->vtable_component_begin(),
- VTLayout->getNumVTableComponents(), VTLayout->vtable_thunk_begin(),
- VTLayout->getNumVTableThunks(), RTTI);
- VTable->setInitializer(Init);
-
+ ConstantInitBuilder builder(CGM);
+ auto components = builder.beginStruct();
+ createVTableInitializer(components, *VTLayout, RTTI);
+ components.finishAndSetAsInitializer(VTable);
+
CGM.EmitVTableTypeMetadata(VTable, *VTLayout.get());
return VTable;
@@ -723,7 +726,7 @@ static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM,
/// Compute the required linkage of the vtable for the given class.
///
/// Note that we only call this at the end of the translation unit.
-llvm::GlobalVariable::LinkageTypes
+llvm::GlobalVariable::LinkageTypes
CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
if (!RD->isExternallyVisible())
return llvm::GlobalVariable::InternalLinkage;
@@ -737,7 +740,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
const FunctionDecl *def = nullptr;
if (keyFunction->hasBody(def))
keyFunction = cast<CXXMethodDecl>(def);
-
+
switch (keyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
@@ -751,7 +754,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
return !Context.getLangOpts().AppleKext ?
llvm::GlobalVariable::LinkOnceODRLinkage :
llvm::Function::InternalLinkage;
-
+
return llvm::GlobalVariable::ExternalLinkage;
case TSK_ImplicitInstantiation:
@@ -763,7 +766,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
return !Context.getLangOpts().AppleKext ?
llvm::GlobalVariable::WeakODRLinkage :
llvm::Function::InternalLinkage;
-
+
case TSK_ExplicitInstantiationDeclaration:
llvm_unreachable("Should not have been asked to emit this");
}
@@ -819,7 +822,7 @@ void CodeGenModule::EmitVTable(CXXRecordDecl *theClass) {
VTables.GenerateClassData(theClass);
}
-void
+void
CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) {
if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
DI->completeClassData(RD);
@@ -949,7 +952,10 @@ void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
std::vector<BSEntry> BitsetEntries;
// Create a bit set entry for each address point.
for (auto &&AP : VTLayout.getAddressPoints())
- BitsetEntries.push_back(std::make_pair(AP.first.getBase(), AP.second));
+ BitsetEntries.push_back(
+ std::make_pair(AP.first.getBase(),
+ VTLayout.getVTableOffset(AP.second.VTableIndex) +
+ AP.second.AddressPointIndex));
// Sort the bit set entries for determinism.
std::sort(BitsetEntries.begin(), BitsetEntries.end(),
OpenPOWER on IntegriCloud