From: Anders Carlsson Date: Sat, 5 Dec 2009 17:04:47 +0000 (+0000) Subject: Factor vtable related GlobalVariable creation out into a separate function. Add vtabl... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7ca464366349e6b197cb521794517fa026259ee4;p=clang Factor vtable related GlobalVariable creation out into a separate function. Add vtable linkage test. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90667 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 35caa570ed..6600a24131 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -747,17 +747,11 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual, const CXXMethodDecl *MD = cast(GD.getDecl()); const bool isPure = MD->isPure(); - typedef CXXMethodDecl::method_iterator meth_iter; + // FIXME: Should OverrideOffset's be Offset? - // FIXME: Don't like the nested loops. For very large inheritance - // heirarchies we could have a table on the side with the final overridder - // and just replace each instance of an overridden method once. Would be - // nice to measure the cost/benefit on real code. - - for (meth_iter mi = MD->begin_overridden_methods(), - e = MD->end_overridden_methods(); - mi != e; ++mi) { + for (CXXMethodDecl::method_iterator mi = MD->begin_overridden_methods(), + e = MD->end_overridden_methods(); mi != e; ++mi) { GlobalDecl OGD; const CXXMethodDecl *OMD = *mi; @@ -1332,6 +1326,33 @@ public: }; } +/// createGlobalVariable - Create a global variable to be used for storing +/// either a vtable, a construction vtable or a VTT. The returned global +// variable will have the correct linkage set based on the given record decl. +static llvm::GlobalVariable * +createGlobalVariable(CodeGenModule &CGM, const CXXRecordDecl *RD, + const llvm::Type *Type, llvm::Constant *Init, + const llvm::Twine &Name) { + + // Figure out the right linkage. + llvm::GlobalVariable::LinkageTypes Linkage = + llvm::GlobalValue::LinkOnceODRLinkage; + if (RD->isInAnonymousNamespace()) + Linkage = llvm::GlobalValue::InternalLinkage; + + // Create the variable. + llvm::GlobalVariable *V = + new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true, + Linkage, Init, Name); + + + bool Hidden = CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; + if (Hidden) + V->setVisibility(llvm::GlobalVariable::HiddenVisibility); + + return V; +} + llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) { // Only classes that have virtual bases need a VTT. if (RD->getNumVBases() == 0) @@ -1341,26 +1362,21 @@ llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) { getMangleContext().mangleCXXVTT(RD, OutName); llvm::StringRef Name = OutName.str(); - llvm::GlobalVariable::LinkageTypes linktype; - linktype = llvm::GlobalValue::LinkOnceODRLinkage; - if (RD->isInAnonymousNamespace()) - linktype = llvm::GlobalValue::InternalLinkage; - std::vector inits; - llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); D1(printf("vtt %s\n", RD->getNameAsCString())); + std::vector inits; VTTBuilder b(inits, RD, *this); - llvm::Constant *C; - llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, inits.size()); - C = llvm::ConstantArray::get(type, inits); - llvm::GlobalVariable *vtt = new llvm::GlobalVariable(getModule(), type, true, - linktype, C, Name); - bool Hidden = getDeclVisibilityMode(RD) == LangOptions::Hidden; - if (Hidden) - vtt->setVisibility(llvm::GlobalVariable::HiddenVisibility); - return llvm::ConstantExpr::getBitCast(vtt, Ptr8Ty); + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size()); + + llvm::Constant *Init = llvm::ConstantArray::get(Type, inits); + + llvm::GlobalVariable *VTT = + createGlobalVariable(*this, RD, Type, Init, Name); + + return llvm::ConstantExpr::getBitCast(VTT, Int8PtrTy); } void CGVtableInfo::GenerateClassData(const CXXRecordDecl *RD) { diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp new file mode 100644 index 0000000000..3a1d8f38d3 --- /dev/null +++ b/test/CodeGenCXX/vtable-linkage.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +namespace { + // The vtables should have internal linkage. + struct A { + virtual void f() { } + }; + + struct B : virtual A { + virtual void f() { } + }; + + // CHECK: @_ZTVN12_GLOBAL__N_11BE = internal constant + // CHECK: @_ZTTN12_GLOBAL__N_11BE = internal constant + // CHECK: @_ZTVN12_GLOBAL__N_11AE = internal constant +} + +void f() { B b; }