Index: lib/CodeGen/CGVTables.cpp =================================================================== --- lib/CodeGen/CGVTables.cpp +++ lib/CodeGen/CGVTables.cpp @@ -945,6 +945,25 @@ CharUnits PointerWidth = Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); + // Create split points. In the Itanium ABI, vtable groups may be split at + // boundaries between vtables in that group, which occurs at the transition + // from a non-function pointer to a function pointer. + uint64_t Offset = 0; + bool LastWasFunctionPointer = false; + for (const VTableComponent &Comp : VTLayout.vtable_components()) { + bool IsFunctionPointer = Comp.isFunctionPointerKind(); + if (LastWasFunctionPointer && !IsFunctionPointer) + VTable->addMetadata( + llvm::LLVMContext::MD_splitpoint, + *llvm::MDTuple::get( + getLLVMContext(), + {llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( + Int64Ty, Offset * PointerWidth.getQuantity()))})); + + LastWasFunctionPointer = IsFunctionPointer; + ++Offset; + } + typedef std::pair BSEntry; std::vector BitsetEntries; // Create a bit set entry for each address point. Index: test/CodeGenCXX/splitpoint.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/splitpoint.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -flto -triple x86_64-unknown-linux -fvisibility hidden -emit-llvm -o - %s | FileCheck %s + +// CHECK: @_ZTV1A = +// CHECK-NOT: splitpoint +struct A { + virtual void f(); +}; + +// CHECK: @_ZTV1B = +// CHECK-NOT: splitpoint +struct B { + virtual void g(); +}; + +// CHECK: @_ZTV1C = {{.*}}, !splitpoint [[SP:![0-9]+]] +// CHECK: [[SP]] = !{i64 24} +struct C : A, B { + virtual void f(); +}; + +void A::f() {} +void B::g() {} +void C::f() {}