[llvm] [LLVM] Add C API support for handling global object metadata. (PR #104786)

Tim Besard via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 19 07:20:33 PDT 2024


https://github.com/maleadt created https://github.com/llvm/llvm-project/pull/104786

Upstreaming vendored C API fixes from Julia/LLVM.jl.

>From 5ee20a2cb5e0d62bf084a1df2213dbe54a939f23 Mon Sep 17 00:00:00 2001
From: Tim Besard <tim.besard at gmail.com>
Date: Mon, 19 Aug 2024 16:16:49 +0200
Subject: [PATCH] [LLVM] Add C API support for handling global object metadata.

---
 llvm/docs/ReleaseNotes.rst        |  3 +++
 llvm/lib/IR/Core.cpp              | 38 +++++++++++++++++++++++--------
 llvm/tools/llvm-c-test/metadata.c | 14 ++++++++++--
 3 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index d40bb2682f9ad8..5ebcaa43865633 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -163,6 +163,9 @@ Changes to the C API
 * It is now also possible to run the new pass manager on a single function, by calling
   ``LLVMRunPassesOnFunction`` instead of ``LLVMRunPasses``.
 
+* Metadata APIs (``LLVMHasMetadata``, ``LLVMGetMetadata``, ``LLVMSetMetadata``) now
+  support global object inputs.
+
 Changes to the CodeGen infrastructure
 -------------------------------------
 
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index dcad76ee8491dd..85ca87f273e3bc 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1062,15 +1062,27 @@ void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal) {
   unwrap(OldVal)->replaceAllUsesWith(unwrap(NewVal));
 }
 
-int LLVMHasMetadata(LLVMValueRef Inst) {
-  return unwrap<Instruction>(Inst)->hasMetadata();
+int LLVMHasMetadata(LLVMValueRef Ref) {
+  Value *Val = unwrap<Value>(Ref);
+  if (auto I = dyn_cast<Instruction>(Val))
+    return I->hasMetadata();
+  else if (auto GO = dyn_cast<GlobalObject>(Val))
+    return GO->hasMetadata();
+  else
+    assert(0 && "Expected an instruction or a global object");
 }
 
-LLVMValueRef LLVMGetMetadata(LLVMValueRef Inst, unsigned KindID) {
-  auto *I = unwrap<Instruction>(Inst);
-  assert(I && "Expected instruction");
-  if (auto *MD = I->getMetadata(KindID))
-    return wrap(MetadataAsValue::get(I->getContext(), MD));
+LLVMValueRef LLVMGetMetadata(LLVMValueRef Ref, unsigned KindID) {
+  Value *Val = unwrap<Value>(Ref);
+  if (auto *I = dyn_cast<Instruction>(Val)) {
+    if (auto *MD = I->getMetadata(KindID))
+      return wrap(MetadataAsValue::get(I->getContext(), MD));
+  } else if (auto *GO = dyn_cast<GlobalObject>(Val)) {
+    if (auto *MD = GO->getMetadata(KindID))
+      return wrap(MetadataAsValue::get(GO->getContext(), MD));
+  } else {
+    assert(0 && "Expected an instruction or a global object");
+  }
   return nullptr;
 }
 
@@ -1088,10 +1100,16 @@ static MDNode *extractMDNode(MetadataAsValue *MAV) {
   return MDNode::get(MAV->getContext(), MD);
 }
 
-void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef Val) {
-  MDNode *N = Val ? extractMDNode(unwrap<MetadataAsValue>(Val)) : nullptr;
+void LLVMSetMetadata(LLVMValueRef Ref, unsigned KindID, LLVMValueRef MAV) {
+  Value *Val = unwrap<Value>(Ref);
+  MDNode *N = MAV ? extractMDNode(unwrap<MetadataAsValue>(MAV)) : nullptr;
 
-  unwrap<Instruction>(Inst)->setMetadata(KindID, N);
+  if (auto *I = dyn_cast<Instruction>(Val))
+    I->setMetadata(KindID, N);
+  else if (auto *GO = dyn_cast<GlobalObject>(Val))
+    GO->setMetadata(KindID, N);
+  else
+    assert(0 && "Expected an instruction or a global object");
 }
 
 struct LLVMOpaqueValueMetadataEntry {
diff --git a/llvm/tools/llvm-c-test/metadata.c b/llvm/tools/llvm-c-test/metadata.c
index 4fe8c00c57481b..05aaf397a8fb7e 100644
--- a/llvm/tools/llvm-c-test/metadata.c
+++ b/llvm/tools/llvm-c-test/metadata.c
@@ -33,16 +33,26 @@ int llvm_add_named_metadata_operand(void) {
 int llvm_set_metadata(void) {
   LLVMBuilderRef Builder = LLVMCreateBuilder();
 
-  // This used to trigger an assertion
+  LLVMModuleRef M = LLVMModuleCreateWithName("Mod");
+  LLVMTypeRef FT = LLVMFunctionType(LLVMVoidType(), NULL, 0, 0);
+  LLVMValueRef F = LLVMAddFunction(M, "Fun", FT);
+  LLVMBasicBlockRef BB = LLVMAppendBasicBlock(F, "Entry");
+  LLVMPositionBuilderAtEnd(Builder, BB);
   LLVMValueRef Return = LLVMBuildRetVoid(Builder);
 
+  // This used to trigger an assertion because of MDNode canonicalization
   const char Name[] = "kind";
   LLVMValueRef Int = LLVMConstInt(LLVMInt32Type(), 0, 0);
   LLVMSetMetadata(Return, LLVMGetMDKindID(Name, strlen(Name)),
                   LLVMMDNode(&Int, 1));
 
+  // Test support of global objects (e.g., Function)
+  assert(!LLVMHasMetadata(F));
+  LLVMSetMetadata(F, LLVMGetMDKindID(Name, strlen(Name)), LLVMMDNode(&Int, 1));
+  assert(LLVMHasMetadata(F));
+
   LLVMDisposeBuilder(Builder);
-  LLVMDeleteInstruction(Return);
+  LLVMDisposeModule(M);
 
   return 0;
 }



More information about the llvm-commits mailing list