Skip to content

Commit e646642

Browse files
[MLIR][LLVM] Allow strings in module flag value (llvm#136793)
Expand support a bit beyond integers. Next step is to support more complex metadata values (e.g. !"CG Profile" and !"ProfileSummary"), but that's a bit more complex and deserves it own PR.
1 parent 0975c09 commit e646642

File tree

8 files changed

+78
-42
lines changed

8 files changed

+78
-42
lines changed

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,18 +1332,21 @@ def ModuleFlagAttr
13321332
Represents a single entry of llvm.module.flags metadata
13331333
(llvm::Module::ModuleFlagEntry in LLVM). The first element is a behavior
13341334
flag described by `ModFlagBehaviorAttr`, the second is a string ID
1335-
and third is the value of the flag (currently only integer constants
1336-
are supported).
1335+
and third is the value of the flag. Current supported types of values:
1336+
- Integer constants
1337+
- Strings
13371338

13381339
Example:
13391340
```mlir
13401341
#llvm.mlir.module_flag<error, "wchar_size", 4>
1342+
#llvm.mlir.module_flag<error, "probe-stack", "inline-asm">
13411343
```
13421344
}];
13431345
let parameters = (ins "ModFlagBehavior":$behavior,
13441346
"StringAttr":$key,
1345-
"uint32_t":$value);
1347+
"Attribute":$value);
13461348
let assemblyFormat = "`<` $behavior `,` $key `,` $value `>`";
1349+
let genVerifyDecl = 1;
13471350
}
13481351

13491352
//===----------------------------------------------------------------------===//

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,3 +375,13 @@ TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
375375
return parentFunction.getOperation()->getAttrOfType<TargetFeaturesAttr>(
376376
getAttributeName());
377377
}
378+
379+
LogicalResult
380+
ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
381+
LLVM::ModFlagBehavior flagBehavior, StringAttr key,
382+
Attribute value) {
383+
if (!isa<IntegerAttr, StringAttr>(value))
384+
return emitError()
385+
<< "only integer and string values are currently supported";
386+
return success();
387+
}

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "mlir/Support/LLVM.h"
1717
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
1818

19+
#include "llvm/ADT/TypeSwitch.h"
1920
#include "llvm/IR/IRBuilder.h"
2021
#include "llvm/IR/InlineAsm.h"
2122
#include "llvm/IR/MDBuilder.h"
@@ -273,10 +274,25 @@ static void convertLinkerOptionsOp(ArrayAttr options,
273274
static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
274275
LLVM::ModuleTranslation &moduleTranslation) {
275276
llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
276-
for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>())
277+
for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>()) {
278+
llvm::Metadata *valueMetadata =
279+
llvm::TypeSwitch<Attribute, llvm::Metadata *>(flagAttr.getValue())
280+
.Case<StringAttr>([&](auto strAttr) {
281+
return llvm::MDString::get(builder.getContext(),
282+
strAttr.getValue());
283+
})
284+
.Case<IntegerAttr>([&](auto intAttr) {
285+
return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
286+
llvm::Type::getInt32Ty(builder.getContext()),
287+
intAttr.getInt()));
288+
})
289+
.Default([](auto) { return nullptr; });
290+
291+
assert(valueMetadata && "expected valid metadata");
277292
llvmModule->addModuleFlag(
278293
convertModFlagBehaviorToLLVM(flagAttr.getBehavior()),
279-
flagAttr.getKey().getValue(), flagAttr.getValue());
294+
flagAttr.getKey().getValue(), valueMetadata);
295+
}
280296
}
281297

282298
static LogicalResult

