Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1291,4 +1291,29 @@ def LLVM_DereferenceableAttr : LLVM_Attr<"Dereferenceable", "dereferenceable"> {
let assemblyFormat = "`<` struct(params) `>`";
}

//===----------------------------------------------------------------------===//
// ModuleFlagAttr
//===----------------------------------------------------------------------===//

def ModuleFlagAttr
: LLVM_Attr<"ModuleFlag", "mlir.module_flag"> {
let summary = "LLVM module flag metadata";
let description = [{
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).

Example:
```mlir
#llvm.mlir.module_flag<error, "wchar_size", 4>
```
}];
let parameters = (ins "ModFlagBehavior":$behavior,
"StringAttr":$key,
"uint32_t":$value);
let assemblyFormat = "`<` $behavior `,` $key `,` $value `>`";
}

#endif // LLVMIR_ATTRDEFS
1 change: 1 addition & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def LLVM_Dialect : Dialect {
static StringRef getAliasScopesAttrName() { return "alias_scopes"; }
static StringRef getAccessGroupsAttrName() { return "access_groups"; }
static StringRef getIdentAttrName() { return "llvm.ident"; }
static StringRef getModuleFlags() { return "llvm.module.flags"; }
static StringRef getCommandlineAttrName() { return "llvm.commandline"; }

/// Names of llvm parameter attributes.
Expand Down
33 changes: 33 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
Original file line number Diff line number Diff line change
Expand Up @@ -818,4 +818,37 @@ def FPExceptionBehaviorAttr : LLVM_EnumAttr<
let cppNamespace = "::mlir::LLVM";
}

//===----------------------------------------------------------------------===//
// Module Flag Behavior
//===----------------------------------------------------------------------===//

// These values must match llvm::Module::ModFlagBehavior ones.
// See llvm/include/llvm/IR/Module.h.
def ModFlagBehaviorError
: LLVM_EnumAttrCase<"Error", "error", "Error", 1>;
def ModFlagBehaviorWarning
: LLVM_EnumAttrCase<"Warning", "warning", "Warning", 2>;
def ModFlagBehaviorRequire
: LLVM_EnumAttrCase<"Require", "require", "Require", 3>;
def ModFlagBehaviorOverride
: LLVM_EnumAttrCase<"Override", "override", "Override", 4>;
def ModFlagBehaviorAppend
: LLVM_EnumAttrCase<"Append", "append", "Append", 5>;
def ModFlagBehaviorAppendUnique
: LLVM_EnumAttrCase<"AppendUnique", "append_unique", "AppendUnique", 6>;
def ModFlagBehaviorMax
: LLVM_EnumAttrCase<"Max", "max", "Max", 7>;
def ModFlagBehaviorMin
: LLVM_EnumAttrCase<"Min", "min", "Min", 8>;

def ModFlagBehaviorAttr : LLVM_EnumAttr<
"ModFlagBehavior",
"::llvm::Module::ModFlagBehavior",
"LLVM Module Flag Behavior",
[ModFlagBehaviorError, ModFlagBehaviorWarning, ModFlagBehaviorRequire,
ModFlagBehaviorOverride, ModFlagBehaviorAppend,
ModFlagBehaviorAppendUnique, ModFlagBehaviorMax, ModFlagBehaviorMin]> {
let cppNamespace = "::mlir::LLVM";
}

#endif // LLVMIR_ENUMS
32 changes: 32 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -2183,4 +2183,36 @@ def LLVM_LinkerOptionsOp
let hasVerifier = 1;
}

//===--------------------------------------------------------------------===//
// ModuleFlagsOp
//===--------------------------------------------------------------------===//

def LLVM_ModuleFlagsOp
: LLVM_Op<"module_flags"> {
let summary = "Information about module properties";
let description = [{
Represents the equivalent in MLIR for LLVM's `llvm.module.flags` metadata,
which requires a list of metadata triplets. Each triplet entry is described
by a `ModuleFlagAttr`.

Example:
```mlir
llvm.module.flags [
#llvm.mlir.module_flag<error, "wchar_size", 4>,
#llvm.mlir.module_flag<max, "PIC Level", 2>
]
```
}];
let arguments = (ins ArrayAttr:$flags);
let assemblyFormat = [{
$flags attr-dict
}];

let llvmBuilder = [{
convertModuleFlagsOp($flags, builder, moduleTranslation);
}];

let hasVerifier = 1;
}

