diff options
author | Anders Carlsson <andersca@mac.com> | 2009-12-05 17:04:47 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-12-05 17:04:47 +0000 |
commit | 21bbc1e70506b34b425df057f42756cb341ccf9e (patch) | |
tree | e3381ba1223aa031a72ebf9f03ed7946385fcc8e /clang | |
parent | 19323e02e92f59932e32d48b38c17f46ec096e08 (diff) | |
download | bcm5719-llvm-21bbc1e70506b34b425df057f42756cb341ccf9e.tar.gz bcm5719-llvm-21bbc1e70506b34b425df057f42756cb341ccf9e.zip |
Factor vtable related GlobalVariable creation out into a separate function. Add vtable linkage test.
llvm-svn: 90667
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/CGVtable.cpp | 64 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/vtable-linkage.cpp | 18 |
2 files changed, 58 insertions, 24 deletions
diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp index 35caa570edb..6600a241312 100644 --- a/clang/lib/CodeGen/CGVtable.cpp +++ b/clang/lib/CodeGen/CGVtable.cpp @@ -747,17 +747,11 @@ bool VtableBuilder::OverrideMethod(GlobalDecl GD, bool MorallyVirtual, const CXXMethodDecl *MD = cast<CXXMethodDecl>(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<llvm::Constant *> inits; - llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); D1(printf("vtt %s\n", RD->getNameAsCString())); + std::vector<llvm::Constant *> 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/clang/test/CodeGenCXX/vtable-linkage.cpp b/clang/test/CodeGenCXX/vtable-linkage.cpp new file mode 100644 index 00000000000..3a1d8f38d3f --- /dev/null +++ b/clang/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; } |