[llvm] [IR] enable attaching metadata on ifuncs (PR #158732)
Wael Yehia via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 17 19:56:28 PDT 2025
https://github.com/w2yehia updated https://github.com/llvm/llvm-project/pull/158732
>From 81a9c979385b5d368fcdcf36332ad506d97e1365 Mon Sep 17 00:00:00 2001
From: Wael Yehia <wyehia at ca.ibm.com>
Date: Wed, 3 Sep 2025 19:22:15 +0000
Subject: [PATCH 1/3] [IR] enable attaching metadata on ifuncs
In PR #153049, we have a use case of attaching the !associated metadata to an ifunc.
Since an ifunc is similar to a function declaration, it seems natural to allow metadata on ifuncs.
Currently, the metadata API allows adding Metadata to llvm::Values, so the in-memory IR allows for
metadata on ifuncs, but the IR reader/writer is not aware of that.
Teach the IR parser and writer to support metadata on ifuncs, and update documentation.
---
llvm/docs/LangRef.rst | 7 ++++---
llvm/lib/AsmParser/LLParser.cpp | 3 +++
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 +++
llvm/lib/Bitcode/Writer/ValueEnumerator.cpp | 6 ++++++
llvm/lib/IR/AsmWriter.cpp | 6 ++++++
llvm/test/Assembler/metadata.ll | 8 ++++++++
6 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 6ba3759080cc3..d6b472af033f8 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1020,13 +1020,14 @@ On ELF platforms, IFuncs are resolved by the dynamic linker at load time. On
Mach-O platforms, they are lowered in terms of ``.symbol_resolver`` functions,
which lazily resolve the callee the first time they are called.
-IFunc may have an optional :ref:`linkage type <linkage>` and an optional
-:ref:`visibility style <visibility>`.
+IFunc may have an optional :ref:`linkage type <linkage>`, an optional
+:ref:`visibility style <visibility>`, an option partition, and an optional
+list of attached :ref:`metadata <metadata>`.
Syntax::
@<Name> = [Linkage] [PreemptionSpecifier] [Visibility] ifunc <IFuncTy>, <ResolverTy>* @<Resolver>
- [, partition "name"]
+ [, partition "name"] (, !name !N)*
.. _langref_comdats:
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 1bc2906f63b07..8739b24d4b74b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1258,6 +1258,9 @@ bool LLParser::parseAliasOrIFunc(const std::string &Name, unsigned NameID,
GV->setPartition(Lex.getStrVal());
if (parseToken(lltok::StringConstant, "expected partition string"))
return true;
+ } else if (!IsAlias && Lex.getKind() == lltok::MetadataVar) {
+ if (parseGlobalObjectMetadataAttachment(*GI.get()))
+ return true;
} else {
return tokError("unknown alias or ifunc property!");
}
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index a3f825408d0c2..d9e138edb8ce2 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2630,6 +2630,9 @@ void ModuleBitcodeWriter::writeModuleMetadata() {
for (const Function &F : M)
if (F.isDeclaration() && F.hasMetadata())
AddDeclAttachedMetadata(F);
+ for (const GlobalIFunc &GI : M.ifuncs())
+ if (GI.hasMetadata())
+ AddDeclAttachedMetadata(GI);
// FIXME: Only store metadata for declarations here, and move data for global
// variable definitions to a separate block (PR28134).
for (const GlobalVariable &GV : M.globals())
diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
index e133abe577c22..f497c574ee75d 100644
--- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -495,6 +495,12 @@ ValueEnumerator::ValueEnumerator(const Module &M,
EnumerateMetadata(&F, Op);
}
}
+ for (const GlobalIFunc &GIF : M.ifuncs()) {
+ MDs.clear();
+ GIF.getAllMetadata(MDs);
+ for (const auto &I : MDs)
+ EnumerateMetadata(nullptr, I.second);
+ }
// Optimize constant ordering.
OptimizeConstants(FirstConstant, Values.size());
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index dc6d599fa9585..690dac4e6133b 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1078,6 +1078,7 @@ void SlotTracker::processModule() {
for (const GlobalIFunc &I : TheModule->ifuncs()) {
if (!I.hasName())
CreateModuleSlot(&I);
+ processGlobalObjectMetadata(I);
}
// Add metadata used by named metadata.
@@ -4077,6 +4078,11 @@ void AssemblyWriter::printIFunc(const GlobalIFunc *GI) {
printEscapedString(GI->getPartition(), Out);
Out << '"';
}
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+ GI->getAllMetadata(MDs);
+ if (!MDs.empty()) {
+ printMetadataAttachments(MDs, ", ");
+ }
printInfoComment(*GI);
Out << '\n';
diff --git a/llvm/test/Assembler/metadata.ll b/llvm/test/Assembler/metadata.ll
index 5b62bfafa6d7d..b1fb720eb31f9 100644
--- a/llvm/test/Assembler/metadata.ll
+++ b/llvm/test/Assembler/metadata.ll
@@ -5,6 +5,14 @@
; CHECK-UNMAT: @global = global i32 0, !foo [[M2:![0-9]+]], !foo [[M3:![0-9]+]], !baz [[M3]]
@global = global i32 0, !foo !2, !foo !3, !baz !3
+; CHECK-UNMAT: @ifunc_func = ifunc void (...), ptr @resolver, !foo [[M2]]
+ at ifunc_func = ifunc void (...), ptr @resolver, !foo !2
+
+define internal ptr @resolver() {
+entry:
+ ret ptr @test
+}
+
; CHECK-LABEL: @test
; CHECK: ret void, !foo [[M0:![0-9]+]], !bar [[M1:![0-9]+]]
define void @test() !dbg !1 {
>From 28bb942fa3b10ccbfc6a9a37e2bd58b240009cca Mon Sep 17 00:00:00 2001
From: Wael Yehia <wyehia at ca.ibm.com>
Date: Mon, 15 Sep 2025 22:34:05 +0000
Subject: [PATCH 2/3] call visitGlobalValue from visitGlobalIFunc
---
llvm/lib/IR/Verifier.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 1d3c379f461fa..82be6f203cae2 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -997,6 +997,8 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
}
void Verifier::visitGlobalIFunc(const GlobalIFunc &GI) {
+ visitGlobalValue(GI);
+
Check(GlobalIFunc::isValidLinkage(GI.getLinkage()),
"IFunc should have private, internal, linkonce, weak, linkonce_odr, "
"weak_odr, or external linkage!",
>From cfd36f1e979a1785ed41a86c41135897de62a5dd Mon Sep 17 00:00:00 2001
From: Wael Yehia <wyehia at ca.ibm.com>
Date: Thu, 18 Sep 2025 02:44:04 +0000
Subject: [PATCH 3/3] disallow !dbg and !prof metadata on ifuncs
---
llvm/lib/IR/Verifier.cpp | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 82be6f203cae2..59e3b31f8e291 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -999,6 +999,16 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
void Verifier::visitGlobalIFunc(const GlobalIFunc &GI) {
visitGlobalValue(GI);
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+ GI.getAllMetadata(MDs);
+ for (const auto &I : MDs) {
+ CheckDI(I.first != LLVMContext::MD_dbg,
+ "an ifunc may not have a !dbg attachment", &GI);
+ Check(I.first != LLVMContext::MD_prof,
+ "an ifunc may not have a !prof attachment", &GI);
+ visitMDNode(*I.second, AreDebugLocsAllowed::No);
+ }
+
Check(GlobalIFunc::isValidLinkage(GI.getLinkage()),
"IFunc should have private, internal, linkonce, weak, linkonce_odr, "
"weak_odr, or external linkage!",
More information about the llvm-commits
mailing list