Skip to content

Commit 12dba4d

Browse files
authored
[mlir] Add metadata to Diagnostic. (#99398)
Add metadata to Diagnostic. Motivation: we have a use case where we want to do some filtering in our customized Diagnostic Handler based on some customized info that is not `location` or `severity` or `diagnostic arguments` that are member variables of `Diagnostic`. Specifically, we want to add a unique ID to the `Diagnostic` for the handler to filter in a compiler pass that emits errors in async tasks with multithreading and the diagnostic handling is associated to the task. This patch adds a field of `metadata` to `mlir::Diagnostics` as a general solution. `metadata` is of type `SmallVector<DiagnosticArgument, 0>` to save memory size and reuse existing `DiagnosticArgument` for metadata type.
1 parent 9ad92c4 commit 12dba4d

File tree

6 files changed

+104
-1
lines changed

6 files changed

+104
-1
lines changed

mlir/docs/Diagnostics.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,19 @@ InFlightDiagnostic Operation::emitOpError();
7777
## Diagnostic
7878

7979
A `Diagnostic` in MLIR contains all of the necessary information for reporting a
80-
message to the user. A `Diagnostic` essentially boils down to three main
80+
message to the user. A `Diagnostic` essentially boils down to four main
8181
components:
8282

8383
* [Source Location](#source-locations)
8484
* Severity Level
8585
- Error, Note, Remark, Warning
8686
* Diagnostic Arguments
8787
- The diagnostic arguments are used when constructing the output message.
88+
* Metadata
89+
- Some additional information attached that can be used to identify
90+
this diagnostic other than source location and severity level
91+
(e.g. for diagnostic handlers to do some filtering).
92+
Metadata is not part of the output message.
8893

8994
### Appending arguments
9095

@@ -143,6 +148,11 @@ op->emitError("...").attachNote(noteLoc) << "...";
143148
op->emitError("...").attachNote() << "...";
144149
```
145150
151+
### Managing Metadata
152+
Metadata is a mutable vector of DiagnosticArguments.
153+
It can be accessed and modified as a vector.
154+
155+
146156
## InFlight Diagnostic
147157
148158
Now that [Diagnostics](#diagnostic) have been explained, we introduce the

mlir/include/mlir/IR/Diagnostics.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ class Diagnostic {
271271
return failure();
272272
}
273273

274+
/// Returns the current list of diagnostic metadata.
275+
SmallVectorImpl<DiagnosticArgument> &getMetadata() { return metadata; }
276+
274277
private:
275278
Diagnostic(const Diagnostic &rhs) = delete;
276279
Diagnostic &operator=(const Diagnostic &rhs) = delete;
@@ -290,6 +293,9 @@ class Diagnostic {
290293

291294
/// A list of attached notes.
292295
NoteVector notes;
296+
297+
/// A list of metadata attached to this Diagnostic.
298+
SmallVector<DiagnosticArgument, 0> metadata;
293299
};
294300

295301
inline raw_ostream &operator<<(raw_ostream &os, const Diagnostic &diag) {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: mlir-opt %s -pass-pipeline="builtin.module(func.func(test-diagnostic-metadata))" -verify-diagnostics -o - 2>&1 | FileCheck %s
2+
// COM: This test verifies that diagnostic handler can filter the diagnostic based on its metadata
3+
// COM: whether to emit the errors.
4+
5+
// CHECK-LABEL: Test 'test'
6+
func.func @test() {
7+
// expected-error @+1 {{test diagnostic metadata}}
8+
"test.emit_error"() {
9+
// CHECK: attr = "emit_error"
10+
attr = "emit_error"
11+
} : () -> ()
12+
13+
"test.do_not_emit_error"() {
14+
// CHECK: attr = "do_not_emit_error"
15+
attr = "do_not_emit_error"
16+
} : () -> ()
17+
18+
return
19+
}

mlir/test/lib/IR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_mlir_library(MLIRTestIR
66
TestBuiltinDistinctAttributes.cpp
77
TestClone.cpp
88
TestDiagnostics.cpp
9+
TestDiagnosticsMetadata.cpp
910
TestDominance.cpp
1011
TestFunc.cpp
1112
TestInterfaces.cpp
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//===- TestDiagnosticsMetadata.cpp - Test Diagnostic Metatdata ------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains test passes for constructing and resolving dominance
10+
// information.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "mlir/IR/SymbolTable.h"
15+
#include "mlir/Pass/Pass.h"
16+
#include "llvm/Support/SourceMgr.h"
17+
18+
using namespace mlir;
19+
20+
namespace {
21+
struct TestDiagnosticMetadataPass
22+
: public PassWrapper<TestDiagnosticMetadataPass,
23+
InterfacePass<SymbolOpInterface>> {
24+
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestDiagnosticMetadataPass)
25+
26+
StringRef getArgument() const final { return "test-diagnostic-metadata"; }
27+
StringRef getDescription() const final { return "Test diagnostic metadata."; }
28+
TestDiagnosticMetadataPass() = default;
29+
TestDiagnosticMetadataPass(const TestDiagnosticMetadataPass &) {}
30+
31+
void runOnOperation() override {
32+
llvm::errs() << "Test '" << getOperation().getName() << "'\n";
33+
34+
// Build a diagnostic handler that has filtering capabilities.
35+
ScopedDiagnosticHandler handler(&getContext(), [](mlir::Diagnostic &diag) {
36+
return mlir::success(
37+
llvm::none_of(diag.getMetadata(), [](mlir::DiagnosticArgument &arg) {
38+
return arg.getKind() == mlir::DiagnosticArgument::
39+
DiagnosticArgumentKind::String &&
40+
arg.getAsString().contains("hello");
41+
}));
42+
});
43+
44+
// Emit a diagnostic for every operation with a valid loc.
45+
getOperation()->walk([&](Operation *op) {
46+
if (StringAttr strAttr = op->getAttrOfType<StringAttr>("attr")) {
47+
if (strAttr.getValue() == "emit_error")
48+
emitError(op->getLoc(), "test diagnostic metadata")
49+
.getUnderlyingDiagnostic()
50+
->getMetadata()
51+
.push_back(DiagnosticArgument("hello"));
52+
}
53+
});
54+
}
55+
};
56+
57+
} // namespace
58+
59+
namespace mlir {
60+
namespace test {
61+
void registerTestDiagnosticsMetadataPass() {
62+
PassRegistration<TestDiagnosticMetadataPass>{};
63+
}
64+
} // namespace test
65+
} // namespace mlir

mlir/tools/mlir-opt/mlir-opt.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ void registerTestDataLayoutQuery();
9292
void registerTestDeadCodeAnalysisPass();
9393
void registerTestDecomposeCallGraphTypes();
9494
void registerTestDiagnosticsPass();
95+
void registerTestDiagnosticsMetadataPass();
9596
void registerTestDominancePass();
9697
void registerTestDynamicPipelinePass();
9798
void registerTestEmulateNarrowTypePass();
@@ -226,6 +227,7 @@ void registerTestPasses() {
226227
mlir::test::registerTestDeadCodeAnalysisPass();
227228
mlir::test::registerTestDecomposeCallGraphTypes();
228229
mlir::test::registerTestDiagnosticsPass();
230+
mlir::test::registerTestDiagnosticsMetadataPass();
229231
mlir::test::registerTestDominancePass();
230232
mlir::test::registerTestDynamicPipelinePass();
231233
mlir::test::registerTestEmulateNarrowTypePass();

0 commit comments

Comments
 (0)