Skip to content

Conversation

@demoitem
Copy link
Contributor

This change allows globals to have multiple metadata attached. The GlobalSetMetadata function
only allows only one and is clobbered if more metadata is attempted to be added. The addDebugInfo
function calls addMetadata. This is needed because some languages have global structs containing lots of compiler-generated globals.

@demoitem demoitem requested a review from nikic as a code owner July 14, 2025 23:22
@llvmbot
Copy link
Member

llvmbot commented Jul 14, 2025

@llvm/pr-subscribers-debuginfo

@llvm/pr-subscribers-llvm-ir

Author: peter mckinna (demoitem)

Changes

This change allows globals to have multiple metadata attached. The GlobalSetMetadata function
only allows only one and is clobbered if more metadata is attempted to be added. The addDebugInfo
function calls addMetadata. This is needed because some languages have global structs containing lots of compiler-generated globals.


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

6 Files Affected:

  • (modified) llvm/include/llvm-c/Core.h (+8)
  • (modified) llvm/lib/IR/Core.cpp (+5)
  • (added) llvm/test/Bindings/llvm-c/add_globaldebuginfo.ll (+2)
  • (modified) llvm/tools/llvm-c-test/debuginfo.c (+34)
  • (modified) llvm/tools/llvm-c-test/llvm-c-test.h (+1)
  • (modified) llvm/tools/llvm-c-test/main.c (+2)
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index d645646289025..ec0c5e546fa8f 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2707,6 +2707,14 @@ LLVM_C_ABI void LLVMGlobalEraseMetadata(LLVMValueRef Global, unsigned Kind);
  */
 LLVM_C_ABI void LLVMGlobalClearMetadata(LLVMValueRef Global);
 