mlir/lib/Target/LLVMIR/ModuleImport.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -525,18 +525,20 @@ LogicalResult ModuleImport::convertModuleFlagsMetadata() {
525525

526526
SmallVector<Attribute> moduleFlags;
527527
for (const auto [behavior, key, val] : llvmModuleFlags) {
528-
// Currently only supports most common: int constant values.
529-
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val);
530-
if (!constInt) {
528+
Attribute valAttr = nullptr;
529+
if (auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
530+
valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());
531+
} else if (auto *mdString = dyn_cast<llvm::MDString>(val)) {
532+
valAttr = builder.getStringAttr(mdString->getString());
533+
} else {
531534
emitWarning(mlirModule.getLoc())
532-
<< "unsupported module flag value: " << diagMD(val, llvmModule.get())
533-
<< ", only constant integer currently supported";
535+
<< "unsupported module flag value: " << diagMD(val, llvmModule.get());
534536
continue;
535537
}
536538

537539
moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
538540
convertModFlagBehaviorFromLLVM(behavior),
539-
builder.getStringAttr(key->getString()), constInt->getZExtValue()));
541+
builder.getStringAttr(key->getString()), valAttr));
540542
}
541543

542544
if (!moduleFlags.empty())

mlir/test/Dialect/LLVMIR/invalid.mlir

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,9 +1776,10 @@ llvm.mlir.alias external @y5 : i32 {
17761776
// -----
17771777

17781778
module {
1779-
// expected-error@+2 {{expected integer value}}
1780-
// expected-error@+1 {{failed to parse ModuleFlagAttr parameter 'value' which is to be a `uint32_t`}}
1781-
llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", "yolo">]
1779+
llvm.func @foo()
1780+
1781+
// expected-error@below {{only integer and string values are currently supported}}
1782+
llvm.module_flags [#llvm.mlir.module_flag<error, "yolo", @foo>]
17821783
}
17831784

17841785
// -----
Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
// RUN: mlir-opt %s | mlir-opt | FileCheck %s
22

33
module {
4-
llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4>,
5-
#llvm.mlir.module_flag<min, "PIC Level", 2>,
6-
#llvm.mlir.module_flag<max, "PIE Level", 2>,
7-
#llvm.mlir.module_flag<max, "uwtable", 2>,
8-
#llvm.mlir.module_flag<max, "frame-pointer", 1>]
4+
llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4 : i32>,
5+
#llvm.mlir.module_flag<min, "PIC Level", 2 : i32>,
6+
#llvm.mlir.module_flag<max, "PIE Level", 2 : i32>,
7+
#llvm.mlir.module_flag<max, "uwtable", 2 : i32>,
8+
#llvm.mlir.module_flag<max, "frame-pointer", 1 : i32>,
9+
#llvm.mlir.module_flag<override, "probe-stack", "inline-asm">]
910
}
1011

1112
// CHECK: llvm.module_flags [
12-
// CHECK-SAME: #llvm.mlir.module_flag<error, "wchar_size", 4>,
13-
// CHECK-SAME: #llvm.mlir.module_flag<min, "PIC Level", 2>,
14-
// CHECK-SAME: #llvm.mlir.module_flag<max, "PIE Level", 2>,
15-
// CHECK-SAME: #llvm.mlir.module_flag<max, "uwtable", 2>,
16-
// CHECK-SAME: #llvm.mlir.module_flag<max, "frame-pointer", 1>]
13+
// CHECK-SAME: #llvm.mlir.module_flag<error, "wchar_size", 4 : i32>,
14+
// CHECK-SAME: #llvm.mlir.module_flag<min, "PIC Level", 2 : i32>,
15+
// CHECK-SAME: #llvm.mlir.module_flag<max, "PIE Level", 2 : i32>,
16+
// CHECK-SAME: #llvm.mlir.module_flag<max, "uwtable", 2 : i32>,
17+
// CHECK-SAME: #llvm.mlir.module_flag<max, "frame-pointer", 1 : i32>,
18+
// CHECK-SAME: #llvm.mlir.module_flag<override, "probe-stack", "inline-asm">]
Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
; RUN: mlir-translate -import-llvm -split-input-file -verify-diagnostics %s | FileCheck %s
22

3-
!llvm.module.flags = !{!0, !1, !2, !3, !4}
3+
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
44

55
!0 = !{i32 1, !"wchar_size", i32 4}
66
!1 = !{i32 8, !"PIC Level", i32 2}
77
!2 = !{i32 7, !"PIE Level", i32 2}
88
!3 = !{i32 7, !"uwtable", i32 2}
99
!4 = !{i32 7, !"frame-pointer", i32 1}
10+
!5 = !{i32 4, !"probe-stack", !"inline-asm"}
1011

1112
; CHECK-LABEL: module attributes {{.*}} {
1213
; CHECK: llvm.module_flags [
13-
; CHECK-SAME: #llvm.mlir.module_flag<error, "wchar_size", 4>,
14-
; CHECK-SAME: #llvm.mlir.module_flag<min, "PIC Level", 2>,
15-
; CHECK-SAME: #llvm.mlir.module_flag<max, "PIE Level", 2>,
16-
; CHECK-SAME: #llvm.mlir.module_flag<max, "uwtable", 2>,
17-
; CHECK-SAME: #llvm.mlir.module_flag<max, "frame-pointer", 1>]
18-
; CHECK: }
14+
; CHECK-SAME: #llvm.mlir.module_flag<error, "wchar_size", 4 : i32>,
15+
; CHECK-SAME: #llvm.mlir.module_flag<min, "PIC Level", 2 : i32>,
16+
; CHECK-SAME: #llvm.mlir.module_flag<max, "PIE Level", 2 : i32>,
17+
; CHECK-SAME: #llvm.mlir.module_flag<max, "uwtable", 2 : i32>,
18+
; CHECK-SAME: #llvm.mlir.module_flag<max, "frame-pointer", 1 : i32>,
19+
; CHECK-SAME: #llvm.mlir.module_flag<override, "probe-stack", "inline-asm">]
1920

2021
; // -----
21-
22-
!llvm.module.flags = !{!0}
23-
24-
; expected-warning@-5{{unsupported module flag value: !"yolo_more", only constant integer currently supported}}
25-
!0 = !{i32 1, !"yolo", !"yolo_more"}
22+
; expected-warning@-2 {{unsupported module flag value: !4 = !{!"foo", i32 1}}}
23+
!10 = !{ i32 1, !"foo", i32 1 }
24+
!11 = !{ i32 4, !"bar", i32 37 }
25+
!12 = !{ i32 2, !"qux", i32 42 }
26+
!13 = !{ i32 3, !"qux", !{ !"foo", i32 1 }}
27+
!llvm.module.flags = !{ !10, !11, !12, !13 }

mlir/test/Target/LLVMIR/llvmir.mlir

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,11 +2809,11 @@ llvm.func @call_intrin_with_opbundle(%arg0 : !llvm.ptr) {
28092809
// -----
28102810

28112811
module {
2812-
llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4>,
2813-
#llvm.mlir.module_flag<min, "PIC Level", 2>,
2814-
#llvm.mlir.module_flag<max, "PIE Level", 2>,
2815-
#llvm.mlir.module_flag<max, "uwtable", 2>,
2816-
#llvm.mlir.module_flag<max, "frame-pointer", 1>]
2812+
llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4 : i32>,
2813+
#llvm.mlir.module_flag<min, "PIC Level", 2 : i32>,
2814+
#llvm.mlir.module_flag<max, "PIE Level", 2 : i32>,
2815+
#llvm.mlir.module_flag<max, "uwtable", 2 : i32>,
2816+
#llvm.mlir.module_flag<max, "frame-pointer", 1 : i32>]
28172817
}
28182818

28192819
// CHECK: !llvm.module.flags = !{![[#WCHAR:]], ![[#PIC:]], ![[#PIE:]], ![[#UWTABLE:]], ![[#FrameP:]], ![[#DBG:]]}
@@ -2830,7 +2830,7 @@ module {
28302830
// Verifies that the debug info version is not added twice, if it's already present initially.
28312831

28322832
module {
2833-
llvm.module_flags [#llvm.mlir.module_flag<warning, "Debug Info Version", 3>]
2833+
llvm.module_flags [#llvm.mlir.module_flag<warning, "Debug Info Version", 3 : i32>]
28342834
}
28352835

28362836
// CHECK: !llvm.module.flags = !{![[#DBG:]]}

0 commit comments

Comments
 (0)