https://github.com/Men-cotton updated https://github.com/llvm/llvm-project/pull/203022
>From 82d818b02a9b3abdb0a402afab021e90ef64fff1 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 representable 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 the supported generic metadata subset. Warn and drop attachments outside that subset while continuing to import the function. --- mlir/lib/Target/LLVMIR/ModuleImport.cpp | 41 ++++++- .../Target/LLVMIR/Import/function-metadata.ll | 110 ++++++++++++++++++ 2 files changed, 146 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 3857a5e8d6c61..7a3f3ef1520da 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -3292,18 +3292,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..d7cd94bbc9f08 --- /dev/null +++ b/mlir/test/Target/LLVMIR/Import/function-metadata.ll @@ -0,0 +1,110 @@ +; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s +; RUN: mlir-translate -import-llvm -split-input-file %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN + +; 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} + +; // ----- + +; WARN: warning: unhandled function metadata: +; WARN-SAME: !{{[0-9]+}} = distinct !{!"identity"} +; WARN-SAME: on define void @distinct_metadata() +; CHECK-LABEL: llvm.func @distinct_metadata() +; CHECK-NOT: function_metadata +; CHECK: llvm.return +define void @distinct_metadata() !annotation !0 { + ret void +} + +!0 = distinct !{!"identity"} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
