https://github.com/Men-cotton updated https://github.com/llvm/llvm-project/pull/203022
>From 668e41a707fb1d698edb94f8e5fa65ae98383026 Mon Sep 17 00:00:00 2001 From: mencotton <[email protected]> Date: Mon, 8 Jun 2026 20:54:24 +0900 Subject: [PATCH] [MLIR][LLVM] Preserve unknown function metadata on import Import non-debug function metadata without a kind-specific dialect conversion into LLVMFuncOp function_metadata. Preserve repeated metadata kinds through the generic carrier so LLVM IR import and export can round-trip those attachments. --- mlir/lib/Target/LLVMIR/ModuleImport.cpp | 41 +++++++- .../Target/LLVMIR/Import/function-metadata.ll | 95 +++++++++++++++++++ 2 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 mlir/test/Target/LLVMIR/Import/function-metadata.ll diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index fa40db054f091..3fc6595f3d317 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -3285,18 +3285,49 @@ LogicalResult ModuleImport::processFunction(llvm::Function *func) { // Handle Function attributes. processFunctionAttributes(func, funcOp); - // Convert non-debug metadata by using the dialect interface. + // Convert non-debug metadata by using the dialect interface. Metadata without + // a kind-specific dialect conversion is preserved in the generic function + // metadata carrier. SmallVector<std::pair<unsigned, llvm::MDNode *>> allMetadata; func->getAllMetadata(allMetadata); + SmallVector<StringRef> metadataNames; + llvmModule->getMDKindNames(metadataNames); + SmallVector<Attribute> functionMetadata; for (auto &[kind, node] : allMetadata) { - if (!iface.isConvertibleMetadata(kind)) + if (kind == llvm::LLVMContext::MD_dbg) continue; - if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *this))) { + + llvm::MDNode *metadataNode = node; + auto emitUnhandledFunctionMetadataWarning = [&]() { emitWarning(funcOp.getLoc()) - << "unhandled function metadata: " << diagMD(node, llvmModule.get()) - << " on " << diag(*func); + << "unhandled function metadata: " + << diagMD(metadataNode, llvmModule.get()) << " on " << diag(*func); + }; + + if (!iface.isConvertibleMetadata(kind)) { + auto getNamelessGlobalSymbol = + [this](llvm::GlobalVariable *globalVar) -> FlatSymbolRefAttr { + return getOrCreateNamelessSymbolName(globalVar); + }; + Attribute nodeAttr = convertMetadataToAttr(context, metadataNode, iface, + getNamelessGlobalSymbol); + auto mdNodeAttr = dyn_cast_if_present<LLVM::MDNodeAttr>(nodeAttr); + if (!mdNodeAttr || kind >= metadataNames.size()) { + emitUnhandledFunctionMetadataWarning(); + continue; + } + + functionMetadata.push_back(LLVM::FunctionMetadataAttr::get( + context, builder.getStringAttr(metadataNames[kind]), mdNodeAttr)); + continue; } + + if (failed( + iface.setMetadataAttrs(builder, kind, metadataNode, funcOp, *this))) + emitUnhandledFunctionMetadataWarning(); } + if (!functionMetadata.empty()) + funcOp.setFunctionMetadataAttr(builder.getArrayAttr(functionMetadata)); if (func->isDeclaration()) return success(); diff --git a/mlir/test/Target/LLVMIR/Import/function-metadata.ll b/mlir/test/Target/LLVMIR/Import/function-metadata.ll new file mode 100644 index 0000000000000..6e57ef1664fde --- /dev/null +++ b/mlir/test/Target/LLVMIR/Import/function-metadata.ll @@ -0,0 +1,95 @@ +; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s + +; CHECK-LABEL: llvm.func @repeated_type_metadata +; CHECK-SAME: function_metadata +; CHECK-SAME: #llvm.func_metadata<"type", <#llvm.md_const<0 : i64>, #llvm.md_string<"typeid0">>> +; CHECK-SAME: #llvm.func_metadata<"type", <#llvm.md_const<0 : i64>, #llvm.md_string<"typeid1">>> +define void @repeated_type_metadata() !type !0 !type !1 { + ret void +} + +!0 = !{i64 0, !"typeid0"} +!1 = !{i64 0, !"typeid1"} + +; // ----- + +; CHECK-LABEL: llvm.func @declaration_metadata +; CHECK-SAME: function_metadata +; CHECK-SAME: #llvm.func_metadata<"annotation", <#llvm.md_string<"declaration annotation">>> +declare !annotation !0 void @declaration_metadata() + +!0 = !{!"declaration annotation"} + +; // ----- + +declare void @callee() + +; CHECK-LABEL: llvm.func @function_ref_metadata +; CHECK-SAME: function_metadata +; CHECK-SAME: #llvm.func_metadata<"callees", <#llvm.md_global_value<@callee>>> +define void @function_ref_metadata() !callees !0 { + ret void +} + +!0 = !{ptr @callee} + +; // ----- + +define void @alias_target() { + ret void +} +@alias = alias void (), ptr @alias_target + +; CHECK-LABEL: llvm.func @alias_ref_metadata +; CHECK-SAME: function_metadata +; CHECK-SAME: #llvm.func_metadata<"callees", <#llvm.md_global_value<@alias>>> +define void @alias_ref_metadata() !callees !0 { + ret void +} + +!0 = !{ptr @alias} + +; // ----- + +@global = global i32 0 + +; CHECK-LABEL: llvm.func @global_ref_metadata +; CHECK-SAME: function_metadata +; CHECK-SAME: #llvm.func_metadata<"callees", <#llvm.md_global_value<@global>>> +define void @global_ref_metadata() !callees !0 { + ret void +} + +!0 = !{ptr @global} + +; // ----- + +@0 = global i32 0 + +; CHECK-LABEL: llvm.func @nameless_global_ref_metadata +; CHECK-SAME: function_metadata +; CHECK-SAME: #llvm.func_metadata<"callees", <#llvm.md_global_value<@{{mlir\.llvm\.nameless_global_[0-9]+}}>>> +define void @nameless_global_ref_metadata() !callees !0 { + ret void +} + +!0 = !{ptr @0} + +; // ----- + +@ifunc = ifunc void (), ptr @ifunc_resolver +define ptr @ifunc_resolver() { + ret ptr @ifunc_target +} +define void @ifunc_target() { + ret void +} + +; CHECK-LABEL: llvm.func @ifunc_ref_metadata +; CHECK-SAME: function_metadata +; CHECK-SAME: #llvm.func_metadata<"callees", <#llvm.md_global_value<@ifunc>>> +define void @ifunc_ref_metadata() !callees !0 { + ret void +} + +!0 = !{ptr @ifunc} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
