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

via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 19 07:21:04 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-ir

Author: Tim Besard (maleadt)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/104786.diff


3 Files Affected:

- (modified) llvm/docs/ReleaseNotes.rst (+3) 
- (modified) llvm/lib/IR/Core.cpp (+28-10) 
- (modified) llvm/tools/llvm-c-test/metadata.c (+12-2) 


``````````diff
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;
 }

``````````

</details>


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


More information about the llvm-commits mailing list