Skip to content

Commit cec96ce

Browse files
committed
[MLIR][LLVMIR] Add module flags support
Import and translation support. Note that existing support (prior to this PR) already covers enough in translation specifically to emit "Debug Info Version". Also, the debug info version metadata is being emitted even though the imported IR has no information and is showing up in some tests (will fix that in another PR).
1 parent cb3ce30 commit cec96ce

File tree

13 files changed

+246
-0
lines changed

13 files changed

+246
-0
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,4 +1267,30 @@ def WorkgroupAttributionAttr
12671267
let assemblyFormat = "`<` $num_elements `,` $element_type `>`";
12681268
}
12691269

1270+
//===----------------------------------------------------------------------===//
1271+
// ModuleFlagAttr
1272+
//===----------------------------------------------------------------------===//
1273+
1274+
def ModuleFlagAttr
1275+
: LLVM_Attr<"ModuleFlag", "mlir.module_flag"> {
1276+
let summary = "LLVM module flag metadata";
1277+
let description = [{
1278+
Represents a single entry of llvm.module.flags metadata
1279+
(llvm::Module::ModuleFlagEntry in LLVM). The first element is a behavior
1280+
flag described by `ModFlagBehaviorAttr`, the second is a string ID
1281+
and third is the value of the flag (currently only integer constant
1282+
supported).
1283+
1284+
Example:
1285+
```mlir
1286+
#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>
1287+
]
1288+
```
1289+
}];
1290+
let parameters = (ins "ModFlagBehaviorAttr":$behavior,
1291+
"StringAttr":$key,
1292+
"IntegerAttr":$value);
1293+
let assemblyFormat = "`<` $behavior `,` $key `,` $value `>`";
1294+
}
1295+
12701296
#endif // LLVMIR_ATTRDEFS

mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def LLVM_Dialect : Dialect {
3333
static StringRef getAliasScopesAttrName() { return "alias_scopes"; }
3434
static StringRef getAccessGroupsAttrName() { return "access_groups"; }
3535
static StringRef getIdentAttrName() { return "llvm.ident"; }
36+
static StringRef getModuleFlags() { return "llvm.module.flags"; }
3637
static StringRef getCommandlineAttrName() { return "llvm.commandline"; }
3738

3839
/// Names of llvm parameter attributes.

mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,4 +818,37 @@ def FPExceptionBehaviorAttr : LLVM_EnumAttr<
818818
let cppNamespace = "::mlir::LLVM";
819819
}
820820

821+
//===----------------------------------------------------------------------===//
822+
// Module Flag Behavior
823+
//===----------------------------------------------------------------------===//
824+
825+
// These values must match llvm::Module::ModFlagBehavior ones.
826+
// See llvm/include/llvm/IR/Module.h.
827+
def ModFlagBehaviorError
828+
: LLVM_EnumAttrCase<"Error", "error", "Error", 1>;
829+
def ModFlagBehaviorWarning
830+
: LLVM_EnumAttrCase<"Warning", "warning", "Warning", 2>;
831+
def ModFlagBehaviorRequire
832+
: LLVM_EnumAttrCase<"Require", "require", "Require", 3>;
833+
def ModFlagBehaviorOverride
834+
: LLVM_EnumAttrCase<"Override", "override", "Override", 4>;
835+
def ModFlagBehaviorAppend
836+
: LLVM_EnumAttrCase<"Append", "append", "Append", 5>;
837+
def ModFlagBehaviorAppendUnique
838+
: LLVM_EnumAttrCase<"AppendUnique", "append_unique", "AppendUnique", 6>;
839+
def ModFlagBehaviorMax
840+
: LLVM_EnumAttrCase<"Max", "max", "Max", 7>;
841+
def ModFlagBehaviorMin
842+
: LLVM_EnumAttrCase<"Min", "min", "Min", 8>;
843+
844+
def ModFlagBehaviorAttr : LLVM_EnumAttr<
845+
"ModFlagBehavior",
846+
"::llvm::Module::ModFlagBehavior",
847+
"LLVM Module Flag Behavior",
848+
[ModFlagBehaviorError, ModFlagBehaviorWarning, ModFlagBehaviorRequire,
849+
ModFlagBehaviorOverride, ModFlagBehaviorAppend,
850+
ModFlagBehaviorAppendUnique, ModFlagBehaviorMax, ModFlagBehaviorMin]> {
851+
let cppNamespace = "::mlir::LLVM";
852+
}
853+
821854
#endif // LLVMIR_ENUMS

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,4 +2155,36 @@ def LLVM_LinkerOptionsOp
21552155
let hasVerifier = 1;
21562156
}
21572157

2158+
//===--------------------------------------------------------------------===//
2159+
// ModuleFlagsOp
2160+
//===--------------------------------------------------------------------===//
2161+
2162+
def LLVM_ModuleFlagsOp
2163+
: LLVM_Op<"module_flags"> {
2164+
let summary = "Information about module properties";
2165+
let description = [{
2166+
Represents the equivalent in MLIR for LLVM's `llvm.module.flags` metadata,
2167+
which requires a list of metadata triplets. Each triplet entry is described
2168+
by a `ModuleFlagAttr`.
2169+
2170+
Example:
2171+
```mlir
2172+
llvm.module.flags [
2173+
#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
2174+
#llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>
2175+
]
2176+
```
2177+
}];
2178+
let arguments = (ins ArrayAttr:$flags);
2179+
let assemblyFormat = [{
2180+
$flags attr-dict
2181+
}];
2182+
2183+
let llvmBuilder = [{
2184+
convertModuleFlagsOp($flags, builder, moduleTranslation);
2185+
}];
2186+
2187+
let hasVerifier = 1;
2188+
}
2189+
21582190
#endif // LLVMIR_OPS

mlir/include/mlir/Target/LLVMIR/ModuleImport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,10 @@ class ModuleImport {
218218
/// LLVM dialect operation.
219219
LogicalResult convertLinkerOptionsMetadata();
220220

221+
/// Converts !llvm.module.flags metadata to the XYZ
222+
/// LLVM dialect operation.
223+
LogicalResult convertModuleFlagsMetadata();
224+
221225
/// Converts !llvm.ident metadata to the llvm.ident LLVM ModuleOp attribute.
222226
LogicalResult convertIdentMetadata();
223227

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3711,6 +3711,21 @@ LogicalResult LinkerOptionsOp::verify() {
37113711
return success();
37123712
}
37133713

3714+
//===----------------------------------------------------------------------===//
3715+
// ModuleFlagsOp
3716+
//===----------------------------------------------------------------------===//
3717+
3718+
LogicalResult ModuleFlagsOp::verify() {
3719+
if (mlir::Operation *parentOp = (*this)->getParentOp();
3720+
parentOp && !satisfiesLLVMModule(parentOp))
3721+
return emitOpError("must appear at the module level");
3722+
for (auto &flag : getFlags()) {
3723+
if (!isa<ModuleFlagAttr>(flag))
3724+
return emitOpError("expected a module flag attribute");
3725+
}
3726+
return success();
3727+
}
3728+
37143729
//===----------------------------------------------------------------------===//
37153730
// InlineAsmOp
37163731
//===----------------------------------------------------------------------===//

mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,19 @@ static void convertLinkerOptionsOp(ArrayAttr options,
270270
linkerMDNode->addOperand(listMDNode);
271271
}
272272

273+
static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
274+
LLVM::ModuleTranslation &moduleTranslation) {
275+
llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
276+
for (Attribute attr : flags) {
277+
auto flag = cast<ModuleFlagAttr>(attr);
278+
auto intVal = dyn_cast<IntegerAttr>(flag.getValue());
279+
assert(intVal && "expected integer attribute");
280+
llvmModule->addModuleFlag(
281+
(llvm::Module::ModFlagBehavior)flag.getBehavior().getValue(),
282+
flag.getKey().getValue(), (uint32_t)intVal.getUInt());
283+
}
284+
}
285+
273286
static LogicalResult
274287
convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
275288
LLVM::ModuleTranslation &moduleTranslation) {

mlir/lib/Target/LLVMIR/ModuleImport.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,45 @@ void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) {
517517
debugIntrinsics.insert(intrinsic);
518518
}
519519

520+
LogicalResult ModuleImport::convertModuleFlagsMetadata() {
521+
SmallVector<llvm::Module::ModuleFlagEntry, 4> llvmModuleFlags;
522+
for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
523+
if (named.getName() != LLVMDialect::getModuleFlags())
524+
continue;
525+
llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
526+
break; // there can only be one module flags.
527+
}
528+
529+
SmallVector<Attribute, 4> moduleFlags;
530+
for (const auto [behavior, key, val] : llvmModuleFlags) {
531+
// Currently only supports most common: int constant values.
532+
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val);
533+
if (!constInt) {
534+
return emitWarning(mlirModule.getLoc())
535+
<< "unsupported module flag value: "
536+
<< diagMD(val, llvmModule.get())
537+
<< ", only constant integer currently supported";
538+
}
539+
auto valAttr = builder.getIntegerAttr(
540+
IntegerType::get(context, constInt->getType()->getIntegerBitWidth()),
541+
constInt->getValue());
542+
543+
ModFlagBehaviorAttr behaviorAttr = ModFlagBehaviorAttr::get(
544+
builder.getContext(), (ModFlagBehavior)behavior);
545+
546+
moduleFlags.push_back(
547+
ModuleFlagAttr::get(builder.getContext(), behaviorAttr,
548+
builder.getStringAttr(key->getString()), valAttr));
549+
}
550+
551+
if (!moduleFlags.empty()) {
552+
builder.create<LLVM::ModuleFlagsOp>(mlirModule.getLoc(),
553+
builder.getArrayAttr(moduleFlags));
554+
}
555+
556+
return success();
557+
}
558+
520559
LogicalResult ModuleImport::convertLinkerOptionsMetadata() {
521560
for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
522561
if (named.getName() != "llvm.linker.options")
@@ -596,6 +635,8 @@ LogicalResult ModuleImport::convertMetadata() {
596635
}
597636
if (failed(convertLinkerOptionsMetadata()))
598637
return failure();
638+
if (failed(convertModuleFlagsMetadata()))
639+
return failure();
599640
if (failed(convertIdentMetadata()))
600641
return failure();
601642
if (failed(convertCommandlineMetadata()))

mlir/test/Dialect/LLVMIR/invalid.mlir

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,3 +1764,10 @@ llvm.mlir.alias external @y5 : i32 {
17641764
llvm.return %0 : !llvm.ptr<4>
17651765
}
17661766

1767+
// -----
1768+
1769+
module {
1770+
// expected-error@+2 {{invalid kind of attribute specified}}
1771+
// expected-error@+1 {{failed to parse ModuleFlagAttr parameter 'value' which is to be a `IntegerAttr`}}
1772+
llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", "yolo">]
1773+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: mlir-opt %s | mlir-opt | FileCheck %s
2+
3+
module {
4+
llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
5+
#llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
6+
#llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
7+
#llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
8+
#llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
9+
}
10+
11+
// CHECK: llvm.module_flags [
12+
// CHECK-SAME: #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
13+
// CHECK-SAME: #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
14+
// CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
15+
// CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
16+
// CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]

0 commit comments

Comments
 (0)