#endif // LLVMIR_OPS
3 changes: 3 additions & 0 deletions mlir/include/mlir/Target/LLVMIR/ModuleImport.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ class ModuleImport {
/// LLVM dialect operation.
LogicalResult convertLinkerOptionsMetadata();

/// Converts !llvm.module.flags metadata.
LogicalResult convertModuleFlagsMetadata();

/// Converts !llvm.ident metadata to the llvm.ident LLVM ModuleOp attribute.
LogicalResult convertIdentMetadata();

Expand Down
14 changes: 14 additions & 0 deletions mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3712,6 +3712,20 @@ LogicalResult LinkerOptionsOp::verify() {
return success();
}

//===----------------------------------------------------------------------===//
// ModuleFlagsOp
//===----------------------------------------------------------------------===//

LogicalResult ModuleFlagsOp::verify() {
if (Operation *parentOp = (*this)->getParentOp();
parentOp && !satisfiesLLVMModule(parentOp))
return emitOpError("must appear at the module level");
for (Attribute flag : getFlags())
if (!isa<ModuleFlagAttr>(flag))
return emitOpError("expected a module flag attribute");
return success();
}

//===----------------------------------------------------------------------===//
// InlineAsmOp
//===----------------------------------------------------------------------===//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,15 @@ static void convertLinkerOptionsOp(ArrayAttr options,
linkerMDNode->addOperand(listMDNode);
}

static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
LLVM::ModuleTranslation &moduleTranslation) {
llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>())
llvmModule->addModuleFlag(
convertModFlagBehaviorToLLVM(flagAttr.getBehavior()),
flagAttr.getKey().getValue(), flagAttr.getValue());
}

static LogicalResult
convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
LLVM::ModuleTranslation &moduleTranslation) {
Expand Down
29 changes: 29 additions & 0 deletions mlir/lib/Target/LLVMIR/ModuleImport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,33 @@ void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) {
debugIntrinsics.insert(intrinsic);
}

LogicalResult ModuleImport::convertModuleFlagsMetadata() {
SmallVector<llvm::Module::ModuleFlagEntry> llvmModuleFlags;
llvmModule->getModuleFlagsMetadata(llvmModuleFlags);

SmallVector<Attribute> moduleFlags;
for (const auto [behavior, key, val] : llvmModuleFlags) {
// Currently only supports most common: int constant values.
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val);
if (!constInt) {
emitWarning(mlirModule.getLoc())
<< "unsupported module flag value: " << diagMD(val, llvmModule.get())
<< ", only constant integer currently supported";
continue;
}

moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
convertModFlagBehaviorFromLLVM(behavior),
builder.getStringAttr(key->getString()), constInt->getZExtValue()));
}

if (!moduleFlags.empty())
builder.create<LLVM::ModuleFlagsOp>(mlirModule.getLoc(),
builder.getArrayAttr(moduleFlags));

return success();
}

LogicalResult ModuleImport::convertLinkerOptionsMetadata() {
for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
if (named.getName() != "llvm.linker.options")
Expand Down Expand Up @@ -596,6 +623,8 @@ LogicalResult ModuleImport::convertMetadata() {
}
if (failed(convertLinkerOptionsMetadata()))
return failure();
if (failed(convertModuleFlagsMetadata()))
return failure();
if (failed(convertIdentMetadata()))
return failure();
if (failed(convertCommandlineMetadata()))
Expand Down
7 changes: 7 additions & 0 deletions mlir/test/Dialect/LLVMIR/invalid.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -1764,3 +1764,10 @@ llvm.mlir.alias external @y5 : i32 {
llvm.return %0 : !llvm.ptr<4>
}

// -----

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<error, "wchar_size", "yolo">]
}
16 changes: 16 additions & 0 deletions mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: mlir-opt %s | mlir-opt | FileCheck %s

module {
llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4>,
#llvm.mlir.module_flag<min, "PIC Level", 2>,
#llvm.mlir.module_flag<max, "PIE Level", 2>,
#llvm.mlir.module_flag<max, "uwtable", 2>,
#llvm.mlir.module_flag<max, "frame-pointer", 1>]
}

