r175330 - Emit vtables for an extern template class as available_externally, not as

Richard Smith richard-llvm at metafoo.co.uk
Fri Feb 15 16:51:21 PST 2013


Author: rsmith
Date: Fri Feb 15 18:51:21 2013
New Revision: 175330

URL: http://llvm.org/viewvc/llvm-project?rev=175330&view=rev
Log:
Emit vtables for an extern template class as available_externally, not as
linkonce_odr. Emit construction vtables as internal in this case, since the ABI
does not guarantee that they will be availble externally.

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

Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=175330&r1=175329&r2=175330&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Fri Feb 15 18:51:21 2013
@@ -686,6 +686,14 @@ CodeGenVTables::GenerateConstructionVTab
   llvm::ArrayType *ArrayType = 
     llvm::ArrayType::get(CGM.Int8PtrTy, VTLayout->getNumVTableComponents());
 
+  // Construction vtable symbols are not part of the Itanium ABI, so we cannot
+  // guarantee that they actually will be available externally. Instead, when
+  // emitting an available_externally VTT, we provide references to an internal
+  // linkage construction vtable. The ABI only requires complete-object vtables
+  // to be the same for all instances of a type, not construction vtables.
+  if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
+    Linkage = llvm::GlobalVariable::InternalLinkage;
+
   // Create the variable that will hold the construction vtable.
   llvm::GlobalVariable *VTable = 
     CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, Linkage);
@@ -750,11 +758,8 @@ CodeGenModule::getVTableLinkage(const CX
                  llvm::Function::InternalLinkage;
   
       case TSK_ExplicitInstantiationDeclaration:
-        // FIXME: Use available_externally linkage. However, this currently
-        // breaks LLVM's build due to undefined symbols.
-        //      return llvm::GlobalVariable::AvailableExternallyLinkage;
         return !Context.getLangOpts().AppleKext ?
-                 llvm::GlobalVariable::LinkOnceODRLinkage :
+                 llvm::GlobalVariable::AvailableExternallyLinkage :
                  llvm::Function::InternalLinkage;
     }
   }
@@ -771,10 +776,7 @@ CodeGenModule::getVTableLinkage(const CX
     return llvm::GlobalVariable::LinkOnceODRLinkage;
 
   case TSK_ExplicitInstantiationDeclaration:
-    // FIXME: Use available_externally linkage. However, this currently
-    // breaks LLVM's build due to undefined symbols.
-    //   return llvm::GlobalVariable::AvailableExternallyLinkage;
-    return llvm::GlobalVariable::LinkOnceODRLinkage;
+    return llvm::GlobalVariable::AvailableExternallyLinkage;
 
   case TSK_ExplicitInstantiationDefinition:
       return llvm::GlobalVariable::WeakODRLinkage;

Modified: cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp?rev=175330&r1=175329&r2=175330&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/vtable-linkage.cpp Fri Feb 15 18:51:21 2013
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o %t
 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o %t.hidden
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-optzns -O3 -emit-llvm -o %t.opt
 // RUN: FileCheck --check-prefix=CHECK-1 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-2 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-2-HIDDEN %s < %t.hidden
@@ -12,7 +13,9 @@
 // RUN: FileCheck --check-prefix=CHECK-7 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-8 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-9 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-9-OPT %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-10 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-10-OPT %s < %t.opt
 // RUN: FileCheck --check-prefix=CHECK-11 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-12 %s < %t
 // RUN: FileCheck --check-prefix=CHECK-13 %s < %t
@@ -160,11 +163,13 @@ void use_F() {
 // F<int> is an explicit template instantiation declaration without a
 // key function, so its vtable should have external linkage.
 // CHECK-9: @_ZTV1FIiE = external unnamed_addr constant
+// CHECK-9-OPT: @_ZTV1FIiE = available_externally unnamed_addr constant
 
 // E<int> is an explicit template instantiation declaration. It has a
 // key function that is not instantiated, so we should only reference
 // its vtable, not define it.
 // CHECK-10: @_ZTV1EIiE = external unnamed_addr constant
+// CHECK-10-OPT: @_ZTV1EIiE = available_externally unnamed_addr constant
 
 // The anonymous struct for e has no linkage, so the vtable should have
 // internal linkage.
@@ -214,3 +219,24 @@ public:
 void use_H() {
   H<int> h;
 }
+
+// RUN: FileCheck --check-prefix=CHECK-I %s < %t
+// RUN: FileCheck --check-prefix=CHECK-I-OPT %s < %t.opt
+
+// I<int> has an explicit instantiation declaration and needs a VTT and
+// construction vtables. We emit the VTT available_externally, but point it at
+// internal construction vtables because there is no way to form a reference to
+// the real construction vtables.
+
+// CHECK-I: @_ZTV1IIiE = external unnamed_addr constant
+// CHECK-I: @_ZTT1IIiE = external unnamed_addr constant
+// CHECK-I-NOT: @_ZTC1IIiE
+//
+// CHECK-I-OPT: @_ZTV1IIiE = available_externally unnamed_addr constant
+// CHECK-I-OPT: @_ZTT1IIiE = available_externally unnamed_addr constant {{.*}} @_ZTC1IIiE0_6VBase2
+// CHECK-I-OPT: @_ZTC1IIiE0_6VBase2 = internal unnamed_addr constant
+struct VBase1 { virtual void f(); }; struct VBase2 : virtual VBase1 {};
+template<typename T>
+struct I : VBase2 {};
+extern template struct I<int>;
+I<int> i;





More information about the cfe-commits mailing list