[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.
This commit is contained in:
parent
1d87038375
commit
82d818b02a
2 changed files with 146 additions and 5 deletions
|
|
@ -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();
|
||||
|
|
|
|||
110
mlir/test/Target/LLVMIR/Import/function-metadata.ll
Normal file
110
mlir/test/Target/LLVMIR/Import/function-metadata.ll
Normal file
|
|
@ -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"}
|
||||
Loading…
Reference in a new issue