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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits