From 002362bbd875d2892564779c5693dbb621dc7c1d Mon Sep 17 00:00:00 2001 From: peter mckinna Date: Thu, 14 Aug 2025 22:59:39 +1000 Subject: [PATCH] Add LLVMGlobalAddDebugInfo to Core.cpp (#148747) 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. --- llvm/include/llvm-c/Core.h | 16 ++++++++ llvm/lib/IR/Core.cpp | 10 +++++ .../Bindings/llvm-c/add_globaldebuginfo.ll | 2 + llvm/tools/llvm-c-test/debuginfo.c | 37 +++++++++++++++++++ llvm/tools/llvm-c-test/llvm-c-test.h | 1 + llvm/tools/llvm-c-test/main.c | 2 + 6 files changed, 68 insertions(+) create mode 100644 llvm/test/Bindings/llvm-c/add_globaldebuginfo.ll diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 9879d0d3a17a..d02cf984167c 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -2694,6 +2694,14 @@ LLVM_C_ABI void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes); LLVM_C_ABI void LLVMGlobalSetMetadata(LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD); +/** + * Adds a metadata attachment. + * + * @see llvm::GlobalObject::addMetadata() + */ +LLVM_C_ABI void LLVMGlobalAddMetadata(LLVMValueRef Global, unsigned Kind, + LLVMMetadataRef MD); + /** * Erases a metadata attachment of the given kind if it exists. * @@ -2708,6 +2716,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 f7ef4aa473ef..8b5965ba45a6 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2186,6 +2186,11 @@ void LLVMGlobalSetMetadata(LLVMValueRef Global, unsigned Kind, unwrap(Global)->setMetadata(Kind, unwrap(MD)); } +void LLVMGlobalAddMetadata(LLVMValueRef Global, unsigned Kind, + LLVMMetadataRef MD) { + unwrap(Global)->addMetadata(Kind, *unwrap(MD)); +} + void LLVMGlobalEraseMetadata(LLVMValueRef Global, unsigned Kind) { unwrap(Global)->eraseMetadata(Kind); } @@ -2194,6 +2199,11 @@ void LLVMGlobalClearMetadata(LLVMValueRef Global) { unwrap(Global)->clearMetadata(); } +void LLVMGlobalAddDebugInfo(LLVMValueRef Global, LLVMMetadataRef GVE) { + unwrap(Global)->addDebugInfo( + unwrap(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 000000000000..da6536a9ce40 --- /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 e73f69743805..3fddd0287f1a 100644 --- a/llvm/tools/llvm-c-test/debuginfo.c +++ b/llvm/tools/llvm-c-test/debuginfo.c @@ -416,3 +416,40 @@ 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); + // use AddMetadata to add twice + int kindId = LLVMGetMDKindID("dbg", 3); + LLVMGlobalAddMetadata(Global, kindId, GVE); + size_t numEntries; + LLVMValueMetadataEntry *ME = LLVMGlobalCopyAllMetadata(Global, &numEntries); + assert(ME != NULL); + assert(numEntries == 2); + + 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 1da6596cd5a8..4c5a88ce0447 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 badbe4b13b6b..d1963b702888 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")) {