+/**
+ * Add debuginfo metadata to this global.
+ *
+ * @see llvm::GlobalVariable::addDebugInfo()
+ */
+LLVM_C_ABI void LLVMGlobalAddDebugInfo(LLVMValueRef Global,
+                                       LLVMMetadataRef GVE);
+
 /**
  * Retrieves an array of metadata entries representing the metadata attached to
  * this value. The caller is responsible for freeing this array by calling
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index f7ef4aa473ef5..988249ed23d9d 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -2194,6 +2194,11 @@ void LLVMGlobalClearMetadata(LLVMValueRef Global) {
   unwrap<GlobalObject>(Global)->clearMetadata();
 }
 
+void LLVMGlobalAddDebugInfo(LLVMValueRef Global, LLVMMetadataRef GVE) {
+  unwrap<GlobalVariable>(Global)->addDebugInfo(
+      unwrap<DIGlobalVariableExpression>(GVE));
+}
+
 /*--.. Operations on global variables ......................................--*/
 
 LLVMValueRef LLVMAddGlobal(LLVMModuleRef M, LLVMTypeRef Ty, const char *Name) {
diff --git a/llvm/test/Bindings/llvm-c/add_globaldebuginfo.ll b/llvm/test/Bindings/llvm-c/add_globaldebuginfo.ll
new file mode 100644
index 0000000000000..da6536a9ce407
--- /dev/null
+++ b/llvm/test/Bindings/llvm-c/add_globaldebuginfo.ll
@@ -0,0 +1,2 @@
+; RUN: llvm-c-test --add-globaldebuginfo < /dev/null
+; This used to trigger an assertion
diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c
index e73f69743805c..df70f6626ec14 100644
--- a/llvm/tools/llvm-c-test/debuginfo.c
+++ b/llvm/tools/llvm-c-test/debuginfo.c
@@ -416,3 +416,37 @@ int llvm_di_type_get_name(void) {
 
   return 0;
 }
+
+int llvm_add_globaldebuginfo(void) {
+  const char *Filename = "debuginfo.c";
+  LLVMModuleRef M = LLVMModuleCreateWithName(Filename);
+  LLVMDIBuilderRef Builder = LLVMCreateDIBuilder(M);
+  LLVMMetadataRef File =
+      LLVMDIBuilderCreateFile(Builder, Filename, strlen(Filename), ".", 1);
+
+  LLVMMetadataRef GlobalVarValueExpr =
+      LLVMDIBuilderCreateConstantValueExpression(Builder, 0);
+  LLVMMetadataRef Int64Ty =
+      LLVMDIBuilderCreateBasicType(Builder, "Int64", 5, 64, 0, LLVMDIFlagZero);
+  LLVMMetadataRef Int64TypeDef = LLVMDIBuilderCreateTypedef(
+      Builder, Int64Ty, "int64_t", 7, File, 42, File, 0);
+
+  LLVMMetadataRef GVE = LLVMDIBuilderCreateGlobalVariableExpression(
+      Builder, File, "global", 6, "", 0, File, 1, Int64TypeDef, true,
+      GlobalVarValueExpr, NULL, 0);
+
+  LLVMTypeRef RecType =
+      LLVMStructCreateNamed(LLVMGetModuleContext(M), "struct");
+  LLVMValueRef Global = LLVMAddGlobal(M, RecType, "global");
+
+  LLVMGlobalAddDebugInfo(Global, GVE);
+  size_t numEntries;
+  LLVMValueMetadataEntry *ME = LLVMGlobalCopyAllMetadata(Global, &numEntries);
+  assert(ME != NULL);
+  assert(numEntries == 1);
+
+  LLVMDisposeDIBuilder(Builder);
+  LLVMDisposeModule(M);
+
+  return 0;
+}
diff --git a/llvm/tools/llvm-c-test/llvm-c-test.h b/llvm/tools/llvm-c-test/llvm-c-test.h
index 1da6596cd5a8f..4c5a88ce0447e 100644
--- a/llvm/tools/llvm-c-test/llvm-c-test.h
+++ b/llvm/tools/llvm-c-test/llvm-c-test.h
@@ -45,6 +45,7 @@ int llvm_add_named_metadata_operand(void);
 int llvm_set_metadata(void);
 int llvm_replace_md_operand(void);
 int llvm_is_a_value_as_metadata(void);
+int llvm_add_globaldebuginfo(void);
 
 // object.c
 int llvm_object_list_sections(void);
diff --git a/llvm/tools/llvm-c-test/main.c b/llvm/tools/llvm-c-test/main.c
index badbe4b13b6ba..d1963b702888b 100644
--- a/llvm/tools/llvm-c-test/main.c
+++ b/llvm/tools/llvm-c-test/main.c
@@ -101,6 +101,8 @@ int main(int argc, char **argv) {
     return llvm_replace_md_operand();
   } else if (argc == 2 && !strcmp(argv[1], "--is-a-value-as-metadata")) {
     return llvm_is_a_value_as_metadata();
+  } else if (argc == 2 && !strcmp(argv[1], "--add-globaldebuginfo")) {
+    return llvm_add_globaldebuginfo();
   } else if (argc == 2 && !strcmp(argv[1], "--test-function-attributes")) {
     return llvm_test_function_attributes();
   } else if (argc == 2 && !strcmp(argv[1], "--test-callsite-attributes")) {

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make more sense to expose LLVMGlobalAddMetadata as a primitive.

@github-actions
Copy link

github-actions bot commented Jul 21, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@demoitem
Copy link
Contributor Author

Ok, I have exposed the GlobalAddMetadata but I think I still need the DebugInfo as users don't need to get the
kindId which could be problematic or perhaps overly complicated as one has to know the kindId needed
is for the "dbg" type.
As for the testing. Other tests seem to rely on an assert mechanism. If there is a better way to test this I would use it.

@demoitem
Copy link
Contributor Author

Ping

@demoitem
Copy link
Contributor Author

demoitem commented Aug 5, 2025

Are there any reviewers out there? Just asking.

@nikic nikic added the debuginfo label Aug 6, 2025
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@demoitem
Copy link
Contributor Author

demoitem commented Aug 7, 2025

Thanks @nikic I dont have commit access, could you merge this PR for me?

@demoitem
Copy link
Contributor Author

Ping

@nikic nikic merged commit 002362b into llvm:main Aug 14, 2025
10 checks passed
@kstoimenov
Copy link
Contributor

Looks like this broke sanitizer bots. Could you please take a look: https://lab.llvm.org/buildbot/#/builders/24/builds/11561

int kindId = LLVMGetMDKindID("dbg", 3);
LLVMGlobalAddMetadata(Global, kindId, GVE);
size_t numEntries;
LLVMValueMetadataEntry *ME = LLVMGlobalCopyAllMetadata(Global, &numEntries);
Copy link
Collaborator

@mikaelholmen mikaelholmen Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If compiling without asserts you get

../tools/llvm-c-test/debuginfo.c:447:27: error: unused variable 'ME' [-Werror,-Wunused-variable]
  447 |   LLVMValueMetadataEntry *ME = LLVMGlobalCopyAllMetadata(Global, &numEntries);
      |                           ^~
1 error generated.

here.

@mikaelholmen
Copy link
Collaborator

Looks like this broke sanitizer bots. Could you please take a look: https://lab.llvm.org/buildbot/#/builders/24/builds/11561

Yeah, for me, if I just build with ASAN and run lit tests then

Bindings/llvm-c/add_globaldebuginfo.ll

fails the same way as in the failed build bot.

Ping @demoitem

@nikic
Copy link
Contributor

nikic commented Aug 15, 2025

I think 5985620 should fix it.

@mikaelholmen
Copy link
Collaborator

I think 5985620 should fix it.

Yep, thanks!

@demoitem demoitem deleted the globaldebuginfo branch August 16, 2025 11:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants