https://github.com/Men-cotton updated https://github.com/llvm/llvm-project/pull/203021
>From 98c27df0b5038a358b7a9f72d130d7113b8b92a8 Mon Sep 17 00:00:00 2001 From: mencotton <[email protected]> Date: Mon, 8 Jun 2026 20:52:56 +0900 Subject: [PATCH] [MLIR][LLVM] Translate LLVMFuncOp function metadata Materialize LLVMFuncOp function_metadata through ModuleTranslation metadata conversion. Attach function metadata after module-level symbols are mapped so metadata references to functions, globals, aliases, and ifuncs can be resolved. --- mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 53 +++++- .../test/Target/LLVMIR/function-metadata.mlir | 156 ++++++++++++++++++ 2 files changed, 204 insertions(+), 5 deletions(-) create mode 100644 mlir/test/Target/LLVMIR/function-metadata.mlir diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index 2193b415637a3..c56104dbb8d4b 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -1617,6 +1617,45 @@ FailureOr<llvm::Metadata *> ModuleTranslation::convertMetadataAttr( }); } +/// Converts generic function metadata from `func` and attaches it to +/// `llvmFunc`. +static LogicalResult convertFunctionMetadata(ModuleTranslation &translation, + LLVMFuncOp func, + llvm::Function *llvmFunc) { + ArrayAttr metadata = func.getFunctionMetadataAttr(); + if (!metadata) + return success(); + + for (auto entry : metadata.getAsRange<LLVM::FunctionMetadataAttr>()) { + StringRef metadataName = entry.getMetadataName().getValue(); + + FailureOr<llvm::Metadata *> md = + translation.convertMetadataAttr(entry.getNode(), [&]() { + return func.emitError() + << "failed to convert function_metadata entry '" + << metadataName << "': "; + }); + if (failed(md)) + return failure(); + llvm::MDNode *node = llvm::dyn_cast_if_present<llvm::MDNode>(*md); + if (!node) + return func.emitError() << "failed to convert function_metadata entry '" + << metadataName << "'"; + llvmFunc->addMetadata(metadataName, *node); + } + return success(); +} + +static LogicalResult convertFunctionMetadata(ModuleTranslation &translation, + Operation *module) { + for (auto function : getModuleBody(module).getOps<LLVMFuncOp>()) { + llvm::Function *llvmFunc = translation.lookupFunction(function.getName()); + if (failed(convertFunctionMetadata(translation, function, llvmFunc))) + return failure(); + } + return success(); +} + LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) { // Clear the block, branch value mappings, they are only relevant within one // function. @@ -2036,18 +2075,20 @@ ModuleTranslation::convertParameterAttrs(Location loc, LogicalResult ModuleTranslation::convertFunctionSignatures() { // Declare all functions first because there may be function calls that form a - // call graph with cycles, or global initializers that reference functions. + // call graph with cycles, global initializers that reference functions, or + // metadata that references functions declared later in the module. for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) { llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction( function.getName(), cast<llvm::FunctionType>(convertType(function.getFunctionType()))); llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee()); + mapFunction(function.getName(), llvmFunc); + } + + for (auto function : getModuleBody(mlirModule).getOps<LLVMFuncOp>()) { + llvm::Function *llvmFunc = lookupFunction(function.getName()); llvmFunc->setLinkage(convertLinkageToLLVM(function.getLinkage())); llvmFunc->setCallingConv(convertCConvToLLVM(function.getCConv())); - mapFunction(function.getName(), llvmFunc); - if (function.getFunctionMetadataAttr()) - return function.emitError() - << "not yet implemented: translating function_metadata to LLVM IR"; addRuntimePreemptionSpecifier(function.getDsoLocal(), llvmFunc); // Convert function attributes. @@ -2620,6 +2661,8 @@ mlir::translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext, return nullptr; if (failed(translator.convertIFuncs())) return nullptr; + if (failed(convertFunctionMetadata(translator, module))) + return nullptr; if (failed(translator.createTBAAMetadata())) return nullptr; if (failed(translator.createIdentMetadata())) diff --git a/mlir/test/Target/LLVMIR/function-metadata.mlir b/mlir/test/Target/LLVMIR/function-metadata.mlir new file mode 100644 index 0000000000000..8816369b3d02a --- /dev/null +++ b/mlir/test/Target/LLVMIR/function-metadata.mlir @@ -0,0 +1,156 @@ +// RUN: mlir-translate -verify-diagnostics -split-input-file -mlir-to-llvmir %s | FileCheck %s + +// CHECK-LABEL: define void @function_metadata() +// CHECK-SAME: !type ![[TYPE:[0-9]+]] +// CHECK-SAME: !annotation ![[ANNOTATION:[0-9]+]] +llvm.func @function_metadata() attributes { + function_metadata = [ + #llvm.func_metadata<"annotation", #llvm.md_node< + #llvm.md_string<"function annotation"> + >>, + #llvm.func_metadata<"type", #llvm.md_node< + #llvm.md_const<0 : i64>, + #llvm.md_string<"typeid"> + >> + ] +} { + llvm.return +} + +// CHECK-DAG: ![[ANNOTATION]] = !{!"function annotation"} +// CHECK-DAG: ![[TYPE]] = !{i64 0, !"typeid"} + +// ----- + +// CHECK-LABEL: declare !annotation +// CHECK-SAME: ![[DECL_ANNOTATION:[0-9]+]] void @declaration_metadata() +llvm.func @declaration_metadata() attributes { + function_metadata = [ + #llvm.func_metadata<"annotation", #llvm.md_node< + #llvm.md_string<"declaration annotation"> + >> + ] +} + +// CHECK-DAG: ![[DECL_ANNOTATION]] = !{!"declaration annotation"} + +// ----- + +// CHECK-LABEL: define void @uses_later() +// CHECK-SAME: !callee ![[LATER_NODE:[0-9]+]] +llvm.func @uses_later() attributes { + function_metadata = [ + #llvm.func_metadata<"callee", #llvm.md_node<#llvm.md_string<"later">, #llvm.md_value<@later>>> + ] +} { + llvm.return +} + +llvm.func @later() { + llvm.return +} + +// CHECK-DAG: ![[LATER_NODE]] = !{!"later", ptr @later} + +// ----- + +llvm.mlir.global internal @metadata_global(0 : i32) : i32 + +// CHECK-LABEL: define void @uses_global() +// CHECK-SAME: !callee ![[GLOBAL_NODE:[0-9]+]] +llvm.func @uses_global() attributes { + function_metadata = [ + #llvm.func_metadata<"callee", #llvm.md_node<#llvm.md_value<@metadata_global>>> + ] +} { + llvm.return +} + +// CHECK-DAG: ![[GLOBAL_NODE]] = !{ptr @metadata_global} + +// ----- + +llvm.func @metadata_alias_target() { + llvm.return +} + +llvm.mlir.alias external @metadata_alias : !llvm.func<void ()> { + %0 = llvm.mlir.addressof @metadata_alias_target : !llvm.ptr + llvm.return %0 : !llvm.ptr +} + +// CHECK-LABEL: define void @uses_alias() +// CHECK-SAME: !callee ![[ALIAS_NODE:[0-9]+]] +llvm.func @uses_alias() attributes { + function_metadata = [ + #llvm.func_metadata<"callee", #llvm.md_node<#llvm.md_value<@metadata_alias>>> + ] +} { + llvm.return +} + +// CHECK-DAG: ![[ALIAS_NODE]] = !{ptr @metadata_alias} + +// ----- + +llvm.mlir.ifunc external @metadata_ifunc : !llvm.func<void ()>, !llvm.ptr @metadata_ifunc_resolver + +llvm.func @metadata_ifunc_resolver() -> !llvm.ptr { + %0 = llvm.mlir.addressof @metadata_ifunc_target : !llvm.ptr + llvm.return %0 : !llvm.ptr +} + +llvm.func @metadata_ifunc_target() { + llvm.return +} + +// CHECK-LABEL: define void @uses_ifunc() +// CHECK-SAME: !callee ![[IFUNC_NODE:[0-9]+]] +llvm.func @uses_ifunc() attributes { + function_metadata = [ + #llvm.func_metadata<"callee", #llvm.md_node<#llvm.md_value<@metadata_ifunc>>> + ] +} { + llvm.return +} + +// CHECK-DAG: ![[IFUNC_NODE]] = !{ptr @metadata_ifunc} + +// ----- + +// CHECK-LABEL: define void @repeated_kind_metadata() +// CHECK-SAME: !type ![[TYPE0:[0-9]+]] +// CHECK-SAME: !type ![[TYPE1:[0-9]+]] +llvm.func @repeated_kind_metadata() attributes { + function_metadata = [ + #llvm.func_metadata<"type", #llvm.md_node<#llvm.md_const<0 : i64>, #llvm.md_string<"typeid0">>>, + #llvm.func_metadata<"type", #llvm.md_node<#llvm.md_const<0 : i64>, #llvm.md_string<"typeid1">>> + ] +} { + llvm.return +} + +// CHECK-DAG: ![[TYPE0]] = !{i64 0, !"typeid0"} +// CHECK-DAG: ![[TYPE1]] = !{i64 0, !"typeid1"} + +// ----- + +// expected-error @below{{failed to convert function_metadata entry 'callee': could not resolve metadata reference '@missing'}} +llvm.func @missing_function_metadata_ref() attributes { + function_metadata = [ + #llvm.func_metadata<"callee", #llvm.md_node<#llvm.md_value<@missing>>> + ] +} { + llvm.return +} + +// ----- + +// expected-error @below{{failed to convert function_metadata entry 'bad': expected integer attribute in metadata constant}} +llvm.func @malformed_function_metadata() attributes { + function_metadata = [ + #llvm.func_metadata<"bad", #llvm.md_node<#llvm.md_const<"not an integer">>> + ] +} { + llvm.return +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
