Index: include/llvm-c/Core.h =================================================================== --- include/llvm-c/Core.h +++ include/llvm-c/Core.h @@ -2126,6 +2126,58 @@ */ void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes); +/** + * Sets a metadata attachment, erasing the existing metadata attachment if + * it already exists for the given kind. + * + * @see llvm::GlobalObject::setMetadata() + */ +void LLVMGlobalSetMetadata(LLVMValueRef Global, unsigned Kind, + LLVMMetadataRef MD); + +/** + * Erases a metadata attachment of the given kind if it exists. + * + * @see llvm::GlobalObject::eraseMetadata() + */ +void LLVMGlobalEraseMetadata(LLVMValueRef Global, unsigned Kind); + +/** + * Removes all metadata attachments from this value. + * + * @see llvm::GlobalObject::clearMetadata() + */ +void LLVMGlobalClearMetadata(LLVMValueRef Glob); + +/** + * Retrieves an array of metadata entries representing the metadata attached to + * this value. The caller is responsible for freeing this array by calling + * \c LLVMDisposeValueMetadataEntries. + * + * @see llvm::GlobalObject::getAllMetadata() + */ +LLVMValueMetadataEntry *LLVMGlobalCopyAllMetadata(LLVMValueRef Value, + size_t *NumEntries); + +/** + * Destroys value metadata entries. + */ +void LLVMDisposeValueMetadataEntries(LLVMValueMetadataEntry *Entries); + +/** + * Returns the kind of a value metadata entry at a specific index. + */ +unsigned LLVMValueMetadataEntriesGetKind(LLVMValueMetadataEntry *Entries, + unsigned Index); + +/** + * Returns the underlying metadata node of a value metadata entry at a + * specific index. + */ +LLVMMetadataRef +LLVMValueMetadataEntriesGetMetadata(LLVMValueMetadataEntry *Entries, + unsigned Index); + /** * @} */ @@ -2753,6 +2805,16 @@ */ void LLVMSetMetadata(LLVMValueRef Val, unsigned KindID, LLVMValueRef Node); +/** + * Returns the metadata associated with an instruction value, but filters out + * all the debug locations. + * + * @see llvm::Instruction::getAllMetadataOtherThanDebugLoc() + */ +LLVMValueMetadataEntry * +LLVMInstructionGetAllMetadataOtherThanDebugLoc(LLVMValueRef Instr, + size_t *NumEntries); + /** * Obtain the basic block to which an instruction belongs. * Index: include/llvm-c/Types.h =================================================================== --- include/llvm-c/Types.h +++ include/llvm-c/Types.h @@ -96,6 +96,13 @@ */ typedef struct LLVMOpaqueNamedMDNode *LLVMNamedMDNodeRef; +/** + * Represents an entry in a Global Object's metadata attachments. + * + * This models std::pair + */ +typedef struct LLVMOpaqueValueMetadataEntry LLVMValueMetadataEntry; + /** * Represents an LLVM basic block builder. * Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -868,6 +868,14 @@ unwrap(Inst)->setMetadata(KindID, N); } +LLVMValueMetadataEntry * +LLVMInstructionGetAllMetadataOtherThanDebugLoc(LLVMValueRef Value, + size_t *NumEntries) { + return llvm_getMetadata(NumEntries, [&Value](MetadataEntries &Entries) { + unwrap(Value)->getAllMetadata(Entries); + }); +} + /*--.. Conversion functions ................................................--*/ #define LLVM_DEFINE_VALUE_CAST(name) \ @@ -1872,6 +1880,73 @@ "only GlobalValue, AllocaInst, LoadInst and StoreInst have alignment"); } +struct LLVMOpaqueValueMetadataEntry { + unsigned Kind; + LLVMMetadataRef Metadata; +}; + +using MetadataEntries = SmallVectorImpl>; +static LLVMValueMetadataEntry * +llvm_getMetadata(size_t *NumEntries, + llvm::function_ref AccessMD) { + SmallVector, 8> MVEs; + AccessMD(MVEs); + + LLVMOpaqueValueMetadataEntry *Result = + static_cast( + safe_malloc(MVEs.size() * sizeof(LLVMOpaqueValueMetadataEntry))); + for (unsigned i = 0; i < MVEs.size(); ++i) { + const auto &ModuleFlag = MVEs[i]; + Result[i].Kind = ModuleFlag.first; + Result[i].Metadata = wrap(ModuleFlag.second); + } + *NumEntries = MVEs.size(); + return Result; +} + +LLVMValueMetadataEntry *LLVMGlobalCopyAllMetadata(LLVMValueRef Value, + size_t *NumEntries) { + return llvm_getMetadata(NumEntries, [&Value](MetadataEntries &Entries) { + if (Instruction *Instr = dyn_cast(unwrap(Value))) { + Instr->getAllMetadata(Entries); + } else { + unwrap(Value)->getAllMetadata(Entries); + } + }); +} + +unsigned LLVMValueMetadataEntriesGetKind(LLVMValueMetadataEntry *Entries, + unsigned Index) { + LLVMOpaqueValueMetadataEntry MVE = + static_cast(Entries[Index]); + return MVE.Kind; +} + +LLVMMetadataRef +LLVMValueMetadataEntriesGetMetadata(LLVMValueMetadataEntry *Entries, + unsigned Index) { + LLVMOpaqueValueMetadataEntry MVE = + static_cast(Entries[Index]); + return MVE.Metadata; +} + +void LLVMDisposeValueMetadataEntries(LLVMValueMetadataEntry *Entries) { + free(Entries); +} + +void LLVMGlobalSetMetadata(LLVMValueRef Global, unsigned Kind, + LLVMMetadataRef MD) { + unwrap(Global)->setMetadata(Kind, unwrapDI(MD)); +} + +void LLVMGlobalEraseMetadata(LLVMValueRef Global, unsigned Kind) { + unwrap(Global)->eraseMetadata(Kind); +} + +void LLVMGlobalClearMetadata(LLVMValueRef Global) { + unwrap(Global)->clearMetadata(); +} + /*--.. Operations on global variables ......................................--*/ LLVMValueRef LLVMAddGlobal(LLVMModuleRef M, LLVMTypeRef Ty, const char *Name) { Index: test/Bindings/llvm-c/echo.ll =================================================================== --- test/Bindings/llvm-c/echo.ll +++ test/Bindings/llvm-c/echo.ll @@ -166,11 +166,22 @@ ret void } -!llvm.module.flags = !{!0} -!named = !{!1, !2, !3} - -!0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = distinct !{} -!2 = distinct !{} -!3 = !{!4} -!4 = distinct !{} +define void @with_debuginfo() !dbg !4 { + ret void, !dbg !7 +} + +!llvm.dbg.cu = !{!0, !2} +!llvm.module.flags = !{!3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "echo.ll", directory: "/llvm/test/Bindings/llvm-c/echo.ll") +!2 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = distinct !DISubprogram(name: "with_debuginfo", linkageName: "_with_debuginfo", scope: null, file: !1, line: 42, type: !5, isLocal: false, isDefinition: true, scopeLine: 1519, flags: DIFlagPrototyped, isOptimized: true, unit: !0, templateParams: !6, retainedNodes: !6) +!5 = !DISubroutineType(types: !6) +!6 = !{} +!7 = !DILocation(line: 42, scope: !8, inlinedAt: !11) +!8 = distinct !DILexicalBlock(scope: !9, file: !1, line: 42, column: 12) +!9 = distinct !DISubprogram(name: "fake_inlined_block", linkageName: "_fake_inlined_block", scope: null, file: !1, line: 82, type: !5, isLocal: false, isDefinition: true, scopeLine: 82, flags: DIFlagPrototyped, isOptimized: true, unit: !2, templateParams: !6, retainedNodes: !6) +!10 = distinct !DILocation(line: 84, scope: !8, inlinedAt: !11) +!11 = !DILocation(line: 42, scope: !4) Index: tools/llvm-c-test/echo.cpp =================================================================== --- tools/llvm-c-test/echo.cpp +++ tools/llvm-c-test/echo.cpp @@ -16,6 +16,7 @@ //===----------------------------------------------------------------------===// #include "llvm-c-test.h" +#include "llvm-c/DebugInfo.h" #include "llvm-c/Target.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/ErrorHandling.h" @@ -728,6 +729,19 @@ exit(-1); } + auto Ctx = LLVMGetModuleContext(M); + size_t NumMetadataEntries; + auto *AllMetadata = + LLVMInstructionGetAllMetadataOtherThanDebugLoc(Src, + &NumMetadataEntries); + for (unsigned i = 0; i < NumMetadataEntries; ++i) { + unsigned Kind = LLVMValueMetadataEntriesGetKind(AllMetadata, i); + LLVMMetadataRef MD = LLVMValueMetadataEntriesGetMetadata(AllMetadata, i); + LLVMSetMetadata(Dst, Kind, LLVMMetadataAsValue(Ctx, MD)); + } + LLVMDisposeValueMetadataEntries(AllMetadata); + LLVMSetInstDebugLocation(Builder, Dst); + check_value_kind(Dst, LLVMInstructionValueKind); return VMap[Src] = Dst; } @@ -999,6 +1013,15 @@ if (auto I = LLVMGetInitializer(Cur)) LLVMSetInitializer(G, clone_constant(I, M)); + size_t NumMetadataEntries; + auto *AllMetadata = LLVMGlobalCopyAllMetadata(Cur, &NumMetadataEntries); + for (unsigned i = 0; i < NumMetadataEntries; ++i) { + unsigned Kind = LLVMValueMetadataEntriesGetKind(AllMetadata, i); + LLVMMetadataRef MD = LLVMValueMetadataEntriesGetMetadata(AllMetadata, i); + LLVMGlobalSetMetadata(G, Kind, MD); + } + LLVMDisposeValueMetadataEntries(AllMetadata); + LLVMSetGlobalConstant(G, LLVMIsGlobalConstant(Cur)); LLVMSetThreadLocal(G, LLVMIsThreadLocal(Cur)); LLVMSetExternallyInitialized(G, LLVMIsExternallyInitialized(Cur)); @@ -1050,6 +1073,15 @@ LLVMSetPersonalityFn(Fun, P); } + size_t NumMetadataEntries; + auto *AllMetadata = LLVMGlobalCopyAllMetadata(Cur, &NumMetadataEntries); + for (unsigned i = 0; i < NumMetadataEntries; ++i) { + unsigned Kind = LLVMValueMetadataEntriesGetKind(AllMetadata, i); + LLVMMetadataRef MD = LLVMValueMetadataEntriesGetMetadata(AllMetadata, i); + LLVMGlobalSetMetadata(Fun, Kind, MD); + } + LLVMDisposeValueMetadataEntries(AllMetadata); + FunCloner FC(Cur, Fun); FC.CloneBBs(Cur);