kubamracek created this revision.
kubamracek added reviewers: rjmccall, pcc, fhahn.
kubamracek added a project: clang.
kubamracek requested review of this revision.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D112929

Files:
  clang/lib/CodeGen/CGVTables.cpp
  clang/test/CodeGenCXX/vcall-visibility-metadata-ranges.cpp
  clang/test/CodeGenCXX/vcall-visibility-metadata.cpp

Index: clang/test/CodeGenCXX/vcall-visibility-metadata.cpp
===================================================================
--- clang/test/CodeGenCXX/vcall-visibility-metadata.cpp
+++ clang/test/CodeGenCXX/vcall-visibility-metadata.cpp
@@ -8,7 +8,7 @@
 
 // Anonymous namespace.
 namespace {
-// CHECK: @_ZTVN12_GLOBAL__N_11AE = {{.*}} !vcall_visibility [[VIS_TU:![0-9]+]]
+// CHECK: @_ZTVN12_GLOBAL__N_11AE = {{.*}} !vcall_visibility [[VIS_TU_A:![0-9]+]]
 // CHECK-MS: @anon.{{.*}} = private unnamed_addr constant {{.*}}struct.(anonymous namespace)::A{{.*}} !vcall_visibility [[VIS_TU:![0-9]+]]
 struct A {
   A() {}
@@ -21,7 +21,7 @@
 
 
 // Hidden visibility.
-// CHECK: @_ZTV1B = {{.*}} !vcall_visibility [[VIS_DSO:![0-9]+]]
+// CHECK: @_ZTV1B = {{.*}} !vcall_visibility [[VIS_DSO_B:![0-9]+]]
 // CHECK-MS: @anon.{{.*}} = private unnamed_addr constant {{.*}}struct.B{{.*}} !vcall_visibility [[VIS_DSO:![0-9]+]]
 struct __attribute__((visibility("hidden"))) B {
   B() {}
@@ -100,8 +100,8 @@
 
 // CHECK-MS-DAG: [[VIS_DSO]] = !{i64 1}
 // CHECK-MS-DAG: [[VIS_TU]] = !{i64 2}
-// CHECK-DAG: [[VIS_DSO]] = !{i64 1}
-// CHECK-DAG: [[VIS_TU]] = !{i64 2}
+// CHECK-DAG: [[VIS_DSO_B]] = !{i64 1, i64 16, i64 24}
+// CHECK-DAG: [[VIS_TU_A]] = !{i64 2, i64 16, i64 24}
 // CHECK-VFE-DAG: !{i32 1, !"Virtual Function Elim", i32 1}
 // CHECK-NOVFE-DAG: !{i32 1, !"Virtual Function Elim", i32 0}
 
Index: clang/test/CodeGenCXX/vcall-visibility-metadata-ranges.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/vcall-visibility-metadata-ranges.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -flto -flto-unit -triple x86_64-unknown-linux -emit-llvm -fvirtual-function-elimination -fwhole-program-vtables -fno-rtti -o - %s | FileCheck %s
+
+//
+// (1) Base class with DSO visibility
+//
+
+class __attribute__((visibility("hidden"))) Base1 {
+  virtual void baseFunc() { }
+};
+void *new_Base1() { return new Base1(); }
+
+// CHECK:      @_ZTV5Base1 = {{.*}} constant { [3 x i8*] } { [3 x i8*] [
+// CHECK-SAME:   i8* null
+// CHECK-SAME:   i8* null
+// CHECK-SAME:   i8* bitcast (void (%class.Base1*)* @_ZN5Base18baseFuncEv to i8*)
+// CHECK-SAME: ] }, {{.*}} !vcall_visibility [[VIS_BASE1:![0-9]+]]
+
+
+
+//
+// (2) A subclass with TU visibility, so the vtable should have one part with DSO visibility (from the superclass) and one part with TU visibility
+//
+
+namespace {
+class Sub : public Base1 {
+  virtual void baseFunc() { }
+  virtual void subOnlyFunc() { }
+};
+}
+void *new_Sub() { return new Sub(); }
+
+// CHECK:      @_ZTVN12_GLOBAL__N_13SubE = {{.*}} constant { [4 x i8*] } { [4 x i8*] [
+// CHECK-SAME:   i8* null
+// CHECK-SAME:   i8* null
+// CHECK-SAME:   i8* bitcast (void (%"class.(anonymous namespace)::Sub"*)* @_ZN12_GLOBAL__N_13Sub8baseFuncEv to i8*)
+// CHECK-SAME:   i8* bitcast (void (%"class.(anonymous namespace)::Sub"*)* @_ZN12_GLOBAL__N_13Sub11subOnlyFuncEv to i8*)
+// CHECK-SAME: ] }, {{.*}}, !vcall_visibility [[VIS_SUB:![0-9]+]]
+
+
+
+//
+// (3) A subclass with multiple inheritance
+//
+
+namespace {
+struct __attribute__((visibility("hidden"))) Base2 {
+  virtual void secondBaseFunc() { }
+};
+}
+void *new_Base2() { return new Base2(); }
+
+namespace {
+class MultipleInheritanceSub : public Base1, public Base2 {
+  virtual void baseFunc() { }
+  virtual void secondBaseFunc() { }
+  virtual void anotherSubOnlyFunc() { }
+};
+}
+void *new_MultipleInheritanceSub() { return new MultipleInheritanceSub(); }
+
+// CHECK:      @_ZTVN12_GLOBAL__N_122MultipleInheritanceSubE = {{.*}} constant { [5 x i8*], [3 x i8*] } {
+// CHECK-SAME:   [5 x i8*] [
+// CHECK-SAME:     i8* null,
+// CHECK-SAME      i8* null, 
+// CHECK-SAME:     i8* bitcast (void (%"class.(anonymous namespace)::MultipleInheritanceSub"*)* @_ZN12_GLOBAL__N_122MultipleInheritanceSub8baseFuncEv to i8*), 
+// CHECK-SAME:     i8* bitcast (void (%"class.(anonymous namespace)::MultipleInheritanceSub"*)* @_ZN12_GLOBAL__N_122MultipleInheritanceSub14secondBaseFuncEv to i8*), 
+// CHECK-SAME:     i8* bitcast (void (%"class.(anonymous namespace)::MultipleInheritanceSub"*)* @_ZN12_GLOBAL__N_122MultipleInheritanceSub18anotherSubOnlyFuncEv to i8*)
+// CHECK-SAME:   ],
+// CHECK-SAME:   [3 x i8*] [
+// CHECK-SAME:     i8* inttoptr (i64 -8 to i8*),
+// CHECK-SAME:     i8* null, 
+// CHECK-SAME:     i8* bitcast (void (%"class.(anonymous namespace)::MultipleInheritanceSub"*)* @_ZThn8_N12_GLOBAL__N_122MultipleInheritanceSub14secondBaseFuncEv to i8*)
+// CHECK-SAME:   ]
+// CHECK-SAME: }, {{.*}}, !vcall_visibility [[VIS_MUL_BASE1:![0-9]+]], !vcall_visibility [[VIS_MUL_BASE2:![0-9]+]]
+
+
+
+//
+// Metadata
+//
+
+// CHECK-DAG: [[VIS_BASE1]]     = !{i64 1, i64 16, i64 24}
+// CHECK-DAG: [[VIS_SUB]]       = !{i64 1, i64 16, i64 32}
+// CHECK-DAG: [[VIS_MUL_BASE1]] = !{i64 1, i64 16, i64 40}
+// CHECK-DAG: [[VIS_MUL_BASE2]] = !{i64 1, i64 56, i64 64}
Index: clang/lib/CodeGen/CGVTables.cpp
===================================================================
--- clang/lib/CodeGen/CGVTables.cpp
+++ clang/lib/CodeGen/CGVTables.cpp
@@ -1255,12 +1255,15 @@
   CharUnits PointerWidth =
       Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
 
-  typedef std::pair<const CXXRecordDecl *, unsigned> AddressPoint;
+  // tuple of {base, address point, vtable end}
+  typedef std::tuple<const CXXRecordDecl *, unsigned, unsigned> AddressPoint;
   std::vector<AddressPoint> AddressPoints;
-  for (auto &&AP : VTLayout.getAddressPoints())
-    AddressPoints.push_back(std::make_pair(
-        AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) +
-                                AP.second.AddressPointIndex));
+  for (auto &&AP : VTLayout.getAddressPoints()) {
+    unsigned VTableOffset = VTLayout.getVTableOffset(AP.second.VTableIndex);
+    unsigned APOffset = VTableOffset + AP.second.AddressPointIndex;
+    unsigned End = VTableOffset + VTLayout.getVTableSize(AP.second.VTableIndex);
+    AddressPoints.push_back(std::make_tuple(AP.first.getBase(), APOffset, End));
+  }
 
   // Sort the address points for determinism.
   llvm::sort(AddressPoints, [this](const AddressPoint &AP1,
@@ -1271,13 +1274,13 @@
     std::string S1;
     llvm::raw_string_ostream O1(S1);
     getCXXABI().getMangleContext().mangleTypeName(
-        QualType(AP1.first->getTypeForDecl(), 0), O1);
+        QualType(std::get<0>(AP1)->getTypeForDecl(), 0), O1);
     O1.flush();
 
     std::string S2;
     llvm::raw_string_ostream O2(S2);
     getCXXABI().getMangleContext().mangleTypeName(
-        QualType(AP2.first->getTypeForDecl(), 0), O2);
+        QualType(std::get<0>(AP2)->getTypeForDecl(), 0), O2);
     O2.flush();
 
     if (S1 < S2)
@@ -1285,13 +1288,14 @@
     if (S1 != S2)
       return false;
 
-    return AP1.second < AP2.second;
+    return std::get<1>(AP1) < std::get<1>(AP2);
   });
 
   ArrayRef<VTableComponent> Comps = VTLayout.vtable_components();
   for (auto AP : AddressPoints) {
     // Create type metadata for the address point.
-    AddVTableTypeMetadata(VTable, PointerWidth * AP.second, AP.first);
+    AddVTableTypeMetadata(VTable, PointerWidth * std::get<1>(AP),
+                          std::get<0>(AP));
 
     // The class associated with each address point could also potentially be
     // used for indirect calls via a member function pointer, so we need to
@@ -1303,7 +1307,7 @@
       llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType(
           Context.getMemberPointerType(
               Comps[I].getFunctionDecl()->getType(),
-              Context.getRecordType(AP.first).getTypePtr()));
+              Context.getRecordType(std::get<0>(AP)).getTypePtr()));
       VTable->addTypeMetadata((PointerWidth * I).getQuantity(), MD);
     }
   }
