[cfe-commits] r90667 - in /cfe/trunk: lib/CodeGen/CGVtable.cpp test/CodeGenCXX/vtable-linkage.cpp

Anders Carlsson andersca at mac.com
Sat Dec 5 09:04:47 PST 2009


Author: andersca
Date: Sat Dec  5 11:04:47 2009
New Revision: 90667

URL: http://llvm.org/viewvc/llvm-project?rev=90667&view=rev
Log:
Factor vtable related GlobalVariable creation out into a separate function. Add vtable linkage test.

Added:
    cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGVtable.cpp

Modified: cfe/trunk/lib/CodeGen/CGVtable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.cpp?rev=90667&r1=90666&r2=90667&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Sat Dec  5 11:04:47 2009
@@ -747,17 +747,11 @@
   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 @@
 };
 }
 
+/// 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 @@
   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) {

Added: cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp?rev=90667&view=auto

==============================================================================
--- cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp Sat Dec  5 11:04:47 2009
@@ -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; }





More information about the cfe-commits mailing list