Index: llvm/lib/Transforms/IPO/LowerTypeTests.cpp =================================================================== --- llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -474,7 +474,8 @@ void createJumpTableEntry(raw_ostream &AsmOS, raw_ostream &ConstraintOS, Triple::ArchType JumpTableArch, SmallVectorImpl &AsmArgs, Function *Dest); - void verifyTypeMDNode(GlobalObject *GO, MDNode *Type); + void verifyTypeMDNode(GlobalObject *GO, MDNode *Type, + bool NoCfiSectionEnforcement); void buildBitSetsFromFunctions(ArrayRef TypeIds, ArrayRef Functions); void buildBitSetsFromFunctionsNative(ArrayRef TypeIds, @@ -1186,13 +1187,14 @@ } } -void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *Type) { +void LowerTypeTestsModule::verifyTypeMDNode(GlobalObject *GO, MDNode *Type, + bool NoCfiSectionEnforcement) { if (Type->getNumOperands() != 2) report_fatal_error("All operands of type metadata must have 2 elements"); if (GO->isThreadLocal()) report_fatal_error("Bit set element may not be thread-local"); - if (isa(GO) && GO->hasSection()) + if (isa(GO) && GO->hasSection() && !NoCfiSectionEnforcement) report_fatal_error( "A member of a type identifier may not have an explicit section"); @@ -2007,6 +2009,9 @@ } } + const bool NoCfiSectionEnforcement = + M.getModuleFlag("No CFI Section Enforcement") != nullptr; + DenseMap GlobalTypeMembers; for (GlobalObject &GO : M.global_objects()) { if (isa(GO) && GO.isDeclarationForLinker()) @@ -2037,7 +2042,7 @@ IsExported, Types); GlobalTypeMembers[&GO] = GTM; for (MDNode *Type : Types) { - verifyTypeMDNode(&GO, Type); + verifyTypeMDNode(&GO, Type, NoCfiSectionEnforcement); auto &Info = TypeIdInfo[Type->getOperand(1)]; Info.UniqueId = ++CurUniqueId; Info.RefGlobals.push_back(GTM); Index: llvm/test/Transforms/GlobalDCE/virtual-functions-sections.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/GlobalDCE/virtual-functions-sections.ll @@ -0,0 +1,32 @@ +; RUN: opt < %s -globaldce -lowertypetests -lowertypetests-summary-action=export -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata) + +@vtable = internal unnamed_addr constant { [2 x i8*] } { [2 x i8*] [ + i8* bitcast (void ()* @vfunc1_live to i8*), + i8* bitcast (void ()* @vfunc2_dead to i8*) +]}, align 8, !type !0, !type !1, !vcall_visibility !{i64 2}, section "my_custom_section" +!0 = !{i64 0, !"vfunc1.type"} +!1 = !{i64 8, !"vfunc2.type"} + +define internal void @vfunc1_live() { + ; CHECK: define internal void @vfunc1_live( + ret void +} + +define internal void @vfunc2_dead() { + ; CHECK-NOT: define internal void @vfunc2_dead( + ret void +} + +define void @main() { + %1 = ptrtoint { [2 x i8*] }* @vtable to i64 ; to keep @vtable alive + %2 = tail call { i8*, i1 } @llvm.type.checked.load(i8* null, i32 0, metadata !"vfunc1.type") + ret void +} + +!998 = !{i32 1, !"Virtual Function Elim", i32 1} +!999 = !{i32 1, !"No CFI Section Enforcement", i32 1} +!llvm.module.flags = !{!998, !999}