Skip to content

Commit 685fbb5

Browse files
committed
update the docs
1 parent 70d6b56 commit 685fbb5

File tree

2 files changed

+20
-16
lines changed

2 files changed

+20
-16
lines changed

mlir/docs/Bindings/Python.md

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,26 @@ added to an attached operation, they need to be re-parented to the containing
216216
module).
217217

218218
Due to the validity and parenting accounting needs, `PyOperation` is the owner
219-
for regions and blocks and needs to be a top-level type that we can count on not
220-
aliasing. This let's us do things like selectively invalidating instances when
221-
mutations occur without worrying that there is some alias to the same operation
222-
in the hierarchy. Operations are also the only entity that are allowed to be in
223-
a detached state, and they are interned at the context level so that there is
224-
never more than one Python `mlir.ir.Operation` object for a unique
225-
`MlirOperation`, regardless of how it is obtained.
219+
for regions and blocks. Operations are also the only entity that are allowed to be in
220+
a detached state.
221+
222+
**Note**: Multiple `PyOperation` objects (i.e., the Python objects themselves) can alias a single `mlir::Operation`.
223+
This means, for example, if you have `py_op1` and `py_op2` which wrap the same `mlir::Operation op`
224+
and you somehow transform `op` (e.g., you run a pass on `op`) then walking the MLIR AST via either/or `py_op1`, `py_op2`
225+
will reflect the same MLIR AST. This is perfectly safe and supported. What is not supported is invalidating any
226+
operation while there exist multiple Python objects wrapping that operation **and then manipulating those wrappers**.
227+
For example if `py_op1` and `py_op2` wrap the same operation under a root `py_op3` and then `py_op3` is
228+
transformed such that the operation referenced (by `py_op1`, `py_op2`) is erased. Then `py_op1`, `py_op2`
229+
become "undefined" in a sense; manipulating them in any way is "formally forbidden". Note, this also applies to
230+
`SymbolTable` mutation, which is considered a transformation of the root `SymbolTable`-supporting operation for the
231+
purposes of the discussion here. The "best practices" recommendation is to structure your code such that
232+
233+
1. First, query/manipulate various Python wrapper objects `py_op1`, `py_op2`, `py_op3`, etc.;
234+
2. Second, Transform the AST/erase operations/etc. via a single root object;
235+
3. End.
236+
237+
Ideally this should be done in a function body so that "End" corresponds to the end of the function and there are no
238+
risks of Python wrapper objects leaking/living longer than necessary.
226239

227240
The C/C++ API allows for Region/Block to also be detached, but it simplifies the
228241
ownership model a lot to eliminate that possibility in this API, allowing the
@@ -238,11 +251,6 @@ blocks. We may end up needing an op-local one at some point TBD, depending on
238251
how hard it is to guarantee how mutations interact with their Python peer
239252
objects. We can cross that bridge easily when we get there.
240253

241-
Module, when used purely from the Python API, can't alias anyway, so we can use
242-
it as a top-level ref type without a live-list for interning. If the API ever
243-
changes such that this cannot be guaranteed (i.e. by letting you marshal a
244-
native-defined Module in), then there would need to be a live table for it too.
245-
246254
## User-level API
247255

248256
### Context Management

mlir/lib/Bindings/Python/MainModule.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,4 @@ NB_MODULE(_mlir, m) {
139139
auto passModule =
140140
m.def_submodule("passmanager", "MLIR Pass Management Bindings");
141141
populatePassManagerSubmodule(passModule);
142-
143-
m.def("test_raise_exception", []() {
144-
throw std::runtime_error("wtfbbq");
145-
});
146142
}

0 commit comments

Comments
 (0)