Files
clang-p2996/mlir/test/python/ir/exception.py
Rahul Kayaith 3ea4c5014d [mlir][python] Capture error diagnostics in exceptions
This updates most (all?) error-diagnostic-emitting python APIs to
capture error diagnostics and include them in the raised exception's
message:
```
>>> Operation.parse('"arith.addi"() : () -> ()'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
mlir._mlir_libs.MLIRError: Unable to parse operation assembly:
error: "-":1:1: 'arith.addi' op requires one result
 note: "-":1:1: see current operation: "arith.addi"() : () -> ()
```

The diagnostic information is available on the exception for users who
may want to customize the error message:
```
>>> try:
...   Operation.parse('"arith.addi"() : () -> ()')
... except MLIRError as e:
...   print(e.message)
...   print(e.error_diagnostics)
...   print(e.error_diagnostics[0].message)
...
Unable to parse operation assembly
[<mlir._mlir_libs._mlir.ir.DiagnosticInfo object at 0x7fed32bd6b70>]
'arith.addi' op requires one result
```

Error diagnostics captured in exceptions aren't propagated to diagnostic
handlers, to avoid double-reporting of errors. The context-level
`emit_error_diagnostics` option can be used to revert to the old
behaviour, causing error diagnostics to be reported to handlers instead
of as part of exceptions.

API changes:
- `Operation.verify` now raises an exception on verification failure,
  instead of returning `false`
- The exception raised by the following methods has been changed to
  `MLIRError`:
  - `PassManager.run`
  - `{Module,Operation,Type,Attribute}.parse`
  - `{RankedTensorType,UnrankedTensorType}.get`
  - `{MemRefType,UnrankedMemRefType}.get`
  - `VectorType.get`
  - `FloatAttr.get`

closes #60595

depends on D144804, D143830

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D143869
2023-03-07 14:59:22 -05:00

78 lines
2.6 KiB
Python

# RUN: %PYTHON %s | FileCheck %s
import gc
from mlir.ir import *
def run(f):
print("\nTEST:", f.__name__)
f()
gc.collect()
assert Context._get_live_count() == 0
return f
# CHECK-LABEL: TEST: test_exception
@run
def test_exception():
ctx = Context()
ctx.allow_unregistered_dialects = True
try:
Operation.parse("""
func.func @foo() {
"test.use"(%0) : (i64) -> () loc("use")
%0 = "test.def"() : () -> i64 loc("def")
return
}
""", context=ctx)
except MLIRError as e:
# CHECK: Exception: <
# CHECK: Unable to parse operation assembly:
# CHECK: error: "use": operand #0 does not dominate this use
# CHECK: note: "use": see current operation: "test.use"(%0) : (i64) -> ()
# CHECK: note: "def": operand defined here (op in the same block)
# CHECK: >
print(f"Exception: <{e}>")
# CHECK: message: Unable to parse operation assembly
print(f"message: {e.message}")
# CHECK: error_diagnostics[0]: loc("use") operand #0 does not dominate this use
# CHECK: error_diagnostics[0].notes[0]: loc("use") see current operation: "test.use"(%0) : (i64) -> ()
# CHECK: error_diagnostics[0].notes[1]: loc("def") operand defined here (op in the same block)
print("error_diagnostics[0]: ", e.error_diagnostics[0].location, e.error_diagnostics[0].message)
print("error_diagnostics[0].notes[0]: ", e.error_diagnostics[0].notes[0].location, e.error_diagnostics[0].notes[0].message)
print("error_diagnostics[0].notes[1]: ", e.error_diagnostics[0].notes[1].location, e.error_diagnostics[0].notes[1].message)
# CHECK-LABEL: test_emit_error_diagnostics
@run
def test_emit_error_diagnostics():
ctx = Context()
loc = Location.unknown(ctx)
handler_diags = []
def handler(d):
handler_diags.append(str(d))
return True
ctx.attach_diagnostic_handler(handler)
try:
Attribute.parse("not an attr", ctx)
except MLIRError as e:
# CHECK: emit_error_diagnostics=False:
# CHECK: e.error_diagnostics: ['expected attribute value']
# CHECK: handler_diags: []
print(f"emit_error_diagnostics=False:")
print(f"e.error_diagnostics: {[str(diag) for diag in e.error_diagnostics]}")
print(f"handler_diags: {handler_diags}")
ctx.emit_error_diagnostics = True
try:
Attribute.parse("not an attr", ctx)
except MLIRError as e:
# CHECK: emit_error_diagnostics=True:
# CHECK: e.error_diagnostics: []
# CHECK: handler_diags: ['expected attribute value']
print(f"emit_error_diagnostics=True:")
print(f"e.error_diagnostics: {[str(diag) for diag in e.error_diagnostics]}")
print(f"handler_diags: {handler_diags}")