MLIR 22.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// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8//===----------------------------------------------------------------------===//
9
10#ifndef MLIR_BINDINGS_PYTHON_IRMODULES_H
11#define MLIR_BINDINGS_PYTHON_IRMODULES_H
12
13#include <optional>
14#include <sstream>
15#include <utility>
16#include <vector>
17
18#include "Globals.h"
19#include "NanobindUtils.h"
20#include "mlir-c/AffineExpr.h"
21#include "mlir-c/AffineMap.h"
23#include "mlir-c/Diagnostics.h"
24#include "mlir-c/IR.h"
25#include "mlir-c/IntegerSet.h"
26#include "mlir-c/Transforms.h"
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/Support/ThreadPool.h"
31
32namespace mlir {
33namespace python {
34
35class PyBlock;
36class PyDiagnostic;
39class PyLocation;
41class PyMlirContext;
43class PyModule;
44class PyOperation;
45class PyOperationBase;
46class PyType;
47class PySymbolTable;
48class PyValue;
49
50/// Template for a reference to a concrete type which captures a python
51/// reference to its underlying python object.
52template <typename T>
54public:
55 PyObjectRef(T *referrent, nanobind::object object)
56 : referrent(referrent), object(std::move(object)) {
57 assert(this->referrent &&
58 "cannot construct PyObjectRef with null referrent");
59 assert(this->object && "cannot construct PyObjectRef with null object");
60 }
61 PyObjectRef(PyObjectRef &&other) noexcept
62 : referrent(other.referrent), object(std::move(other.object)) {
63 other.referrent = nullptr;
64 assert(!other.object);
65 }
67 : referrent(other.referrent), object(other.object /* copies */) {}
68 ~PyObjectRef() = default;
69
71 if (!object)
72 return 0;
73 return Py_REFCNT(object.ptr());
74 }
75
76 /// Releases the object held by this instance, returning it.
77 /// This is the proper thing to return from a function that wants to return
78 /// the reference. Note that this does not work from initializers.
79 nanobind::object releaseObject() {
80 assert(referrent && object);
81 referrent = nullptr;
82 auto stolen = std::move(object);
83 return stolen;
84 }
85
86 T *get() { return referrent; }
88 assert(referrent && object);
89 return referrent;
90 }
91 nanobind::object getObject() {
92 assert(referrent && object);
93 return object;
94 }
95 operator bool() const { return referrent && object; }
96
97 using NBTypedT = nanobind::typed<nanobind::object, T>;
98
99private:
100 T *referrent;
101 nanobind::object object;
102};
103
104/// Tracks an entry in the thread context stack. New entries are pushed onto
105/// here for each with block that activates a new InsertionPoint, Context or
106/// Location.
107///
108/// Pushing either a Location or InsertionPoint also pushes its associated
109/// Context. Pushing a Context will not modify the Location or InsertionPoint
110/// unless if they are from a different context, in which case, they are
111/// cleared.
113public:
119
120 PyThreadContextEntry(FrameKind frameKind, nanobind::object context,
121 nanobind::object insertionPoint,
122 nanobind::object location)
123 : context(std::move(context)), insertionPoint(std::move(insertionPoint)),
124 location(std::move(location)), frameKind(frameKind) {}
125
126 /// Gets the top of stack context and return nullptr if not defined.
128
129 /// Gets the top of stack insertion point and return nullptr if not defined.
131
132 /// Gets the top of stack location and returns nullptr if not defined.
134
138 FrameKind getFrameKind() { return frameKind; }
139
140 /// Stack management.
142 static nanobind::object pushContext(nanobind::object context);
143 static void popContext(PyMlirContext &context);
144 static nanobind::object pushInsertionPoint(nanobind::object insertionPoint);
145 static void popInsertionPoint(PyInsertionPoint &insertionPoint);
146 static nanobind::object pushLocation(nanobind::object location);
147 static void popLocation(PyLocation &location);
148
149 /// Gets the thread local stack.
150 static std::vector<PyThreadContextEntry> &getStack();
151
152private:
153 static void push(FrameKind frameKind, nanobind::object context,
154 nanobind::object insertionPoint, nanobind::object location);
155
156 /// An object reference to the PyContext.
157 nanobind::object context;
158 /// An object reference to the current insertion point.
159 nanobind::object insertionPoint;
160 /// An object reference to the current location.
161 nanobind::object location;
162 // The kind of push that was performed.
163 FrameKind frameKind;
164};
165
166/// Wrapper around MlirLlvmThreadPool
167/// Python object owns the C++ thread pool
169public:
171 ownedThreadPool = std::make_unique<llvm::DefaultThreadPool>();
172 }
173 PyThreadPool(const PyThreadPool &) = delete;
175
176 int getMaxConcurrency() const { return ownedThreadPool->getMaxConcurrency(); }
177 MlirLlvmThreadPool get() { return wrap(ownedThreadPool.get()); }
178
179 std::string _mlir_thread_pool_ptr() const {
180 std::stringstream ss;
181 ss << ownedThreadPool.get();
182 return ss.str();
183 }
184
185private:
186 std::unique_ptr<llvm::ThreadPoolInterface> ownedThreadPool;
187};
188
189/// Wrapper around MlirContext.
192public:
193 PyMlirContext() = delete;
194 PyMlirContext(MlirContext context);
195 PyMlirContext(const PyMlirContext &) = delete;
197
198 /// Returns a context reference for the singleton PyMlirContext wrapper for
199 /// the given context.
200 static PyMlirContextRef forContext(MlirContext context);
202
203 /// Accesses the underlying MlirContext.
204 MlirContext get() { return context; }
205
206 /// Gets a strong reference to this context, which will ensure it is kept
207 /// alive for the life of the reference.
209 return PyMlirContextRef(this, nanobind::cast(this));
210 }
211
212 /// Gets a capsule wrapping the void* within the MlirContext.
213 nanobind::object getCapsule();
214
215 /// Creates a PyMlirContext from the MlirContext wrapped by a capsule.
216 /// Note that PyMlirContext instances are uniqued, so the returned object
217 /// may be a pre-existing object. Ownership of the underlying MlirContext
218 /// is taken by calling this function.
219 static nanobind::object createFromCapsule(nanobind::object capsule);
220
221 /// Gets the count of live context objects. Used for testing.
222 static size_t getLiveCount();
223
224 /// Gets the count of live modules associated with this context.
225 /// Used for testing.
226 size_t getLiveModuleCount();
227
228 /// Enter and exit the context manager.
229 static nanobind::object contextEnter(nanobind::object context);
230 void contextExit(const nanobind::object &excType,
231 const nanobind::object &excVal,
232 const nanobind::object &excTb);
233
234 /// Attaches a Python callback as a diagnostic handler, returning a
235 /// registration object (internally a PyDiagnosticHandler).
236 nanobind::object attachDiagnosticHandler(nanobind::object callback);
237
238 /// Controls whether error diagnostics should be propagated to diagnostic
239 /// handlers, instead of being captured by `ErrorCapture`.
240 void setEmitErrorDiagnostics(bool value) { emitErrorDiagnostics = value; }
241 bool getEmitErrorDiagnostics() { return emitErrorDiagnostics; }
242 struct ErrorCapture;
243
244private:
245 // Interns the mapping of live MlirContext::ptr to PyMlirContext instances,
246 // preserving the relationship that an MlirContext maps to a single
247 // PyMlirContext wrapper. This could be replaced in the future with an
248 // extension mechanism on the MlirContext for stashing user pointers.
249 // Note that this holds a handle, which does not imply ownership.
250 // Mappings will be removed when the context is destructed.
251 using LiveContextMap = llvm::DenseMap<void *, PyMlirContext *>;
252 static nanobind::ft_mutex live_contexts_mutex;
253 static LiveContextMap &getLiveContexts();
254
255 // Interns all live modules associated with this context. Modules tracked
256 // in this map are valid. When a module is invalidated, it is removed
257 // from this map, and while it still exists as an instance, any
258 // attempt to access it will raise an error.
259 using LiveModuleMap =
261 LiveModuleMap liveModules;
262
263 bool emitErrorDiagnostics = false;
264
265 MlirContext context;
266 friend class PyModule;
267 friend class PyOperation;
268};
269
270/// Used in function arguments when None should resolve to the current context
271/// manager set instance.
273 : public Defaulting<DefaultingPyMlirContext, PyMlirContext> {
274public:
276 static constexpr const char kTypeDescription[] = "Context";
277 static PyMlirContext &resolve();
278};
279
280/// Base class for all objects that directly or indirectly depend on an
281/// MlirContext. The lifetime of the context will extend at least to the
282/// lifetime of these instances.
283/// Immutable objects that depend on a context extend this directly.
285public:
286 BaseContextObject(PyMlirContextRef ref) : contextRef(std::move(ref)) {
287 assert(this->contextRef &&
288 "context object constructed with null context ref");
289 }
290
291 /// Accesses the context reference.
292 PyMlirContextRef &getContext() { return contextRef; }
293
294private:
295 PyMlirContextRef contextRef;
296};
297
298/// Wrapper around an MlirLocation.
300public:
301 PyLocation(PyMlirContextRef contextRef, MlirLocation loc)
302 : BaseContextObject(std::move(contextRef)), loc(loc) {}
303
304 operator MlirLocation() const { return loc; }
305 MlirLocation get() const { return loc; }
306
307 /// Enter and exit the context manager.
308 static nanobind::object contextEnter(nanobind::object location);
309 void contextExit(const nanobind::object &excType,
310 const nanobind::object &excVal,
311 const nanobind::object &excTb);
312
313 /// Gets a capsule wrapping the void* within the MlirLocation.
314 nanobind::object getCapsule();
315
316 /// Creates a PyLocation from the MlirLocation wrapped by a capsule.
317 /// Note that PyLocation instances are uniqued, so the returned object
318 /// may be a pre-existing object. Ownership of the underlying MlirLocation
319 /// is taken by calling this function.
320 static PyLocation createFromCapsule(nanobind::object capsule);
321
322private:
323 MlirLocation loc;
324};
325
326/// Python class mirroring the C MlirDiagnostic struct. Note that these structs
327/// are only valid for the duration of a diagnostic callback and attempting
328/// to access them outside of that will raise an exception. This applies to
329/// nested diagnostics (in the notes) as well.
331public:
332 PyDiagnostic(MlirDiagnostic diagnostic) : diagnostic(diagnostic) {}
333 void invalidate();
334 bool isValid() { return valid; }
337 nanobind::str getMessage();
338 nanobind::tuple getNotes();
339
340 /// Materialized diagnostic information. This is safe to access outside the
341 /// diagnostic callback.
345 std::string message;
346 std::vector<DiagnosticInfo> notes;
347 };
349
350private:
351 MlirDiagnostic diagnostic;
352
353 void checkValid();
354 /// If notes have been materialized from the diagnostic, then this will
355 /// be populated with the corresponding objects (all castable to
356 /// PyDiagnostic).
357 std::optional<nanobind::tuple> materializedNotes;
358 bool valid = true;
359};
360
361/// Represents a diagnostic handler attached to the context. The handler's
362/// callback will be invoked with PyDiagnostic instances until the detach()
363/// method is called or the context is destroyed. A diagnostic handler can be
364/// the subject of a `with` block, which will detach it when the block exits.
365///
366/// Since diagnostic handlers can call back into Python code which can do
367/// unsafe things (i.e. recursively emitting diagnostics, raising exceptions,
368/// etc), this is generally not deemed to be a great user-level API. Users
369/// should generally use some form of DiagnosticCollector. If the handler raises
370/// any exceptions, they will just be emitted to stderr and dropped.
371///
372/// The unique usage of this class means that its lifetime management is
373/// different from most other parts of the API. Instances are always created
374/// in an attached state and can transition to a detached state by either:
375/// a) The context being destroyed and unregistering all handlers.
376/// b) An explicit call to detach().
377/// The object may remain live from a Python perspective for an arbitrary time
378/// after detachment, but there is nothing the user can do with it (since there
379/// is no way to attach an existing handler object).
381public:
382 PyDiagnosticHandler(MlirContext context, nanobind::object callback);
384
385 bool isAttached() { return registeredID.has_value(); }
386 bool getHadError() { return hadError; }
387
388 /// Detaches the handler. Does nothing if not attached.
389 void detach();
390
391 nanobind::object contextEnter() { return nanobind::cast(this); }
392 void contextExit(const nanobind::object &excType,
393 const nanobind::object &excVal,
394 const nanobind::object &excTb) {
395 detach();
396 }
397
398private:
399 MlirContext context;
400 nanobind::object callback;
401 std::optional<MlirDiagnosticHandlerID> registeredID;
402 bool hadError = false;
403 friend class PyMlirContext;
404};
405
406/// RAII object that captures any error diagnostics emitted to the provided
407/// context.
410 : ctx(ctx), handlerID(mlirContextAttachDiagnosticHandler(
411 ctx->get(), handler, /*userData=*/this,
412 /*deleteUserData=*/nullptr)) {}
414 mlirContextDetachDiagnosticHandler(ctx->get(), handlerID);
415 assert(errors.empty() && "unhandled captured errors");
416 }
417
418 std::vector<PyDiagnostic::DiagnosticInfo> take() {
419 return std::move(errors);
420 };
421
422private:
424 MlirDiagnosticHandlerID handlerID;
425 std::vector<PyDiagnostic::DiagnosticInfo> errors;
426
427 static MlirLogicalResult handler(MlirDiagnostic diag, void *userData);
428};
429
430/// Wrapper around an MlirDialect. This is exported as `DialectDescriptor` in
431/// order to differentiate it from the `Dialect` base class which is extended by
432/// plugins which extend dialect functionality through extension python code.
433/// This should be seen as the "low-level" object and `Dialect` as the
434/// high-level, user facing object.
436public:
437 PyDialectDescriptor(PyMlirContextRef contextRef, MlirDialect dialect)
438 : BaseContextObject(std::move(contextRef)), dialect(dialect) {}
439
440 MlirDialect get() { return dialect; }
441
442private:
443 MlirDialect dialect;
444};
445
446/// User-level object for accessing dialects with dotted syntax such as:
447/// ctx.dialect.std
449public:
451 : BaseContextObject(std::move(contextRef)) {}
452
453 MlirDialect getDialectForKey(const std::string &key, bool attrError);
454};
455
456/// User-level dialect object. For dialects that have a registered extension,
457/// this will be the base class of the extension dialect type. For un-extended,
458/// objects of this type will be returned directly.
460public:
461 PyDialect(nanobind::object descriptor) : descriptor(std::move(descriptor)) {}
462
463 nanobind::object getDescriptor() { return descriptor; }
464
465private:
466 nanobind::object descriptor;
467};
468
469/// Wrapper around an MlirDialectRegistry.
470/// Upon construction, the Python wrapper takes ownership of the
471/// underlying MlirDialectRegistry.
473public:
475 PyDialectRegistry(MlirDialectRegistry registry) : registry(registry) {}
477 if (!mlirDialectRegistryIsNull(registry))
479 }
482 : registry(other.registry) {
483 other.registry = {nullptr};
484 }
485
486 operator MlirDialectRegistry() const { return registry; }
487 MlirDialectRegistry get() const { return registry; }
488
489 nanobind::object getCapsule();
490 static PyDialectRegistry createFromCapsule(nanobind::object capsule);
491
492private:
493 MlirDialectRegistry registry;
494};
495
496/// Used in function arguments when None should resolve to the current context
497/// manager set instance.
499 : public Defaulting<DefaultingPyLocation, PyLocation> {
500public:
502 static constexpr const char kTypeDescription[] = "Location";
503 static PyLocation &resolve();
504
505 operator MlirLocation() const { return *get(); }
506};
507
508/// Wrapper around MlirModule.
509/// This is the top-level, user-owned object that contains regions/ops/blocks.
510class PyModule;
513public:
514 /// Returns a PyModule reference for the given MlirModule. This always returns
515 /// a new object.
516 static PyModuleRef forModule(MlirModule module);
517 PyModule(PyModule &) = delete;
519 ~PyModule();
520
521 /// Gets the backing MlirModule.
522 MlirModule get() { return module; }
523
524 /// Gets a strong reference to this module.
526 return PyModuleRef(this, nanobind::borrow<nanobind::object>(handle));
527 }
528
529 /// Gets a capsule wrapping the void* within the MlirModule.
530 /// Note that the module does not (yet) provide a corresponding factory for
531 /// constructing from a capsule as that would require uniquing PyModule
532 /// instances, which is not currently done.
533 nanobind::object getCapsule();
534
535 /// Creates a PyModule from the MlirModule wrapped by a capsule.
536 /// Note this returns a new object BUT clearMlirModule() must be called to
537 /// prevent double-frees (of the underlying mlir::Module).
538 static nanobind::object createFromCapsule(nanobind::object capsule);
539
540 void clearMlirModule() { module = {nullptr}; }
541
542private:
543 PyModule(PyMlirContextRef contextRef, MlirModule module);
544 MlirModule module;
545 nanobind::handle handle;
546};
547
548class PyAsmState;
549
550/// Base class for PyOperation and PyOpView which exposes the primary, user
551/// visible methods for manipulating it.
553public:
554 virtual ~PyOperationBase() = default;
555 /// Implements the bound 'print' method and helps with others.
556 void print(std::optional<int64_t> largeElementsLimit,
557 std::optional<int64_t> largeResourceLimit, bool enableDebugInfo,
558 bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope,
559 bool useNameLocAsPrefix, bool assumeVerified,
560 nanobind::object fileObject, bool binary, bool skipRegions);
561 void print(PyAsmState &state, nanobind::object fileObject, bool binary);
562
563 nanobind::object
564 getAsm(bool binary, std::optional<int64_t> largeElementsLimit,
565 std::optional<int64_t> largeResourceLimit, bool enableDebugInfo,
566 bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope,
567 bool useNameLocAsPrefix, bool assumeVerified, bool skipRegions);
568
569 // Implement the bound 'writeBytecode' method.
570 void writeBytecode(const nanobind::object &fileObject,
571 std::optional<int64_t> bytecodeVersion);
572
573 // Implement the walk method.
574 void walk(std::function<MlirWalkResult(MlirOperation)> callback,
575 MlirWalkOrder walkOrder);
576
577 /// Moves the operation before or after the other operation.
578 void moveAfter(PyOperationBase &other);
579 void moveBefore(PyOperationBase &other);
580
581 /// Given an operation 'other' that is within the same parent block, return
582 /// whether the current operation is before 'other' in the operation list
583 /// of the parent block.
584 /// Note: This function has an average complexity of O(1), but worst case may
585 /// take O(N) where N is the number of operations within the parent block.
586 bool isBeforeInBlock(PyOperationBase &other);
587
588 /// Verify the operation. Throws `MLIRError` if verification fails, and
589 /// returns `true` otherwise.
590 bool verify();
591
592 /// Each must provide access to the raw Operation.
593 virtual PyOperation &getOperation() = 0;
594};
595
596/// Wrapper around PyOperation.
597/// Operations exist in either an attached (dependent) or detached (top-level)
598/// state. In the detached state (as on creation), an operation is owned by
599/// the creator and its lifetime extends either until its reference count
600/// drops to zero or it is attached to a parent, at which point its lifetime
601/// is bounded by its top-level parent reference.
602class PyOperation;
603class PyOpView;
606public:
607 ~PyOperation() override;
608 PyOperation &getOperation() override { return *this; }
609
610 /// Returns a PyOperation for the given MlirOperation, optionally associating
611 /// it with a parentKeepAlive.
612 static PyOperationRef
613 forOperation(PyMlirContextRef contextRef, MlirOperation operation,
614 nanobind::object parentKeepAlive = nanobind::object());
615
616 /// Creates a detached operation. The operation must not be associated with
617 /// any existing live operation.
618 static PyOperationRef
619 createDetached(PyMlirContextRef contextRef, MlirOperation operation,
620 nanobind::object parentKeepAlive = nanobind::object());
621
622 /// Parses a source string (either text assembly or bytecode), creating a
623 /// detached operation.
624 static PyOperationRef parse(PyMlirContextRef contextRef,
625 const std::string &sourceStr,
626 const std::string &sourceName);
627
628 /// Detaches the operation from its parent block and updates its state
629 /// accordingly.
632 setDetached();
633 parentKeepAlive = nanobind::object();
634 }
635
636 /// Gets the backing operation.
637 operator MlirOperation() const { return get(); }
638 MlirOperation get() const {
639 checkValid();
640 return operation;
641 }
642
644 return PyOperationRef(this, nanobind::borrow<nanobind::object>(handle));
645 }
646
647 bool isAttached() { return attached; }
648 void setAttached(const nanobind::object &parent = nanobind::object()) {
649 assert(!attached && "operation already attached");
650 attached = true;
651 }
652 void setDetached() {
653 assert(attached && "operation already detached");
654 attached = false;
655 }
656 void checkValid() const;
657
658 /// Gets the owning block or raises an exception if the operation has no
659 /// owning block.
661
662 /// Gets the parent operation or raises an exception if the operation has
663 /// no parent.
664 std::optional<PyOperationRef> getParentOperation();
665
666 /// Gets a capsule wrapping the void* within the MlirOperation.
667 nanobind::object getCapsule();
668
669 /// Creates a PyOperation from the MlirOperation wrapped by a capsule.
670 /// Ownership of the underlying MlirOperation is taken by calling this
671 /// function.
672 static nanobind::object createFromCapsule(const nanobind::object &capsule);
673
674 /// Creates an operation. See corresponding python docstring.
675 static nanobind::object
676 create(std::string_view name, std::optional<std::vector<PyType *>> results,
678 std::optional<nanobind::dict> attributes,
679 std::optional<std::vector<PyBlock *>> successors, int regions,
680 PyLocation &location, const nanobind::object &ip, bool inferType);
681
682 /// Creates an OpView suitable for this operation.
683 nanobind::object createOpView();
684
685 /// Erases the underlying MlirOperation, removes its pointer from the
686 /// parent context's live operations map, and sets the valid bit false.
687 void erase();
688
689 /// Invalidate the operation.
690 void setInvalid() { valid = false; }
691
692 /// Clones this operation.
693 nanobind::object clone(const nanobind::object &ip);
694
695 PyOperation(PyMlirContextRef contextRef, MlirOperation operation);
696
697private:
698 static PyOperationRef createInstance(PyMlirContextRef contextRef,
699 MlirOperation operation,
700 nanobind::object parentKeepAlive);
701
702 MlirOperation operation;
703 nanobind::handle handle;
704 // Keeps the parent alive, regardless of whether it is an Operation or
705 // Module.
706 // TODO: As implemented, this facility is only sufficient for modeling the
707 // trivial module parent back-reference. Generalize this to also account for
708 // transitions from detached to attached and address TODOs in the
709 // ir_operation.py regarding testing corresponding lifetime guarantees.
710 nanobind::object parentKeepAlive;
711 bool attached = true;
712 bool valid = true;
713
714 friend class PyOperationBase;
715 friend class PySymbolTable;
716};
717
718/// A PyOpView is equivalent to the C++ "Op" wrappers: these are the basis for
719/// providing more instance-specific accessors and serve as the base class for
720/// custom ODS-style operation classes. Since this class is subclass on the
721/// python side, it must present an __init__ method that operates in pure
722/// python types.
723class PyOpView : public PyOperationBase {
724public:
725 PyOpView(const nanobind::object &operationObject);
726 PyOperation &getOperation() override { return operation; }
727
728 nanobind::object getOperationObject() { return operationObject; }
729
730 static nanobind::object
731 buildGeneric(std::string_view name, std::tuple<int, bool> opRegionSpec,
732 nanobind::object operandSegmentSpecObj,
733 nanobind::object resultSegmentSpecObj,
734 std::optional<nanobind::list> resultTypeList,
735 nanobind::list operandList,
736 std::optional<nanobind::dict> attributes,
737 std::optional<std::vector<PyBlock *>> successors,
738 std::optional<int> regions, PyLocation &location,
739 const nanobind::object &maybeIp);
740
741 /// Construct an instance of a class deriving from OpView, bypassing its
742 /// `__init__` method. The derived class will typically define a constructor
743 /// that provides a convenient builder, but we need to side-step this when
744 /// constructing an `OpView` for an already-built operation.
745 ///
746 /// The caller is responsible for verifying that `operation` is a valid
747 /// operation to construct `cls` with.
748 static nanobind::object constructDerived(const nanobind::object &cls,
749 const nanobind::object &operation);
750
751private:
752 PyOperation &operation; // For efficient, cast-free access from C++
753 nanobind::object operationObject; // Holds the reference.
754};
755
756/// Wrapper around an MlirRegion.
757/// Regions are managed completely by their containing operation. Unlike the
758/// C++ API, the python API does not support detached regions.
759class PyRegion {
760public:
761 PyRegion(PyOperationRef parentOperation, MlirRegion region)
762 : parentOperation(std::move(parentOperation)), region(region) {
763 assert(!mlirRegionIsNull(region) && "python region cannot be null");
764 }
765 operator MlirRegion() const { return region; }
766
767 MlirRegion get() { return region; }
768 PyOperationRef &getParentOperation() { return parentOperation; }
769
770 void checkValid() { return parentOperation->checkValid(); }
771
772private:
773 PyOperationRef parentOperation;
774 MlirRegion region;
775};
776
777/// Wrapper around an MlirAsmState.
779public:
780 PyAsmState(MlirValue value, bool useLocalScope) {
782 // The OpPrintingFlags are not exposed Python side, create locally and
783 // associate lifetime with the state.
784 if (useLocalScope)
786 state = mlirAsmStateCreateForValue(value, flags);
787 }
788
789 PyAsmState(PyOperationBase &operation, bool useLocalScope) {
791 // The OpPrintingFlags are not exposed Python side, create locally and
792 // associate lifetime with the state.
793 if (useLocalScope)
795 state =
796 mlirAsmStateCreateForOperation(operation.getOperation().get(), flags);
797 }
799 // Delete copy constructors.
800 PyAsmState(PyAsmState &other) = delete;
801 PyAsmState(const PyAsmState &other) = delete;
802
803 MlirAsmState get() { return state; }
804
805private:
806 MlirAsmState state;
807 MlirOpPrintingFlags flags;
808};
809
810/// Wrapper around an MlirBlock.
811/// Blocks are managed completely by their containing operation. Unlike the
812/// C++ API, the python API does not support detached blocks.
813class PyBlock {
814public:
815 PyBlock(PyOperationRef parentOperation, MlirBlock block)
816 : parentOperation(std::move(parentOperation)), block(block) {
817 assert(!mlirBlockIsNull(block) && "python block cannot be null");
818 }
819
820 MlirBlock get() { return block; }
821 PyOperationRef &getParentOperation() { return parentOperation; }
822
823 void checkValid() { return parentOperation->checkValid(); }
824
825 /// Gets a capsule wrapping the void* within the MlirBlock.
826 nanobind::object getCapsule();
827
828private:
829 PyOperationRef parentOperation;
830 MlirBlock block;
831};
832
833/// An insertion point maintains a pointer to a Block and a reference operation.
834/// Calls to insert() will insert a new operation before the
835/// reference operation. If the reference operation is null, then appends to
836/// the end of the block.
838public:
839 /// Creates an insertion point positioned after the last operation in the
840 /// block, but still inside the block.
841 PyInsertionPoint(const PyBlock &block);
842 /// Creates an insertion point positioned before a reference operation.
843 PyInsertionPoint(PyOperationBase &beforeOperationBase);
844 /// Creates an insertion point positioned before a reference operation.
845 PyInsertionPoint(PyOperationRef beforeOperationRef);
846
847 /// Shortcut to create an insertion point at the beginning of the block.
849 /// Shortcut to create an insertion point before the block terminator.
851 /// Shortcut to create an insertion point to the node after the specified
852 /// operation.
854
855 /// Inserts an operation.
856 void insert(PyOperationBase &operationBase);
857
858 /// Enter and exit the context manager.
859 static nanobind::object contextEnter(nanobind::object insertionPoint);
860 void contextExit(const nanobind::object &excType,
861 const nanobind::object &excVal,
862 const nanobind::object &excTb);
863
864 PyBlock &getBlock() { return block; }
865 std::optional<PyOperationRef> &getRefOperation() { return refOperation; }
866
867private:
868 // Trampoline constructor that avoids null initializing members while
869 // looking up parents.
870 PyInsertionPoint(PyBlock block, std::optional<PyOperationRef> refOperation)
871 : refOperation(std::move(refOperation)), block(std::move(block)) {}
872
873 std::optional<PyOperationRef> refOperation;
874 PyBlock block;
875};
876/// Wrapper around the generic MlirType.
877/// The lifetime of a type is bound by the PyContext that created it.
878class PyType : public BaseContextObject {
879public:
880 PyType(PyMlirContextRef contextRef, MlirType type)
881 : BaseContextObject(std::move(contextRef)), type(type) {}
882 bool operator==(const PyType &other) const;
883 operator MlirType() const { return type; }
884 MlirType get() const { return type; }
885
886 /// Gets a capsule wrapping the void* within the MlirType.
887 nanobind::object getCapsule();
888
889 /// Creates a PyType from the MlirType wrapped by a capsule.
890 /// Note that PyType instances are uniqued, so the returned object
891 /// may be a pre-existing object. Ownership of the underlying MlirType
892 /// is taken by calling this function.
893 static PyType createFromCapsule(nanobind::object capsule);
894
895 nanobind::object maybeDownCast();
896
897private:
898 MlirType type;
899};
900
901/// A TypeID provides an efficient and unique identifier for a specific C++
902/// type. This allows for a C++ type to be compared, hashed, and stored in an
903/// opaque context. This class wraps around the generic MlirTypeID.
904class PyTypeID {
905public:
906 PyTypeID(MlirTypeID typeID) : typeID(typeID) {}
907 // Note, this tests whether the underlying TypeIDs are the same,
908 // not whether the wrapper MlirTypeIDs are the same, nor whether
909 // the PyTypeID objects are the same (i.e., PyTypeID is a value type).
910 bool operator==(const PyTypeID &other) const;
911 operator MlirTypeID() const { return typeID; }
912 MlirTypeID get() { return typeID; }
913
914 /// Gets a capsule wrapping the void* within the MlirTypeID.
915 nanobind::object getCapsule();
916
917 /// Creates a PyTypeID from the MlirTypeID wrapped by a capsule.
918 static PyTypeID createFromCapsule(nanobind::object capsule);
919
920private:
921 MlirTypeID typeID;
922};
923
924/// CRTP base classes for Python types that subclass Type and should be
925/// castable from it (i.e. via something like IntegerType(t)).
926/// By default, type class hierarchies are one level deep (i.e. a
927/// concrete type class extends PyType); however, intermediate python-visible
928/// base classes can be modeled by specifying a BaseTy.
929template <typename DerivedTy, typename BaseTy = PyType>
930class PyConcreteType : public BaseTy {
931public:
932 // Derived classes must define statics for:
933 // IsAFunctionTy isaFunction
934 // const char *pyClassName
935 using ClassTy = nanobind::class_<DerivedTy, BaseTy>;
936 using IsAFunctionTy = bool (*)(MlirType);
937 using GetTypeIDFunctionTy = MlirTypeID (*)();
938 static constexpr GetTypeIDFunctionTy getTypeIdFunction = nullptr;
939
940 PyConcreteType() = default;
941 PyConcreteType(PyMlirContextRef contextRef, MlirType t)
942 : BaseTy(std::move(contextRef), t) {}
945
946 static MlirType castFrom(PyType &orig) {
947 if (!DerivedTy::isaFunction(orig)) {
948 auto origRepr =
949 nanobind::cast<std::string>(nanobind::repr(nanobind::cast(orig)));
950 throw nanobind::value_error((llvm::Twine("Cannot cast type to ") +
951 DerivedTy::pyClassName + " (from " +
952 origRepr + ")")
953 .str()
954 .c_str());
955 }
956 return orig;
957 }
958
959 static void bind(nanobind::module_ &m) {
960 auto cls = ClassTy(m, DerivedTy::pyClassName);
961 cls.def(nanobind::init<PyType &>(), nanobind::keep_alive<0, 1>(),
962 nanobind::arg("cast_from_type"));
963 cls.def_static(
964 "isinstance",
965 [](PyType &otherType) -> bool {
966 return DerivedTy::isaFunction(otherType);
967 },
968 nanobind::arg("other"));
969 cls.def_prop_ro_static(
970 "static_typeid",
971 [](nanobind::object & /*class*/) {
972 if (DerivedTy::getTypeIdFunction)
973 return PyTypeID(DerivedTy::getTypeIdFunction());
974 throw nanobind::attribute_error(
975 (DerivedTy::pyClassName + llvm::Twine(" has no typeid."))
976 .str()
977 .c_str());
978 },
979 nanobind::sig("def static_typeid(/) -> TypeID"));
980 cls.def_prop_ro("typeid", [](PyType &self) {
981 return nanobind::cast<PyTypeID>(nanobind::cast(self).attr("typeid"));
982 });
983 cls.def("__repr__", [](DerivedTy &self) {
984 PyPrintAccumulator printAccum;
985 printAccum.parts.append(DerivedTy::pyClassName);
986 printAccum.parts.append("(");
987 mlirTypePrint(self, printAccum.getCallback(), printAccum.getUserData());
988 printAccum.parts.append(")");
989 return printAccum.join();
990 });
991
992 if (DerivedTy::getTypeIdFunction) {
994 DerivedTy::getTypeIdFunction(),
995 nanobind::cast<nanobind::callable>(nanobind::cpp_function(
996 [](PyType pyType) -> DerivedTy { return pyType; })));
997 }
998
999 DerivedTy::bindDerived(cls);
1000 }
1001
1002 /// Implemented by derived classes to add methods to the Python subclass.
1003 static void bindDerived(ClassTy &m) {}
1004};
1005
1006/// Wrapper around the generic MlirAttribute.
1007/// The lifetime of a type is bound by the PyContext that created it.
1009public:
1010 PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
1011 : BaseContextObject(std::move(contextRef)), attr(attr) {}
1012 bool operator==(const PyAttribute &other) const;
1013 operator MlirAttribute() const { return attr; }
1014 MlirAttribute get() const { return attr; }
1015
1016 /// Gets a capsule wrapping the void* within the MlirAttribute.
1017 nanobind::object getCapsule();
1018
1019 /// Creates a PyAttribute from the MlirAttribute wrapped by a capsule.
1020 /// Note that PyAttribute instances are uniqued, so the returned object
1021 /// may be a pre-existing object. Ownership of the underlying MlirAttribute
1022 /// is taken by calling this function.
1023 static PyAttribute createFromCapsule(const nanobind::object &capsule);
1024
1025 nanobind::object maybeDownCast();
1026
1027private:
1028 MlirAttribute attr;
1029};
1030
1031/// Represents a Python MlirNamedAttr, carrying an optional owned name.
1032/// TODO: Refactor this and the C-API to be based on an Identifier owned
1033/// by the context so as to avoid ownership issues here.
1035public:
1036 /// Constructs a PyNamedAttr that retains an owned name. This should be
1037 /// used in any code that originates an MlirNamedAttribute from a python
1038 /// string.
1039 /// The lifetime of the PyNamedAttr must extend to the lifetime of the
1040 /// passed attribute.
1041 PyNamedAttribute(MlirAttribute attr, std::string ownedName);
1042
1044
1045private:
1046 // Since the MlirNamedAttr contains an internal pointer to the actual
1047 // memory of the owned string, it must be heap allocated to remain valid.
1048 // Otherwise, strings that fit within the small object optimization threshold
1049 // will have their memory address change as the containing object is moved,
1050 // resulting in an invalid aliased pointer.
1051 std::unique_ptr<std::string> ownedName;
1052};
1053
1054/// CRTP base classes for Python attributes that subclass Attribute and should
1055/// be castable from it (i.e. via something like StringAttr(attr)).
1056/// By default, attribute class hierarchies are one level deep (i.e. a
1057/// concrete attribute class extends PyAttribute); however, intermediate
1058/// python-visible base classes can be modeled by specifying a BaseTy.
1059template <typename DerivedTy, typename BaseTy = PyAttribute>
1060class PyConcreteAttribute : public BaseTy {
1061public:
1062 // Derived classes must define statics for:
1063 // IsAFunctionTy isaFunction
1064 // const char *pyClassName
1065 using ClassTy = nanobind::class_<DerivedTy, BaseTy>;
1066 using IsAFunctionTy = bool (*)(MlirAttribute);
1067 using GetTypeIDFunctionTy = MlirTypeID (*)();
1068 static constexpr GetTypeIDFunctionTy getTypeIdFunction = nullptr;
1069
1071 PyConcreteAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
1072 : BaseTy(std::move(contextRef), attr) {}
1075
1076 static MlirAttribute castFrom(PyAttribute &orig) {
1077 if (!DerivedTy::isaFunction(orig)) {
1078 auto origRepr =
1079 nanobind::cast<std::string>(nanobind::repr(nanobind::cast(orig)));
1080 throw nanobind::value_error((llvm::Twine("Cannot cast attribute to ") +
1081 DerivedTy::pyClassName + " (from " +
1082 origRepr + ")")
1083 .str()
1084 .c_str());
1085 }
1086 return orig;
1087 }
1088
1089 static void bind(nanobind::module_ &m, PyType_Slot *slots = nullptr) {
1090 ClassTy cls;
1091 if (slots) {
1092 cls = ClassTy(m, DerivedTy::pyClassName, nanobind::type_slots(slots));
1093 } else {
1094 cls = ClassTy(m, DerivedTy::pyClassName);
1095 }
1096 cls.def(nanobind::init<PyAttribute &>(), nanobind::keep_alive<0, 1>(),
1097 nanobind::arg("cast_from_attr"));
1098 cls.def_static(
1099 "isinstance",
1100 [](PyAttribute &otherAttr) -> bool {
1101 return DerivedTy::isaFunction(otherAttr);
1102 },
1103 nanobind::arg("other"));
1104 cls.def_prop_ro(
1105 "type",
1106 [](PyAttribute &attr) -> nanobind::typed<nanobind::object, PyType> {
1107 return PyType(attr.getContext(), mlirAttributeGetType(attr))
1108 .maybeDownCast();
1109 });
1110 cls.def_prop_ro_static(
1111 "static_typeid",
1112 [](nanobind::object & /*class*/) -> PyTypeID {
1113 if (DerivedTy::getTypeIdFunction)
1114 return PyTypeID(DerivedTy::getTypeIdFunction());
1115 throw nanobind::attribute_error(
1116 (DerivedTy::pyClassName + llvm::Twine(" has no typeid."))
1117 .str()
1118 .c_str());
1119 },
1120 nanobind::sig("def static_typeid(/) -> TypeID"));
1121 cls.def_prop_ro("typeid", [](PyAttribute &self) {
1122 return nanobind::cast<PyTypeID>(nanobind::cast(self).attr("typeid"));
1123 });
1124 cls.def("__repr__", [](DerivedTy &self) {
1125 PyPrintAccumulator printAccum;
1126 printAccum.parts.append(DerivedTy::pyClassName);
1127 printAccum.parts.append("(");
1128 mlirAttributePrint(self, printAccum.getCallback(),
1129 printAccum.getUserData());
1130 printAccum.parts.append(")");
1131 return printAccum.join();
1132 });
1133
1134 if (DerivedTy::getTypeIdFunction) {
1136 DerivedTy::getTypeIdFunction(),
1137 nanobind::cast<nanobind::callable>(
1138 nanobind::cpp_function([](PyAttribute pyAttribute) -> DerivedTy {
1139 return pyAttribute;
1140 })));
1141 }
1142
1143 DerivedTy::bindDerived(cls);
1144 }
1145
1146 /// Implemented by derived classes to add methods to the Python subclass.
1147 static void bindDerived(ClassTy &m) {}
1148};
1149
1150class PyStringAttribute : public PyConcreteAttribute<PyStringAttribute> {
1151public:
1153 static constexpr const char *pyClassName = "StringAttr";
1157
1158 static void bindDerived(ClassTy &c);
1159};
1160
1161/// Wrapper around the generic MlirValue.
1162/// Values are managed completely by the operation that resulted in their
1163/// definition. For op result value, this is the operation that defines the
1164/// value. For block argument values, this is the operation that contains the
1165/// block to which the value is an argument (blocks cannot be detached in Python
1166/// bindings so such operation always exists).
1167class PyValue {
1168public:
1169 // The virtual here is "load bearing" in that it enables RTTI
1170 // for PyConcreteValue CRTP classes that support maybeDownCast.
1171 // See PyValue::maybeDownCast.
1172 virtual ~PyValue() = default;
1173 PyValue(PyOperationRef parentOperation, MlirValue value)
1174 : parentOperation(std::move(parentOperation)), value(value) {}
1175 operator MlirValue() const { return value; }
1176
1177 MlirValue get() { return value; }
1178 PyOperationRef &getParentOperation() { return parentOperation; }
1179
1180 void checkValid() { return parentOperation->checkValid(); }
1181
1182 /// Gets a capsule wrapping the void* within the MlirValue.
1183 nanobind::object getCapsule();
1184
1185 nanobind::object maybeDownCast();
1186
1187 /// Creates a PyValue from the MlirValue wrapped by a capsule. Ownership of
1188 /// the underlying MlirValue is still tied to the owning operation.
1189 static PyValue createFromCapsule(nanobind::object capsule);
1190
1191private:
1192 PyOperationRef parentOperation;
1193 MlirValue value;
1194};
1195
1196/// Wrapper around MlirAffineExpr. Affine expressions are owned by the context.
1198public:
1199 PyAffineExpr(PyMlirContextRef contextRef, MlirAffineExpr affineExpr)
1200 : BaseContextObject(std::move(contextRef)), affineExpr(affineExpr) {}
1201 bool operator==(const PyAffineExpr &other) const;
1202 operator MlirAffineExpr() const { return affineExpr; }
1203 MlirAffineExpr get() const { return affineExpr; }
1204
1205 /// Gets a capsule wrapping the void* within the MlirAffineExpr.
1206 nanobind::object getCapsule();
1207
1208 /// Creates a PyAffineExpr from the MlirAffineExpr wrapped by a capsule.
1209 /// Note that PyAffineExpr instances are uniqued, so the returned object
1210 /// may be a pre-existing object. Ownership of the underlying MlirAffineExpr
1211 /// is taken by calling this function.
1212 static PyAffineExpr createFromCapsule(const nanobind::object &capsule);
1213
1214 PyAffineExpr add(const PyAffineExpr &other) const;
1215 PyAffineExpr mul(const PyAffineExpr &other) const;
1217 PyAffineExpr ceilDiv(const PyAffineExpr &other) const;
1218 PyAffineExpr mod(const PyAffineExpr &other) const;
1219
1220private:
1221 MlirAffineExpr affineExpr;
1222};
1223
1225public:
1226 PyAffineMap(PyMlirContextRef contextRef, MlirAffineMap affineMap)
1227 : BaseContextObject(std::move(contextRef)), affineMap(affineMap) {}
1228 bool operator==(const PyAffineMap &other) const;
1229 operator MlirAffineMap() const { return affineMap; }
1230 MlirAffineMap get() const { return affineMap; }
1231
1232 /// Gets a capsule wrapping the void* within the MlirAffineMap.
1233 nanobind::object getCapsule();
1234
1235 /// Creates a PyAffineMap from the MlirAffineMap wrapped by a capsule.
1236 /// Note that PyAffineMap instances are uniqued, so the returned object
1237 /// may be a pre-existing object. Ownership of the underlying MlirAffineMap
1238 /// is taken by calling this function.
1239 static PyAffineMap createFromCapsule(const nanobind::object &capsule);
1240
1241private:
1242 MlirAffineMap affineMap;
1243};
1244
1246public:
1247 PyIntegerSet(PyMlirContextRef contextRef, MlirIntegerSet integerSet)
1248 : BaseContextObject(std::move(contextRef)), integerSet(integerSet) {}
1249 bool operator==(const PyIntegerSet &other) const;
1250 operator MlirIntegerSet() const { return integerSet; }
1251 MlirIntegerSet get() const { return integerSet; }
1252
1253 /// Gets a capsule wrapping the void* within the MlirIntegerSet.
1254 nanobind::object getCapsule();
1255
1256 /// Creates a PyIntegerSet from the MlirAffineMap wrapped by a capsule.
1257 /// Note that PyIntegerSet instances may be uniqued, so the returned object
1258 /// may be a pre-existing object. Integer sets are owned by the context.
1259 static PyIntegerSet createFromCapsule(const nanobind::object &capsule);
1260
1261private:
1262 MlirIntegerSet integerSet;
1263};
1264
1265/// Bindings for MLIR symbol tables.
1267public:
1268 /// Constructs a symbol table for the given operation.
1269 explicit PySymbolTable(PyOperationBase &operation);
1270
1271 /// Destroys the symbol table.
1273
1274 /// Returns the symbol (opview) with the given name, throws if there is no
1275 /// such symbol in the table.
1276 nanobind::object dunderGetItem(const std::string &name);
1277
1278 /// Removes the given operation from the symbol table and erases it.
1279 void erase(PyOperationBase &symbol);
1280
1281 /// Removes the operation with the given name from the symbol table and erases
1282 /// it, throws if there is no such symbol in the table.
1283 void dunderDel(const std::string &name);
1284
1285 /// Inserts the given operation into the symbol table. The operation must have
1286 /// the symbol trait.
1288
1289 /// Gets and sets the name of a symbol op.
1291 static void setSymbolName(PyOperationBase &symbol, const std::string &name);
1292
1293 /// Gets and sets the visibility of a symbol op.
1295 static void setVisibility(PyOperationBase &symbol,
1296 const std::string &visibility);
1297
1298 /// Replaces all symbol uses within an operation. See the API
1299 /// mlirSymbolTableReplaceAllSymbolUses for all caveats.
1300 static void replaceAllSymbolUses(const std::string &oldSymbol,
1301 const std::string &newSymbol,
1302 PyOperationBase &from);
1303
1304 /// Walks all symbol tables under and including 'from'.
1305 static void walkSymbolTables(PyOperationBase &from, bool allSymUsesVisible,
1306 nanobind::object callback);
1307
1308 /// Casts the bindings class into the C API structure.
1309 operator MlirSymbolTable() { return symbolTable; }
1310
1311private:
1312 PyOperationRef operation;
1313 MlirSymbolTable symbolTable;
1314};
1315
1316/// Custom exception that allows access to error diagnostic information. This is
1317/// converted to the `ir.MLIRError` python exception when thrown.
1319 MLIRError(llvm::Twine message,
1320 std::vector<PyDiagnostic::DiagnosticInfo> &&errorDiagnostics = {})
1321 : message(message.str()), errorDiagnostics(std::move(errorDiagnostics)) {}
1322 std::string message;
1323 std::vector<PyDiagnostic::DiagnosticInfo> errorDiagnostics;
1324};
1325
1326void populateIRAffine(nanobind::module_ &m);
1327void populateIRAttributes(nanobind::module_ &m);
1328void populateIRCore(nanobind::module_ &m);
1329void populateIRInterfaces(nanobind::module_ &m);
1330void populateIRTypes(nanobind::module_ &m);
1331
1332} // namespace python
1333} // namespace mlir
1334
1335namespace nanobind {
1336namespace detail {
1337
1338template <>
1339struct type_caster<mlir::python::DefaultingPyMlirContext>
1340 : MlirDefaultingCaster<mlir::python::DefaultingPyMlirContext> {};
1341template <>
1342struct type_caster<mlir::python::DefaultingPyLocation>
1343 : MlirDefaultingCaster<mlir::python::DefaultingPyLocation> {};
1344
1345} // namespace detail
1346} // namespace nanobind
1347
1348#endif // MLIR_BINDINGS_PYTHON_IRMODULES_H
MlirAsmState mlirAsmStateCreateForValue(MlirValue value, MlirOpPrintingFlags flags)
Definition IR.cpp:178
MlirOpPrintingFlags mlirOpPrintingFlagsCreate()
Definition IR.cpp:202
void mlirOpPrintingFlagsUseLocalScope(MlirOpPrintingFlags flags)
Definition IR.cpp:233
MlirAsmState mlirAsmStateCreateForOperation(MlirOperation op, MlirOpPrintingFlags flags)
Definition IR.cpp:157
MlirType mlirAttributeGetType(MlirAttribute attribute)
Definition IR.cpp:1279
void mlirOperationRemoveFromParent(MlirOperation op)
Definition IR.cpp:641
void mlirOpPrintingFlagsDestroy(MlirOpPrintingFlags flags)
Definition IR.cpp:206
void mlirTypePrint(MlirType type, MlirStringCallback callback, void *userData)
Definition IR.cpp:1260
static std::string diag(const llvm::Value &value)
PyMlirContextRef & getContext()
Accesses the context reference.
Definition IRModule.h:292
BaseContextObject(PyMlirContextRef ref)
Definition IRModule.h:286
Used in function arguments when None should resolve to the current context manager set instance.
Definition IRModule.h:499
static PyLocation & resolve()
Definition IRCore.cpp:951
static constexpr const char kTypeDescription[]
Definition IRModule.h:502
Defaulting()=default
Type casters require the type to be default constructible, but using such an instance is illegal.
Used in function arguments when None should resolve to the current context manager set instance.
Definition IRModule.h:273
static constexpr const char kTypeDescription[]
Definition IRModule.h:276
Defaulting()=default
Type casters require the type to be default constructible, but using such an instance is illegal.
static PyMlirContext & resolve()
Definition IRCore.cpp:672
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:1197
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirAffineExpr.
Definition IRAffine.cpp:365
static PyAffineExpr createFromCapsule(const nanobind::object &capsule)
Creates a PyAffineExpr from the MlirAffineExpr wrapped by a capsule.
Definition IRAffine.cpp:369
PyAffineExpr(PyMlirContextRef contextRef, MlirAffineExpr affineExpr)
Definition IRModule.h:1199
PyAffineExpr ceilDiv(const PyAffineExpr &other) const
PyAffineExpr mul(const PyAffineExpr &other) const
PyAffineExpr mod(const PyAffineExpr &other) const
PyAffineExpr floorDiv(const PyAffineExpr &other) const
bool operator==(const PyAffineExpr &other) const
Definition IRAffine.cpp:361
PyAffineExpr add(const PyAffineExpr &other) const
MlirAffineExpr get() const
Definition IRModule.h:1203
PyAffineMap(PyMlirContextRef contextRef, MlirAffineMap affineMap)
Definition IRModule.h:1226
bool operator==(const PyAffineMap &other) const
Definition IRAffine.cpp:419
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirAffineMap.
Definition IRAffine.cpp:423
MlirAffineMap get() const
Definition IRModule.h:1230
static PyAffineMap createFromCapsule(const nanobind::object &capsule)
Creates a PyAffineMap from the MlirAffineMap wrapped by a capsule.
Definition IRAffine.cpp:427
Wrapper around an MlirAsmState.
Definition IRModule.h:778
PyAsmState(PyOperationBase &operation, bool useLocalScope)
Definition IRModule.h:789
PyAsmState(MlirValue value, bool useLocalScope)
Definition IRModule.h:780
PyAsmState(PyAsmState &other)=delete
PyAsmState(const PyAsmState &other)=delete
MlirAsmState get()
Definition IRModule.h:803
Wrapper around the generic MlirAttribute.
Definition IRModule.h:1008
static PyAttribute createFromCapsule(const nanobind::object &capsule)
Creates a PyAttribute from the MlirAttribute wrapped by a capsule.
Definition IRCore.cpp:2036
PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
Definition IRModule.h:1010
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirAttribute.
Definition IRCore.cpp:2032
nanobind::object maybeDownCast()
Definition IRCore.cpp:2044
MlirAttribute get() const
Definition IRModule.h:1014
bool operator==(const PyAttribute &other) const
Definition IRCore.cpp:2028
Wrapper around an MlirBlock.
Definition IRModule.h:813
PyOperationRef & getParentOperation()
Definition IRModule.h:821
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirBlock.
Definition IRCore.cpp:196
PyBlock(PyOperationRef parentOperation, MlirBlock block)
Definition IRModule.h:815
MlirTypeID(*)() GetTypeIDFunctionTy
Definition IRModule.h:1067
static MlirAttribute castFrom(PyAttribute &orig)
Definition IRModule.h:1076
nanobind::class_< DerivedTy, BaseTy > ClassTy
Definition IRModule.h:1065
static constexpr GetTypeIDFunctionTy getTypeIdFunction
Definition IRModule.h:1068
static void bind(nanobind::module_ &m, PyType_Slot *slots=nullptr)
Definition IRModule.h:1089
bool(*)(MlirAttribute) IsAFunctionTy
Definition IRModule.h:1066
PyConcreteAttribute(PyAttribute &orig)
Definition IRModule.h:1073
PyConcreteAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
Definition IRModule.h:1071
static void bindDerived(ClassTy &m)
Implemented by derived classes to add methods to the Python subclass.
Definition IRModule.h:1147
nanobind::class_< DerivedTy, BaseTy > ClassTy
Definition IRModule.h:935
static void bind(nanobind::module_ &m)
Definition IRModule.h:959
PyConcreteType(PyType &orig)
Definition IRModule.h:943
MlirTypeID(*)() GetTypeIDFunctionTy
Definition IRModule.h:937
bool(*)(MlirType) IsAFunctionTy
Definition IRModule.h:936
static void bindDerived(ClassTy &m)
Implemented by derived classes to add methods to the Python subclass.
Definition IRModule.h:1003
static constexpr GetTypeIDFunctionTy getTypeIdFunction
Definition IRModule.h:938
PyConcreteType(PyMlirContextRef contextRef, MlirType t)
Definition IRModule.h:941
static MlirType castFrom(PyType &orig)
Definition IRModule.h:946
Represents a diagnostic handler attached to the context.
Definition IRModule.h:380
PyDiagnosticHandler(MlirContext context, nanobind::object callback)
Definition IRCore.cpp:828
nanobind::object contextEnter()
Definition IRModule.h:391
void detach()
Detaches the handler. Does nothing if not attached.
Definition IRCore.cpp:834
void contextExit(const nanobind::object &excType, const nanobind::object &excVal, const nanobind::object &excTb)
Definition IRModule.h:392
Python class mirroring the C MlirDiagnostic struct.
Definition IRModule.h:330
nanobind::tuple getNotes()
Definition IRCore.cpp:872
nanobind::str getMessage()
Definition IRCore.cpp:864
DiagnosticInfo getInfo()
Definition IRCore.cpp:888
PyDiagnostic(MlirDiagnostic diagnostic)
Definition IRModule.h:332
MlirDiagnosticSeverity getSeverity()
Definition IRCore.cpp:852
PyDialectDescriptor(PyMlirContextRef contextRef, MlirDialect dialect)
Definition IRModule.h:437
Wrapper around an MlirDialectRegistry.
Definition IRModule.h:472
PyDialectRegistry(PyDialectRegistry &&other) noexcept
Definition IRModule.h:481
nanobind::object getCapsule()
Definition IRCore.cpp:913
PyDialectRegistry(PyDialectRegistry &)=delete
static PyDialectRegistry createFromCapsule(nanobind::object capsule)
Definition IRCore.cpp:917
MlirDialectRegistry get() const
Definition IRModule.h:487
PyDialectRegistry(MlirDialectRegistry registry)
Definition IRModule.h:475
PyDialect(nanobind::object descriptor)
Definition IRModule.h:461
nanobind::object getDescriptor()
Definition IRModule.h:463
PyDialects(PyMlirContextRef contextRef)
Definition IRModule.h:450
MlirDialect getDialectForKey(const std::string &key, bool attrError)
Definition IRCore.cpp:900
void registerTypeCaster(MlirTypeID mlirTypeID, nanobind::callable typeCaster, bool replace=false)
Adds a user-friendly type caster.
Definition IRModule.cpp:87
static PyGlobals & get()
Most code should get the globals via this static accessor.
Definition Globals.h:39
An insertion point maintains a pointer to a Block and a reference operation.
Definition IRModule.h:837
static PyInsertionPoint atBlockTerminator(PyBlock &block)
Shortcut to create an insertion point before the block terminator.
Definition IRCore.cpp:1992
static PyInsertionPoint atBlockBegin(PyBlock &block)
Shortcut to create an insertion point at the beginning of the block.
Definition IRCore.cpp:1979
void contextExit(const nanobind::object &excType, const nanobind::object &excVal, const nanobind::object &excTb)
Definition IRCore.cpp:2018
static PyInsertionPoint after(PyOperationBase &op)
Shortcut to create an insertion point to the node after the specified operation.
Definition IRCore.cpp:2001
PyInsertionPoint(const PyBlock &block)
Creates an insertion point positioned after the last operation in the block, but still inside the blo...
Definition IRCore.cpp:1944
void insert(PyOperationBase &operationBase)
Inserts an operation.
Definition IRCore.cpp:1953
static nanobind::object contextEnter(nanobind::object insertionPoint)
Enter and exit the context manager.
Definition IRCore.cpp:2014
std::optional< PyOperationRef > & getRefOperation()
Definition IRModule.h:865
static PyIntegerSet createFromCapsule(const nanobind::object &capsule)
Creates a PyIntegerSet from the MlirAffineMap wrapped by a capsule.
Definition IRAffine.cpp:503
MlirIntegerSet get() const
Definition IRModule.h:1251
bool operator==(const PyIntegerSet &other) const
Definition IRAffine.cpp:495
PyIntegerSet(PyMlirContextRef contextRef, MlirIntegerSet integerSet)
Definition IRModule.h:1247
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirIntegerSet.
Definition IRAffine.cpp:499
Wrapper around an MlirLocation.
Definition IRModule.h:299
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirLocation.
Definition IRCore.cpp:929
PyLocation(PyMlirContextRef contextRef, MlirLocation loc)
Definition IRModule.h:301
static PyLocation createFromCapsule(nanobind::object capsule)
Creates a PyLocation from the MlirLocation wrapped by a capsule.
Definition IRCore.cpp:933
void contextExit(const nanobind::object &excType, const nanobind::object &excVal, const nanobind::object &excTb)
Definition IRCore.cpp:945
static nanobind::object contextEnter(nanobind::object location)
Enter and exit the context manager.
Definition IRCore.cpp:941
MlirLocation get() const
Definition IRModule.h:305
PyMlirContext(const PyMlirContext &)=delete
PyMlirContext(PyMlirContext &&)=delete
MlirContext get()
Accesses the underlying MlirContext.
Definition IRModule.h:204
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:208
static size_t getLiveCount()
Gets the count of live context objects. Used for testing.
Definition IRCore.cpp:593
size_t getLiveModuleCount()
Gets the count of live modules associated with this context.
Definition IRCore.cpp:2012
nanobind::object attachDiagnosticHandler(nanobind::object callback)
Attaches a Python callback as a diagnostic handler, returning a registration object (internally a PyD...
Definition IRCore.cpp:608
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirContext.
Definition IRCore.cpp:557
void contextExit(const nanobind::object &excType, const nanobind::object &excVal, const nanobind::object &excTb)
Definition IRCore.cpp:602
static PyMlirContextRef forContext(MlirContext context)
Returns a context reference for the singleton PyMlirContext wrapper for the given context.
Definition IRCore.cpp:568
static nanobind::object createFromCapsule(nanobind::object capsule)
Creates a PyMlirContext from the MlirContext wrapped by a capsule.
Definition IRCore.cpp:561
static nanobind::object contextEnter(nanobind::object context)
Enter and exit the context manager.
Definition IRCore.cpp:598
void setEmitErrorDiagnostics(bool value)
Controls whether error diagnostics should be propagated to diagnostic handlers, instead of being capt...
Definition IRModule.h:240
MlirModule get()
Gets the backing MlirModule.
Definition IRModule.h:522
static PyModuleRef forModule(MlirModule module)
Returns a PyModule reference for the given MlirModule.
Definition IRCore.cpp:978
static nanobind::object createFromCapsule(nanobind::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:525
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirModule.
Definition IRCore.cpp:1010
PyModule(PyModule &)=delete
PyModule(PyMlirContext &&)=delete
PyNamedAttribute(MlirAttribute attr, std::string ownedName)
Constructs a PyNamedAttr that retains an owned name.
Definition IRCore.cpp:2062
MlirNamedAttribute namedAttr
Definition IRModule.h:1043
Template for a reference to a concrete type which captures a python reference to its underlying pytho...
Definition IRModule.h:53
nanobind::typed< nanobind::object, T > NBTypedT
Definition IRModule.h:97
nanobind::object getObject()
Definition IRModule.h:91
PyObjectRef(T *referrent, nanobind::object object)
Definition IRModule.h:55
nanobind::object releaseObject()
Releases the object held by this instance, returning it.
Definition IRModule.h:79
PyObjectRef(PyObjectRef &&other) noexcept
Definition IRModule.h:61
PyObjectRef(const PyObjectRef &other)
Definition IRModule.h:66
A PyOpView is equivalent to the C++ "Op" wrappers: these are the basis for providing more instance-sp...
Definition IRModule.h:723
PyOperation & getOperation() override
Each must provide access to the raw Operation.
Definition IRModule.h:726
static nanobind::object constructDerived(const nanobind::object &cls, const nanobind::object &operation)
Construct an instance of a class deriving from OpView, bypassing its __init__ method.
Definition IRCore.cpp:1926
static nanobind::object buildGeneric(std::string_view name, std::tuple< int, bool > opRegionSpec, nanobind::object operandSegmentSpecObj, nanobind::object resultSegmentSpecObj, std::optional< nanobind::list > resultTypeList, nanobind::list operandList, std::optional< nanobind::dict > attributes, std::optional< std::vector< PyBlock * > > successors, std::optional< int > regions, PyLocation &location, const nanobind::object &maybeIp)
Definition IRCore.cpp:1742
nanobind::object getOperationObject()
Definition IRModule.h:728
PyOpView(const nanobind::object &operationObject)
Definition IRCore.cpp:1934
Base class for PyOperation and PyOpView which exposes the primary, user visible methods for manipulat...
Definition IRModule.h:552
void walk(std::function< MlirWalkResult(MlirOperation)> callback, MlirWalkOrder walkOrder)
Definition IRCore.cpp:1167
bool isBeforeInBlock(PyOperationBase &other)
Given an operation 'other' that is within the same parent block, return whether the current operation...
Definition IRCore.cpp:1245
nanobind::object getAsm(bool binary, std::optional< int64_t > largeElementsLimit, std::optional< int64_t > largeResourceLimit, bool enableDebugInfo, bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope, bool useNameLocAsPrefix, bool assumeVerified, bool skipRegions)
Definition IRCore.cpp:1199
void print(PyAsmState &state, nanobind::object fileObject, bool binary)
virtual ~PyOperationBase()=default
void moveAfter(PyOperationBase &other)
Moves the operation before or after the other operation.
Definition IRCore.cpp:1227
void print(std::optional< int64_t > largeElementsLimit, std::optional< int64_t > largeResourceLimit, bool enableDebugInfo, bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope, bool useNameLocAsPrefix, bool assumeVerified, nanobind::object fileObject, bool binary, bool skipRegions)
Implements the bound 'print' method and helps with others.
void writeBytecode(const nanobind::object &fileObject, std::optional< int64_t > bytecodeVersion)
Definition IRCore.cpp:1145
void moveBefore(PyOperationBase &other)
Definition IRCore.cpp:1236
virtual PyOperation & getOperation()=0
Each must provide access to the raw Operation.
bool verify()
Verify the operation.
Definition IRCore.cpp:1253
PyOperation & getOperation() override
Each must provide access to the raw Operation.
Definition IRModule.h:608
void detachFromParent()
Detaches the operation from its parent block and updates its state accordingly.
Definition IRModule.h:630
PyOperation(PyMlirContextRef contextRef, MlirOperation operation)
Definition IRCore.cpp:1018
friend class PyOperationBase
Definition IRModule.h:714
void erase()
Erases the underlying MlirOperation, removes its pointer from the parent context's live operations ma...
Definition IRCore.cpp:1444
static nanobind::object createFromCapsule(const nanobind::object &capsule)
Creates a PyOperation from the MlirOperation wrapped by a capsule.
Definition IRCore.cpp:1285
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirOperation.
Definition IRCore.cpp:1280
static PyOperationRef createDetached(PyMlirContextRef contextRef, MlirOperation operation, nanobind::object parentKeepAlive=nanobind::object())
Creates a detached operation.
Definition IRCore.cpp:1070
nanobind::object clone(const nanobind::object &ip)
Clones this operation.
Definition IRCore.cpp:1424
PyOperationRef getRef()
Definition IRModule.h:643
MlirOperation get() const
Definition IRModule.h:638
static PyOperationRef forOperation(PyMlirContextRef contextRef, MlirOperation operation, nanobind::object parentKeepAlive=nanobind::object())
Returns a PyOperation for the given MlirOperation, optionally associating it with a parentKeepAlive.
Definition IRCore.cpp:1063
friend class PySymbolTable
Definition IRModule.h:715
void setAttached(const nanobind::object &parent=nanobind::object())
Definition IRModule.h:648
std::optional< PyOperationRef > getParentOperation()
Gets the parent operation or raises an exception if the operation has no parent.
Definition IRCore.cpp:1261
nanobind::object createOpView()
Creates an OpView suitable for this operation.
Definition IRCore.cpp:1433
PyBlock getBlock()
Gets the owning block or raises an exception if the operation has no owning block.
Definition IRCore.cpp:1271
static nanobind::object create(std::string_view name, std::optional< std::vector< PyType * > > results, llvm::ArrayRef< MlirValue > operands, std::optional< nanobind::dict > attributes, std::optional< std::vector< PyBlock * > > successors, int regions, PyLocation &location, const nanobind::object &ip, bool inferType)
Creates an operation. See corresponding python docstring.
Definition IRCore.cpp:1309
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:1079
void setInvalid()
Invalidate the operation.
Definition IRModule.h:690
PyRegion(PyOperationRef parentOperation, MlirRegion region)
Definition IRModule.h:761
PyOperationRef & getParentOperation()
Definition IRModule.h:768
static constexpr GetTypeIDFunctionTy getTypeIdFunction
Definition IRModule.h:1155
static constexpr IsAFunctionTy isaFunction
Definition IRModule.h:1152
static constexpr const char * pyClassName
Definition IRModule.h:1153
static void bindDerived(ClassTy &c)
Bindings for MLIR symbol tables.
Definition IRModule.h:1266
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:2197
static void walkSymbolTables(PyOperationBase &from, bool allSymUsesVisible, nanobind::object callback)
Walks all symbol tables under and including 'from'.
Definition IRCore.cpp:2283
static void replaceAllSymbolUses(const std::string &oldSymbol, const std::string &newSymbol, PyOperationBase &from)
Replaces all symbol uses within an operation.
Definition IRCore.cpp:2271
static void setVisibility(PyOperationBase &symbol, const std::string &visibility)
Definition IRCore.cpp:2253
static void setSymbolName(PyOperationBase &symbol, const std::string &name)
Definition IRCore.cpp:2227
~PySymbolTable()
Destroys the symbol table.
Definition IRModule.h:1272
PyStringAttribute insert(PyOperationBase &symbol)
Inserts the given operation into the symbol table.
Definition IRCore.cpp:2202
void erase(PyOperationBase &symbol)
Removes the given operation from the symbol table and erases it.
Definition IRCore.cpp:2187
PySymbolTable(PyOperationBase &operation)
Constructs a symbol table for the given operation.
Definition IRCore.cpp:2166
static PyStringAttribute getSymbolName(PyOperationBase &symbol)
Gets and sets the name of a symbol op.
Definition IRCore.cpp:2214
static PyStringAttribute getVisibility(PyOperationBase &symbol)
Gets and sets the visibility of a symbol op.
Definition IRCore.cpp:2242
nanobind::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:2174
Tracks an entry in the thread context stack.
Definition IRModule.h:112
static PyThreadContextEntry * getTopOfStack()
Stack management.
Definition IRCore.cpp:692
static void popLocation(PyLocation &location)
Definition IRCore.cpp:804
static nanobind::object pushLocation(nanobind::object location)
Definition IRCore.cpp:795
static nanobind::object pushContext(nanobind::object context)
Definition IRCore.cpp:754
static PyLocation * getDefaultLocation()
Gets the top of stack location and returns nullptr if not defined.
Definition IRCore.cpp:749
static void popInsertionPoint(PyInsertionPoint &insertionPoint)
Definition IRCore.cpp:784
static nanobind::object pushInsertionPoint(nanobind::object insertionPoint)
Definition IRCore.cpp:772
static void popContext(PyMlirContext &context)
Definition IRCore.cpp:761
static PyInsertionPoint * getDefaultInsertionPoint()
Gets the top of stack insertion point and return nullptr if not defined.
Definition IRCore.cpp:744
static PyMlirContext * getDefaultContext()
Gets the top of stack context and return nullptr if not defined.
Definition IRCore.cpp:739
static std::vector< PyThreadContextEntry > & getStack()
Gets the thread local stack.
Definition IRCore.cpp:687
PyThreadContextEntry(FrameKind frameKind, nanobind::object context, nanobind::object insertionPoint, nanobind::object location)
Definition IRModule.h:120
PyInsertionPoint * getInsertionPoint()
Definition IRCore.cpp:727
std::string _mlir_thread_pool_ptr() const
Definition IRModule.h:179
PyThreadPool(const PyThreadPool &)=delete
int getMaxConcurrency() const
Definition IRModule.h:176
PyThreadPool(PyThreadPool &&)=delete
MlirLlvmThreadPool get()
Definition IRModule.h:177
A TypeID provides an efficient and unique identifier for a specific C++ type.
Definition IRModule.h:904
static PyTypeID createFromCapsule(nanobind::object capsule)
Creates a PyTypeID from the MlirTypeID wrapped by a capsule.
Definition IRCore.cpp:2112
bool operator==(const PyTypeID &other) const
Definition IRCore.cpp:2118
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirTypeID.
Definition IRCore.cpp:2108
PyTypeID(MlirTypeID typeID)
Definition IRModule.h:906
Wrapper around the generic MlirType.
Definition IRModule.h:878
PyType(PyMlirContextRef contextRef, MlirType type)
Definition IRModule.h:880
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirType.
Definition IRCore.cpp:2078
MlirType get() const
Definition IRModule.h:884
static PyType createFromCapsule(nanobind::object capsule)
Creates a PyType from the MlirType wrapped by a capsule.
Definition IRCore.cpp:2082
nanobind::object maybeDownCast()
Definition IRCore.cpp:2090
bool operator==(const PyType &other) const
Definition IRCore.cpp:2074
Wrapper around the generic MlirValue.
Definition IRModule.h:1167
PyValue(PyOperationRef parentOperation, MlirValue value)
Definition IRModule.h:1173
static PyValue createFromCapsule(nanobind::object capsule)
Creates a PyValue from the MlirValue wrapped by a capsule.
Definition IRCore.cpp:2145
nanobind::object maybeDownCast()
Definition IRCore.cpp:2130
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirValue.
Definition IRCore.cpp:2126
virtual ~PyValue()=default
PyOperationRef & getParentOperation()
Definition IRModule.h:1178
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.
MLIR_CAPI_EXPORTED void mlirContextDetachDiagnosticHandler(MlirContext context, MlirDiagnosticHandlerID id)
Detaches an attached diagnostic handler from the context given its identifier.
uint64_t MlirDiagnosticHandlerID
Opaque identifier of a diagnostic handler, useful to detach a handler.
Definition Diagnostics.h:41
MlirDiagnostic wrap(mlir::Diagnostic &diagnostic)
Definition Diagnostics.h:24
MLIR_CAPI_EXPORTED MlirTypeID mlirStringAttrGetTypeID(void)
Returns the typeID of a String attribute.
MLIR_CAPI_EXPORTED bool mlirAttributeIsAString(MlirAttribute attr)
Checks whether the given attribute is a string attribute.
MlirWalkOrder
Traversal order for operation walk.
Definition IR.h:844
MLIR_CAPI_EXPORTED void mlirDialectRegistryDestroy(MlirDialectRegistry registry)
Takes a dialect registry owned by the caller and destroys it.
Definition IR.cpp:149
MLIR_CAPI_EXPORTED void mlirAttributePrint(MlirAttribute attr, MlirStringCallback callback, void *userData)
Prints a location by sending chunks of the string representation and forwarding userData to callback`...
Definition IR.cpp:1298
MlirWalkResult
Operation walk result.
Definition IR.h:837
static bool mlirBlockIsNull(MlirBlock block)
Checks whether a block is null.
Definition IR.h:933
MLIR_CAPI_EXPORTED void mlirSymbolTableDestroy(MlirSymbolTable symbolTable)
Destroys the symbol table created with mlirSymbolTableCreate.
Definition IR.cpp:1349
static bool mlirDialectRegistryIsNull(MlirDialectRegistry registry)
Checks if the dialect registry is null.
Definition IR.h:244
static bool mlirRegionIsNull(MlirRegion region)
Checks whether a region is null.
Definition IR.h:872
MLIR_CAPI_EXPORTED MlirDialectRegistry mlirDialectRegistryCreate(void)
Creates a dialect registry and transfers its ownership to the caller.
Definition IR.cpp:145
void populateIRAttributes(nanobind::module_ &m)
void populateIRInterfaces(nb::module_ &m)
PyObjectRef< PyOperation > PyOperationRef
Definition IRModule.h:604
void populateIRAffine(nanobind::module_ &m)
PyObjectRef< PyMlirContext > PyMlirContextRef
Wrapper around MlirContext.
Definition IRModule.h:190
void populateIRTypes(nanobind::module_ &m)
void populateIRCore(nanobind::module_ &m)
PyObjectRef< PyModule > PyModuleRef
Definition IRModule.h:511
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:116
Named MLIR attribute.
Definition IR.h:76
Accumulates into a python string from a method that accepts an MlirStringCallback.
MlirStringCallback getCallback()
MLIRError(llvm::Twine message, std::vector< PyDiagnostic::DiagnosticInfo > &&errorDiagnostics={})
Definition IRModule.h:1319
std::vector< PyDiagnostic::DiagnosticInfo > errorDiagnostics
Definition IRModule.h:1323
Materialized diagnostic information.
Definition IRModule.h:342
std::vector< DiagnosticInfo > notes
Definition IRModule.h:346
RAII object that captures any error diagnostics emitted to the provided context.
Definition IRModule.h:408
std::vector< PyDiagnostic::DiagnosticInfo > take()
Definition IRModule.h:418