https://github.com/Prabhuk updated https://github.com/llvm/llvm-project/pull/204266
>From d9350077f8146cf43ec702be2d386614e88c1966 Mon Sep 17 00:00:00 2001 From: prabhukr <[email protected]> Date: Tue, 16 Jun 2026 16:15:50 -0700 Subject: [PATCH 1/6] Uncorrelate CFI and Callgraph related type metadata annotations Note: This patch will be broken into separate smaller patches for clang and llvm after discussion. When -fexperimental-call-graph-section flag is set, it adds type metadata to all the functions whose addresses are taken and does not have local linkage. When this flag is set along with CFI, the type metadata is added to all the vtable functions including destructors. This changes which functions are to be treated as CFI functions and includes such vtable entries to become part of the CFI check jumptables. To disambiguate intentions of CFI and callgraph mechanisms, this patch renames metadata set by callgraph mechanism to !callgraph (MD_callgraph). This prevents inflating the list of CFI functions when callgraph section is enabled along with CFI. --- clang/lib/CodeGen/CodeGenModule.cpp | 14 +++++++------ .../CodeGen/call-graph-section-callback.cpp | 2 +- .../CodeGen/call-graph-section-templates.cpp | 16 +++++++-------- .../call-graph-section-virtual-methods.cpp | 4 ++-- clang/test/CodeGen/call-graph-section.c | 14 ++++++------- clang/test/CodeGen/call-graph-section.cpp | 20 +++++++++---------- llvm/include/llvm/IR/FixedMetadataKinds.def | 2 ++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +- llvm/lib/IR/Metadata.cpp | 6 +++--- .../Transforms/IPO/ThinLTOBitcodeWriter.cpp | 15 ++++++++++++++ .../ARM/call-graph-section-addrtaken.ll | 6 +++--- .../ARM/call-graph-section-tailcall.ll | 8 ++++---- .../X86/call-graph-section-addrtaken.ll | 6 +++--- .../X86/call-graph-section-tailcall.ll | 8 ++++---- 14 files changed, 71 insertions(+), 52 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 41049d85121be..25675f99258b4 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3395,17 +3395,19 @@ static bool hasExistingGeneralizedTypeMD(llvm::Function *F) { void CodeGenModule::createIndirectFunctionTypeMD(const FunctionDecl *FD, llvm::Function *F) { - // Return if generalized type metadata is already attached. - if (hasExistingGeneralizedTypeMD(F)) - return; - // All functions which are not internal linkage could be indirect targets. // Address taken functions with internal linkage could be indirect targets. if (!F->hasLocalLinkage() || F->getFunction().hasAddressTaken(nullptr, /*IgnoreCallbackUses=*/true, /*IgnoreAssumeLikeCalls=*/true, - /*IgnoreLLVMUsed=*/false)) - F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType())); + /*IgnoreLLVMUsed=*/false)) { + F->addMetadata(llvm::LLVMContext::MD_callgraph, + *llvm::MDTuple::get( + getLLVMContext(), + {llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( + llvm::Type::getInt64Ty(getLLVMContext()), 0)), + CreateMetadataIdentifierGeneralized(FD->getType())})); + } } void CodeGenModule::createFunctionTypeMetadataForIcall(const FunctionDecl *FD, diff --git a/clang/test/CodeGen/call-graph-section-callback.cpp b/clang/test/CodeGen/call-graph-section-callback.cpp index e9b0a1818e3a4..080fa07e41847 100644 --- a/clang/test/CodeGen/call-graph-section-callback.cpp +++ b/clang/test/CodeGen/call-graph-section-callback.cpp @@ -10,7 +10,7 @@ typedef void (*CallbackFn)(int); // Callback function with "internal" linkage. // CHECK-LABEL: define internal void @_ZL10myCallbacki( -// CHECK-SAME: {{.*}} !type [[F_CALLBACK:![0-9]+]] +// CHECK-SAME: {{.*}} !callgraph [[F_CALLBACK:![0-9]+]] static void myCallback(int value) { volatile int sink = value; diff --git a/clang/test/CodeGen/call-graph-section-templates.cpp b/clang/test/CodeGen/call-graph-section-templates.cpp index 39030d27a4ea9..e6c43a41a86ab 100644 --- a/clang/test/CodeGen/call-graph-section-templates.cpp +++ b/clang/test/CodeGen/call-graph-section-templates.cpp @@ -17,27 +17,27 @@ template <class T> class Cls2 { public: // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f1Ev( - // FT-SAME: {{.*}} !type [[F_TCLS2F1:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F1:![0-9]+]] void f1() {} // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f2ES0_( - // FT-SAME: {{.*}} !type [[F_TCLS2F2:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F2:![0-9]+]] void f2(T a) {} // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f3EPS0_( - // FT-SAME: {{.*}} !type [[F_TCLS2F3:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F3:![0-9]+]] void f3(T *a) {} // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f4EPKS0_( - // FT-SAME: {{.*}} !type [[F_TCLS2F4:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F4:![0-9]+]] void f4(const T *a) {} // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f5ERS0_( - // FT-SAME: {{.*}} !type [[F_TCLS2F5:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F5:![0-9]+]] void f5(T &a) {} // FT-LABEL: define {{.*}} void @_ZN4Cls2I4Cls1E2f6ERKS0_( - // FT-SAME: {{.*}} !type [[F_TCLS2F6:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F6:![0-9]+]] void f6(const T &a) {} // Mixed type function pointer member @@ -58,7 +58,7 @@ template <class T> T *T_func(T a, T *b, const T *c, T &d, const T &e) { return b; } // CST-LABEL: define {{.*}} @_Z3foov -// CST-SAME: {{.*}} !type [[F_TCLS2F1:![0-9]+]] +// CST-SAME: {{.*}} !callgraph [[F_TCLS2F1:![0-9]+]] void foo() { // Methods for Cls2<Cls1> is checked above within the template description. Cls2<Cls1> Obj; @@ -99,7 +99,7 @@ void foo() { } // CST-LABEL: define {{.*}} @_Z6T_funcI4Cls1EPT_S1_S2_PKS1_RS1_RS3_( -// CST-SAME: {{.*}} !type [[F_TFUNC_CLS1:![0-9]+]] +// CST-SAME: {{.*}} !callgraph [[F_TFUNC_CLS1:![0-9]+]] // CST: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFvvE.generalized"} // CST: [[F_TFUNC_CLS1_CT]] = !{[[F_TFUNC_CLS1:![0-9]+]]} diff --git a/clang/test/CodeGen/call-graph-section-virtual-methods.cpp b/clang/test/CodeGen/call-graph-section-virtual-methods.cpp index afeeae146ec41..7aa7a8cf740ea 100644 --- a/clang/test/CodeGen/call-graph-section-virtual-methods.cpp +++ b/clang/test/CodeGen/call-graph-section-virtual-methods.cpp @@ -12,13 +12,13 @@ class Base { public: // FT-LABEL: define {{.*}} @_ZN4Base2vfEPc( - // FT-SAME: {{.*}} !type [[F_TVF:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TVF:![0-9]+]] virtual int vf(char *a) { return 0; }; }; class Derived : public Base { public: - // FT: define {{.*}} @_ZN7Derived2vfEPc({{.*}} !type [[F_TVF]] + // FT: define {{.*}} @_ZN7Derived2vfEPc({{.*}} !callgraph [[F_TVF]] int vf(char *a) override { return 1; }; }; diff --git a/clang/test/CodeGen/call-graph-section.c b/clang/test/CodeGen/call-graph-section.c index 69cdd59549190..9d8e99a9ad098 100644 --- a/clang/test/CodeGen/call-graph-section.c +++ b/clang/test/CodeGen/call-graph-section.c @@ -7,12 +7,12 @@ // RUN: -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,MS %s // CHECK-LABEL: define {{(dso_local)?}} void @foo( -// CHECK-SAME: {{.*}} !type [[F_TVOID:![0-9]+]] +// CHECK-SAME: {{.*}} !callgraph [[F_TVOID:![0-9]+]] void foo() { } // CHECK-LABEL: define {{(dso_local)?}} void @bar( -// CHECK-SAME: {{.*}} !type [[F_TVOID]] +// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]] void bar() { void (*fp)() = foo; // ITANIUM: call {{.*}}, !callee_type [[F_TVOID_CT:![0-9]+]] @@ -21,19 +21,19 @@ void bar() { } // CHECK-LABEL: define {{(dso_local)?}} i32 @baz( -// CHECK-SAME: {{.*}} !type [[F_TPRIMITIVE:![0-9]+]] +// CHECK-SAME: {{.*}} !callgraph [[F_TPRIMITIVE:![0-9]+]] int baz(char a, float b, double c) { return 1; } // CHECK-LABEL: define {{(dso_local)?}} ptr @qux( -// CHECK-SAME: {{.*}} !type [[F_TPTR:![0-9]+]] +// CHECK-SAME: {{.*}} !callgraph [[F_TPTR:![0-9]+]] int *qux(char *a, float *b, double *c) { return 0; } // CHECK-LABEL: define {{(dso_local)?}} void @corge( -// CHECK-SAME: {{.*}} !type [[F_TVOID]] +// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]] void corge() { int (*fp_baz)(char, float, double) = baz; // CHECK: call i32 {{.*}}, !callee_type [[F_TPRIMITIVE_CT:![0-9]+]] @@ -53,11 +53,11 @@ struct st2 { }; // CHECK-LABEL: define {{(dso_local)?}} void @stparam( -// CHECK-SAME: {{.*}} !type [[F_TSTRUCT:![0-9]+]] +// CHECK-SAME: {{.*}} !callgraph [[F_TSTRUCT:![0-9]+]] void stparam(struct st2 a, struct st2 *b) {} // CHECK-LABEL: define {{(dso_local)?}} void @stf( -// CHECK-SAME: {{.*}} !type [[F_TVOID]] +// CHECK-SAME: {{.*}} !callgraph [[F_TVOID]] void stf() { struct st1 St1; St1.fp = qux; diff --git a/clang/test/CodeGen/call-graph-section.cpp b/clang/test/CodeGen/call-graph-section.cpp index 86ed3ee2337a7..5265eda31ccf9 100644 --- a/clang/test/CodeGen/call-graph-section.cpp +++ b/clang/test/CodeGen/call-graph-section.cpp @@ -12,7 +12,7 @@ class Cls1 { public: // FT-LABEL: define {{.*}} ptr @_ZN4Cls18receiverEPcPf( - // FT-SAME: {{.*}} !type [[F_TCLS1RECEIVER:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS1RECEIVER:![0-9]+]] static int *receiver(char *a, float *b) { return 0; } }; @@ -21,39 +21,39 @@ class Cls2 { int *(*fp)(char *, float *); // FT-LABEL: define {{.*}} i32 @_ZN4Cls22f1Ecfd( - // FT-SAME: {{.*}} !type [[F_TCLS2F1:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F1:![0-9]+]] int f1(char a, float b, double c) { return 0; } // FT-LABEL: define {{.*}} ptr @_ZN4Cls22f2EPcPfPd( - // FT-SAME: {{.*}} !type [[F_TCLS2F2:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F2:![0-9]+]] int *f2(char *a, float *b, double *c) { return 0; } // FT-LABEL: define {{.*}} void @_ZN4Cls22f3E4Cls1( - // FT-SAME: {{.*}} !type [[F_TCLS2F3F4:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F3F4:![0-9]+]] void f3(Cls1 a) {} // FT-LABEL: define {{.*}} void @_ZN4Cls22f4E4Cls1( - // FT-SAME: {{.*}} !type [[F_TCLS2F3F4]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F3F4]] void f4(const Cls1 a) {} // FT-LABEL: define {{.*}} void @_ZN4Cls22f5EP4Cls1( - // FT-SAME: {{.*}} !type [[F_TCLS2F5:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F5:![0-9]+]] void f5(Cls1 *a) {} // FT-LABEL: define {{.*}} void @_ZN4Cls22f6EPK4Cls1( - // FT-SAME: {{.*}} !type [[F_TCLS2F6:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F6:![0-9]+]] void f6(const Cls1 *a) {} // FT-LABEL: define {{.*}} void @_ZN4Cls22f7ER4Cls1( - // FT-SAME: {{.*}} !type [[F_TCLS2F7:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F7:![0-9]+]] void f7(Cls1 &a) {} // FT-LABEL: define {{.*}} void @_ZN4Cls22f8ERK4Cls1( - // FT-SAME: {{.*}} !type [[F_TCLS2F8:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F8:![0-9]+]] void f8(const Cls1 &a) {} // FT-LABEL: define {{.*}} void @_ZNK4Cls22f9Ev( - // FT-SAME: {{.*}} !type [[F_TCLS2F9:![0-9]+]] + // FT-SAME: {{.*}} !callgraph [[F_TCLS2F9:![0-9]+]] void f9() const {} }; diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def index 552c1f60f2d38..a6c8d84b56ce5 100644 --- a/llvm/include/llvm/IR/FixedMetadataKinds.def +++ b/llvm/include/llvm/IR/FixedMetadataKinds.def @@ -64,3 +64,5 @@ LLVM_FIXED_MD_KIND(MD_inline_history, "inline_history", 49) LLVM_FIXED_MD_KIND(MD_elf_section_properties, "elf_section_properties", 50) LLVM_FIXED_MD_KIND(MD_unique_id, "guid", 51) LLVM_FIXED_MD_KIND(MD_mem_cache_hint, "mem.cache_hint", 52) +LLVM_FIXED_MD_KIND(MD_callgraph, "callgraph", 53) + diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index cdb9d760606f6..84efbff3de598 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1756,7 +1756,7 @@ void AsmPrinter::emitStackUsage(const MachineFunction &MF) { /// type metadata. Returns null if metadata cannot be found. static ConstantInt *extractNumericCGTypeId(const Function &F) { SmallVector<MDNode *, 2> Types; - F.getMetadata(LLVMContext::MD_type, Types); + F.getMetadata(LLVMContext::MD_callgraph, Types); for (const auto &Type : Types) { if (Type->hasGeneralizedMDString()) { MDString *MDGeneralizedTypeId = cast<MDString>(Type->getOperand(1)); diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index 491c788fc4445..0194b8f0a2083 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -1891,14 +1891,14 @@ void GlobalObject::copyMetadata(const GlobalObject *Other, unsigned Offset) { Other->getAllMetadata(MDs); for (auto &MD : MDs) { // We need to adjust the type metadata offset. - if (Offset != 0 && MD.first == LLVMContext::MD_type) { + if (Offset != 0 && (MD.first == LLVMContext::MD_type || + MD.first == LLVMContext::MD_callgraph)) { auto *OffsetConst = cast<ConstantInt>( cast<ConstantAsMetadata>(MD.second->getOperand(0))->getValue()); Metadata *TypeId = MD.second->getOperand(1); auto *NewOffsetMD = ConstantAsMetadata::get(ConstantInt::get( OffsetConst->getType(), OffsetConst->getValue() + Offset)); - addMetadata(LLVMContext::MD_type, - *MDNode::get(getContext(), {NewOffsetMD, TypeId})); + addMetadata(MD.first, *MDNode::get(getContext(), {NewOffsetMD, TypeId})); continue; } // If an offset adjustment was specified we need to modify the DIExpression diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index c14c9b869525d..01a0f3385a3c0 100644 --- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -169,6 +169,21 @@ void promoteTypeIds(Module &M, StringRef ModuleId) { LLVMContext::MD_type, *MDNode::get(M.getContext(), {MD->getOperand(0), I->second})); } + + SmallVector<MDNode *, 1> CGMDs; + GO.getMetadata(LLVMContext::MD_callgraph, CGMDs); + + GO.eraseMetadata(LLVMContext::MD_callgraph); + for (auto *MD : CGMDs) { + auto I = LocalToGlobal.find(MD->getOperand(1)); + if (I == LocalToGlobal.end()) { + GO.addMetadata(LLVMContext::MD_callgraph, *MD); + continue; + } + GO.addMetadata( + LLVMContext::MD_callgraph, + *MDNode::get(M.getContext(), {MD->getOperand(0), I->second})); + } } } diff --git a/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll b/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll index 9e243aec1128d..8bb9230316288 100644 --- a/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll +++ b/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll @@ -5,16 +5,16 @@ ; RUN: llc -mtriple=arm-unknown-linux --call-graph-section -o - < %s | FileCheck %s -declare !type !0 void @_Z6doWorkPFviE(ptr) +declare !callgraph !0 void @_Z6doWorkPFviE(ptr) -define i32 @_Z4testv() !type !1 { +define i32 @_Z4testv() !callgraph !1 { entry: call void @_Z6doWorkPFviE(ptr nonnull @_ZL10myCallbacki) ret i32 0 } ; CHECK: _ZL10myCallbacki: -define internal void @_ZL10myCallbacki(i32 %value) !type !2 { +define internal void @_ZL10myCallbacki(i32 %value) !callgraph !2 { entry: %sink = alloca i32, align 4 store volatile i32 %value, ptr %sink, align 4 diff --git a/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll b/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll index 35e570bdde405..c6152ef7c732b 100644 --- a/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll +++ b/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll @@ -3,13 +3,13 @@ ; RUN: llc -mtriple=arm-unknown-linux --call-graph-section -filetype=obj -o - < %s | \ ; RUN: llvm-readelf -x .llvm.callgraph - | FileCheck %s -define i32 @check_tailcall(ptr %func, i8 %x) !type !0 { +define i32 @check_tailcall(ptr %func, i8 %x) !callgraph !0 { entry: %call = tail call i32 %func(i8 signext %x), !callee_type !1 ret i32 %call } -define i32 @main(i32 %argc) !type !3 { +define i32 @main(i32 %argc) !callgraph !3 { entry: %andop = and i32 %argc, 1 %cmp = icmp eq i32 %andop, 0 @@ -18,9 +18,9 @@ entry: ret i32 %call.i } -declare !type !2 i32 @foo(i8 signext) +declare !callgraph !2 i32 @foo(i8 signext) -declare !type !2 i32 @bar(i8 signext) +declare !callgraph !2 i32 @bar(i8 signext) !0 = !{i64 0, !"_ZTSFiPvcE.generalized"} !1 = !{!2} diff --git a/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll b/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll index ab8498d8d3451..42d46e005fce5 100644 --- a/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll +++ b/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll @@ -5,16 +5,16 @@ ; RUN: llc -mtriple=x86_64-unknown-linux --call-graph-section -o - < %s | FileCheck %s -declare !type !0 void @_Z6doWorkPFviE(ptr) +declare !callgraph !0 void @_Z6doWorkPFviE(ptr) -define i32 @_Z4testv() !type !1 { +define i32 @_Z4testv() !callgraph !1 { entry: call void @_Z6doWorkPFviE(ptr nonnull @_ZL10myCallbacki) ret i32 0 } ; CHECK: _ZL10myCallbacki: -define internal void @_ZL10myCallbacki(i32 %value) !type !2 { +define internal void @_ZL10myCallbacki(i32 %value) !callgraph !2 { entry: %sink = alloca i32, align 4 store volatile i32 %value, ptr %sink, align 4 diff --git a/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll b/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll index 49cc335bf7379..7246a02003445 100644 --- a/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll +++ b/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll @@ -6,13 +6,13 @@ ; RUN: llc -mtriple=x86_64-unknown-linux --call-graph-section -filetype=obj -o - < %s | \ ; RUN: llvm-readelf -x .llvm.callgraph - | FileCheck %s -define i32 @check_tailcall(ptr %func, i8 %x) !type !0 { +define i32 @check_tailcall(ptr %func, i8 %x) !callgraph !0 { entry: %call = tail call i32 %func(i8 signext %x), !callee_type !1 ret i32 %call } -define i32 @main(i32 %argc) !type !3 { +define i32 @main(i32 %argc) !callgraph !3 { entry: %andop = and i32 %argc, 1 %cmp = icmp eq i32 %andop, 0 @@ -21,9 +21,9 @@ entry: ret i32 %call.i } -declare !type !2 i32 @foo(i8 signext) +declare !callgraph !2 i32 @foo(i8 signext) -declare !type !2 i32 @bar(i8 signext) +declare !callgraph !2 i32 @bar(i8 signext) !0 = !{i64 0, !"_ZTSFiPvcE.generalized"} !1 = !{!2} >From 973ab944bf99d79d1b6a432dd87d297d8dfecb5d Mon Sep 17 00:00:00 2001 From: prabhukr <[email protected]> Date: Wed, 17 Jun 2026 17:50:40 -0700 Subject: [PATCH 2/6] remove has existing genaralized type metadata calls --- clang/lib/CodeGen/CodeGenModule.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 25675f99258b4..e7f058dcd4776 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3388,11 +3388,6 @@ static void setLinkageForGV(llvm::GlobalValue *GV, const NamedDecl *ND) { GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); } -static bool hasExistingGeneralizedTypeMD(llvm::Function *F) { - llvm::MDNode *MD = F->getMetadata(llvm::LLVMContext::MD_type); - return MD && MD->hasGeneralizedMDString(); -} - void CodeGenModule::createIndirectFunctionTypeMD(const FunctionDecl *FD, llvm::Function *F) { // All functions which are not internal linkage could be indirect targets. @@ -3425,12 +3420,10 @@ void CodeGenModule::createFunctionTypeMetadataForIcall(const FunctionDecl *FD, /*GeneralizePointers=*/false); llvm::Metadata *MD = CreateMetadataIdentifierForType(FnType); F->addTypeMetadata(0, MD); - // Add the generalized identifier if not added already. - if (!hasExistingGeneralizedTypeMD(F)) { - QualType GenPtrFnType = GeneralizeFunctionType(getContext(), FD->getType(), - /*GeneralizePointers=*/true); - F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(GenPtrFnType)); - } + + QualType GenPtrFnType = GeneralizeFunctionType(getContext(), FD->getType(), + /*GeneralizePointers=*/true); + F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(GenPtrFnType)); // Emit a hash-based bit set entry for cross-DSO calls. if (CodeGenOpts.SanitizeCfiCrossDso) >From e001c26e5848a01acac3cde2414ac5d59418525d Mon Sep 17 00:00:00 2001 From: prabhukr <[email protected]> Date: Thu, 18 Jun 2026 12:07:28 -0700 Subject: [PATCH 3/6] Drop vtable index from callgraph and callee type metadata --- clang/lib/CodeGen/CodeGenModule.cpp | 9 ++--- .../CodeGen/call-graph-section-callback.cpp | 2 +- .../CodeGen/call-graph-section-templates.cpp | 26 +++++++------- .../call-graph-section-virtual-methods.cpp | 4 +-- clang/test/CodeGen/call-graph-section.c | 16 ++++----- clang/test/CodeGen/call-graph-section.cpp | 36 +++++++++---------- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 12 ++++--- llvm/lib/CodeGen/MachineFunction.cpp | 2 +- llvm/lib/IR/Metadata.cpp | 6 ++-- llvm/lib/IR/Verifier.cpp | 21 +++++------ .../Transforms/IPO/ThinLTOBitcodeWriter.cpp | 15 ++++---- llvm/test/Assembler/callee-type-metadata.ll | 4 +-- .../calleetypeid-directcall-mismatched.ll | 6 ++-- .../callsite-emit-calleetypeid-tailcall.ll | 4 +-- .../AArch64/callsite-emit-calleetypeid.ll | 2 +- .../ARM/call-graph-section-addrtaken.ll | 6 ++-- .../ARM/call-graph-section-assembly.ll | 6 ++-- .../ARM/call-graph-section-tailcall.ll | 6 ++-- llvm/test/CodeGen/ARM/call-graph-section.ll | 6 ++-- .../ARM/calleetypeid-directcall-mismatched.ll | 6 ++-- .../callsite-emit-calleetypeid-tailcall.ll | 4 +-- .../CodeGen/ARM/callsite-emit-calleetypeid.ll | 2 +- ...te-info-ambiguous-indirect-call-typeid.mir | 4 +-- .../CodeGen/MIR/X86/call-site-info-typeid.mir | 2 +- .../MIR/X86/callsite-emit-calleetypeid.ll | 2 +- .../calleetypeid-directcall-mismatched.ll | 6 ++-- .../callsite-emit-calleetypeid-tailcall.ll | 4 +-- .../RISCV/callsite-emit-calleetypeid.ll | 2 +- .../X86/call-graph-section-addrtaken.ll | 6 ++-- .../X86/call-graph-section-assembly.ll | 6 ++-- .../X86/call-graph-section-tailcall.ll | 6 ++-- llvm/test/CodeGen/X86/call-graph-section.ll | 6 ++-- .../X86/calleetypeid-directcall-mismatched.ll | 6 ++-- .../callsite-emit-calleetypeid-tailcall.ll | 4 +-- .../CodeGen/X86/callsite-emit-calleetypeid.ll | 2 +- .../Inline/drop-callee-type-metadata.ll | 12 +++---- .../InstCombine/drop-callee-type-metadata.ll | 6 ++-- .../SimplifyCFG/merge-callee-type-metadata.ll | 12 +++---- llvm/test/Verifier/callee-type-metadata.ll | 12 +++---- 39 files changed, 144 insertions(+), 155 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e7f058dcd4776..ec9f46c341a60 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3399,9 +3399,7 @@ void CodeGenModule::createIndirectFunctionTypeMD(const FunctionDecl *FD, F->addMetadata(llvm::LLVMContext::MD_callgraph, *llvm::MDTuple::get( getLLVMContext(), - {llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt64Ty(getLLVMContext()), 0)), - CreateMetadataIdentifierGeneralized(FD->getType())})); + {CreateMetadataIdentifierGeneralized(FD->getType())})); } } @@ -3442,10 +3440,7 @@ void CodeGenModule::createCalleeTypeMetadataForIcall(const QualType &QT, return; llvm::Metadata *TypeIdMD = CreateMetadataIdentifierGeneralized(QT); - llvm::MDTuple *TypeTuple = llvm::MDTuple::get( - getLLVMContext(), {llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt64Ty(getLLVMContext()), 0)), - TypeIdMD}); + llvm::MDTuple *TypeTuple = llvm::MDTuple::get(getLLVMContext(), {TypeIdMD}); llvm::MDTuple *MDN = llvm::MDNode::get(getLLVMContext(), {TypeTuple}); CB->setMetadata(llvm::LLVMContext::MD_callee_type, MDN); } diff --git a/clang/test/CodeGen/call-graph-section-callback.cpp b/clang/test/CodeGen/call-graph-section-callback.cpp index 080fa07e41847..c943050d6d59f 100644 --- a/clang/test/CodeGen/call-graph-section-callback.cpp +++ b/clang/test/CodeGen/call-graph-section-callback.cpp @@ -27,4 +27,4 @@ int takeCallbackAddress() { return 0; } -// CHECK: [[F_CALLBACK]] = !{i64 0, !"_ZTSFviE.generalized"} +// CHECK: [[F_CALLBACK]] = !{!"_ZTSFviE.generalized"} diff --git a/clang/test/CodeGen/call-graph-section-templates.cpp b/clang/test/CodeGen/call-graph-section-templates.cpp index e6c43a41a86ab..c26170585e8fd 100644 --- a/clang/test/CodeGen/call-graph-section-templates.cpp +++ b/clang/test/CodeGen/call-graph-section-templates.cpp @@ -44,12 +44,12 @@ class Cls2 { T *(*fp)(T a, T *b, const T *c, T &d, const T &e); }; -// FT: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFvvE.generalized"} -// FT: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"} -// FT: [[F_TCLS2F3]] = !{i64 0, !"_ZTSFvP4Cls1E.generalized"} -// FT: [[F_TCLS2F4]] = !{i64 0, !"_ZTSFvPK4Cls1E.generalized"} -// FT: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"} -// FT: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"} +// FT: [[F_TCLS2F1]] = !{!"_ZTSFvvE.generalized"} +// FT: [[F_TCLS2F2]] = !{!"_ZTSFv4Cls1E.generalized"} +// FT: [[F_TCLS2F3]] = !{!"_ZTSFvP4Cls1E.generalized"} +// FT: [[F_TCLS2F4]] = !{!"_ZTSFvPK4Cls1E.generalized"} +// FT: [[F_TCLS2F5]] = !{!"_ZTSFvR4Cls1E.generalized"} +// FT: [[F_TCLS2F6]] = !{!"_ZTSFvRK4Cls1E.generalized"} //////////////////////////////////////////////////////////////////////////////// // Callsites (check for indirect callsite operand bundles) @@ -101,17 +101,17 @@ void foo() { // CST-LABEL: define {{.*}} @_Z6T_funcI4Cls1EPT_S1_S2_PKS1_RS1_RS3_( // CST-SAME: {{.*}} !callgraph [[F_TFUNC_CLS1:![0-9]+]] -// CST: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFvvE.generalized"} +// CST: [[F_TCLS2F1]] = !{!"_ZTSFvvE.generalized"} // CST: [[F_TFUNC_CLS1_CT]] = !{[[F_TFUNC_CLS1:![0-9]+]]} -// CST: [[F_TFUNC_CLS1]] = !{i64 0, !"_ZTSFP4Cls1S_S0_PKS_RS_RS1_E.generalized"} +// CST: [[F_TFUNC_CLS1]] = !{!"_ZTSFP4Cls1S_S0_PKS_RS_RS1_E.generalized"} // CST: [[F_TCLS2F1_CT]] = !{[[F_TCLS2F1:![0-9]+]]} // CST: [[F_TCLS2F2_CT]] = !{[[F_TCLS2F2:![0-9]+]]} -// CST: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"} +// CST: [[F_TCLS2F2]] = !{!"_ZTSFv4Cls1E.generalized"} // CST: [[F_TCLS2F3_CT]] = !{[[F_TCLS2F3:![0-9]+]]} -// CST: [[F_TCLS2F3]] = !{i64 0, !"_ZTSFvP4Cls1E.generalized"} +// CST: [[F_TCLS2F3]] = !{!"_ZTSFvP4Cls1E.generalized"} // CST: [[F_TCLS2F4_CT]] = !{[[F_TCLS2F4:![0-9]+]]} -// CST: [[F_TCLS2F4]] = !{i64 0, !"_ZTSFvPK4Cls1E.generalized"} +// CST: [[F_TCLS2F4]] = !{!"_ZTSFvPK4Cls1E.generalized"} // CST: [[F_TCLS2F5_CT]] = !{[[F_TCLS2F5:![0-9]+]]} -// CST: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"} +// CST: [[F_TCLS2F5]] = !{!"_ZTSFvR4Cls1E.generalized"} // CST: [[F_TCLS2F6_CT]] = !{[[F_TCLS2F6:![0-9]+]]} -// CST: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"} +// CST: [[F_TCLS2F6]] = !{!"_ZTSFvRK4Cls1E.generalized"} diff --git a/clang/test/CodeGen/call-graph-section-virtual-methods.cpp b/clang/test/CodeGen/call-graph-section-virtual-methods.cpp index 7aa7a8cf740ea..34c22c467080b 100644 --- a/clang/test/CodeGen/call-graph-section-virtual-methods.cpp +++ b/clang/test/CodeGen/call-graph-section-virtual-methods.cpp @@ -22,7 +22,7 @@ class Base { int vf(char *a) override { return 1; }; }; - // FT: [[F_TVF]] = !{i64 0, !"_ZTSFiPcE.generalized"} + // FT: [[F_TVF]] = !{!"_ZTSFiPcE.generalized"} //////////////////////////////////////////////////////////////////////////////// // Callsites (check for indirect callsite operand bundles) @@ -53,4 +53,4 @@ class Base { } // CST: [[F_TVF_CT]] = !{[[F_TVF:![0-9]+]]} - // CST: [[F_TVF]] = !{i64 0, !"_ZTSFiPcE.generalized"} + // CST: [[F_TVF]] = !{!"_ZTSFiPcE.generalized"} diff --git a/clang/test/CodeGen/call-graph-section.c b/clang/test/CodeGen/call-graph-section.c index 9d8e99a9ad098..94581674dc5e3 100644 --- a/clang/test/CodeGen/call-graph-section.c +++ b/clang/test/CodeGen/call-graph-section.c @@ -74,20 +74,20 @@ void stf() { fp_stparam(St2, &St2); } -// ITANIUM: [[F_TVOID]] = !{i64 0, !"_ZTSFvE.generalized"} +// ITANIUM: [[F_TVOID]] = !{!"_ZTSFvE.generalized"} // ITANIUM: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]} -// ITANIUM: [[F_TPRIMITIVE]] = !{i64 0, !"_ZTSFicfdE.generalized"} -// ITANIUM: [[F_TPTR]] = !{i64 0, !"_ZTSFPiPcPfPdE.generalized"} +// ITANIUM: [[F_TPRIMITIVE]] = !{!"_ZTSFicfdE.generalized"} +// ITANIUM: [[F_TPTR]] = !{!"_ZTSFPiPcPfPdE.generalized"} // ITANIUM: [[F_TPRIMITIVE_CT]] = !{[[F_TPRIMITIVE:![0-9]+]]} // ITANIUM: [[F_TPTR_CT]] = !{[[F_TPTR:![0-9]+]]} -// ITANIUM: [[F_TSTRUCT]] = !{i64 0, !"_ZTSFv3st2PS_E.generalized"} +// ITANIUM: [[F_TSTRUCT]] = !{!"_ZTSFv3st2PS_E.generalized"} // ITANIUM: [[F_TSTRUCT_CT]] = !{[[F_TSTRUCT:![0-9]+]]} -// MS: [[F_TVOID]] = !{i64 0, !"[email protected]"} +// MS: [[F_TVOID]] = !{!"[email protected]"} // MS: [[F_TVOID_CT]] = !{[[F_TVOID:![0-9]+]]} -// MS: [[F_TPRIMITIVE]] = !{i64 0, !"[email protected]"} -// MS: [[F_TPTR]] = !{i64 0, !"[email protected]"} +// MS: [[F_TPRIMITIVE]] = !{!"[email protected]"} +// MS: [[F_TPTR]] = !{!"[email protected]"} // MS: [[F_TPRIMITIVE_CT]] = !{[[F_TPRIMITIVE:![0-9]+]]} // MS: [[F_TPTR_CT]] = !{[[F_TPTR:![0-9]+]]} -// MS: [[F_TSTRUCT]] = !{i64 0, !"?6AXUst2@@PEAU0@@Z.generalized"} +// MS: [[F_TSTRUCT]] = !{!"?6AXUst2@@PEAU0@@Z.generalized"} // MS: [[F_TSTRUCT_CT]] = !{[[F_TSTRUCT:![0-9]+]]} diff --git a/clang/test/CodeGen/call-graph-section.cpp b/clang/test/CodeGen/call-graph-section.cpp index 5265eda31ccf9..a358ff9d2d551 100644 --- a/clang/test/CodeGen/call-graph-section.cpp +++ b/clang/test/CodeGen/call-graph-section.cpp @@ -57,15 +57,15 @@ class Cls2 { void f9() const {} }; -// FT: [[F_TCLS1RECEIVER]] = !{i64 0, !"_ZTSFPiPcPfE.generalized"} -// FT: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFicfdE.generalized"} -// FT: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFPiPcPfPdE.generalized"} -// FT: [[F_TCLS2F3F4]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"} -// FT: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvP4Cls1E.generalized"} -// FT: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvPK4Cls1E.generalized"} -// FT: [[F_TCLS2F7]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"} -// FT: [[F_TCLS2F8]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"} -// FT: [[F_TCLS2F9]] = !{i64 0, !"_ZTSKFvvE.generalized"} +// FT: [[F_TCLS1RECEIVER]] = !{!"_ZTSFPiPcPfE.generalized"} +// FT: [[F_TCLS2F1]] = !{!"_ZTSFicfdE.generalized"} +// FT: [[F_TCLS2F2]] = !{!"_ZTSFPiPcPfPdE.generalized"} +// FT: [[F_TCLS2F3F4]] = !{!"_ZTSFv4Cls1E.generalized"} +// FT: [[F_TCLS2F5]] = !{!"_ZTSFvP4Cls1E.generalized"} +// FT: [[F_TCLS2F6]] = !{!"_ZTSFvPK4Cls1E.generalized"} +// FT: [[F_TCLS2F7]] = !{!"_ZTSFvR4Cls1E.generalized"} +// FT: [[F_TCLS2F8]] = !{!"_ZTSFvRK4Cls1E.generalized"} +// FT: [[F_TCLS2F9]] = !{!"_ZTSKFvvE.generalized"} //////////////////////////////////////////////////////////////////////////////// // Callsites (check for indirect callsites' callee_type metadata ) @@ -120,28 +120,28 @@ void foo() { } // CST: [[F_TCLS1RECEIVER_CT]] = !{[[F_TCLS1RECEIVER:![0-9]+]]} -// CST: [[F_TCLS1RECEIVER]] = !{i64 0, !"_ZTSFPiPcPfE.generalized"} +// CST: [[F_TCLS1RECEIVER]] = !{!"_ZTSFPiPcPfE.generalized"} // CST: [[F_TCLS2F1_CT]] = !{[[F_TCLS2F1:![0-9]+]]} -// CST: [[F_TCLS2F1]] = !{i64 0, !"_ZTSFicfdE.generalized"} +// CST: [[F_TCLS2F1]] = !{!"_ZTSFicfdE.generalized"} // CST: [[F_TCLS2F2_CT]] = !{[[F_TCLS2F2:![0-9]+]]} -// CST: [[F_TCLS2F2]] = !{i64 0, !"_ZTSFPiPcPfPdE.generalized"} +// CST: [[F_TCLS2F2]] = !{!"_ZTSFPiPcPfPdE.generalized"} // CST: [[F_TCLS2F3F4_CT]] = !{[[F_TCLS2F3F4:![0-9]+]]} -// CST: [[F_TCLS2F3F4]] = !{i64 0, !"_ZTSFv4Cls1E.generalized"} +// CST: [[F_TCLS2F3F4]] = !{!"_ZTSFv4Cls1E.generalized"} // CST: [[F_TCLS2F5_CT]] = !{[[F_TCLS2F5:![0-9]+]]} -// CST: [[F_TCLS2F5]] = !{i64 0, !"_ZTSFvP4Cls1E.generalized"} +// CST: [[F_TCLS2F5]] = !{!"_ZTSFvP4Cls1E.generalized"} // CST: [[F_TCLS2F6_CT]] = !{[[F_TCLS2F6:![0-9]+]]} -// CST: [[F_TCLS2F6]] = !{i64 0, !"_ZTSFvPK4Cls1E.generalized"} +// CST: [[F_TCLS2F6]] = !{!"_ZTSFvPK4Cls1E.generalized"} // CST: [[F_TCLS2F7_CT]] = !{[[F_TCLS2F7:![0-9]+]]} -// CST: [[F_TCLS2F7]] = !{i64 0, !"_ZTSFvR4Cls1E.generalized"} +// CST: [[F_TCLS2F7]] = !{!"_ZTSFvR4Cls1E.generalized"} // CST: [[F_TCLS2F8_CT]] = !{[[F_TCLS2F8:![0-9]+]]} -// CST: [[F_TCLS2F8]] = !{i64 0, !"_ZTSFvRK4Cls1E.generalized"} +// CST: [[F_TCLS2F8]] = !{!"_ZTSFvRK4Cls1E.generalized"} // CST: [[F_TCLS2F9_CT]] = !{[[F_TCLS2F9:![0-9]+]]} -// CST: [[F_TCLS2F9]] = !{i64 0, !"_ZTSKFvvE.generalized"} +// CST: [[F_TCLS2F9]] = !{!"_ZTSKFvvE.generalized"} diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 84efbff3de598..acc3cfb0edc81 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1758,11 +1758,13 @@ static ConstantInt *extractNumericCGTypeId(const Function &F) { SmallVector<MDNode *, 2> Types; F.getMetadata(LLVMContext::MD_callgraph, Types); for (const auto &Type : Types) { - if (Type->hasGeneralizedMDString()) { - MDString *MDGeneralizedTypeId = cast<MDString>(Type->getOperand(1)); - uint64_t TypeIdVal = llvm::MD5Hash(MDGeneralizedTypeId->getString()); - IntegerType *Int64Ty = Type::getInt64Ty(F.getContext()); - return ConstantInt::get(Int64Ty, TypeIdVal); + if (Type->getNumOperands() == 1 && isa<MDString>(Type->getOperand(0))) { + MDString *MDGeneralizedTypeId = cast<MDString>(Type->getOperand(0)); + if (MDGeneralizedTypeId->getString().ends_with(".generalized")) { + uint64_t TypeIdVal = llvm::MD5Hash(MDGeneralizedTypeId->getString()); + IntegerType *Int64Ty = Type::getInt64Ty(F.getContext()); + return ConstantInt::get(Int64Ty, TypeIdVal); + } } } return nullptr; diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index 2922922535333..c03fc8b5152af 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -758,7 +758,7 @@ MachineFunction::CallSiteInfo::CallSiteInfo(const CallBase &CB) { for (const MDOperand &Op : CalleeTypeList->operands()) { MDNode *TypeMD = cast<MDNode>(Op); - MDString *TypeIdStr = cast<MDString>(TypeMD->getOperand(1)); + MDString *TypeIdStr = cast<MDString>(TypeMD->getOperand(0)); // Compute numeric type id from generalized type id string uint64_t TypeIdVal = MD5Hash(TypeIdStr->getString()); IntegerType *Int64Ty = Type::getInt64Ty(CB.getContext()); diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index 0194b8f0a2083..491c788fc4445 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -1891,14 +1891,14 @@ void GlobalObject::copyMetadata(const GlobalObject *Other, unsigned Offset) { Other->getAllMetadata(MDs); for (auto &MD : MDs) { // We need to adjust the type metadata offset. - if (Offset != 0 && (MD.first == LLVMContext::MD_type || - MD.first == LLVMContext::MD_callgraph)) { + if (Offset != 0 && MD.first == LLVMContext::MD_type) { auto *OffsetConst = cast<ConstantInt>( cast<ConstantAsMetadata>(MD.second->getOperand(0))->getValue()); Metadata *TypeId = MD.second->getOperand(1); auto *NewOffsetMD = ConstantAsMetadata::get(ConstantInt::get( OffsetConst->getType(), OffsetConst->getValue() + Offset)); - addMetadata(MD.first, *MDNode::get(getContext(), {NewOffsetMD, TypeId})); + addMetadata(LLVMContext::MD_type, + *MDNode::get(getContext(), {NewOffsetMD, TypeId})); continue; } // If an offset adjustment was specified we need to modify the DIExpression diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 18d6578dec646..7ab98d0b98cc5 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5650,12 +5650,6 @@ void Verifier::visitCallsiteMetadata(Instruction &I, MDNode *MD) { visitCallStackMetadata(MD); } -static inline bool isConstantIntMetadataOperand(const Metadata *MD) { - if (auto *VAL = dyn_cast<ValueAsMetadata>(MD)) - return isa<ConstantInt>(VAL->getValue()); - return false; -} - void Verifier::visitCalleeTypeMetadata(Instruction &I, MDNode *MD) { Check(isa<CallBase>(I), "!callee_type metadata should only exist on calls", &I); @@ -5663,14 +5657,15 @@ void Verifier::visitCalleeTypeMetadata(Instruction &I, MDNode *MD) { Check(isa<MDNode>(Op), "The callee_type metadata must be a list of type metadata nodes", Op); auto *TypeMD = cast<MDNode>(Op); - Check(TypeMD->getNumOperands() == 2, - "Well-formed generalized type metadata must contain exactly two " - "operands", + Check(TypeMD->getNumOperands() == 1, + "Well-formed generalized callgraph metadata must contain exactly one " + "operand", Op); - Check(isConstantIntMetadataOperand(TypeMD->getOperand(0)) && - mdconst::extract<ConstantInt>(TypeMD->getOperand(0))->isZero(), - "The first operand of type metadata for functions must be zero", Op); - Check(TypeMD->hasGeneralizedMDString(), + Check(isa<MDString>(TypeMD->getOperand(0)), + "The operand of type metadata for functions must be an MDString", Op); + Check(cast<MDString>(TypeMD->getOperand(0)) + ->getString() + .ends_with(".generalized"), "Only generalized type metadata can be part of the callee_type " "metadata list", Op); diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index 01a0f3385a3c0..a486979a58c2d 100644 --- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -175,14 +175,15 @@ void promoteTypeIds(Module &M, StringRef ModuleId) { GO.eraseMetadata(LLVMContext::MD_callgraph); for (auto *MD : CGMDs) { - auto I = LocalToGlobal.find(MD->getOperand(1)); - if (I == LocalToGlobal.end()) { - GO.addMetadata(LLVMContext::MD_callgraph, *MD); - continue; + if (MD->getNumOperands() == 1) { + auto I = LocalToGlobal.find(MD->getOperand(0)); + if (I == LocalToGlobal.end()) { + GO.addMetadata(LLVMContext::MD_callgraph, *MD); + continue; + } + GO.addMetadata(LLVMContext::MD_callgraph, + *MDNode::get(M.getContext(), {I->second})); } - GO.addMetadata( - LLVMContext::MD_callgraph, - *MDNode::get(M.getContext(), {MD->getOperand(0), I->second})); } } } diff --git a/llvm/test/Assembler/callee-type-metadata.ll b/llvm/test/Assembler/callee-type-metadata.ll index 9c3cfbe82fc13..305aedd0b2895 100644 --- a/llvm/test/Assembler/callee-type-metadata.ll +++ b/llvm/test/Assembler/callee-type-metadata.ll @@ -16,6 +16,6 @@ entry: declare !type !2 i32 @_Z3barc(i8 signext) -!0 = !{i64 0, !"_ZTSFiPvcE.generalized"} +!0 = !{!"_ZTSFiPvcE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFicE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} diff --git a/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll index c4c54175ecd9f..b0140a56dbc6a 100644 --- a/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll +++ b/llvm/test/CodeGen/AArch64/calleetypeid-directcall-mismatched.ll @@ -25,8 +25,8 @@ entry: declare !type !2 i32 @fizz(i32, i32) -!0 = !{i64 0, !"_ZTSFiiiiE.generalized"} +!0 = !{!"_ZTSFiiiiE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFiiiE.generalized"} +!2 = !{!"_ZTSFiiiE.generalized"} !3 = !{!4} -!4 = !{i64 0, !"_ZTSFicE.generalized"} +!4 = !{!"_ZTSFicE.generalized"} diff --git a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid-tailcall.ll b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid-tailcall.ll index b47607ec135ae..44cb4bba6e4b2 100644 --- a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid-tailcall.ll +++ b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid-tailcall.ll @@ -14,6 +14,6 @@ entry: ret i32 %call } -!0 = !{i64 0, !"_ZTSFiPvcE.generalized"} +!0 = !{!"_ZTSFiPvcE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFicE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} diff --git a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll index 94b657c6ea908..c918558d8bd82 100644 --- a/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/AArch64/callsite-emit-calleetypeid.ll @@ -17,4 +17,4 @@ entry: } !0 = !{!1} -!1 = !{i64 0, !"_ZTSFvcE.generalized"} +!1 = !{!"_ZTSFvcE.generalized"} diff --git a/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll b/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll index 8bb9230316288..3ffdb65aed8dc 100644 --- a/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll +++ b/llvm/test/CodeGen/ARM/call-graph-section-addrtaken.ll @@ -22,9 +22,9 @@ entry: ret void } -!0 = !{i64 0, !"_ZTSFvPFviEE.generalized"} -!1 = !{i64 0, !"_ZTSFivE.generalized"} -!2 = !{i64 0, !"_ZTSFviE.generalized"} +!0 = !{!"_ZTSFvPFviEE.generalized"} +!1 = !{!"_ZTSFivE.generalized"} +!2 = !{!"_ZTSFviE.generalized"} ; CHECK: .section .llvm.callgraph,"o",%llvm_call_graph,.text ;; Version diff --git a/llvm/test/CodeGen/ARM/call-graph-section-assembly.ll b/llvm/test/CodeGen/ARM/call-graph-section-assembly.ll index 8e8881ee722fb..d06b12636c7af 100644 --- a/llvm/test/CodeGen/ARM/call-graph-section-assembly.ll +++ b/llvm/test/CodeGen/ARM/call-graph-section-assembly.ll @@ -29,11 +29,11 @@ entry: } !0 = !{!1} -!1 = !{i64 0, !"_ZTSFvE.generalized"} +!1 = !{!"_ZTSFvE.generalized"} !2 = !{!3} -!3 = !{i64 0, !"_ZTSFicE.generalized"} +!3 = !{!"_ZTSFicE.generalized"} !4 = !{!5} -!5 = !{i64 0, !"_ZTSFPvS_E.generalized"} +!5 = !{!"_ZTSFPvS_E.generalized"} ; CHECK: .section .llvm.callgraph,"o",%llvm_call_graph,.text ;; Version diff --git a/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll b/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll index c6152ef7c732b..eeceea7bc73ab 100644 --- a/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll +++ b/llvm/test/CodeGen/ARM/call-graph-section-tailcall.ll @@ -22,10 +22,10 @@ declare !callgraph !2 i32 @foo(i8 signext) declare !callgraph !2 i32 @bar(i8 signext) -!0 = !{i64 0, !"_ZTSFiPvcE.generalized"} +!0 = !{!"_ZTSFiPvcE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFicE.generalized"} -!3 = !{i64 0, !"_ZTSFiiE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} +!3 = !{!"_ZTSFiiE.generalized"} ; CHECK: Hex dump of section '.llvm.callgraph': ; CHECK-NEXT: 0x00000000 00050000 00008e19 0b7f3326 e3000154 diff --git a/llvm/test/CodeGen/ARM/call-graph-section.ll b/llvm/test/CodeGen/ARM/call-graph-section.ll index 167cc6f3c73bd..9619de4669f32 100644 --- a/llvm/test/CodeGen/ARM/call-graph-section.ll +++ b/llvm/test/CodeGen/ARM/call-graph-section.ll @@ -22,12 +22,12 @@ entry: ;; Check that the numeric type id (md5 hash) for the below type ids are emitted ;; to the callgraph section. -!0 = !{i64 0, !"_ZTSFvE.generalized"} +!0 = !{!"_ZTSFvE.generalized"} !1 = !{!0} -!2 = !{i64 0, !"_ZTSFicE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} !3 = !{!2} !4 = !{!5} -!5 = !{i64 0, !"_ZTSFPvS_E.generalized"} +!5 = !{!"_ZTSFPvS_E.generalized"} ;; Make sure following type IDs are in call graph section ;; 0x5eecb3e2444f731f, 0x814b8e305486bc59, 0xf897fd777ade6814 diff --git a/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll index 8f7b0506a5e39..7969e904b2ffa 100644 --- a/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll +++ b/llvm/test/CodeGen/ARM/calleetypeid-directcall-mismatched.ll @@ -25,8 +25,8 @@ entry: declare !type !2 i32 @fizz(i32, i32) -!0 = !{i64 0, !"_ZTSFiiiiE.generalized"} +!0 = !{!"_ZTSFiiiiE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFiiiE.generalized"} +!2 = !{!"_ZTSFiiiE.generalized"} !3 = !{!4} -!4 = !{i64 0, !"_ZTSFicE.generalized"} +!4 = !{!"_ZTSFicE.generalized"} diff --git a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid-tailcall.ll b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid-tailcall.ll index 05e1e8bf0502b..c5a33e61e85e0 100644 --- a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid-tailcall.ll +++ b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid-tailcall.ll @@ -14,6 +14,6 @@ entry: ret i32 %call } -!0 = !{i64 0, !"_ZTSFiPvcE.generalized"} +!0 = !{!"_ZTSFiPvcE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFicE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} diff --git a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll index a65e5c5f8c015..7e1ab0068ff07 100644 --- a/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/ARM/callsite-emit-calleetypeid.ll @@ -17,4 +17,4 @@ entry: } !0 = !{!1} -!1 = !{i64 0, !"_ZTSFvcE.generalized"} +!1 = !{!"_ZTSFvcE.generalized"} diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir index cb78898f3a0d4..5573be87fbb2d 100644 --- a/llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir +++ b/llvm/test/CodeGen/MIR/X86/call-site-info-ambiguous-indirect-call-typeid.mir @@ -16,8 +16,8 @@ } !0 = !{!1, !2} - !1 = !{i64 0, !"callee_type0.generalized"} - !2 = !{i64 0, !"callee_type2.generalized"} + !1 = !{!"callee_type0.generalized"} + !2 = !{!"callee_type2.generalized"} ... --- name: ambiguous_caller diff --git a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir index 303b8fac22a9c..dd835abab5256 100644 --- a/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir +++ b/llvm/test/CodeGen/MIR/X86/call-site-info-typeid.mir @@ -16,7 +16,7 @@ } !0 = !{!1} - !1 = !{i64 0, !"_ZTSFvcE.generalized"} + !1 = !{!"_ZTSFvcE.generalized"} ... --- name: call_foo diff --git a/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll index fe1980e3f5605..c49d8152a7751 100644 --- a/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/MIR/X86/callsite-emit-calleetypeid.ll @@ -86,4 +86,4 @@ entry: } !0 = !{!1} -!1 = !{i64 0, !"_ZTSFvcE.generalized"} +!1 = !{!"_ZTSFvcE.generalized"} diff --git a/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll index 34493cec0eab0..e2c191fa03e27 100644 --- a/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll +++ b/llvm/test/CodeGen/RISCV/calleetypeid-directcall-mismatched.ll @@ -26,8 +26,8 @@ entry: declare !type !2 i32 @fizz(i32, i32) -!0 = !{i64 0, !"_ZTSFiiiiE.generalized"} +!0 = !{!"_ZTSFiiiiE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFiiiE.generalized"} +!2 = !{!"_ZTSFiiiE.generalized"} !3 = !{!4} -!4 = !{i64 0, !"_ZTSFicE.generalized"} +!4 = !{!"_ZTSFicE.generalized"} diff --git a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid-tailcall.ll b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid-tailcall.ll index 6e1fe92dac8f7..337820875b9df 100644 --- a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid-tailcall.ll +++ b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid-tailcall.ll @@ -15,6 +15,6 @@ entry: ret i32 %call } -!0 = !{i64 0, !"_ZTSFiPvcE.generalized"} +!0 = !{!"_ZTSFiPvcE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFicE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} diff --git a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll index 1f91f4103abbb..ec7f4abc0bc2d 100644 --- a/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/RISCV/callsite-emit-calleetypeid.ll @@ -18,4 +18,4 @@ entry: } !0 = !{!1} -!1 = !{i64 0, !"_ZTSFvcE.generalized"} +!1 = !{!"_ZTSFvcE.generalized"} diff --git a/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll b/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll index 42d46e005fce5..06daa8fa38810 100644 --- a/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll +++ b/llvm/test/CodeGen/X86/call-graph-section-addrtaken.ll @@ -22,9 +22,9 @@ entry: ret void } -!0 = !{i64 0, !"_ZTSFvPFviEE.generalized"} -!1 = !{i64 0, !"_ZTSFivE.generalized"} -!2 = !{i64 0, !"_ZTSFviE.generalized"} +!0 = !{!"_ZTSFvPFviEE.generalized"} +!1 = !{!"_ZTSFivE.generalized"} +!2 = !{!"_ZTSFviE.generalized"} ; CHECK: .section .llvm.callgraph,"o",@llvm_call_graph,.text ;; Version diff --git a/llvm/test/CodeGen/X86/call-graph-section-assembly.ll b/llvm/test/CodeGen/X86/call-graph-section-assembly.ll index 02d71073b65c5..7d85ddee24fa1 100644 --- a/llvm/test/CodeGen/X86/call-graph-section-assembly.ll +++ b/llvm/test/CodeGen/X86/call-graph-section-assembly.ll @@ -29,11 +29,11 @@ entry: } !0 = !{!1} -!1 = !{i64 0, !"_ZTSFvE.generalized"} +!1 = !{!"_ZTSFvE.generalized"} !2 = !{!3} -!3 = !{i64 0, !"_ZTSFicE.generalized"} +!3 = !{!"_ZTSFicE.generalized"} !4 = !{!5} -!5 = !{i64 0, !"_ZTSFPvS_E.generalized"} +!5 = !{!"_ZTSFPvS_E.generalized"} ; CHECK: .section .llvm.callgraph,"o",@llvm_call_graph,.text ;; Version diff --git a/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll b/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll index 7246a02003445..753995a9733bf 100644 --- a/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll +++ b/llvm/test/CodeGen/X86/call-graph-section-tailcall.ll @@ -25,10 +25,10 @@ declare !callgraph !2 i32 @foo(i8 signext) declare !callgraph !2 i32 @bar(i8 signext) -!0 = !{i64 0, !"_ZTSFiPvcE.generalized"} +!0 = !{!"_ZTSFiPvcE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFicE.generalized"} -!3 = !{i64 0, !"_ZTSFiiE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} +!3 = !{!"_ZTSFiiE.generalized"} ; CHECK: Hex dump of section '.llvm.callgraph': ; CHECK-NEXT: 0x00000000 00050000 00000000 00008e19 0b7f3326 diff --git a/llvm/test/CodeGen/X86/call-graph-section.ll b/llvm/test/CodeGen/X86/call-graph-section.ll index 8a1c6ca627cb5..fec66ea5da588 100644 --- a/llvm/test/CodeGen/X86/call-graph-section.ll +++ b/llvm/test/CodeGen/X86/call-graph-section.ll @@ -25,12 +25,12 @@ entry: ;; Check that the numeric type id (md5 hash) for the below type ids are emitted ;; to the callgraph section. -!0 = !{i64 0, !"_ZTSFvE.generalized"} +!0 = !{!"_ZTSFvE.generalized"} !1 = !{!0} -!2 = !{i64 0, !"_ZTSFicE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} !3 = !{!2} !4 = !{!5} -!5 = !{i64 0, !"_ZTSFPvS_E.generalized"} +!5 = !{!"_ZTSFPvS_E.generalized"} ;; Make sure following type IDs are in call graph section ;; 0x5eecb3e2444f731f, 0x814b8e305486bc59, 0xf897fd777ade6814 diff --git a/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll b/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll index 7881ea7d59314..05edbfd649415 100644 --- a/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll +++ b/llvm/test/CodeGen/X86/calleetypeid-directcall-mismatched.ll @@ -25,8 +25,8 @@ entry: declare !type !2 i32 @fizz(i32, i32) -!0 = !{i64 0, !"_ZTSFiiiiE.generalized"} +!0 = !{!"_ZTSFiiiiE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFiiiE.generalized"} +!2 = !{!"_ZTSFiiiE.generalized"} !3 = !{!4} -!4 = !{i64 0, !"_ZTSFicE.generalized"} +!4 = !{!"_ZTSFicE.generalized"} diff --git a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid-tailcall.ll b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid-tailcall.ll index 8f6b7a6d7f240..9a868db8e4297 100644 --- a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid-tailcall.ll +++ b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid-tailcall.ll @@ -14,6 +14,6 @@ entry: ret i32 %call } -!0 = !{i64 0, !"_ZTSFiPvcE.generalized"} +!0 = !{!"_ZTSFiPvcE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFicE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} diff --git a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll index e97a6ac75e111..5981b58bdf7e9 100644 --- a/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll +++ b/llvm/test/CodeGen/X86/callsite-emit-calleetypeid.ll @@ -17,4 +17,4 @@ entry: } !0 = !{!1} -!1 = !{i64 0, !"_ZTSFvcE.generalized"} +!1 = !{!"_ZTSFvcE.generalized"} diff --git a/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll index 547588089c5b0..5495441a45738 100644 --- a/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll +++ b/llvm/test/Transforms/Inline/drop-callee-type-metadata.ll @@ -29,13 +29,13 @@ entry: } declare !type !2 i32 @_Z3fooc(i8 signext) -!0 = !{i64 0, !"_ZTSFiPvcE.generalized"} +!0 = !{!"_ZTSFiPvcE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFicE.generalized"} -!3 = !{i64 0, !"_ZTSFivE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} +!3 = !{!"_ZTSFivE.generalized"} ;. -; CHECK: [[META0]] = !{i64 0, !"_ZTSFiPvcE.generalized"} +; CHECK: [[META0]] = !{!"_ZTSFiPvcE.generalized"} ; CHECK: [[META1]] = !{[[META2:![0-9]+]]} -; CHECK: [[META2]] = !{i64 0, !"_ZTSFicE.generalized"} -; CHECK: [[META3]] = !{i64 0, !"_ZTSFivE.generalized"} +; CHECK: [[META2]] = !{!"_ZTSFicE.generalized"} +; CHECK: [[META3]] = !{!"_ZTSFivE.generalized"} ;. diff --git a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll index 83215f78be1b0..e5296f96690f5 100644 --- a/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll +++ b/llvm/test/Transforms/InstCombine/drop-callee-type-metadata.ll @@ -17,9 +17,9 @@ entry: declare !type !2 i32 @_Z3fooc(i8 signext) -!0 = !{i64 0, !"_ZTSFivE.generalized"} +!0 = !{!"_ZTSFivE.generalized"} !1 = !{!2} -!2 = !{i64 0, !"_ZTSFicE.generalized"} +!2 = !{!"_ZTSFicE.generalized"} ;. -; CHECK: [[META0]] = !{i64 0, !"_ZTSFivE.generalized"} +; CHECK: [[META0]] = !{!"_ZTSFivE.generalized"} ;. diff --git a/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll index 3e56939b1642f..03bfb8e31d0b9 100644 --- a/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll +++ b/llvm/test/Transforms/SimplifyCFG/merge-callee-type-metadata.ll @@ -150,18 +150,18 @@ if.end: ; preds = %if.else, %if.then declare ptr @_Znwm(i64) -!0 = !{i64 0, !"callee_type0.generalized"} -!1 = !{i64 0, !"callee_type1.generalized"} -!2 = !{i64 0, !"callee_type2.generalized"} +!0 = !{!"callee_type0.generalized"} +!1 = !{!"callee_type1.generalized"} +!2 = !{!"callee_type2.generalized"} !3 = !{!0} !4 = !{!2} !5 = !{!1, !2} !6 = !{!0, !2} ;. ; CHECK: [[META0]] = !{[[META1:![0-9]+]], [[META2:![0-9]+]]} -; CHECK: [[META1]] = !{i64 0, !"callee_type2.generalized"} -; CHECK: [[META2]] = !{i64 0, !"callee_type0.generalized"} +; CHECK: [[META1]] = !{!"callee_type2.generalized"} +; CHECK: [[META2]] = !{!"callee_type0.generalized"} ; CHECK: [[META3]] = !{[[META2]]} ; CHECK: [[META4]] = !{[[META2]], [[META1]], [[META5:![0-9]+]]} -; CHECK: [[META5]] = !{i64 0, !"callee_type1.generalized"} +; CHECK: [[META5]] = !{!"callee_type1.generalized"} ;. diff --git a/llvm/test/Verifier/callee-type-metadata.ll b/llvm/test/Verifier/callee-type-metadata.ll index 50cf37b941fe9..fc19ab72678e7 100644 --- a/llvm/test/Verifier/callee-type-metadata.ll +++ b/llvm/test/Verifier/callee-type-metadata.ll @@ -11,14 +11,12 @@ entry: %x_val = load i8, ptr %x.addr, align 1 ; CHECK: The callee_type metadata must be a list of type metadata nodes %call = call i32 %fptr(i8 signext %x_val), !callee_type !0 - ; CHECK: Well-formed generalized type metadata must contain exactly two operands + ; CHECK: The operand of type metadata for functions must be an MDString %call1 = call i32 %fptr(i8 signext %x_val), !callee_type !2 - ; CHECK: The first operand of type metadata for functions must be zero + ; CHECK: Well-formed generalized callgraph metadata must contain exactly one operand %call2 = call i32 %fptr(i8 signext %x_val), !callee_type !4 - ; CHECK: The first operand of type metadata for functions must be zero - %call3 = call i32 %fptr(i8 signext %x_val), !callee_type !6 ; CHECK: Only generalized type metadata can be part of the callee_type metadata list - %call4 = call i32 %fptr(i8 signext %x_val), !callee_type !8 + %call3 = call i32 %fptr(i8 signext %x_val), !callee_type !6 ret i32 %call } @@ -27,7 +25,5 @@ entry: !2 = !{!2} !3 = !{i64 1, !"_ZTSFicE"} !4 = !{!3} -!5 = !{!"expected_int", !"_ZTSFicE"} +!5 = !{!"_ZTSFicE"} !6 = !{!5} -!7 = !{i64 0, !"_ZTSFicE"} -!8 = !{!7} >From e11f3403b4c6f0fc5d7bdb89b42795e5141cffe3 Mon Sep 17 00:00:00 2001 From: prabhukr <[email protected]> Date: Thu, 18 Jun 2026 12:15:39 -0700 Subject: [PATCH 4/6] Rename type metdata to callgraph metadata in comments and in IR verifier messages. --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +- llvm/lib/IR/Verifier.cpp | 16 +++++++++------- llvm/test/Verifier/callee-type-metadata.ll | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index acc3cfb0edc81..c6671a4ffef25 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1753,7 +1753,7 @@ void AsmPrinter::emitStackUsage(const MachineFunction &MF) { } /// Extracts a generalized numeric type identifier of a Function's type from -/// type metadata. Returns null if metadata cannot be found. +/// callgraph metadata. Returns null if metadata cannot be found. static ConstantInt *extractNumericCGTypeId(const Function &F) { SmallVector<MDNode *, 2> Types; F.getMetadata(LLVMContext::MD_callgraph, Types); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 7ab98d0b98cc5..394a50fcac204 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5655,18 +5655,20 @@ void Verifier::visitCalleeTypeMetadata(Instruction &I, MDNode *MD) { &I); for (Metadata *Op : MD->operands()) { Check(isa<MDNode>(Op), - "The callee_type metadata must be a list of type metadata nodes", Op); - auto *TypeMD = cast<MDNode>(Op); - Check(TypeMD->getNumOperands() == 1, + "The callee_type metadata must be a list of callgraph metadata nodes", + Op); + auto *CallgraphMD = cast<MDNode>(Op); + Check(CallgraphMD->getNumOperands() == 1, "Well-formed generalized callgraph metadata must contain exactly one " "operand", Op); - Check(isa<MDString>(TypeMD->getOperand(0)), - "The operand of type metadata for functions must be an MDString", Op); - Check(cast<MDString>(TypeMD->getOperand(0)) + Check(isa<MDString>(CallgraphMD->getOperand(0)), + "The operand of callgraph metadata for functions must be an MDString", + Op); + Check(cast<MDString>(CallgraphMD->getOperand(0)) ->getString() .ends_with(".generalized"), - "Only generalized type metadata can be part of the callee_type " + "Only generalized callgraph metadata can be part of the callee_type " "metadata list", Op); } diff --git a/llvm/test/Verifier/callee-type-metadata.ll b/llvm/test/Verifier/callee-type-metadata.ll index fc19ab72678e7..e40d36ae0f234 100644 --- a/llvm/test/Verifier/callee-type-metadata.ll +++ b/llvm/test/Verifier/callee-type-metadata.ll @@ -9,13 +9,13 @@ entry: store i8 %x, ptr %x.addr, align 1 %fptr = load ptr, ptr %func.addr, align 8 %x_val = load i8, ptr %x.addr, align 1 - ; CHECK: The callee_type metadata must be a list of type metadata nodes + ; CHECK: The callee_type metadata must be a list of callgraph metadata nodes %call = call i32 %fptr(i8 signext %x_val), !callee_type !0 - ; CHECK: The operand of type metadata for functions must be an MDString + ; CHECK: The operand of callgraph metadata for functions must be an MDString %call1 = call i32 %fptr(i8 signext %x_val), !callee_type !2 ; CHECK: Well-formed generalized callgraph metadata must contain exactly one operand %call2 = call i32 %fptr(i8 signext %x_val), !callee_type !4 - ; CHECK: Only generalized type metadata can be part of the callee_type metadata list + ; CHECK: Only generalized callgraph metadata can be part of the callee_type metadata list %call3 = call i32 %fptr(i8 signext %x_val), !callee_type !6 ret i32 %call } >From 6b6f002841dbc62c61ed4b2fad273c070be7663f Mon Sep 17 00:00:00 2001 From: prabhukr <[email protected]> Date: Thu, 18 Jun 2026 12:50:41 -0700 Subject: [PATCH 5/6] fix documentation/comments and remove unused helper. --- clang/lib/CodeGen/CodeGenModule.h | 6 +-- .../CodeGen/call-graph-section-internal.cpp | 2 +- llvm/docs/CalleeTypeMetadata.rst | 7 ++-- llvm/docs/CallgraphMetadata.rst | 38 +++++++++++++++++++ llvm/docs/Reference.rst | 1 + llvm/include/llvm/IR/Metadata.h | 7 ---- 6 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 llvm/docs/CallgraphMetadata.rst diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 959e02924a9f7..f6f672741ca95 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1738,11 +1738,11 @@ class CodeGenModule : public CodeGenTypeCache { void createFunctionTypeMetadataForIcall(const FunctionDecl *FD, llvm::Function *F); - /// Create and attach type metadata if the function is a potential indirect - /// call target to support call graph section. + /// Create and attach callgraph metadata if the function is a potential + /// indirect call target to support call graph section. void createIndirectFunctionTypeMD(const FunctionDecl *FD, llvm::Function *F); - /// Create and attach type metadata to the given call. + /// Create and attach callee_type metadata to the given call. void createCalleeTypeMetadataForIcall(const QualType &QT, llvm::CallBase *CB); /// Set type metadata to the given function. diff --git a/clang/test/CodeGen/call-graph-section-internal.cpp b/clang/test/CodeGen/call-graph-section-internal.cpp index aea48675dfa27..923cb4ed053b0 100644 --- a/clang/test/CodeGen/call-graph-section-internal.cpp +++ b/clang/test/CodeGen/call-graph-section-internal.cpp @@ -2,7 +2,7 @@ // Check that we do not generate callee_type metadata for indirect calls // to functions with internal linkage (e.g., types in anonymous namespaces), -// as their type metadata identifiers are distinct MDNodes instead of +// as their callgraph metadata identifiers are distinct MDNodes instead of // generalized strings, which would fail the LLVM Verifier. namespace { diff --git a/llvm/docs/CalleeTypeMetadata.rst b/llvm/docs/CalleeTypeMetadata.rst index 45d0657966a8c..863f3de446bf2 100644 --- a/llvm/docs/CalleeTypeMetadata.rst +++ b/llvm/docs/CalleeTypeMetadata.rst @@ -7,11 +7,12 @@ Introduction This ``!callee_type`` metadata is introduced to support the generation of a call graph section in the object file. The ``!callee_type`` metadata is used to identify the types of the intended callees of indirect call instructions. The ``!callee_type`` metadata is a -list of one or more generalized ``!type`` metadata objects (See :doc:`TypeMetadata`) with each ``!type`` +list of one or more generalized ``!callgraph`` metadata objects (See :doc:`CallgraphMetadata`) with each ``!callgraph`` metadata pointing to a callee's :ref:`type identifier <calleetype-type-identifier>`. -LLVM's `Control Flow Integrity (CFI)`_ also uses the ``!type`` metadata in its implementation. -.. _Control Flow Integrity (CFI): https://clang.llvm.org/docs/ControlFlowIntegrity.html +While ``!callee_type`` and ``!callgraph`` are private to the Call Graph Section pipeline and contain no offsets, +LLVM's `Control Flow Integrity (CFI)`_ uses a structurally similar ``!type`` metadata in its implementation (See :doc:`TypeMetadata`), +which shares the same type identifier format but includes a leading offset for vtable compatibility. .. _calleetype-type-identifier: diff --git a/llvm/docs/CallgraphMetadata.rst b/llvm/docs/CallgraphMetadata.rst new file mode 100644 index 0000000000000..b85fc006872e4 --- /dev/null +++ b/llvm/docs/CallgraphMetadata.rst @@ -0,0 +1,38 @@ +================== +Callgraph Metadata +================== + +Introduction +============ + +The ``!callgraph`` metadata is introduced to support the generation of a call graph +section in the object file. It associates a function definition with its generalized +type identifier. + +Syntax +====== + +A ``!callgraph`` metadata node is attached to a function definition as follows: + +.. code-block:: llvm + + define void @foo() !callgraph !0 + !0 = !{!"_ZTSFvvE.generalized"} + +The metadata node is a 1-element tuple containing only the generalized type identifier +as an ``MDString``, without any offset. + +Relation to Control Flow Integrity (CFI) +======================================== + +While ``!callgraph`` metadata is structurally similar to LLVM's ``!type`` metadata +(which is used by `Control Flow Integrity (CFI)`_ and Whole Program Devirtualization), +they serve different purposes: + +* **!type (CFI)**: Contains an offset (e.g., ``!{i64 0, !"_ZTSFvvE.generalized"}``) to support virtual table offset calculations and devirtualization. This requires ThinLTO symbol promotion and LTO splitting. +* **!callgraph (Call Graph Section)**: Does not contain an offset. This is private to the Call Graph Section pipeline and bypasses ThinLTO promotion, avoiding unnecessary symbol export and LTO splitting bloat. + +The generalized type identifier format used by both is identical. For more details on the +generalized type identifier format and CFI's metadata, see :doc:`TypeMetadata` and :doc:`CalleeTypeMetadata`. + +.. _Control Flow Integrity (CFI): https://clang.llvm.org/docs/ControlFlowIntegrity.html diff --git a/llvm/docs/Reference.rst b/llvm/docs/Reference.rst index 56e367388b1a8..eb6ad28ea1bd4 100644 --- a/llvm/docs/Reference.rst +++ b/llvm/docs/Reference.rst @@ -56,6 +56,7 @@ LLVM and API reference documentation. CIBestPractices AIToolPolicy CalleeTypeMetadata + CallgraphMetadata CallGraphSection InterfaceExportAnnotations PCSectionsMetadata diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h index b9288740a7145..73adeb3416ab1 100644 --- a/llvm/include/llvm/IR/Metadata.h +++ b/llvm/include/llvm/IR/Metadata.h @@ -1255,13 +1255,6 @@ class MDNode : public Metadata { bool isReplaceable() const { return isTemporary() || isAlwaysReplaceable(); } bool isAlwaysReplaceable() const { return getMetadataID() == DIAssignIDKind; } - /// Check if this is a valid generalized type metadata node. - bool hasGeneralizedMDString() { - if (getNumOperands() < 2 || !isa<MDString>(getOperand(1))) - return false; - return cast<MDString>(getOperand(1))->getString().ends_with(".generalized"); - } - unsigned getNumTemporaryUses() const { assert(isTemporary() && "Only for temporaries"); return Context.getReplaceableUses()->getNumUses(); >From 59917bb79bac3317729c7f716ed27c971df8c637 Mon Sep 17 00:00:00 2001 From: prabhukr <[email protected]> Date: Thu, 18 Jun 2026 12:53:23 -0700 Subject: [PATCH 6/6] Copy callgraph metadata during function merging. --- llvm/lib/Transforms/IPO/MergeFunctions.cpp | 2 ++ .../MergeFunc/callgraph-function-merging.ll | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 llvm/test/Transforms/MergeFunc/callgraph-function-merging.ll diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp index ac8a21ea24320..2d4cc9b9c138e 100644 --- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp +++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -803,6 +803,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) { // Ensure CFI type metadata is propagated to the new function. copyMetadataIfPresent(G, NewG, "type"); copyMetadataIfPresent(G, NewG, "kcfi_type"); + copyMetadataIfPresent(G, NewG, "callgraph"); removeUsers(G); G->replaceAllUsesWith(NewG); G->eraseFromParent(); @@ -900,6 +901,7 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) { // Ensure CFI type metadata is propagated to the new function. copyMetadataIfPresent(F, NewF, "type"); copyMetadataIfPresent(F, NewF, "kcfi_type"); + copyMetadataIfPresent(F, NewF, "callgraph"); removeUsers(F); F->replaceAllUsesWith(NewF); diff --git a/llvm/test/Transforms/MergeFunc/callgraph-function-merging.ll b/llvm/test/Transforms/MergeFunc/callgraph-function-merging.ll new file mode 100644 index 0000000000000..0202412f62fa3 --- /dev/null +++ b/llvm/test/Transforms/MergeFunc/callgraph-function-merging.ll @@ -0,0 +1,25 @@ +; RUN: opt -S -passes=mergefunc < %s | FileCheck %s + +; Verify that !callgraph metadata is correctly preserved and copied to the new +; thunk/backing functions when two identical functions are merged, and that +; the metadata nodes are correctly uniqued. + +declare void @dummy() + +; CHECK: define void @func1(ptr {{.*}}) {{.*}} !callgraph [[MD:![0-9]+]] { +; CHECK: define void @func2(ptr {{.*}}) {{.*}} !callgraph [[MD]] { + +define void @func1(ptr %a) unnamed_addr !callgraph !0 { + call void @dummy() + ret void +} + +define void @func2(ptr %a) unnamed_addr !callgraph !1 { + call void @dummy() + ret void +} + +!0 = !{!"_ZTSFvPvE.generalized"} +!1 = !{!"_ZTSFvPvE.generalized"} + +; CHECK: [[MD]] = !{!"_ZTSFvPvE.generalized"} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
