MLIR  17.0.0git
IRModule.h
Go to the documentation of this file.
1 //===- IRModules.h - IR Submodules of pybind module -----------------------===//
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 #ifndef MLIR_BINDINGS_PYTHON_IRMODULES_H
10 #define MLIR_BINDINGS_PYTHON_IRMODULES_H
11 
12 #include <optional>
13 #include <utility>
14 #include <vector>
15 
16 #include "PybindUtils.h"
17 
18 #include "mlir-c/AffineExpr.h"
19 #include "mlir-c/AffineMap.h"
20 #include "mlir-c/Diagnostics.h"
21 #include "mlir-c/IR.h"
22 #include "mlir-c/IntegerSet.h"
23 #include "llvm/ADT/DenseMap.h"
24 
25 namespace mlir {
26 namespace python {
27 
28 class PyBlock;
29 class PyDiagnostic;
30 class PyDiagnosticHandler;
31 class PyInsertionPoint;
32 class PyLocation;
33 class DefaultingPyLocation;
34 class PyMlirContext;
35 class DefaultingPyMlirContext;
36 class PyModule;
37 class PyOperation;
38 class PyType;
39 class PySymbolTable;
40 class PyValue;
41 
42 /// Template for a reference to a concrete type which captures a python
43 /// reference to its underlying python object.
44 template <typename T>
45 class PyObjectRef {
46 public:
47  PyObjectRef(T *referrent, pybind11::object object)
48  : referrent(referrent), object(std::move(object)) {
49  assert(this->referrent &&
50  "cannot construct PyObjectRef with null referrent");
51  assert(this->object && "cannot construct PyObjectRef with null object");
52  }
54  : referrent(other.referrent), object(std::move(other.object)) {
55  other.referrent = nullptr;
56  assert(!other.object);
57  }
58  PyObjectRef(const PyObjectRef &other)
59  : referrent(other.referrent), object(other.object /* copies */) {}
60  ~PyObjectRef() = default;
61 
62  int getRefCount() {
63  if (!object)
64  return 0;
65  return object.ref_count();
66  }
67 
68  /// Releases the object held by this instance, returning it.
69  /// This is the proper thing to return from a function that wants to return
70  /// the reference. Note that this does not work from initializers.
71  pybind11::object releaseObject() {
72  assert(referrent && object);
73  referrent = nullptr;
74  auto stolen = std::move(object);
75  return stolen;
76  }
77 
78  T *get() { return referrent; }
79  T *operator->() {
80  assert(referrent && object);
81  return referrent;
82  }
83  pybind11::object getObject() {
84  assert(referrent && object);
85  return object;
86  }
87  operator bool() const { return referrent && object; }
88 
89 private:
90  T *referrent;
91  pybind11::object object;
92 };
93 
94 /// Tracks an entry in the thread context stack. New entries are pushed onto
95 /// here for each with block that activates a new InsertionPoint, Context or
96 /// Location.
97 ///
98 /// Pushing either a Location or InsertionPoint also pushes its associated
99 /// Context. Pushing a Context will not modify the Location or InsertionPoint
100 /// unless if they are from a different context, in which case, they are
101 /// cleared.
103 public:
104  enum class FrameKind {
105  Context,
107  Location,
108  };
109 
110  PyThreadContextEntry(FrameKind frameKind, pybind11::object context,
111  pybind11::object insertionPoint,
112  pybind11::object location)
113  : context(std::move(context)), insertionPoint(std::move(insertionPoint)),
114  location(std::move(location)), frameKind(frameKind) {}
115 
116  /// Gets the top of stack context and return nullptr if not defined.
118 
119  /// Gets the top of stack insertion point and return nullptr if not defined.
121 
122  /// Gets the top of stack location and returns nullptr if not defined.
123  static PyLocation *getDefaultLocation();
124 
128  FrameKind getFrameKind() { return frameKind; }
129 
130  /// Stack management.
132  static pybind11::object pushContext(PyMlirContext &context);
133  static void popContext(PyMlirContext &context);
134  static pybind11::object pushInsertionPoint(PyInsertionPoint &insertionPoint);
135  static void popInsertionPoint(PyInsertionPoint &insertionPoint);
136  static pybind11::object pushLocation(PyLocation &location);
137  static void popLocation(PyLocation &location);
138 
139  /// Gets the thread local stack.
140  static std::vector<PyThreadContextEntry> &getStack();
141 
142 private:
143  static void push(FrameKind frameKind, pybind11::object context,
144  pybind11::object insertionPoint, pybind11::object location);
145 
146  /// An object reference to the PyContext.
147  pybind11::object context;
148  /// An object reference to the current insertion point.
149  pybind11::object insertionPoint;
150  /// An object reference to the current location.
151  pybind11::object location;
152  // The kind of push that was performed.
153  FrameKind frameKind;
154 };
155 
156 /// Wrapper around MlirContext.
159 public:
160  PyMlirContext() = delete;
161  PyMlirContext(const PyMlirContext &) = delete;
163 
164  /// For the case of a python __init__ (py::init) method, pybind11 is quite
165  /// strict about needing to return a pointer that is not yet associated to
166  /// an py::object. Since the forContext() method acts like a pool, possibly
167  /// returning a recycled context, it does not satisfy this need. The usual
168  /// way in python to accomplish such a thing is to override __new__, but
169  /// that is also not supported by pybind11. Instead, we use this entry
170  /// point which always constructs a fresh context (which cannot alias an
171  /// existing one because it is fresh).
173 
174  /// Returns a context reference for the singleton PyMlirContext wrapper for
175  /// the given context.
176  static PyMlirContextRef forContext(MlirContext context);
177  ~PyMlirContext();
178 
179  /// Accesses the underlying MlirContext.
180  MlirContext get() { return context; }
181 
182  /// Gets a strong reference to this context, which will ensure it is kept
183  /// alive for the life of the reference.
185  return PyMlirContextRef(this, pybind11::cast(this));
186  }
187 
188  /// Gets a capsule wrapping the void* within the MlirContext.
189  pybind11::object getCapsule();
190 
191  /// Creates a PyMlirContext from the MlirContext wrapped by a capsule.
192  /// Note that PyMlirContext instances are uniqued, so the returned object
193  /// may be a pre-existing object. Ownership of the underlying MlirContext
194  /// is taken by calling this function.
195  static pybind11::object createFromCapsule(pybind11::object capsule);
196 
197  /// Gets the count of live context objects. Used for testing.
198  static size_t getLiveCount();
199 
200  /// Gets the count of live operations associated with this context.
201  /// Used for testing.
202  size_t getLiveOperationCount();
203 
204  /// Clears the live operations map, returning the number of entries which were
205  /// invalidated. To be used as a safety mechanism so that API end-users can't
206  /// corrupt by holding references they shouldn't have accessed in the first
207  /// place.
208  size_t clearLiveOperations();
209 
210  /// Gets the count of live modules associated with this context.
211  /// Used for testing.
212  size_t getLiveModuleCount();
213 
214  /// Enter and exit the context manager.
215  pybind11::object contextEnter();
216  void contextExit(const pybind11::object &excType,
217  const pybind11::object &excVal,
218  const pybind11::object &excTb);
219 
220  /// Attaches a Python callback as a diagnostic handler, returning a
221  /// registration object (internally a PyDiagnosticHandler).
222  pybind11::object attachDiagnosticHandler(pybind11::object callback);
223 
224  /// Controls whether error diagnostics should be propagated to diagnostic
225  /// handlers, instead of being captured by `ErrorCapture`.
226  void setEmitErrorDiagnostics(bool value) { emitErrorDiagnostics = value; }
227  struct ErrorCapture;
228 
229 private:
230  PyMlirContext(MlirContext context);
231  // Interns the mapping of live MlirContext::ptr to PyMlirContext instances,
232  // preserving the relationship that an MlirContext maps to a single
233  // PyMlirContext wrapper. This could be replaced in the future with an
234  // extension mechanism on the MlirContext for stashing user pointers.
235  // Note that this holds a handle, which does not imply ownership.
236  // Mappings will be removed when the context is destructed.
237  using LiveContextMap = llvm::DenseMap<void *, PyMlirContext *>;
238  static LiveContextMap &getLiveContexts();
239 
240  // Interns all live modules associated with this context. Modules tracked
241  // in this map are valid. When a module is invalidated, it is removed
242  // from this map, and while it still exists as an instance, any
243  // attempt to access it will raise an error.
244  using LiveModuleMap =
246  LiveModuleMap liveModules;
247 
248  // Interns all live operations associated with this context. Operations
249  // tracked in this map are valid. When an operation is invalidated, it is
250  // removed from this map, and while it still exists as an instance, any
251  // attempt to access it will raise an error.
252  using LiveOperationMap =
254  LiveOperationMap liveOperations;
255 
256  bool emitErrorDiagnostics = false;
257 
258  MlirContext context;
259  friend class PyModule;
260  friend class PyOperation;
261 };
262 
263 /// Used in function arguments when None should resolve to the current context
264 /// manager set instance.
266  : public Defaulting<DefaultingPyMlirContext, PyMlirContext> {
267 public:
269  static constexpr const char kTypeDescription[] = "mlir.ir.Context";
270  static PyMlirContext &resolve();
271 };
272 
273 /// Base class for all objects that directly or indirectly depend on an
274 /// MlirContext. The lifetime of the context will extend at least to the
275 /// lifetime of these instances.
276 /// Immutable objects that depend on a context extend this directly.
278 public:
279  BaseContextObject(PyMlirContextRef ref) : contextRef(std::move(ref)) {
280  assert(this->contextRef &&
281  "context object constructed with null context ref");
282  }
283 
284  /// Accesses the context reference.
285  PyMlirContextRef &getContext() { return contextRef; }
286 
287 private:
288  PyMlirContextRef contextRef;
289 };
290 
291 /// Wrapper around an MlirLocation.
293 public:
294  PyLocation(PyMlirContextRef contextRef, MlirLocation loc)
295  : BaseContextObject(std::move(contextRef)), loc(loc) {}
296 
297  operator MlirLocation() const { return loc; }
298  MlirLocation get() const { return loc; }
299 
300  /// Enter and exit the context manager.
301  pybind11::object contextEnter();
302  void contextExit(const pybind11::object &excType,
303  const pybind11::object &excVal,
304  const pybind11::object &excTb);
305 
306  /// Gets a capsule wrapping the void* within the MlirLocation.
307  pybind11::object getCapsule();
308 
309  /// Creates a PyLocation from the MlirLocation wrapped by a capsule.
310  /// Note that PyLocation instances are uniqued, so the returned object
311  /// may be a pre-existing object. Ownership of the underlying MlirLocation
312  /// is taken by calling this function.
313  static PyLocation createFromCapsule(pybind11::object capsule);
314 
315 private:
316  MlirLocation loc;
317 };
318 
319 /// Python class mirroring the C MlirDiagnostic struct. Note that these structs
320 /// are only valid for the duration of a diagnostic callback and attempting
321 /// to access them outside of that will raise an exception. This applies to
322 /// nested diagnostics (in the notes) as well.
324 public:
325  PyDiagnostic(MlirDiagnostic diagnostic) : diagnostic(diagnostic) {}
326  void invalidate();
327  bool isValid() { return valid; }
330  pybind11::str getMessage();
331  pybind11::tuple getNotes();
332 
333  /// Materialized diagnostic information. This is safe to access outside the
334  /// diagnostic callback.
335  struct DiagnosticInfo {
338  std::string message;
339  std::vector<DiagnosticInfo> notes;
340  };
342 
343 private:
344  MlirDiagnostic diagnostic;
345 
346  void checkValid();
347  /// If notes have been materialized from the diagnostic, then this will
348  /// be populated with the corresponding objects (all castable to
349  /// PyDiagnostic).
350  std::optional<pybind11::tuple> materializedNotes;
351  bool valid = true;
352 };
353 
354 /// Represents a diagnostic handler attached to the context. The handler's
355 /// callback will be invoked with PyDiagnostic instances until the detach()
356 /// method is called or the context is destroyed. A diagnostic handler can be
357 /// the subject of a `with` block, which will detach it when the block exits.
358 ///
359 /// Since diagnostic handlers can call back into Python code which can do
360 /// unsafe things (i.e. recursively emitting diagnostics, raising exceptions,
361 /// etc), this is generally not deemed to be a great user-level API. Users
362 /// should generally use some form of DiagnosticCollector. If the handler raises
363 /// any exceptions, they will just be emitted to stderr and dropped.
364 ///
365 /// The unique usage of this class means that its lifetime management is
366 /// different from most other parts of the API. Instances are always created
367 /// in an attached state and can transition to a detached state by either:
368 /// a) The context being destroyed and unregistering all handlers.
369 /// b) An explicit call to detach().
370 /// The object may remain live from a Python perspective for an arbitrary time
371 /// after detachment, but there is nothing the user can do with it (since there
372 /// is no way to attach an existing handler object).
374 public:
375  PyDiagnosticHandler(MlirContext context, pybind11::object callback);
377 
378  bool isAttached() { return registeredID.has_value(); }
379  bool getHadError() { return hadError; }
380 
381  /// Detaches the handler. Does nothing if not attached.
382  void detach();
383 
384  pybind11::object contextEnter() { return pybind11::cast(this); }
385  void contextExit(const pybind11::object &excType,
386  const pybind11::object &excVal,
387  const pybind11::object &excTb) {
388  detach();
389  }
390 
391 private:
392  MlirContext context;
393  pybind11::object callback;
394  std::optional<MlirDiagnosticHandlerID> registeredID;
395  bool hadError = false;
396  friend class PyMlirContext;
397 };
398 
399 /// RAII object that captures any error diagnostics emitted to the provided
400 /// context.
403  : ctx(ctx), handlerID(mlirContextAttachDiagnosticHandler(
404  ctx->get(), handler, /*userData=*/this,
405  /*deleteUserData=*/nullptr)) {}
407  mlirContextDetachDiagnosticHandler(ctx->get(), handlerID);
408  assert(errors.empty() && "unhandled captured errors");
409  }
410 
411  std::vector<PyDiagnostic::DiagnosticInfo> take() {
412  return std::move(errors);
413  };
414 
415 private:
416  PyMlirContextRef ctx;
417  MlirDiagnosticHandlerID handlerID;
418  std::vector<PyDiagnostic::DiagnosticInfo> errors;
419 
420  static MlirLogicalResult handler(MlirDiagnostic diag, void *userData);
421 };
422 
423 /// Wrapper around an MlirDialect. This is exported as `DialectDescriptor` in
424 /// order to differentiate it from the `Dialect` base class which is extended by
425 /// plugins which extend dialect functionality through extension python code.
426 /// This should be seen as the "low-level" object and `Dialect` as the
427 /// high-level, user facing object.
429 public:
430  PyDialectDescriptor(PyMlirContextRef contextRef, MlirDialect dialect)
431  : BaseContextObject(std::move(contextRef)), dialect(dialect) {}
432 
433  MlirDialect get() { return dialect; }
434 
435 private:
436  MlirDialect dialect;
437 };
438 
439 /// User-level object for accessing dialects with dotted syntax such as:
440 /// ctx.dialect.std
442 public:
444  : BaseContextObject(std::move(contextRef)) {}
445 
446  MlirDialect getDialectForKey(const std::string &key, bool attrError);
447 };
448 
449 /// User-level dialect object. For dialects that have a registered extension,
450 /// this will be the base class of the extension dialect type. For un-extended,
451 /// objects of this type will be returned directly.
452 class PyDialect {
453 public:
454  PyDialect(pybind11::object descriptor) : descriptor(std::move(descriptor)) {}
455 
456  pybind11::object getDescriptor() { return descriptor; }
457 
458 private:
459  pybind11::object descriptor;
460 };
461 
462 /// Wrapper around an MlirDialectRegistry.
463 /// Upon construction, the Python wrapper takes ownership of the
464 /// underlying MlirDialectRegistry.
466 public:
468  PyDialectRegistry(MlirDialectRegistry registry) : registry(registry) {}
470  if (!mlirDialectRegistryIsNull(registry))
471  mlirDialectRegistryDestroy(registry);
472  }
474  PyDialectRegistry(PyDialectRegistry &&other) : registry(other.registry) {
475  other.registry = {nullptr};
476  }
477 
478  operator MlirDialectRegistry() const { return registry; }
479  MlirDialectRegistry get() const { return registry; }
480 
481  pybind11::object getCapsule();
482  static PyDialectRegistry createFromCapsule(pybind11::object capsule);
483 
484 private:
485  MlirDialectRegistry registry;
486 };
487 
488 /// Used in function arguments when None should resolve to the current context
489 /// manager set instance.
491  : public Defaulting<DefaultingPyLocation, PyLocation> {
492 public:
494  static constexpr const char kTypeDescription[] = "mlir.ir.Location";
495  static PyLocation &resolve();
496 
497  operator MlirLocation() const { return *get(); }
498 };
499 
500 /// Wrapper around MlirModule.
501 /// This is the top-level, user-owned object that contains regions/ops/blocks.
502 class PyModule;
504 class PyModule : public BaseContextObject {
505 public:
506  /// Returns a PyModule reference for the given MlirModule. This may return
507  /// a pre-existing or new object.
508  static PyModuleRef forModule(MlirModule module);
509  PyModule(PyModule &) = delete;
510  PyModule(PyMlirContext &&) = delete;
511  ~PyModule();
512 
513  /// Gets the backing MlirModule.
514  MlirModule get() { return module; }
515 
516  /// Gets a strong reference to this module.
518  return PyModuleRef(this,
519  pybind11::reinterpret_borrow<pybind11::object>(handle));
520  }
521 
522  /// Gets a capsule wrapping the void* within the MlirModule.
523  /// Note that the module does not (yet) provide a corresponding factory for
524  /// constructing from a capsule as that would require uniquing PyModule
525  /// instances, which is not currently done.
526  pybind11::object getCapsule();
527 
528  /// Creates a PyModule from the MlirModule wrapped by a capsule.
529  /// Note that PyModule instances are uniqued, so the returned object
530  /// may be a pre-existing object. Ownership of the underlying MlirModule
531  /// is taken by calling this function.
532  static pybind11::object createFromCapsule(pybind11::object capsule);
533 
534 private:
535  PyModule(PyMlirContextRef contextRef, MlirModule module);
536  MlirModule module;
537  pybind11::handle handle;
538 };
539 
540 /// Base class for PyOperation and PyOpView which exposes the primary, user
541 /// visible methods for manipulating it.
543 public:
544  virtual ~PyOperationBase() = default;
545  /// Implements the bound 'print' method and helps with others.
546  void print(pybind11::object fileObject, bool binary,
547  std::optional<int64_t> largeElementsLimit, bool enableDebugInfo,
548  bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope,
549  bool assumeVerified);
550  pybind11::object getAsm(bool binary,
551  std::optional<int64_t> largeElementsLimit,
552  bool enableDebugInfo, bool prettyDebugInfo,
553  bool printGenericOpForm, bool useLocalScope,
554  bool assumeVerified);
555 
556  // Implement the bound 'writeBytecode' method.
557  void writeBytecode(const pybind11::object &fileObject);
558 
559  /// Moves the operation before or after the other operation.
560  void moveAfter(PyOperationBase &other);
561  void moveBefore(PyOperationBase &other);
562 
563  /// Verify the operation. Throws `MLIRError` if verification fails, and
564  /// returns `true` otherwise.
565  bool verify();
566 
567  /// Each must provide access to the raw Operation.
568  virtual PyOperation &getOperation() = 0;
569 };
570 
571 /// Wrapper around PyOperation.
572 /// Operations exist in either an attached (dependent) or detached (top-level)
573 /// state. In the detached state (as on creation), an operation is owned by
574 /// the creator and its lifetime extends either until its reference count
575 /// drops to zero or it is attached to a parent, at which point its lifetime
576 /// is bounded by its top-level parent reference.
577 class PyOperation;
580 public:
581  ~PyOperation() override;
582  PyOperation &getOperation() override { return *this; }
583 
584  /// Returns a PyOperation for the given MlirOperation, optionally associating
585  /// it with a parentKeepAlive.
586  static PyOperationRef
587  forOperation(PyMlirContextRef contextRef, MlirOperation operation,
588  pybind11::object parentKeepAlive = pybind11::object());
589 
590  /// Creates a detached operation. The operation must not be associated with
591  /// any existing live operation.
592  static PyOperationRef
593  createDetached(PyMlirContextRef contextRef, MlirOperation operation,
594  pybind11::object parentKeepAlive = pybind11::object());
595 
596  /// Parses a source string (either text assembly or bytecode), creating a
597  /// detached operation.
598  static PyOperationRef parse(PyMlirContextRef contextRef,
599  const std::string &sourceStr,
600  const std::string &sourceName);
601 
602  /// Detaches the operation from its parent block and updates its state
603  /// accordingly.
606  setDetached();
607  parentKeepAlive = pybind11::object();
608  }
609 
610  /// Gets the backing operation.
611  operator MlirOperation() const { return get(); }
612  MlirOperation get() const {
613  checkValid();
614  return operation;
615  }
616 
618  return PyOperationRef(
619  this, pybind11::reinterpret_borrow<pybind11::object>(handle));
620  }
621 
622  bool isAttached() { return attached; }
623  void setAttached(const pybind11::object &parent = pybind11::object()) {
624  assert(!attached && "operation already attached");
625  attached = true;
626  }
627  void setDetached() {
628  assert(attached && "operation already detached");
629  attached = false;
630  }
631  void checkValid() const;
632 
633  /// Gets the owning block or raises an exception if the operation has no
634  /// owning block.
635  PyBlock getBlock();
636 
637  /// Gets the parent operation or raises an exception if the operation has
638  /// no parent.
639  std::optional<PyOperationRef> getParentOperation();
640 
641  /// Gets a capsule wrapping the void* within the MlirOperation.
642  pybind11::object getCapsule();
643 
644  /// Creates a PyOperation from the MlirOperation wrapped by a capsule.
645  /// Ownership of the underlying MlirOperation is taken by calling this
646  /// function.
647  static pybind11::object createFromCapsule(pybind11::object capsule);
648 
649  /// Creates an operation. See corresponding python docstring.
650  static pybind11::object
651  create(const std::string &name, std::optional<std::vector<PyType *>> results,
652  std::optional<std::vector<PyValue *>> operands,
653  std::optional<pybind11::dict> attributes,
654  std::optional<std::vector<PyBlock *>> successors, int regions,
655  DefaultingPyLocation location, const pybind11::object &ip);
656 
657  /// Creates an OpView suitable for this operation.
658  pybind11::object createOpView();
659 
660  /// Erases the underlying MlirOperation, removes its pointer from the
661  /// parent context's live operations map, and sets the valid bit false.
662  void erase();
663 
664  /// Invalidate the operation.
665  void setInvalid() { valid = false; }
666 
667  /// Clones this operation.
668  pybind11::object clone(const pybind11::object &ip);
669 
670 private:
671  PyOperation(PyMlirContextRef contextRef, MlirOperation operation);
672  static PyOperationRef createInstance(PyMlirContextRef contextRef,
673  MlirOperation operation,
674  pybind11::object parentKeepAlive);
675 
676  MlirOperation operation;
677  pybind11::handle handle;
678  // Keeps the parent alive, regardless of whether it is an Operation or
679  // Module.
680  // TODO: As implemented, this facility is only sufficient for modeling the
681  // trivial module parent back-reference. Generalize this to also account for
682  // transitions from detached to attached and address TODOs in the
683  // ir_operation.py regarding testing corresponding lifetime guarantees.
684  pybind11::object parentKeepAlive;
685  bool attached = true;
686  bool valid = true;
687 
688  friend class PyOperationBase;
689  friend class PySymbolTable;
690 };
691 
692 /// A PyOpView is equivalent to the C++ "Op" wrappers: these are the basis for
693 /// providing more instance-specific accessors and serve as the base class for
694 /// custom ODS-style operation classes. Since this class is subclass on the
695 /// python side, it must present an __init__ method that operates in pure
696 /// python types.
697 class PyOpView : public PyOperationBase {
698 public:
699  PyOpView(const pybind11::object &operationObject);
700  PyOperation &getOperation() override { return operation; }
701 
702  pybind11::object getOperationObject() { return operationObject; }
703 
704  static pybind11::object
705  buildGeneric(const pybind11::object &cls, pybind11::list resultTypeList,
706  pybind11::list operandList,
707  std::optional<pybind11::dict> attributes,
708  std::optional<std::vector<PyBlock *>> successors,
709  std::optional<int> regions, DefaultingPyLocation location,
710  const pybind11::object &maybeIp);
711 
712  /// Construct an instance of a class deriving from OpView, bypassing its
713  /// `__init__` method. The derived class will typically define a constructor
714  /// that provides a convenient builder, but we need to side-step this when
715  /// constructing an `OpView` for an already-built operation.
716  ///
717  /// The caller is responsible for verifying that `operation` is a valid
718  /// operation to construct `cls` with.
719  static pybind11::object constructDerived(const pybind11::object &cls,
720  const PyOperation &operation);
721 
722 private:
723  PyOperation &operation; // For efficient, cast-free access from C++
724  pybind11::object operationObject; // Holds the reference.
725 };
726 
727 /// Wrapper around an MlirRegion.
728 /// Regions are managed completely by their containing operation. Unlike the
729 /// C++ API, the python API does not support detached regions.
730 class PyRegion {
731 public:
732  PyRegion(PyOperationRef parentOperation, MlirRegion region)
733  : parentOperation(std::move(parentOperation)), region(region) {
734  assert(!mlirRegionIsNull(region) && "python region cannot be null");
735  }
736  operator MlirRegion() const { return region; }
737 
738  MlirRegion get() { return region; }
739  PyOperationRef &getParentOperation() { return parentOperation; }
740 
741  void checkValid() { return parentOperation->checkValid(); }
742 
743 private:
744  PyOperationRef parentOperation;
745  MlirRegion region;
746 };
747 
748 /// Wrapper around an MlirBlock.
749 /// Blocks are managed completely by their containing operation. Unlike the
750 /// C++ API, the python API does not support detached blocks.
751 class PyBlock {
752 public:
753  PyBlock(PyOperationRef parentOperation, MlirBlock block)
754  : parentOperation(std::move(parentOperation)), block(block) {
755  assert(!mlirBlockIsNull(block) && "python block cannot be null");
756  }
757 
758  MlirBlock get() { return block; }
759  PyOperationRef &getParentOperation() { return parentOperation; }
760 
761  void checkValid() { return parentOperation->checkValid(); }
762 
763 private:
764  PyOperationRef parentOperation;
765  MlirBlock block;
766 };
767 
768 /// An insertion point maintains a pointer to a Block and a reference operation.
769 /// Calls to insert() will insert a new operation before the
770 /// reference operation. If the reference operation is null, then appends to
771 /// the end of the block.
773 public:
774  /// Creates an insertion point positioned after the last operation in the
775  /// block, but still inside the block.
776  PyInsertionPoint(PyBlock &block);
777  /// Creates an insertion point positioned before a reference operation.
778  PyInsertionPoint(PyOperationBase &beforeOperationBase);
779 
780  /// Shortcut to create an insertion point at the beginning of the block.
781  static PyInsertionPoint atBlockBegin(PyBlock &block);
782  /// Shortcut to create an insertion point before the block terminator.
784 
785  /// Inserts an operation.
786  void insert(PyOperationBase &operationBase);
787 
788  /// Enter and exit the context manager.
789  pybind11::object contextEnter();
790  void contextExit(const pybind11::object &excType,
791  const pybind11::object &excVal,
792  const pybind11::object &excTb);
793 
794  PyBlock &getBlock() { return block; }
795 
796 private:
797  // Trampoline constructor that avoids null initializing members while
798  // looking up parents.
799  PyInsertionPoint(PyBlock block, std::optional<PyOperationRef> refOperation)
800  : refOperation(std::move(refOperation)), block(std::move(block)) {}
801 
802  std::optional<PyOperationRef> refOperation;
803  PyBlock block;
804 };
805 /// Wrapper around the generic MlirType.
806 /// The lifetime of a type is bound by the PyContext that created it.
807 class PyType : public BaseContextObject {
808 public:
809  PyType(PyMlirContextRef contextRef, MlirType type)
810  : BaseContextObject(std::move(contextRef)), type(type) {}
811  bool operator==(const PyType &other);
812  operator MlirType() const { return type; }
813  MlirType get() const { return type; }
814 
815  /// Gets a capsule wrapping the void* within the MlirType.
816  pybind11::object getCapsule();
817 
818  /// Creates a PyType from the MlirType wrapped by a capsule.
819  /// Note that PyType instances are uniqued, so the returned object
820  /// may be a pre-existing object. Ownership of the underlying MlirType
821  /// is taken by calling this function.
822  static PyType createFromCapsule(pybind11::object capsule);
823 
824 private:
825  MlirType type;
826 };
827 
828 /// CRTP base classes for Python types that subclass Type and should be
829 /// castable from it (i.e. via something like IntegerType(t)).
830 /// By default, type class hierarchies are one level deep (i.e. a
831 /// concrete type class extends PyType); however, intermediate python-visible
832 /// base classes can be modeled by specifying a BaseTy.
833 template <typename DerivedTy, typename BaseTy = PyType>
834 class PyConcreteType : public BaseTy {
835 public:
836  // Derived classes must define statics for:
837  // IsAFunctionTy isaFunction
838  // const char *pyClassName
839  using ClassTy = pybind11::class_<DerivedTy, BaseTy>;
840  using IsAFunctionTy = bool (*)(MlirType);
841 
842  PyConcreteType() = default;
843  PyConcreteType(PyMlirContextRef contextRef, MlirType t)
844  : BaseTy(std::move(contextRef), t) {}
846  : PyConcreteType(orig.getContext(), castFrom(orig)) {}
847 
848  static MlirType castFrom(PyType &orig) {
849  if (!DerivedTy::isaFunction(orig)) {
850  auto origRepr = pybind11::repr(pybind11::cast(orig)).cast<std::string>();
851  throw SetPyError(PyExc_ValueError, llvm::Twine("Cannot cast type to ") +
852  DerivedTy::pyClassName +
853  " (from " + origRepr + ")");
854  }
855  return orig;
856  }
857 
858  static void bind(pybind11::module &m) {
859  auto cls = ClassTy(m, DerivedTy::pyClassName, pybind11::module_local());
860  cls.def(pybind11::init<PyType &>(), pybind11::keep_alive<0, 1>(),
861  pybind11::arg("cast_from_type"));
862  cls.def_static(
863  "isinstance",
864  [](PyType &otherType) -> bool {
865  return DerivedTy::isaFunction(otherType);
866  },
867  pybind11::arg("other"));
868  DerivedTy::bindDerived(cls);
869  }
870 
871  /// Implemented by derived classes to add methods to the Python subclass.
872  static void bindDerived(ClassTy &m) {}
873 };
874 
875 /// Wrapper around the generic MlirAttribute.
876 /// The lifetime of a type is bound by the PyContext that created it.
878 public:
879  PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
880  : BaseContextObject(std::move(contextRef)), attr(attr) {}
881  bool operator==(const PyAttribute &other);
882  operator MlirAttribute() const { return attr; }
883  MlirAttribute get() const { return attr; }
884 
885  /// Gets a capsule wrapping the void* within the MlirAttribute.
886  pybind11::object getCapsule();
887 
888  /// Creates a PyAttribute from the MlirAttribute wrapped by a capsule.
889  /// Note that PyAttribute instances are uniqued, so the returned object
890  /// may be a pre-existing object. Ownership of the underlying MlirAttribute
891  /// is taken by calling this function.
892  static PyAttribute createFromCapsule(pybind11::object capsule);
893 
894 private:
895  MlirAttribute attr;
896 };
897 
898 /// Represents a Python MlirNamedAttr, carrying an optional owned name.
899 /// TODO: Refactor this and the C-API to be based on an Identifier owned
900 /// by the context so as to avoid ownership issues here.
902 public:
903  /// Constructs a PyNamedAttr that retains an owned name. This should be
904  /// used in any code that originates an MlirNamedAttribute from a python
905  /// string.
906  /// The lifetime of the PyNamedAttr must extend to the lifetime of the
907  /// passed attribute.
908  PyNamedAttribute(MlirAttribute attr, std::string ownedName);
909 
911 
912 private:
913  // Since the MlirNamedAttr contains an internal pointer to the actual
914  // memory of the owned string, it must be heap allocated to remain valid.
915  // Otherwise, strings that fit within the small object optimization threshold
916  // will have their memory address change as the containing object is moved,
917  // resulting in an invalid aliased pointer.
918  std::unique_ptr<std::string> ownedName;
919 };
920 
921 /// CRTP base classes for Python attributes that subclass Attribute and should
922 /// be castable from it (i.e. via something like StringAttr(attr)).
923 /// By default, attribute class hierarchies are one level deep (i.e. a
924 /// concrete attribute class extends PyAttribute); however, intermediate
925 /// python-visible base classes can be modeled by specifying a BaseTy.
926 template <typename DerivedTy, typename BaseTy = PyAttribute>
927 class PyConcreteAttribute : public BaseTy {
928 public:
929  // Derived classes must define statics for:
930  // IsAFunctionTy isaFunction
931  // const char *pyClassName
932  using ClassTy = pybind11::class_<DerivedTy, BaseTy>;
933  using IsAFunctionTy = bool (*)(MlirAttribute);
934 
935  PyConcreteAttribute() = default;
936  PyConcreteAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
937  : BaseTy(std::move(contextRef), attr) {}
939  : PyConcreteAttribute(orig.getContext(), castFrom(orig)) {}
940 
941  static MlirAttribute castFrom(PyAttribute &orig) {
942  if (!DerivedTy::isaFunction(orig)) {
943  auto origRepr = pybind11::repr(pybind11::cast(orig)).cast<std::string>();
944  throw SetPyError(PyExc_ValueError,
945  llvm::Twine("Cannot cast attribute to ") +
946  DerivedTy::pyClassName + " (from " + origRepr + ")");
947  }
948  return orig;
949  }
950 
951  static void bind(pybind11::module &m) {
952  auto cls = ClassTy(m, DerivedTy::pyClassName, pybind11::buffer_protocol(),
953  pybind11::module_local());
954  cls.def(pybind11::init<PyAttribute &>(), pybind11::keep_alive<0, 1>(),
955  pybind11::arg("cast_from_attr"));
956  cls.def_static(
957  "isinstance",
958  [](PyAttribute &otherAttr) -> bool {
959  return DerivedTy::isaFunction(otherAttr);
960  },
961  pybind11::arg("other"));
962  cls.def_property_readonly("type", [](PyAttribute &attr) {
963  return PyType(attr.getContext(), mlirAttributeGetType(attr));
964  });
965  DerivedTy::bindDerived(cls);
966  }
967 
968  /// Implemented by derived classes to add methods to the Python subclass.
969  static void bindDerived(ClassTy &m) {}
970 };
971 
972 /// Wrapper around the generic MlirValue.
973 /// Values are managed completely by the operation that resulted in their
974 /// definition. For op result value, this is the operation that defines the
975 /// value. For block argument values, this is the operation that contains the
976 /// block to which the value is an argument (blocks cannot be detached in Python
977 /// bindings so such operation always exists).
978 class PyValue {
979 public:
980  PyValue(PyOperationRef parentOperation, MlirValue value)
981  : parentOperation(std::move(parentOperation)), value(value) {}
982  operator MlirValue() const { return value; }
983 
984  MlirValue get() { return value; }
985  PyOperationRef &getParentOperation() { return parentOperation; }
986 
987  void checkValid() { return parentOperation->checkValid(); }
988 
989  /// Gets a capsule wrapping the void* within the MlirValue.
990  pybind11::object getCapsule();
991 
992  /// Creates a PyValue from the MlirValue wrapped by a capsule. Ownership of
993  /// the underlying MlirValue is still tied to the owning operation.
994  static PyValue createFromCapsule(pybind11::object capsule);
995 
996 private:
997  PyOperationRef parentOperation;
998  MlirValue value;
999 };
1000 
1001 /// Wrapper around MlirAffineExpr. Affine expressions are owned by the context.
1003 public:
1004  PyAffineExpr(PyMlirContextRef contextRef, MlirAffineExpr affineExpr)
1005  : BaseContextObject(std::move(contextRef)), affineExpr(affineExpr) {}
1006  bool operator==(const PyAffineExpr &other);
1007  operator MlirAffineExpr() const { return affineExpr; }
1008  MlirAffineExpr get() const { return affineExpr; }
1009 
1010  /// Gets a capsule wrapping the void* within the MlirAffineExpr.
1011  pybind11::object getCapsule();
1012 
1013  /// Creates a PyAffineExpr from the MlirAffineExpr wrapped by a capsule.
1014  /// Note that PyAffineExpr instances are uniqued, so the returned object
1015  /// may be a pre-existing object. Ownership of the underlying MlirAffineExpr
1016  /// is taken by calling this function.
1017  static PyAffineExpr createFromCapsule(pybind11::object capsule);
1018 
1019  PyAffineExpr add(const PyAffineExpr &other) const;
1020  PyAffineExpr mul(const PyAffineExpr &other) const;
1021  PyAffineExpr floorDiv(const PyAffineExpr &other) const;
1022  PyAffineExpr ceilDiv(const PyAffineExpr &other) const;
1023  PyAffineExpr mod(const PyAffineExpr &other) const;
1024 
1025 private:
1026  MlirAffineExpr affineExpr;
1027 };
1028 
1030 public:
1031  PyAffineMap(PyMlirContextRef contextRef, MlirAffineMap affineMap)
1032  : BaseContextObject(std::move(contextRef)), affineMap(affineMap) {}
1033  bool operator==(const PyAffineMap &other);
1034  operator MlirAffineMap() const { return affineMap; }
1035  MlirAffineMap get() const { return affineMap; }
1036 
1037  /// Gets a capsule wrapping the void* within the MlirAffineMap.
1038  pybind11::object getCapsule();
1039 
1040  /// Creates a PyAffineMap from the MlirAffineMap wrapped by a capsule.
1041  /// Note that PyAffineMap instances are uniqued, so the returned object
1042  /// may be a pre-existing object. Ownership of the underlying MlirAffineMap
1043  /// is taken by calling this function.
1044  static PyAffineMap createFromCapsule(pybind11::object capsule);
1045 
1046 private:
1047  MlirAffineMap affineMap;
1048 };
1049 
1051 public:
1052  PyIntegerSet(PyMlirContextRef contextRef, MlirIntegerSet integerSet)
1053  : BaseContextObject(std::move(contextRef)), integerSet(integerSet) {}
1054  bool operator==(const PyIntegerSet &other);
1055  operator MlirIntegerSet() const { return integerSet; }
1056  MlirIntegerSet get() const { return integerSet; }
1057 
1058  /// Gets a capsule wrapping the void* within the MlirIntegerSet.
1059  pybind11::object getCapsule();
1060 
1061  /// Creates a PyIntegerSet from the MlirAffineMap wrapped by a capsule.
1062  /// Note that PyIntegerSet instances may be uniqued, so the returned object
1063  /// may be a pre-existing object. Integer sets are owned by the context.
1064  static PyIntegerSet createFromCapsule(pybind11::object capsule);
1065 
1066 private:
1067  MlirIntegerSet integerSet;
1068 };
1069 
1070 /// Bindings for MLIR symbol tables.
1072 public:
1073  /// Constructs a symbol table for the given operation.
1074  explicit PySymbolTable(PyOperationBase &operation);
1075 
1076  /// Destroys the symbol table.
1078 
1079  /// Returns the symbol (opview) with the given name, throws if there is no
1080  /// such symbol in the table.
1081  pybind11::object dunderGetItem(const std::string &name);
1082 
1083  /// Removes the given operation from the symbol table and erases it.
1084  void erase(PyOperationBase &symbol);
1085 
1086  /// Removes the operation with the given name from the symbol table and erases
1087  /// it, throws if there is no such symbol in the table.
1088  void dunderDel(const std::string &name);
1089 
1090  /// Inserts the given operation into the symbol table. The operation must have
1091  /// the symbol trait.
1093 
1094  /// Gets and sets the name of a symbol op.
1095  static PyAttribute getSymbolName(PyOperationBase &symbol);
1096  static void setSymbolName(PyOperationBase &symbol, const std::string &name);
1097 
1098  /// Gets and sets the visibility of a symbol op.
1099  static PyAttribute getVisibility(PyOperationBase &symbol);
1100  static void setVisibility(PyOperationBase &symbol,
1101  const std::string &visibility);
1102 
1103  /// Replaces all symbol uses within an operation. See the API
1104  /// mlirSymbolTableReplaceAllSymbolUses for all caveats.
1105  static void replaceAllSymbolUses(const std::string &oldSymbol,
1106  const std::string &newSymbol,
1107  PyOperationBase &from);
1108 
1109  /// Walks all symbol tables under and including 'from'.
1110  static void walkSymbolTables(PyOperationBase &from, bool allSymUsesVisible,
1111  pybind11::object callback);
1112 
1113  /// Casts the bindings class into the C API structure.
1114  operator MlirSymbolTable() { return symbolTable; }
1115 
1116 private:
1117  PyOperationRef operation;
1118  MlirSymbolTable symbolTable;
1119 };
1120 
1121 /// Custom exception that allows access to error diagnostic information. This is
1122 /// converted to the `ir.MLIRError` python exception when thrown.
1123 struct MLIRError {
1124  MLIRError(llvm::Twine message,
1125  std::vector<PyDiagnostic::DiagnosticInfo> &&errorDiagnostics = {})
1126  : message(message.str()), errorDiagnostics(std::move(errorDiagnostics)) {}
1127  std::string message;
1128  std::vector<PyDiagnostic::DiagnosticInfo> errorDiagnostics;
1129 };
1130 
1131 void populateIRAffine(pybind11::module &m);
1132 void populateIRAttributes(pybind11::module &m);
1133 void populateIRCore(pybind11::module &m);
1134 void populateIRInterfaces(pybind11::module &m);
1135 void populateIRTypes(pybind11::module &m);
1136 
1137 } // namespace python
1138 } // namespace mlir
1139 
1140 namespace pybind11 {
1141 namespace detail {
1142 
1143 template <>
1144 struct type_caster<mlir::python::DefaultingPyMlirContext>
1145  : MlirDefaultingCaster<mlir::python::DefaultingPyMlirContext> {};
1146 template <>
1147 struct type_caster<mlir::python::DefaultingPyLocation>
1148  : MlirDefaultingCaster<mlir::python::DefaultingPyLocation> {};
1149 
1150 } // namespace detail
1151 } // namespace pybind11
1152 
1153 #endif // MLIR_BINDINGS_PYTHON_IRMODULES_H
static std::string diag(const llvm::Value &value)
Base class for all objects that directly or indirectly depend on an MlirContext.
Definition: IRModule.h:277
PyMlirContextRef & getContext()
Accesses the context reference.
Definition: IRModule.h:285
BaseContextObject(PyMlirContextRef ref)
Definition: IRModule.h:279
Used in function arguments when None should resolve to the current context manager set instance.
Definition: IRModule.h:491
static PyLocation & resolve()
Definition: IRCore.cpp:949
static constexpr const char kTypeDescription[]
Definition: IRModule.h:494
Used in function arguments when None should resolve to the current context manager set instance.
Definition: IRModule.h:266
static constexpr const char kTypeDescription[]
Definition: IRModule.h:269
static PyMlirContext & resolve()
Definition: IRCore.cpp:672
CRTP template for special wrapper types that are allowed to be passed in as 'None' function arguments...
Definition: PybindUtils.h:45
Defaulting()=default
Type casters require the type to be default constructible, but using such an instance is illegal.
Wrapper around MlirAffineExpr. Affine expressions are owned by the context.
Definition: IRModule.h:1002
static PyAffineExpr createFromCapsule(pybind11::object capsule)
Creates a PyAffineExpr from the MlirAffineExpr wrapped by a capsule.
Definition: IRAffine.cpp:359
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirAffineExpr.
Definition: IRAffine.cpp:354
PyAffineExpr(PyMlirContextRef contextRef, MlirAffineExpr affineExpr)
Definition: IRModule.h:1004
PyAffineExpr ceilDiv(const PyAffineExpr &other) const
PyAffineExpr mul(const PyAffineExpr &other) const
bool operator==(const PyAffineExpr &other)
Definition: IRAffine.cpp:350
PyAffineExpr mod(const PyAffineExpr &other) const
PyAffineExpr floorDiv(const PyAffineExpr &other) const
PyAffineExpr add(const PyAffineExpr &other) const
MlirAffineExpr get() const
Definition: IRModule.h:1008
bool operator==(const PyAffineMap &other)
Definition: IRAffine.cpp:409
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirAffineMap.
Definition: IRAffine.cpp:413
PyAffineMap(PyMlirContextRef contextRef, MlirAffineMap affineMap)
Definition: IRModule.h:1031
MlirAffineMap get() const
Definition: IRModule.h:1035
static PyAffineMap createFromCapsule(pybind11::object capsule)
Creates a PyAffineMap from the MlirAffineMap wrapped by a capsule.
Definition: IRAffine.cpp:417
Wrapper around the generic MlirAttribute.
Definition: IRModule.h:877
PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
Definition: IRModule.h:879
static PyAttribute createFromCapsule(pybind11::object capsule)
Creates a PyAttribute from the MlirAttribute wrapped by a capsule.
Definition: IRCore.cpp:1747
bool operator==(const PyAttribute &other)
Definition: IRCore.cpp:1739
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirAttribute.
Definition: IRCore.cpp:1743
MlirAttribute get() const
Definition: IRModule.h:883
Wrapper around an MlirBlock.
Definition: IRModule.h:751
MlirBlock get()
Definition: IRModule.h:758
PyOperationRef & getParentOperation()
Definition: IRModule.h:759
PyBlock(PyOperationRef parentOperation, MlirBlock block)
Definition: IRModule.h:753
CRTP base classes for Python attributes that subclass Attribute and should be castable from it (i....
Definition: IRModule.h:927
pybind11::class_< DerivedTy, BaseTy > ClassTy
Definition: IRModule.h:932
static MlirAttribute castFrom(PyAttribute &orig)
Definition: IRModule.h:941
static void bind(pybind11::module &m)
Definition: IRModule.h:951
bool(*)(MlirAttribute) IsAFunctionTy
Definition: IRModule.h:933
PyConcreteAttribute(PyAttribute &orig)
Definition: IRModule.h:938
PyConcreteAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
Definition: IRModule.h:936
static void bindDerived(ClassTy &m)
Implemented by derived classes to add methods to the Python subclass.
Definition: IRModule.h:969
CRTP base classes for Python types that subclass Type and should be castable from it (i....
Definition: IRModule.h:834
static void bind(pybind11::module &m)
Definition: IRModule.h:858
pybind11::class_< DerivedTy, BaseTy > ClassTy
Definition: IRModule.h:839
PyConcreteType(PyType &orig)
Definition: IRModule.h:845
bool(*)(MlirType) IsAFunctionTy
Definition: IRModule.h:840
static void bindDerived(ClassTy &m)
Implemented by derived classes to add methods to the Python subclass.
Definition: IRModule.h:872
PyConcreteType(PyMlirContextRef contextRef, MlirType t)
Definition: IRModule.h:843
static MlirType castFrom(PyType &orig)
Definition: IRModule.h:848
Represents a diagnostic handler attached to the context.
Definition: IRModule.h:373
void contextExit(const pybind11::object &excType, const pybind11::object &excVal, const pybind11::object &excTb)
Definition: IRModule.h:385
void detach()
Detaches the handler. Does nothing if not attached.
Definition: IRCore.cpp:837
PyDiagnosticHandler(MlirContext context, pybind11::object callback)
Definition: IRCore.cpp:831
pybind11::object contextEnter()
Definition: IRModule.h:384
Python class mirroring the C MlirDiagnostic struct.
Definition: IRModule.h:323
pybind11::str getMessage()
Definition: IRCore.cpp:867
PyLocation getLocation()
Definition: IRCore.cpp:860
DiagnosticInfo getInfo()
Definition: IRCore.cpp:888
PyDiagnostic(MlirDiagnostic diagnostic)
Definition: IRModule.h:325
MlirDiagnosticSeverity getSeverity()
Definition: IRCore.cpp:855
pybind11::tuple getNotes()
Definition: IRCore.cpp:875
Wrapper around an MlirDialect.
Definition: IRModule.h:428
PyDialectDescriptor(PyMlirContextRef contextRef, MlirDialect dialect)
Definition: IRModule.h:430
Wrapper around an MlirDialectRegistry.
Definition: IRModule.h:465
PyDialectRegistry(PyDialectRegistry &)=delete
static PyDialectRegistry createFromCapsule(pybind11::object capsule)
Definition: IRCore.cpp:915
MlirDialectRegistry get() const
Definition: IRModule.h:479
pybind11::object getCapsule()
Definition: IRCore.cpp:910
PyDialectRegistry(MlirDialectRegistry registry)
Definition: IRModule.h:468
PyDialectRegistry(PyDialectRegistry &&other)
Definition: IRModule.h:474
User-level dialect object.
Definition: IRModule.h:452
PyDialect(pybind11::object descriptor)
Definition: IRModule.h:454
pybind11::object getDescriptor()
Definition: IRModule.h:456
User-level object for accessing dialects with dotted syntax such as: ctx.dialect.std.
Definition: IRModule.h:441
PyDialects(PyMlirContextRef contextRef)
Definition: IRModule.h:443
MlirDialect getDialectForKey(const std::string &key, bool attrError)
Definition: IRCore.cpp:899
An insertion point maintains a pointer to a Block and a reference operation.
Definition: IRModule.h:772
static PyInsertionPoint atBlockTerminator(PyBlock &block)
Shortcut to create an insertion point before the block terminator.
Definition: IRCore.cpp:1716
PyInsertionPoint(PyBlock &block)
Creates an insertion point positioned after the last operation in the block, but still inside the blo...
Definition: IRCore.cpp:1671
static PyInsertionPoint atBlockBegin(PyBlock &block)
Shortcut to create an insertion point at the beginning of the block.
Definition: IRCore.cpp:1703
void insert(PyOperationBase &operationBase)
Inserts an operation.
Definition: IRCore.cpp:1677
void contextExit(const pybind11::object &excType, const pybind11::object &excVal, const pybind11::object &excTb)
Definition: IRCore.cpp:1729
pybind11::object contextEnter()
Enter and exit the context manager.
Definition: IRCore.cpp:1725
static PyIntegerSet createFromCapsule(pybind11::object capsule)
Creates a PyIntegerSet from the MlirAffineMap wrapped by a capsule.
Definition: IRAffine.cpp:495
bool operator==(const PyIntegerSet &other)
Definition: IRAffine.cpp:486
MlirIntegerSet get() const
Definition: IRModule.h:1056
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirIntegerSet.
Definition: IRAffine.cpp:490
PyIntegerSet(PyMlirContextRef contextRef, MlirIntegerSet integerSet)
Definition: IRModule.h:1052
Wrapper around an MlirLocation.
Definition: IRModule.h:292
PyLocation(PyMlirContextRef contextRef, MlirLocation loc)
Definition: IRModule.h:294
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirLocation.
Definition: IRCore.cpp:927
static PyLocation createFromCapsule(pybind11::object capsule)
Creates a PyLocation from the MlirLocation wrapped by a capsule.
Definition: IRCore.cpp:931
void contextExit(const pybind11::object &excType, const pybind11::object &excVal, const pybind11::object &excTb)
Definition: IRCore.cpp:943
pybind11::object contextEnter()
Enter and exit the context manager.
Definition: IRCore.cpp:939
MlirLocation get() const
Definition: IRModule.h:298
pybind11::object attachDiagnosticHandler(pybind11::object callback)
Attaches a Python callback as a diagnostic handler, returning a registration object (internally a PyD...
Definition: IRCore.cpp:607
PyMlirContext(const PyMlirContext &)=delete
PyMlirContext(PyMlirContext &&)=delete
MlirContext get()
Accesses the underlying MlirContext.
Definition: IRModule.h:180
PyMlirContextRef getRef()
Gets a strong reference to this context, which will ensure it is kept alive for the life of the refer...
Definition: IRModule.h:184
static pybind11::object createFromCapsule(pybind11::object capsule)
Creates a PyMlirContext from the MlirContext wrapped by a capsule.
Definition: IRCore.cpp:549
static size_t getLiveCount()
Gets the count of live context objects. Used for testing.
Definition: IRCore.cpp:583
static PyMlirContext * createNewContextForInit()
For the case of a python init (py::init) method, pybind11 is quite strict about needing to return a p...
Definition: IRCore.cpp:556
size_t getLiveModuleCount()
Gets the count of live modules associated with this context.
Definition: IRCore.cpp:595
pybind11::object contextEnter()
Enter and exit the context manager.
Definition: IRCore.cpp:597
size_t clearLiveOperations()
Clears the live operations map, returning the number of entries which were invalidated.
Definition: IRCore.cpp:587
void contextExit(const pybind11::object &excType, const pybind11::object &excVal, const pybind11::object &excTb)
Definition: IRCore.cpp:601
static PyMlirContextRef forContext(MlirContext context)
Returns a context reference for the singleton PyMlirContext wrapper for the given context.
Definition: IRCore.cpp:561
size_t getLiveOperationCount()
Gets the count of live operations associated with this context.
Definition: IRCore.cpp:585
void setEmitErrorDiagnostics(bool value)
Controls whether error diagnostics should be propagated to diagnostic handlers, instead of being capt...
Definition: IRModule.h:226
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirContext.
Definition: IRCore.cpp:545
MlirModule get()
Gets the backing MlirModule.
Definition: IRModule.h:514
static PyModuleRef forModule(MlirModule module)
Returns a PyModule reference for the given MlirModule.
Definition: IRCore.cpp:977
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirModule.
Definition: IRCore.cpp:1010
static pybind11::object createFromCapsule(pybind11::object capsule)
Creates a PyModule from the MlirModule wrapped by a capsule.
Definition: IRCore.cpp:1003
PyModuleRef getRef()
Gets a strong reference to this module.
Definition: IRModule.h:517
PyModule(PyModule &)=delete
PyModule(PyMlirContext &&)=delete
Represents a Python MlirNamedAttr, carrying an optional owned name.
Definition: IRModule.h:901
PyNamedAttribute(MlirAttribute attr, std::string ownedName)
Constructs a PyNamedAttr that retains an owned name.
Definition: IRCore.cpp:1759
MlirNamedAttribute namedAttr
Definition: IRModule.h:910
Template for a reference to a concrete type which captures a python reference to its underlying pytho...
Definition: IRModule.h:45
PyObjectRef(T *referrent, pybind11::object object)
Definition: IRModule.h:47
pybind11::object getObject()
Definition: IRModule.h:83
pybind11::object releaseObject()
Releases the object held by this instance, returning it.
Definition: IRModule.h:71
PyObjectRef(PyObjectRef &&other)
Definition: IRModule.h:53
PyObjectRef(const PyObjectRef &other)
Definition: IRModule.h:58
A PyOpView is equivalent to the C++ "Op" wrappers: these are the basis for providing more instance-sp...
Definition: IRModule.h:697
PyOpView(const pybind11::object &operationObject)
Definition: IRCore.cpp:1661
pybind11::object getOperationObject()
Definition: IRModule.h:702
static pybind11::object constructDerived(const pybind11::object &cls, const PyOperation &operation)
Construct an instance of a class deriving from OpView, bypassing its __init__ method.
Definition: IRCore.cpp:1650
static pybind11::object buildGeneric(const pybind11::object &cls, pybind11::list resultTypeList, pybind11::list operandList, std::optional< pybind11::dict > attributes, std::optional< std::vector< PyBlock * >> successors, std::optional< int > regions, DefaultingPyLocation location, const pybind11::object &maybeIp)
Definition: IRCore.cpp:1395
PyOperation & getOperation() override
Each must provide access to the raw Operation.
Definition: IRModule.h:700
Base class for PyOperation and PyOpView which exposes the primary, user visible methods for manipulat...
Definition: IRModule.h:542
virtual PyOperation & getOperation()=0
Each must provide access to the raw Operation.
pybind11::object getAsm(bool binary, std::optional< int64_t > largeElementsLimit, bool enableDebugInfo, bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope, bool assumeVerified)
Definition: IRCore.cpp:1139
virtual ~PyOperationBase()=default
void print(pybind11::object fileObject, bool binary, std::optional< int64_t > largeElementsLimit, bool enableDebugInfo, bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope, bool assumeVerified)
Implements the bound 'print' method and helps with others.
Definition: IRCore.cpp:1102
void moveAfter(PyOperationBase &other)
Moves the operation before or after the other operation.
Definition: IRCore.cpp:1161
void moveBefore(PyOperationBase &other)
Definition: IRCore.cpp:1170
bool verify()
Verify the operation.
Definition: IRCore.cpp:1179
void writeBytecode(const pybind11::object &fileObject)
Definition: IRCore.cpp:1131
pybind11::object clone(const pybind11::object &ip)
Clones this operation.
Definition: IRCore.cpp:1358
void detachFromParent()
Detaches the operation from its parent block and updates its state accordingly.
Definition: IRModule.h:604
void erase()
Erases the underlying MlirOperation, removes its pointer from the parent context's live operations ma...
Definition: IRCore.cpp:1378
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirOperation.
Definition: IRCore.cpp:1206
PyOperation & getOperation() override
Each must provide access to the raw Operation.
Definition: IRModule.h:582
PyOperationRef getRef()
Definition: IRModule.h:617
static pybind11::object create(const std::string &name, std::optional< std::vector< PyType * >> results, std::optional< std::vector< PyValue * >> operands, std::optional< pybind11::dict > attributes, std::optional< std::vector< PyBlock * >> successors, int regions, DefaultingPyLocation location, const pybind11::object &ip)
Creates an operation. See corresponding python docstring.
Definition: IRCore.cpp:1235
MlirOperation get() const
Definition: IRModule.h:612
void setAttached(const pybind11::object &parent=pybind11::object())
Definition: IRModule.h:623
pybind11::object createOpView()
Creates an OpView suitable for this operation.
Definition: IRCore.cpp:1367
static PyOperationRef forOperation(PyMlirContextRef contextRef, MlirOperation operation, pybind11::object parentKeepAlive=pybind11::object())
Returns a PyOperation for the given MlirOperation, optionally associating it with a parentKeepAlive.
Definition: IRCore.cpp:1054
std::optional< PyOperationRef > getParentOperation()
Gets the parent operation or raises an exception if the operation has no parent.
Definition: IRCore.cpp:1187
PyBlock getBlock()
Gets the owning block or raises an exception if the operation has no owning block.
Definition: IRCore.cpp:1197
static PyOperationRef createDetached(PyMlirContextRef contextRef, MlirOperation operation, pybind11::object parentKeepAlive=pybind11::object())
Creates a detached operation.
Definition: IRCore.cpp:1070
static PyOperationRef parse(PyMlirContextRef contextRef, const std::string &sourceStr, const std::string &sourceName)
Parses a source string (either text assembly or bytecode), creating a detached operation.
Definition: IRCore.cpp:1084
static pybind11::object createFromCapsule(pybind11::object capsule)
Creates a PyOperation from the MlirOperation wrapped by a capsule.
Definition: IRCore.cpp:1211
void checkValid() const
Definition: IRCore.cpp:1096
void setInvalid()
Invalidate the operation.
Definition: IRModule.h:665
Wrapper around an MlirRegion.
Definition: IRModule.h:730
PyRegion(PyOperationRef parentOperation, MlirRegion region)
Definition: IRModule.h:732
PyOperationRef & getParentOperation()
Definition: IRModule.h:739
MlirRegion get()
Definition: IRModule.h:738
Bindings for MLIR symbol tables.
Definition: IRModule.h:1071
void dunderDel(const std::string &name)
Removes the operation with the given name from the symbol table and erases it, throws if there is no ...
Definition: IRCore.cpp:1846
PyAttribute insert(PyOperationBase &symbol)
Inserts the given operation into the symbol table.
Definition: IRCore.cpp:1851
static PyAttribute getSymbolName(PyOperationBase &symbol)
Gets and sets the name of a symbol op.
Definition: IRCore.cpp:1863
static void replaceAllSymbolUses(const std::string &oldSymbol, const std::string &newSymbol, PyOperationBase &from)
Replaces all symbol uses within an operation.
Definition: IRCore.cpp:1919
static void setVisibility(PyOperationBase &symbol, const std::string &visibility)
Definition: IRCore.cpp:1901
static void setSymbolName(PyOperationBase &symbol, const std::string &name)
Definition: IRCore.cpp:1875
~PySymbolTable()
Destroys the symbol table.
Definition: IRModule.h:1077
void erase(PyOperationBase &symbol)
Removes the given operation from the symbol table and erases it.
Definition: IRCore.cpp:1836
PySymbolTable(PyOperationBase &operation)
Constructs a symbol table for the given operation.
Definition: IRCore.cpp:1816
pybind11::object dunderGetItem(const std::string &name)
Returns the symbol (opview) with the given name, throws if there is no such symbol in the table.
Definition: IRCore.cpp:1824
static void walkSymbolTables(PyOperationBase &from, bool allSymUsesVisible, pybind11::object callback)
Walks all symbol tables under and including 'from'.
Definition: IRCore.cpp:1931
static PyAttribute getVisibility(PyOperationBase &symbol)
Gets and sets the visibility of a symbol op.
Definition: IRCore.cpp:1890
Tracks an entry in the thread context stack.
Definition: IRModule.h:102
static PyThreadContextEntry * getTopOfStack()
Stack management.
Definition: IRCore.cpp:693
static void popLocation(PyLocation &location)
Definition: IRCore.cpp:807
PyThreadContextEntry(FrameKind frameKind, pybind11::object context, pybind11::object insertionPoint, pybind11::object location)
Definition: IRModule.h:110
static pybind11::object pushContext(PyMlirContext &context)
Definition: IRCore.cpp:755
static PyLocation * getDefaultLocation()
Gets the top of stack location and returns nullptr if not defined.
Definition: IRCore.cpp:750
static void popInsertionPoint(PyInsertionPoint &insertionPoint)
Definition: IRCore.cpp:785
static void popContext(PyMlirContext &context)
Definition: IRCore.cpp:763
static PyInsertionPoint * getDefaultInsertionPoint()
Gets the top of stack insertion point and return nullptr if not defined.
Definition: IRCore.cpp:745
static pybind11::object pushInsertionPoint(PyInsertionPoint &insertionPoint)
Definition: IRCore.cpp:774
static pybind11::object pushLocation(PyLocation &location)
Definition: IRCore.cpp:798
PyMlirContext * getContext()
Definition: IRCore.cpp:722
static PyMlirContext * getDefaultContext()
Gets the top of stack context and return nullptr if not defined.
Definition: IRCore.cpp:740
static std::vector< PyThreadContextEntry > & getStack()
Gets the thread local stack.
Definition: IRCore.cpp:688
PyInsertionPoint * getInsertionPoint()
Definition: IRCore.cpp:728
Wrapper around the generic MlirType.
Definition: IRModule.h:807
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirType.
Definition: IRCore.cpp:1775
static PyType createFromCapsule(pybind11::object capsule)
Creates a PyType from the MlirType wrapped by a capsule.
Definition: IRCore.cpp:1779
bool operator==(const PyType &other)
Definition: IRCore.cpp:1771
PyType(PyMlirContextRef contextRef, MlirType type)
Definition: IRModule.h:809
MlirType get() const
Definition: IRModule.h:813
Wrapper around the generic MlirValue.
Definition: IRModule.h:978
static PyValue createFromCapsule(pybind11::object capsule)
Creates a PyValue from the MlirValue wrapped by a capsule.
Definition: IRCore.cpp:1795
PyValue(PyOperationRef parentOperation, MlirValue value)
Definition: IRModule.h:980
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirValue.
Definition: IRCore.cpp:1791
MlirValue get()
Definition: IRModule.h:984
PyOperationRef & getParentOperation()
Definition: IRModule.h:985
MlirDiagnosticSeverity
Severity of a diagnostic.
Definition: Diagnostics.h:32
MLIR_CAPI_EXPORTED MlirDiagnosticHandlerID mlirContextAttachDiagnosticHandler(MlirContext context, MlirDiagnosticHandler handler, void *userData, void(*deleteUserData)(void *))
Attaches the diagnostic handler to the context.
Definition: Diagnostics.cpp:56
MLIR_CAPI_EXPORTED void mlirContextDetachDiagnosticHandler(MlirContext context, MlirDiagnosticHandlerID id)
Detaches an attached diagnostic handler from the context given its identifier.
Definition: Diagnostics.cpp:72
uint64_t MlirDiagnosticHandlerID
Opaque identifier of a diagnostic handler, useful to detach a handler.
Definition: Diagnostics.h:41
MLIR_CAPI_EXPORTED void mlirDialectRegistryDestroy(MlirDialectRegistry registry)
Takes a dialect registry owned by the caller and destroys it.
Definition: IR.cpp:110
MLIR_CAPI_EXPORTED MlirType mlirAttributeGetType(MlirAttribute attribute)
Gets the type of this attribute.
Definition: IR.cpp:820
static bool mlirBlockIsNull(MlirBlock block)
Checks whether a block is null.
Definition: IR.h:641
MLIR_CAPI_EXPORTED void mlirSymbolTableDestroy(MlirSymbolTable symbolTable)
Destroys the symbol table created with mlirSymbolTableCreate.
Definition: IR.cpp:886
static bool mlirDialectRegistryIsNull(MlirDialectRegistry registry)
Checks if the dialect registry is null.
Definition: IR.h:216
static bool mlirRegionIsNull(MlirRegion region)
Checks whether a region is null.
Definition: IR.h:584
MLIR_CAPI_EXPORTED MlirDialectRegistry mlirDialectRegistryCreate(void)
Creates a dialect registry and transfers its ownership to the caller.
Definition: IR.cpp:106
MLIR_CAPI_EXPORTED void mlirOperationRemoveFromParent(MlirOperation op)
Removes the given operation from its parent block.
Definition: IR.cpp:386
void populateIRAttributes(pybind11::module &m)
void populateIRTypes(pybind11::module &m)
PyObjectRef< PyMlirContext > PyMlirContextRef
Wrapper around MlirContext.
Definition: IRModule.h:157
void populateIRAffine(pybind11::module &m)
PyObjectRef< PyModule > PyModuleRef
Definition: IRModule.h:503
pybind11::error_already_set SetPyError(PyObject *excClass, const llvm::Twine &message)
Definition: PybindUtils.cpp:12
void populateIRCore(pybind11::module &m)
PyObjectRef< PyOperation > PyOperationRef
Definition: IRModule.h:578
void populateIRInterfaces(py::module &m)
Include the generated interface declarations.
An opaque reference to a diagnostic, always owned by the diagnostics engine (context).
Definition: Diagnostics.h:26
A logical result value, essentially a boolean with named states.
Definition: Support.h:114
Named MLIR attribute.
Definition: IR.h:75
Custom exception that allows access to error diagnostic information.
Definition: IRModule.h:1123
MLIRError(llvm::Twine message, std::vector< PyDiagnostic::DiagnosticInfo > &&errorDiagnostics={})
Definition: IRModule.h:1124
std::vector< PyDiagnostic::DiagnosticInfo > errorDiagnostics
Definition: IRModule.h:1128
Materialized diagnostic information.
Definition: IRModule.h:335
std::vector< DiagnosticInfo > notes
Definition: IRModule.h:339
RAII object that captures any error diagnostics emitted to the provided context.
Definition: IRModule.h:401
std::vector< PyDiagnostic::DiagnosticInfo > take()
Definition: IRModule.h:411
ErrorCapture(PyMlirContextRef ctx)
Definition: IRModule.h:402