// CHECK: llvm.module_flags [
// CHECK-SAME: #llvm.mlir.module_flag<error, "wchar_size", 4>,
// CHECK-SAME: #llvm.mlir.module_flag<min, "PIC Level", 2>,
// CHECK-SAME: #llvm.mlir.module_flag<max, "PIE Level", 2>,
// CHECK-SAME: #llvm.mlir.module_flag<max, "uwtable", 2>,
// CHECK-SAME: #llvm.mlir.module_flag<max, "frame-pointer", 1>]
25 changes: 25 additions & 0 deletions mlir/test/Target/LLVMIR/Import/module-flags.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; RUN: mlir-translate -import-llvm -split-input-file -verify-diagnostics %s | FileCheck %s

!llvm.module.flags = !{!0, !1, !2, !3, !4}

!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}

; CHECK-LABEL: module attributes {{.*}} {
; CHECK: llvm.module_flags [
; CHECK-SAME: #llvm.mlir.module_flag<error, "wchar_size", 4>,
; CHECK-SAME: #llvm.mlir.module_flag<min, "PIC Level", 2>,
; CHECK-SAME: #llvm.mlir.module_flag<max, "PIE Level", 2>,
; CHECK-SAME: #llvm.mlir.module_flag<max, "uwtable", 2>,
; CHECK-SAME: #llvm.mlir.module_flag<max, "frame-pointer", 1>]
; CHECK: }

; // -----

!llvm.module.flags = !{!0}

; expected-warning@-5{{unsupported module flag value: !"yolo_more", only constant integer currently supported}}
!0 = !{i32 1, !"yolo", !"yolo_more"}
14 changes: 14 additions & 0 deletions mlir/test/Target/LLVMIR/llvmir-invalid.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,20 @@ llvm.func @foo() {

// -----

llvm.func @foo() {
// expected-error @below{{must appear at the module level}}
llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4>]
}

// -----

module attributes {} {
// expected-error @below{{expected a module flag attribute}}
llvm.module_flags [4 : i32]
}

// -----

module @does_not_exist {
// expected-error @below{{resource does not exist}}
llvm.mlir.global internal constant @constant(dense_resource<test0> : tensor<4xf32>) : !llvm.array<4 x f32>
Expand Down
19 changes: 19 additions & 0 deletions mlir/test/Target/LLVMIR/llvmir.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -2763,3 +2763,22 @@ llvm.func @call_intrin_with_opbundle(%arg0 : !llvm.ptr) {
// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr %0, i32 16) ]
// CHECK-NEXT: ret void
// CHECK-NEXT: }

// -----

module {
llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4>,
#llvm.mlir.module_flag<min, "PIC Level", 2>,
#llvm.mlir.module_flag<max, "PIE Level", 2>,
#llvm.mlir.module_flag<max, "uwtable", 2>,
#llvm.mlir.module_flag<max, "frame-pointer", 1>]
}

// CHECK: !llvm.module.flags = !{![[#DBG:]], ![[#WCHAR:]], ![[#PIC:]], ![[#PIE:]], ![[#UWTABLE:]], ![[#FrameP:]]}

// CHECK: ![[#DBG]] = !{i32 2, !"Debug Info Version", i32 3}
// CHECK: ![[#WCHAR]] = !{i32 1, !"wchar_size", i32 4}
// CHECK: ![[#PIC]] = !{i32 8, !"PIC Level", i32 2}
// CHECK: ![[#PIE]] = !{i32 7, !"PIE Level", i32 2}
// CHECK: ![[#UWTABLE]] = !{i32 7, !"uwtable", i32 2}
// CHECK: ![[#FrameP]] = !{i32 7, !"frame-pointer", i32 1}
2 changes: 2 additions & 0 deletions mlir/test/mlir-translate/split-markers.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
// CHECK-OUTPUT-NEXT: ModuleID

// CHECK-ROUNDTRIP: module {{.*}} {
// FIXME: importer forces debug info version even without importing one.
// CHECK-ROUNDTRIP-NEXT: llvm.module_flag
// CHECK-ROUNDTRIP-NEXT: }
// CHECK-ROUNDTRIP-EMPTY:
// CHECK-ROUNDTRIP: module
Expand Down