diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td index 0f195ff82c3ff..f53f95ee9ba49 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -1332,18 +1332,21 @@ def ModuleFlagAttr Represents a single entry of llvm.module.flags metadata (llvm::Module::ModuleFlagEntry in LLVM). The first element is a behavior flag described by `ModFlagBehaviorAttr`, the second is a string ID - and third is the value of the flag (currently only integer constants - are supported). + and third is the value of the flag. Current supported types of values: + - Integer constants + - Strings Example: ```mlir #llvm.mlir.module_flag + #llvm.mlir.module_flag ``` }]; let parameters = (ins "ModFlagBehavior":$behavior, "StringAttr":$key, - "uint32_t":$value); + "Attribute":$value); let assemblyFormat = "`<` $behavior `,` $key `,` $value `>`"; + let genVerifyDecl = 1; } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp index e4f9d6f987401..f3ebb8a565ea4 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp @@ -375,3 +375,13 @@ TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) { return parentFunction.getOperation()->getAttrOfType( getAttributeName()); } + +LogicalResult +ModuleFlagAttr::verify(function_ref emitError, + LLVM::ModFlagBehavior flagBehavior, StringAttr key, + Attribute value) { + if (!isa(value)) + return emitError() + << "only integer and string values are currently supported"; + return success(); +} diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp index 7038b5d73d266..e816a3e218452 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp @@ -16,6 +16,7 @@ #include "mlir/Support/LLVM.h" #include "mlir/Target/LLVMIR/ModuleTranslation.h" +#include "llvm/ADT/TypeSwitch.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/MDBuilder.h" @@ -273,10 +274,25 @@ static void convertLinkerOptionsOp(ArrayAttr options, static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { llvm::Module *llvmModule = moduleTranslation.getLLVMModule(); - for (auto flagAttr : flags.getAsRange()) + for (auto flagAttr : flags.getAsRange()) { + llvm::Metadata *valueMetadata = + llvm::TypeSwitch(flagAttr.getValue()) + .Case([&](auto strAttr) { + return llvm::MDString::get(builder.getContext(), + strAttr.getValue()); + }) + .Case([&](auto intAttr) { + return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(builder.getContext()), + intAttr.getInt())); + }) + .Default([](auto) { return nullptr; }); + + assert(valueMetadata && "expected valid metadata"); llvmModule->addModuleFlag( convertModFlagBehaviorToLLVM(flagAttr.getBehavior()), - flagAttr.getKey().getValue(), flagAttr.getValue()); + flagAttr.getKey().getValue(), valueMetadata); + } } static LogicalResult diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index df7c8d6ea3579..3f80002c15ebb 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -525,18 +525,20 @@ LogicalResult ModuleImport::convertModuleFlagsMetadata() { SmallVector moduleFlags; for (const auto [behavior, key, val] : llvmModuleFlags) { - // Currently only supports most common: int constant values. - auto *constInt = llvm::mdconst::dyn_extract(val); - if (!constInt) { + Attribute valAttr = nullptr; + if (auto *constInt = llvm::mdconst::dyn_extract(val)) { + valAttr = builder.getI32IntegerAttr(constInt->getZExtValue()); + } else if (auto *mdString = dyn_cast(val)) { + valAttr = builder.getStringAttr(mdString->getString()); + } else { emitWarning(mlirModule.getLoc()) - << "unsupported module flag value: " << diagMD(val, llvmModule.get()) - << ", only constant integer currently supported"; + << "unsupported module flag value: " << diagMD(val, llvmModule.get()); continue; } moduleFlags.push_back(builder.getAttr( convertModFlagBehaviorFromLLVM(behavior), - builder.getStringAttr(key->getString()), constInt->getZExtValue())); + builder.getStringAttr(key->getString()), valAttr)); } if (!moduleFlags.empty()) diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir index 0cd6b1f20a1bf..a3cd9572933ae 100644 --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -1776,9 +1776,10 @@ llvm.mlir.alias external @y5 : i32 { // ----- module { - // expected-error@+2 {{expected integer value}} - // expected-error@+1 {{failed to parse ModuleFlagAttr parameter 'value' which is to be a `uint32_t`}} - llvm.module_flags [#llvm.mlir.module_flag] + llvm.func @foo() + + // expected-error@below {{only integer and string values are currently supported}} + llvm.module_flags [#llvm.mlir.module_flag] } // ----- diff --git a/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir index d99a93c1e8565..a94514da9818f 100644 --- a/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir @@ -1,16 +1,18 @@ // RUN: mlir-opt %s | mlir-opt | FileCheck %s module { - llvm.module_flags [#llvm.mlir.module_flag, - #llvm.mlir.module_flag, - #llvm.mlir.module_flag, - #llvm.mlir.module_flag, - #llvm.mlir.module_flag] + llvm.module_flags [#llvm.mlir.module_flag, + #llvm.mlir.module_flag, + #llvm.mlir.module_flag, + #llvm.mlir.module_flag, + #llvm.mlir.module_flag, + #llvm.mlir.module_flag] } // CHECK: llvm.module_flags [ -// CHECK-SAME: #llvm.mlir.module_flag, -// CHECK-SAME: #llvm.mlir.module_flag, -// CHECK-SAME: #llvm.mlir.module_flag, -// CHECK-SAME: #llvm.mlir.module_flag, -// CHECK-SAME: #llvm.mlir.module_flag] +// CHECK-SAME: #llvm.mlir.module_flag, +// CHECK-SAME: #llvm.mlir.module_flag, +// CHECK-SAME: #llvm.mlir.module_flag, +// CHECK-SAME: #llvm.mlir.module_flag, +// CHECK-SAME: #llvm.mlir.module_flag, +// CHECK-SAME: #llvm.mlir.module_flag] diff --git a/mlir/test/Target/LLVMIR/Import/module-flags.ll b/mlir/test/Target/LLVMIR/Import/module-flags.ll index b7b686f94c7f4..e6bb2c0ffb32d 100644 --- a/mlir/test/Target/LLVMIR/Import/module-flags.ll +++ b/mlir/test/Target/LLVMIR/Import/module-flags.ll @@ -1,25 +1,27 @@ ; RUN: mlir-translate -import-llvm -split-input-file -verify-diagnostics %s | FileCheck %s -!llvm.module.flags = !{!0, !1, !2, !3, !4} +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{i32 8, !"PIC Level", i32 2} !2 = !{i32 7, !"PIE Level", i32 2} !3 = !{i32 7, !"uwtable", i32 2} !4 = !{i32 7, !"frame-pointer", i32 1} +!5 = !{i32 4, !"probe-stack", !"inline-asm"} ; CHECK-LABEL: module attributes {{.*}} { ; CHECK: llvm.module_flags [ -; CHECK-SAME: #llvm.mlir.module_flag, -; CHECK-SAME: #llvm.mlir.module_flag, -; CHECK-SAME: #llvm.mlir.module_flag, -; CHECK-SAME: #llvm.mlir.module_flag, -; CHECK-SAME: #llvm.mlir.module_flag] -; CHECK: } +; CHECK-SAME: #llvm.mlir.module_flag, +; CHECK-SAME: #llvm.mlir.module_flag, +; CHECK-SAME: #llvm.mlir.module_flag, +; CHECK-SAME: #llvm.mlir.module_flag, +; CHECK-SAME: #llvm.mlir.module_flag, +; CHECK-SAME: #llvm.mlir.module_flag] ; // ----- - -!llvm.module.flags = !{!0} - -; expected-warning@-5{{unsupported module flag value: !"yolo_more", only constant integer currently supported}} -!0 = !{i32 1, !"yolo", !"yolo_more"} +; expected-warning@-2 {{unsupported module flag value: !4 = !{!"foo", i32 1}}} +!10 = !{ i32 1, !"foo", i32 1 } +!11 = !{ i32 4, !"bar", i32 37 } +!12 = !{ i32 2, !"qux", i32 42 } +!13 = !{ i32 3, !"qux", !{ !"foo", i32 1 }} +!llvm.module.flags = !{ !10, !11, !12, !13 } diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir index 3cf08dbeeac8c..74fa327809864 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -2809,11 +2809,11 @@ llvm.func @call_intrin_with_opbundle(%arg0 : !llvm.ptr) { // ----- module { - llvm.module_flags [#llvm.mlir.module_flag, - #llvm.mlir.module_flag, - #llvm.mlir.module_flag, - #llvm.mlir.module_flag, - #llvm.mlir.module_flag] + llvm.module_flags [#llvm.mlir.module_flag, + #llvm.mlir.module_flag, + #llvm.mlir.module_flag, + #llvm.mlir.module_flag, + #llvm.mlir.module_flag] } // CHECK: !llvm.module.flags = !{![[#WCHAR:]], ![[#PIC:]], ![[#PIE:]], ![[#UWTABLE:]], ![[#FrameP:]], ![[#DBG:]]} @@ -2830,7 +2830,7 @@ module { // Verifies that the debug info version is not added twice, if it's already present initially. module { - llvm.module_flags [#llvm.mlir.module_flag] + llvm.module_flags [#llvm.mlir.module_flag] } // CHECK: !llvm.module.flags = !{![[#DBG:]]}