[llvm] 74bea4c - [IR] enable attaching metadata on ifuncs (#158732)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 19 08:42:02 PDT 2025


Author: Wael Yehia
Date: 2025-09-19T11:41:57-04:00
New Revision: 74bea4c1ad34c9044b9e02f7f9688a408676df75

URL: https://github.com/llvm/llvm-project/commit/74bea4c1ad34c9044b9e02f7f9688a408676df75
DIFF: https://github.com/llvm/llvm-project/commit/74bea4c1ad34c9044b9e02f7f9688a408676df75.diff

LOG: [IR] enable attaching metadata on ifuncs (#158732)

Teach the IR parser and writer to support metadata on ifuncs, and update
documentation.

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::GlobalObject, so the in-memory IR allows for metadata on ifuncs,
but the IR reader/writer is not aware of that.

---------

Co-authored-by: Wael Yehia <wyehia at ca.ibm.com>

Added: 
    

Modified: 
    llvm/docs/LangRef.rst
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/test/Assembler/metadata.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 5fd0f6573bb97..e6713c827d6ab 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1022,13 +1022,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 a1d5b36bde64d..c4070e1f44688 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2626,6 +2626,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 094678f32af2b..60e86d4d2b5a5 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1080,6 +1080,7 @@ void SlotTracker::processModule() {
   for (const GlobalIFunc &I : TheModule->ifuncs()) {
     if (!I.hasName())
       CreateModuleSlot(&I);
+    processGlobalObjectMetadata(I);
   }
 
   // Add metadata used by named metadata.
@@ -4079,6 +4080,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/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index e9ee130dd5e91..17cbfa2458375 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -999,6 +999,18 @@ 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!",

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 {


        


More information about the llvm-commits mailing list