This is an archive of the discontinued LLVM Phabricator instance.

[mlir][python] Add bindings for diagnostic handler.
ClosedPublic

Authored by stellaraccident on Jan 3 2022, 4:45 PM.

Details

Summary

I considered multiple approaches for this but settled on this one because I could make the lifetime management work in a reasonably easy way (others had issues with not being able to cast to a Python reference from a C++ constructor). We could stand to have more formatting helpers, but best to get the core mechanism in first.

Diff Detail

Event Timeline

stellaraccident created this revision.Jan 3 2022, 4:45 PM
stellaraccident requested review of this revision.Jan 3 2022, 4:45 PM

Update type metadata.

mehdi_amini added inline comments.Jan 3 2022, 8:26 PM
mlir/lib/Bindings/Python/IRModule.h
336

When are the contextEnter and contextExit method called?

stellaraccident added inline comments.Jan 3 2022, 9:01 PM
mlir/lib/Bindings/Python/IRModule.h
336

They are bound to __enter__ and __exit__ to enable use as a context manager. We do similar naming elsewhere in this module.

mehdi_amini accepted this revision.Jan 3 2022, 9:05 PM

I'd rather wait for @ftynse to have a look as well, I think I understand everything in this patch, but this in the realm of "I wouldn't be able to write this myself" ;)

mlir/lib/Bindings/Python/IRModule.h
336

Right, I wasn't clear, I should have asked: "when is this class used as a context manager?"

But I figured in the meantime by reading the test, so it's fine :)

This revision is now accepted and ready to land.Jan 3 2022, 9:05 PM

I'd rather wait for @ftynse to have a look as well, I think I understand everything in this patch, but this in the realm of "I wouldn't be able to write this myself" ;)

No problem at all getting another set of eyes... I've been needing/dreading this for the past year. A few more days makes no difference :)

re: "I wouldn't be able to write this myself" - I'm sure you could if sufficiently motivated.

For Alex, the primary alternative design I considered/tried was having the DiagnosticHandler be a free-standing class that auto attached on construction like:

with Context(), DiagnosticHandler(callback):
  # do stuff

Trying to make this work ran into all kinds of undocumented and surprising pybind behavior, since you need to get access to the py::object from within the scope of the py::init<> function (so that you can borrow against the python reference count). I couldn't come up with a way to make ownership transfer properly in that situation. I don't expect this is going to be one of those everyday things for people to be doing and opted for a simpler implementation. My hope is that we layer some kind of exception handler thing on top of this so that I can do something like:

with CaptureDiagnostics() as diag_cap:
  # run passes and do stuff
  # If we exit the with exceptionally, then raise a chained exception that includes any diagnostics.

# If we exit successfully:
print(diag_cap.diagnostics)

(or something like that -- need to fiddle with it, and this can be written in pure Python atop this basic facility)

ftynse accepted this revision.Jan 4 2022, 10:41 AM

LGTM! I agree that it's better to write nicer APIs directly in Python, debugging Pybind glue is hard.

mlir/lib/Bindings/Python/IRCore.cpp
515

Nit: this could use a comment that the Python will free the newed object during its GC sweep because of ownership transfer below.

mlir/test/python/ir/diagnostic_handler.py
75

An optional kwargs notes? As in loc.emit_error("foo", notes=[loc.error_note("bar"), other_loc.error_note("qux")]) ?

mlir/test/python/ir/diagnostic_handler.py
75

Yes, something like that. Will need more C-APIs (and more Python), which was further than I wanted to go in this patch.

This revision was landed with ongoing or failed builds.Jan 4 2022, 11:12 AM
This revision was automatically updated to reflect the committed changes.