diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGVTables.cpp | 262 |
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 |