@@ -1313,7 +1317,33 @@
     llvm::DenseSet<const CXXRecordDecl *> Visited;
     llvm::GlobalObject::VCallVisibility TypeVis =
         GetVCallVisibilityLevel(RD, Visited);
-    if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic)
-      VTable->setVCallVisibilityMetadata(TypeVis);
+    if (TypeVis != llvm::GlobalObject::VCallVisibilityPublic) {
+      std::set<size_t> VisitedAddressPointOffsets;
+      for (auto AP : AddressPoints) {
+        size_t AddressPointOffset = std::get<1>(AP);
+        size_t VTableEnd = std::get<2>(AP);
+
+        if (VisitedAddressPointOffsets.count(AddressPointOffset))
+          continue;
+        VisitedAddressPointOffsets.insert(AddressPointOffset);
+
+        // Create !vcall_visibility metadata describing the range of
+        // [address point, vtable end).
+        VTable->addMetadata(
+            llvm::LLVMContext::MD_vcall_visibility,
+            *llvm::MDNode::get(
+                getLLVMContext(),
+                {
+                    llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+                        llvm::Type::getInt64Ty(getLLVMContext()), TypeVis)),
+                    llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+                        llvm::Type::getInt64Ty(getLLVMContext()),
+                        (PointerWidth * AddressPointOffset).getQuantity())),
+                    llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+                        llvm::Type::getInt64Ty(getLLVMContext()),
+                        (PointerWidth * VTableEnd).getQuantity())),
+                }));
+      }
+    }
   }
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to