MLIR  19.0.0git
IRCore.cpp
Go to the documentation of this file.
1 //===- IRModules.cpp - 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 #include "IRModule.h"
10 
11 #include "Globals.h"
12 #include "PybindUtils.h"
13 
16 #include "mlir-c/Debug.h"
17 #include "mlir-c/Diagnostics.h"
18 #include "mlir-c/IR.h"
19 #include "mlir-c/Support.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/ADT/SmallVector.h"
23 
24 #include <optional>
25 #include <utility>
26 
27 namespace py = pybind11;
28 using namespace py::literals;
29 using namespace mlir;
30 using namespace mlir::python;
31 
32 using llvm::SmallVector;
33 using llvm::StringRef;
34 using llvm::Twine;
35 
36 //------------------------------------------------------------------------------
37 // Docstrings (trivial, non-duplicated docstrings are included inline).
38 //------------------------------------------------------------------------------
39 
40 static const char kContextParseTypeDocstring[] =
41  R"(Parses the assembly form of a type.
42 
43 Returns a Type object or raises an MLIRError if the type cannot be parsed.
44 
45 See also: https://mlir.llvm.org/docs/LangRef/#type-system
46 )";
47 
49  R"(Gets a Location representing a caller and callsite)";
50 
51 static const char kContextGetFileLocationDocstring[] =
52  R"(Gets a Location representing a file, line and column)";
53 
54 static const char kContextGetFusedLocationDocstring[] =
55  R"(Gets a Location representing a fused location with optional metadata)";
56 
57 static const char kContextGetNameLocationDocString[] =
58  R"(Gets a Location representing a named location with optional child location)";
59 
60 static const char kModuleParseDocstring[] =
61  R"(Parses a module's assembly format from a string.
62 
63 Returns a new MlirModule or raises an MLIRError if the parsing fails.
64 
65 See also: https://mlir.llvm.org/docs/LangRef/
66 )";
67 
68 static const char kOperationCreateDocstring[] =
69  R"(Creates a new operation.
70 
71 Args:
72  name: Operation name (e.g. "dialect.operation").
73  results: Sequence of Type representing op result types.
74  attributes: Dict of str:Attribute.
75  successors: List of Block for the operation's successors.
76  regions: Number of regions to create.
77  location: A Location object (defaults to resolve from context manager).
78  ip: An InsertionPoint (defaults to resolve from context manager or set to
79  False to disable insertion, even with an insertion point set in the
80  context manager).
81  infer_type: Whether to infer result types.
82 Returns:
83  A new "detached" Operation object. Detached operations can be added
84  to blocks, which causes them to become "attached."
85 )";
86 
87 static const char kOperationPrintDocstring[] =
88  R"(Prints the assembly form of the operation to a file like object.
89 
90 Args:
91  file: The file like object to write to. Defaults to sys.stdout.
92  binary: Whether to write bytes (True) or str (False). Defaults to False.
93  large_elements_limit: Whether to elide elements attributes above this
94  number of elements. Defaults to None (no limit).
95  enable_debug_info: Whether to print debug/location information. Defaults
96  to False.
97  pretty_debug_info: Whether to format debug information for easier reading
98  by a human (warning: the result is unparseable).
99  print_generic_op_form: Whether to print the generic assembly forms of all
100  ops. Defaults to False.
101  use_local_Scope: Whether to print in a way that is more optimized for
102  multi-threaded access but may not be consistent with how the overall
103  module prints.
104  assume_verified: By default, if not printing generic form, the verifier
105  will be run and if it fails, generic form will be printed with a comment
106  about failed verification. While a reasonable default for interactive use,
107  for systematic use, it is often better for the caller to verify explicitly
108  and report failures in a more robust fashion. Set this to True if doing this
109  in order to avoid running a redundant verification. If the IR is actually
110  invalid, behavior is undefined.
111 )";
112 
113 static const char kOperationPrintStateDocstring[] =
114  R"(Prints the assembly form of the operation to a file like object.
115 
116 Args:
117  file: The file like object to write to. Defaults to sys.stdout.
118  binary: Whether to write bytes (True) or str (False). Defaults to False.
119  state: AsmState capturing the operation numbering and flags.
120 )";
121 
122 static const char kOperationGetAsmDocstring[] =
123  R"(Gets the assembly form of the operation with all options available.
124 
125 Args:
126  binary: Whether to return a bytes (True) or str (False) object. Defaults to
127  False.
128  ... others ...: See the print() method for common keyword arguments for
129  configuring the printout.
130 Returns:
131  Either a bytes or str object, depending on the setting of the 'binary'
132  argument.
133 )";
134 
135 static const char kOperationPrintBytecodeDocstring[] =
136  R"(Write the bytecode form of the operation to a file like object.
137 
138 Args:
139  file: The file like object to write to.
140  desired_version: The version of bytecode to emit.
141 Returns:
142  The bytecode writer status.
143 )";
144 
145 static const char kOperationStrDunderDocstring[] =
146  R"(Gets the assembly form of the operation with default options.
147 
148 If more advanced control over the assembly formatting or I/O options is needed,
149 use the dedicated print or get_asm method, which supports keyword arguments to
150 customize behavior.
151 )";
152 
153 static const char kDumpDocstring[] =
154  R"(Dumps a debug representation of the object to stderr.)";
155 
156 static const char kAppendBlockDocstring[] =
157  R"(Appends a new block, with argument types as positional args.
158 
159 Returns:
160  The created block.
161 )";
162 
163 static const char kValueDunderStrDocstring[] =
164  R"(Returns the string form of the value.
165 
166 If the value is a block argument, this is the assembly form of its type and the
167 position in the argument list. If the value is an operation result, this is
168 equivalent to printing the operation that produced it.
169 )";
170 
171 static const char kGetNameAsOperand[] =
172  R"(Returns the string form of value as an operand (i.e., the ValueID).
173 )";
174 
176  R"(Replace all uses of value with the new value, updating anything in
177 the IR that uses 'self' to use the other value instead.
178 )";
179 
180 //------------------------------------------------------------------------------
181 // Utilities.
182 //------------------------------------------------------------------------------
183 
184 /// Helper for creating an @classmethod.
185 template <class Func, typename... Args>
186 py::object classmethod(Func f, Args... args) {
187  py::object cf = py::cpp_function(f, args...);
188  return py::reinterpret_borrow<py::object>((PyClassMethod_New(cf.ptr())));
189 }
190 
191 static py::object
192 createCustomDialectWrapper(const std::string &dialectNamespace,
193  py::object dialectDescriptor) {
194  auto dialectClass = PyGlobals::get().lookupDialectClass(dialectNamespace);
195  if (!dialectClass) {
196  // Use the base class.
197  return py::cast(PyDialect(std::move(dialectDescriptor)));
198  }
199 
200  // Create the custom implementation.
201  return (*dialectClass)(std::move(dialectDescriptor));
202 }
203 
204 static MlirStringRef toMlirStringRef(const std::string &s) {
205  return mlirStringRefCreate(s.data(), s.size());
206 }
207 
208 /// Create a block, using the current location context if no locations are
209 /// specified.
210 static MlirBlock createBlock(const py::sequence &pyArgTypes,
211  const std::optional<py::sequence> &pyArgLocs) {
212  SmallVector<MlirType> argTypes;
213  argTypes.reserve(pyArgTypes.size());
214  for (const auto &pyType : pyArgTypes)
215  argTypes.push_back(pyType.cast<PyType &>());
216 
218  if (pyArgLocs) {
219  argLocs.reserve(pyArgLocs->size());
220  for (const auto &pyLoc : *pyArgLocs)
221  argLocs.push_back(pyLoc.cast<PyLocation &>());
222  } else if (!argTypes.empty()) {
223  argLocs.assign(argTypes.size(), DefaultingPyLocation::resolve());
224  }
225 
226  if (argTypes.size() != argLocs.size())
227  throw py::value_error(("Expected " + Twine(argTypes.size()) +
228  " locations, got: " + Twine(argLocs.size()))
229  .str());
230  return mlirBlockCreate(argTypes.size(), argTypes.data(), argLocs.data());
231 }
232 
233 /// Wrapper for the global LLVM debugging flag.
235  static void set(py::object &o, bool enable) { mlirEnableGlobalDebug(enable); }
236 
237  static bool get(const py::object &) { return mlirIsGlobalDebugEnabled(); }
238 
239  static void bind(py::module &m) {
240  // Debug flags.
241  py::class_<PyGlobalDebugFlag>(m, "_GlobalDebug", py::module_local())
242  .def_property_static("flag", &PyGlobalDebugFlag::get,
243  &PyGlobalDebugFlag::set, "LLVM-wide debug flag");
244  }
245 };
246 
248  static bool dunderContains(const std::string &attributeKind) {
249  return PyGlobals::get().lookupAttributeBuilder(attributeKind).has_value();
250  }
251  static py::function dundeGetItemNamed(const std::string &attributeKind) {
252  auto builder = PyGlobals::get().lookupAttributeBuilder(attributeKind);
253  if (!builder)
254  throw py::key_error(attributeKind);
255  return *builder;
256  }
257  static void dundeSetItemNamed(const std::string &attributeKind,
258  py::function func, bool replace) {
259  PyGlobals::get().registerAttributeBuilder(attributeKind, std::move(func),
260  replace);
261  }
262 
263  static void bind(py::module &m) {
264  py::class_<PyAttrBuilderMap>(m, "AttrBuilder", py::module_local())
265  .def_static("contains", &PyAttrBuilderMap::dunderContains)
266  .def_static("get", &PyAttrBuilderMap::dundeGetItemNamed)
267  .def_static("insert", &PyAttrBuilderMap::dundeSetItemNamed,
268  "attribute_kind"_a, "attr_builder"_a, "replace"_a = false,
269  "Register an attribute builder for building MLIR "
270  "attributes from python values.");
271  }
272 };
273 
274 //------------------------------------------------------------------------------
275 // PyBlock
276 //------------------------------------------------------------------------------
277 
278 py::object PyBlock::getCapsule() {
279  return py::reinterpret_steal<py::object>(mlirPythonBlockToCapsule(get()));
280 }
281 
282 //------------------------------------------------------------------------------
283 // Collections.
284 //------------------------------------------------------------------------------
285 
286 namespace {
287 
288 class PyRegionIterator {
289 public:
290  PyRegionIterator(PyOperationRef operation)
291  : operation(std::move(operation)) {}
292 
293  PyRegionIterator &dunderIter() { return *this; }
294 
295  PyRegion dunderNext() {
296  operation->checkValid();
297  if (nextIndex >= mlirOperationGetNumRegions(operation->get())) {
298  throw py::stop_iteration();
299  }
300  MlirRegion region = mlirOperationGetRegion(operation->get(), nextIndex++);
301  return PyRegion(operation, region);
302  }
303 
304  static void bind(py::module &m) {
305  py::class_<PyRegionIterator>(m, "RegionIterator", py::module_local())
306  .def("__iter__", &PyRegionIterator::dunderIter)
307  .def("__next__", &PyRegionIterator::dunderNext);
308  }
309 
310 private:
311  PyOperationRef operation;
312  int nextIndex = 0;
313 };
314 
315 /// Regions of an op are fixed length and indexed numerically so are represented
316 /// with a sequence-like container.
317 class PyRegionList {
318 public:
319  PyRegionList(PyOperationRef operation) : operation(std::move(operation)) {}
320 
321  PyRegionIterator dunderIter() {
322  operation->checkValid();
323  return PyRegionIterator(operation);
324  }
325 
326  intptr_t dunderLen() {
327  operation->checkValid();
328  return mlirOperationGetNumRegions(operation->get());
329  }
330 
331  PyRegion dunderGetItem(intptr_t index) {
332  // dunderLen checks validity.
333  if (index < 0 || index >= dunderLen()) {
334  throw py::index_error("attempt to access out of bounds region");
335  }
336  MlirRegion region = mlirOperationGetRegion(operation->get(), index);
337  return PyRegion(operation, region);
338  }
339 
340  static void bind(py::module &m) {
341  py::class_<PyRegionList>(m, "RegionSequence", py::module_local())
342  .def("__len__", &PyRegionList::dunderLen)
343  .def("__iter__", &PyRegionList::dunderIter)
344  .def("__getitem__", &PyRegionList::dunderGetItem);
345  }
346 
347 private:
348  PyOperationRef operation;
349 };
350 
351 class PyBlockIterator {
352 public:
353  PyBlockIterator(PyOperationRef operation, MlirBlock next)
354  : operation(std::move(operation)), next(next) {}
355 
356  PyBlockIterator &dunderIter() { return *this; }
357 
358  PyBlock dunderNext() {
359  operation->checkValid();
360  if (mlirBlockIsNull(next)) {
361  throw py::stop_iteration();
362  }
363 
364  PyBlock returnBlock(operation, next);
365  next = mlirBlockGetNextInRegion(next);
366  return returnBlock;
367  }
368 
369  static void bind(py::module &m) {
370  py::class_<PyBlockIterator>(m, "BlockIterator", py::module_local())
371  .def("__iter__", &PyBlockIterator::dunderIter)
372  .def("__next__", &PyBlockIterator::dunderNext);
373  }
374 
375 private:
376  PyOperationRef operation;
377  MlirBlock next;
378 };
379 
380 /// Blocks are exposed by the C-API as a forward-only linked list. In Python,
381 /// we present them as a more full-featured list-like container but optimize
382 /// it for forward iteration. Blocks are always owned by a region.
383 class PyBlockList {
384 public:
385  PyBlockList(PyOperationRef operation, MlirRegion region)
386  : operation(std::move(operation)), region(region) {}
387 
388  PyBlockIterator dunderIter() {
389  operation->checkValid();
390  return PyBlockIterator(operation, mlirRegionGetFirstBlock(region));
391  }
392 
393  intptr_t dunderLen() {
394  operation->checkValid();
395  intptr_t count = 0;
396  MlirBlock block = mlirRegionGetFirstBlock(region);
397  while (!mlirBlockIsNull(block)) {
398  count += 1;
399  block = mlirBlockGetNextInRegion(block);
400  }
401  return count;
402  }
403 
404  PyBlock dunderGetItem(intptr_t index) {
405  operation->checkValid();
406  if (index < 0) {
407  throw py::index_error("attempt to access out of bounds block");
408  }
409  MlirBlock block = mlirRegionGetFirstBlock(region);
410  while (!mlirBlockIsNull(block)) {
411  if (index == 0) {
412  return PyBlock(operation, block);
413  }
414  block = mlirBlockGetNextInRegion(block);
415  index -= 1;
416  }
417  throw py::index_error("attempt to access out of bounds block");
418  }
419 
420  PyBlock appendBlock(const py::args &pyArgTypes,
421  const std::optional<py::sequence> &pyArgLocs) {
422  operation->checkValid();
423  MlirBlock block = createBlock(pyArgTypes, pyArgLocs);
424  mlirRegionAppendOwnedBlock(region, block);
425  return PyBlock(operation, block);
426  }
427 
428  static void bind(py::module &m) {
429  py::class_<PyBlockList>(m, "BlockList", py::module_local())
430  .def("__getitem__", &PyBlockList::dunderGetItem)
431  .def("__iter__", &PyBlockList::dunderIter)
432  .def("__len__", &PyBlockList::dunderLen)
433  .def("append", &PyBlockList::appendBlock, kAppendBlockDocstring,
434  py::arg("arg_locs") = std::nullopt);
435  }
436 
437 private:
438  PyOperationRef operation;
439  MlirRegion region;
440 };
441 
442 class PyOperationIterator {
443 public:
444  PyOperationIterator(PyOperationRef parentOperation, MlirOperation next)
445  : parentOperation(std::move(parentOperation)), next(next) {}
446 
447  PyOperationIterator &dunderIter() { return *this; }
448 
449  py::object dunderNext() {
450  parentOperation->checkValid();
451  if (mlirOperationIsNull(next)) {
452  throw py::stop_iteration();
453  }
454 
455  PyOperationRef returnOperation =
456  PyOperation::forOperation(parentOperation->getContext(), next);
457  next = mlirOperationGetNextInBlock(next);
458  return returnOperation->createOpView();
459  }
460 
461  static void bind(py::module &m) {
462  py::class_<PyOperationIterator>(m, "OperationIterator", py::module_local())
463  .def("__iter__", &PyOperationIterator::dunderIter)
464  .def("__next__", &PyOperationIterator::dunderNext);
465  }
466 
467 private:
468  PyOperationRef parentOperation;
469  MlirOperation next;
470 };
471 
472 /// Operations are exposed by the C-API as a forward-only linked list. In
473 /// Python, we present them as a more full-featured list-like container but
474 /// optimize it for forward iteration. Iterable operations are always owned
475 /// by a block.
476 class PyOperationList {
477 public:
478  PyOperationList(PyOperationRef parentOperation, MlirBlock block)
479  : parentOperation(std::move(parentOperation)), block(block) {}
480 
481  PyOperationIterator dunderIter() {
482  parentOperation->checkValid();
483  return PyOperationIterator(parentOperation,
485  }
486 
487  intptr_t dunderLen() {
488  parentOperation->checkValid();
489  intptr_t count = 0;
490  MlirOperation childOp = mlirBlockGetFirstOperation(block);
491  while (!mlirOperationIsNull(childOp)) {
492  count += 1;
493  childOp = mlirOperationGetNextInBlock(childOp);
494  }
495  return count;
496  }
497 
498  py::object dunderGetItem(intptr_t index) {
499  parentOperation->checkValid();
500  if (index < 0) {
501  throw py::index_error("attempt to access out of bounds operation");
502  }
503  MlirOperation childOp = mlirBlockGetFirstOperation(block);
504  while (!mlirOperationIsNull(childOp)) {
505  if (index == 0) {
506  return PyOperation::forOperation(parentOperation->getContext(), childOp)
507  ->createOpView();
508  }
509  childOp = mlirOperationGetNextInBlock(childOp);
510  index -= 1;
511  }
512  throw py::index_error("attempt to access out of bounds operation");
513  }
514 
515  static void bind(py::module &m) {
516  py::class_<PyOperationList>(m, "OperationList", py::module_local())
517  .def("__getitem__", &PyOperationList::dunderGetItem)
518  .def("__iter__", &PyOperationList::dunderIter)
519  .def("__len__", &PyOperationList::dunderLen);
520  }
521 
522 private:
523  PyOperationRef parentOperation;
524  MlirBlock block;
525 };
526 
527 class PyOpOperand {
528 public:
529  PyOpOperand(MlirOpOperand opOperand) : opOperand(opOperand) {}
530 
531  py::object getOwner() {
532  MlirOperation owner = mlirOpOperandGetOwner(opOperand);
533  PyMlirContextRef context =
534  PyMlirContext::forContext(mlirOperationGetContext(owner));
535  return PyOperation::forOperation(context, owner)->createOpView();
536  }
537 
538  size_t getOperandNumber() { return mlirOpOperandGetOperandNumber(opOperand); }
539 
540  static void bind(py::module &m) {
541  py::class_<PyOpOperand>(m, "OpOperand", py::module_local())
542  .def_property_readonly("owner", &PyOpOperand::getOwner)
543  .def_property_readonly("operand_number",
544  &PyOpOperand::getOperandNumber);
545  }
546 
547 private:
548  MlirOpOperand opOperand;
549 };
550 
551 class PyOpOperandIterator {
552 public:
553  PyOpOperandIterator(MlirOpOperand opOperand) : opOperand(opOperand) {}
554 
555  PyOpOperandIterator &dunderIter() { return *this; }
556 
557  PyOpOperand dunderNext() {
558  if (mlirOpOperandIsNull(opOperand))
559  throw py::stop_iteration();
560 
561  PyOpOperand returnOpOperand(opOperand);
562  opOperand = mlirOpOperandGetNextUse(opOperand);
563  return returnOpOperand;
564  }
565 
566  static void bind(py::module &m) {
567  py::class_<PyOpOperandIterator>(m, "OpOperandIterator", py::module_local())
568  .def("__iter__", &PyOpOperandIterator::dunderIter)
569  .def("__next__", &PyOpOperandIterator::dunderNext);
570  }
571 
572 private:
573  MlirOpOperand opOperand;
574 };
575 
576 } // namespace
577 
578 //------------------------------------------------------------------------------
579 // PyMlirContext
580 //------------------------------------------------------------------------------
581 
582 PyMlirContext::PyMlirContext(MlirContext context) : context(context) {
583  py::gil_scoped_acquire acquire;
584  auto &liveContexts = getLiveContexts();
585  liveContexts[context.ptr] = this;
586 }
587 
589  // Note that the only public way to construct an instance is via the
590  // forContext method, which always puts the associated handle into
591  // liveContexts.
592  py::gil_scoped_acquire acquire;
593  getLiveContexts().erase(context.ptr);
594  mlirContextDestroy(context);
595 }
596 
598  return py::reinterpret_steal<py::object>(mlirPythonContextToCapsule(get()));
599 }
600 
601 py::object PyMlirContext::createFromCapsule(py::object capsule) {
602  MlirContext rawContext = mlirPythonCapsuleToContext(capsule.ptr());
603  if (mlirContextIsNull(rawContext))
604  throw py::error_already_set();
605  return forContext(rawContext).releaseObject();
606 }
607 
609  MlirContext context = mlirContextCreateWithThreading(false);
610  return new PyMlirContext(context);
611 }
612 
614  py::gil_scoped_acquire acquire;
615  auto &liveContexts = getLiveContexts();
616  auto it = liveContexts.find(context.ptr);
617  if (it == liveContexts.end()) {
618  // Create.
619  PyMlirContext *unownedContextWrapper = new PyMlirContext(context);
620  py::object pyRef = py::cast(unownedContextWrapper);
621  assert(pyRef && "cast to py::object failed");
622  liveContexts[context.ptr] = unownedContextWrapper;
623  return PyMlirContextRef(unownedContextWrapper, std::move(pyRef));
624  }
625  // Use existing.
626  py::object pyRef = py::cast(it->second);
627  return PyMlirContextRef(it->second, std::move(pyRef));
628 }
629 
630 PyMlirContext::LiveContextMap &PyMlirContext::getLiveContexts() {
631  static LiveContextMap liveContexts;
632  return liveContexts;
633 }
634 
635 size_t PyMlirContext::getLiveCount() { return getLiveContexts().size(); }
636 
637 size_t PyMlirContext::getLiveOperationCount() { return liveOperations.size(); }
638 
639 std::vector<PyOperation *> PyMlirContext::getLiveOperationObjects() {
640  std::vector<PyOperation *> liveObjects;
641  for (auto &entry : liveOperations)
642  liveObjects.push_back(entry.second.second);
643  return liveObjects;
644 }
645 
647  for (auto &op : liveOperations)
648  op.second.second->setInvalid();
649  size_t numInvalidated = liveOperations.size();
650  liveOperations.clear();
651  return numInvalidated;
652 }
653 
654 void PyMlirContext::clearOperation(MlirOperation op) {
655  auto it = liveOperations.find(op.ptr);
656  if (it != liveOperations.end()) {
657  it->second.second->setInvalid();
658  liveOperations.erase(it);
659  }
660 }
661 
663  typedef struct {
664  PyOperation &rootOp;
665  bool rootSeen;
666  } callBackData;
667  callBackData data{op.getOperation(), false};
668  // Mark all ops below the op that the passmanager will be rooted
669  // at (but not op itself - note the preorder) as invalid.
670  MlirOperationWalkCallback invalidatingCallback = [](MlirOperation op,
671  void *userData) {
672  callBackData *data = static_cast<callBackData *>(userData);
673  if (LLVM_LIKELY(data->rootSeen))
674  data->rootOp.getOperation().getContext()->clearOperation(op);
675  else
676  data->rootSeen = true;
677  };
678  mlirOperationWalk(op.getOperation(), invalidatingCallback,
679  static_cast<void *>(&data), MlirWalkPreOrder);
680 }
681 void PyMlirContext::clearOperationsInside(MlirOperation op) {
684 }
685 
686 size_t PyMlirContext::getLiveModuleCount() { return liveModules.size(); }
687 
688 pybind11::object PyMlirContext::contextEnter() {
689  return PyThreadContextEntry::pushContext(*this);
690 }
691 
692 void PyMlirContext::contextExit(const pybind11::object &excType,
693  const pybind11::object &excVal,
694  const pybind11::object &excTb) {
696 }
697 
698 py::object PyMlirContext::attachDiagnosticHandler(py::object callback) {
699  // Note that ownership is transferred to the delete callback below by way of
700  // an explicit inc_ref (borrow).
701  PyDiagnosticHandler *pyHandler =
702  new PyDiagnosticHandler(get(), std::move(callback));
703  py::object pyHandlerObject =
704  py::cast(pyHandler, py::return_value_policy::take_ownership);
705  pyHandlerObject.inc_ref();
706 
707  // In these C callbacks, the userData is a PyDiagnosticHandler* that is
708  // guaranteed to be known to pybind.
709  auto handlerCallback =
710  +[](MlirDiagnostic diagnostic, void *userData) -> MlirLogicalResult {
711  PyDiagnostic *pyDiagnostic = new PyDiagnostic(diagnostic);
712  py::object pyDiagnosticObject =
713  py::cast(pyDiagnostic, py::return_value_policy::take_ownership);
714 
715  auto *pyHandler = static_cast<PyDiagnosticHandler *>(userData);
716  bool result = false;
717  {
718  // Since this can be called from arbitrary C++ contexts, always get the
719  // gil.
720  py::gil_scoped_acquire gil;
721  try {
722  result = py::cast<bool>(pyHandler->callback(pyDiagnostic));
723  } catch (std::exception &e) {
724  fprintf(stderr, "MLIR Python Diagnostic handler raised exception: %s\n",
725  e.what());
726  pyHandler->hadError = true;
727  }
728  }
729 
730  pyDiagnostic->invalidate();
732  };
733  auto deleteCallback = +[](void *userData) {
734  auto *pyHandler = static_cast<PyDiagnosticHandler *>(userData);
735  assert(pyHandler->registeredID && "handler is not registered");
736  pyHandler->registeredID.reset();
737 
738  // Decrement reference, balancing the inc_ref() above.
739  py::object pyHandlerObject =
740  py::cast(pyHandler, py::return_value_policy::reference);
741  pyHandlerObject.dec_ref();
742  };
743 
744  pyHandler->registeredID = mlirContextAttachDiagnosticHandler(
745  get(), handlerCallback, static_cast<void *>(pyHandler), deleteCallback);
746  return pyHandlerObject;
747 }
748 
749 MlirLogicalResult PyMlirContext::ErrorCapture::handler(MlirDiagnostic diag,
750  void *userData) {
751  auto *self = static_cast<ErrorCapture *>(userData);
752  // Check if the context requested we emit errors instead of capturing them.
753  if (self->ctx->emitErrorDiagnostics)
754  return mlirLogicalResultFailure();
755 
757  return mlirLogicalResultFailure();
758 
759  self->errors.emplace_back(PyDiagnostic(diag).getInfo());
760  return mlirLogicalResultSuccess();
761 }
762 
765  if (!context) {
766  throw std::runtime_error(
767  "An MLIR function requires a Context but none was provided in the call "
768  "or from the surrounding environment. Either pass to the function with "
769  "a 'context=' argument or establish a default using 'with Context():'");
770  }
771  return *context;
772 }
773 
774 //------------------------------------------------------------------------------
775 // PyThreadContextEntry management
776 //------------------------------------------------------------------------------
777 
778 std::vector<PyThreadContextEntry> &PyThreadContextEntry::getStack() {
779  static thread_local std::vector<PyThreadContextEntry> stack;
780  return stack;
781 }
782 
784  auto &stack = getStack();
785  if (stack.empty())
786  return nullptr;
787  return &stack.back();
788 }
789 
790 void PyThreadContextEntry::push(FrameKind frameKind, py::object context,
791  py::object insertionPoint,
792  py::object location) {
793  auto &stack = getStack();
794  stack.emplace_back(frameKind, std::move(context), std::move(insertionPoint),
795  std::move(location));
796  // If the new stack has more than one entry and the context of the new top
797  // entry matches the previous, copy the insertionPoint and location from the
798  // previous entry if missing from the new top entry.
799  if (stack.size() > 1) {
800  auto &prev = *(stack.rbegin() + 1);
801  auto &current = stack.back();
802  if (current.context.is(prev.context)) {
803  // Default non-context objects from the previous entry.
804  if (!current.insertionPoint)
805  current.insertionPoint = prev.insertionPoint;
806  if (!current.location)
807  current.location = prev.location;
808  }
809  }
810 }
811 
813  if (!context)
814  return nullptr;
815  return py::cast<PyMlirContext *>(context);
816 }
817 
819  if (!insertionPoint)
820  return nullptr;
821  return py::cast<PyInsertionPoint *>(insertionPoint);
822 }
823 
825  if (!location)
826  return nullptr;
827  return py::cast<PyLocation *>(location);
828 }
829 
831  auto *tos = getTopOfStack();
832  return tos ? tos->getContext() : nullptr;
833 }
834 
836  auto *tos = getTopOfStack();
837  return tos ? tos->getInsertionPoint() : nullptr;
838 }
839 
841  auto *tos = getTopOfStack();
842  return tos ? tos->getLocation() : nullptr;
843 }
844 
846  py::object contextObj = py::cast(context);
847  push(FrameKind::Context, /*context=*/contextObj,
848  /*insertionPoint=*/py::object(),
849  /*location=*/py::object());
850  return contextObj;
851 }
852 
854  auto &stack = getStack();
855  if (stack.empty())
856  throw std::runtime_error("Unbalanced Context enter/exit");
857  auto &tos = stack.back();
858  if (tos.frameKind != FrameKind::Context && tos.getContext() != &context)
859  throw std::runtime_error("Unbalanced Context enter/exit");
860  stack.pop_back();
861 }
862 
863 py::object
865  py::object contextObj =
866  insertionPoint.getBlock().getParentOperation()->getContext().getObject();
867  py::object insertionPointObj = py::cast(insertionPoint);
868  push(FrameKind::InsertionPoint,
869  /*context=*/contextObj,
870  /*insertionPoint=*/insertionPointObj,
871  /*location=*/py::object());
872  return insertionPointObj;
873 }
874 
876  auto &stack = getStack();
877  if (stack.empty())
878  throw std::runtime_error("Unbalanced InsertionPoint enter/exit");
879  auto &tos = stack.back();
880  if (tos.frameKind != FrameKind::InsertionPoint &&
881  tos.getInsertionPoint() != &insertionPoint)
882  throw std::runtime_error("Unbalanced InsertionPoint enter/exit");
883  stack.pop_back();
884 }
885 
887  py::object contextObj = location.getContext().getObject();
888  py::object locationObj = py::cast(location);
889  push(FrameKind::Location, /*context=*/contextObj,
890  /*insertionPoint=*/py::object(),
891  /*location=*/locationObj);
892  return locationObj;
893 }
894 
896  auto &stack = getStack();
897  if (stack.empty())
898  throw std::runtime_error("Unbalanced Location enter/exit");
899  auto &tos = stack.back();
900  if (tos.frameKind != FrameKind::Location && tos.getLocation() != &location)
901  throw std::runtime_error("Unbalanced Location enter/exit");
902  stack.pop_back();
903 }
904 
905 //------------------------------------------------------------------------------
906 // PyDiagnostic*
907 //------------------------------------------------------------------------------
908 
910  valid = false;
911  if (materializedNotes) {
912  for (auto &noteObject : *materializedNotes) {
913  PyDiagnostic *note = py::cast<PyDiagnostic *>(noteObject);
914  note->invalidate();
915  }
916  }
917 }
918 
920  py::object callback)
921  : context(context), callback(std::move(callback)) {}
922 
924 
926  if (!registeredID)
927  return;
928  MlirDiagnosticHandlerID localID = *registeredID;
929  mlirContextDetachDiagnosticHandler(context, localID);
930  assert(!registeredID && "should have unregistered");
931  // Not strictly necessary but keeps stale pointers from being around to cause
932  // issues.
933  context = {nullptr};
934 }
935 
936 void PyDiagnostic::checkValid() {
937  if (!valid) {
938  throw std::invalid_argument(
939  "Diagnostic is invalid (used outside of callback)");
940  }
941 }
942 
944  checkValid();
945  return mlirDiagnosticGetSeverity(diagnostic);
946 }
947 
949  checkValid();
950  MlirLocation loc = mlirDiagnosticGetLocation(diagnostic);
951  MlirContext context = mlirLocationGetContext(loc);
952  return PyLocation(PyMlirContext::forContext(context), loc);
953 }
954 
956  checkValid();
957  py::object fileObject = py::module::import("io").attr("StringIO")();
958  PyFileAccumulator accum(fileObject, /*binary=*/false);
959  mlirDiagnosticPrint(diagnostic, accum.getCallback(), accum.getUserData());
960  return fileObject.attr("getvalue")();
961 }
962 
964  checkValid();
965  if (materializedNotes)
966  return *materializedNotes;
967  intptr_t numNotes = mlirDiagnosticGetNumNotes(diagnostic);
968  materializedNotes = py::tuple(numNotes);
969  for (intptr_t i = 0; i < numNotes; ++i) {
970  MlirDiagnostic noteDiag = mlirDiagnosticGetNote(diagnostic, i);
971  (*materializedNotes)[i] = PyDiagnostic(noteDiag);
972  }
973  return *materializedNotes;
974 }
975 
977  std::vector<DiagnosticInfo> notes;
978  for (py::handle n : getNotes())
979  notes.emplace_back(n.cast<PyDiagnostic>().getInfo());
980  return {getSeverity(), getLocation(), getMessage(), std::move(notes)};
981 }
982 
983 //------------------------------------------------------------------------------
984 // PyDialect, PyDialectDescriptor, PyDialects, PyDialectRegistry
985 //------------------------------------------------------------------------------
986 
987 MlirDialect PyDialects::getDialectForKey(const std::string &key,
988  bool attrError) {
989  MlirDialect dialect = mlirContextGetOrLoadDialect(getContext()->get(),
990  {key.data(), key.size()});
991  if (mlirDialectIsNull(dialect)) {
992  std::string msg = (Twine("Dialect '") + key + "' not found").str();
993  if (attrError)
994  throw py::attribute_error(msg);
995  throw py::index_error(msg);
996  }
997  return dialect;
998 }
999 
1001  return py::reinterpret_steal<py::object>(
1003 }
1004 
1006  MlirDialectRegistry rawRegistry =
1007  mlirPythonCapsuleToDialectRegistry(capsule.ptr());
1008  if (mlirDialectRegistryIsNull(rawRegistry))
1009  throw py::error_already_set();
1010  return PyDialectRegistry(rawRegistry);
1011 }
1012 
1013 //------------------------------------------------------------------------------
1014 // PyLocation
1015 //------------------------------------------------------------------------------
1016 
1018  return py::reinterpret_steal<py::object>(mlirPythonLocationToCapsule(*this));
1019 }
1020 
1022  MlirLocation rawLoc = mlirPythonCapsuleToLocation(capsule.ptr());
1023  if (mlirLocationIsNull(rawLoc))
1024  throw py::error_already_set();
1026  rawLoc);
1027 }
1028 
1030  return PyThreadContextEntry::pushLocation(*this);
1031 }
1032 
1033 void PyLocation::contextExit(const pybind11::object &excType,
1034  const pybind11::object &excVal,
1035  const pybind11::object &excTb) {
1037 }
1038 
1040  auto *location = PyThreadContextEntry::getDefaultLocation();
1041  if (!location) {
1042  throw std::runtime_error(
1043  "An MLIR function requires a Location but none was provided in the "
1044  "call or from the surrounding environment. Either pass to the function "
1045  "with a 'loc=' argument or establish a default using 'with loc:'");
1046  }
1047  return *location;
1048 }
1049 
1050 //------------------------------------------------------------------------------
1051 // PyModule
1052 //------------------------------------------------------------------------------
1053 
1054 PyModule::PyModule(PyMlirContextRef contextRef, MlirModule module)
1055  : BaseContextObject(std::move(contextRef)), module(module) {}
1056 
1058  py::gil_scoped_acquire acquire;
1059  auto &liveModules = getContext()->liveModules;
1060  assert(liveModules.count(module.ptr) == 1 &&
1061  "destroying module not in live map");
1062  liveModules.erase(module.ptr);
1063  mlirModuleDestroy(module);
1064 }
1065 
1066 PyModuleRef PyModule::forModule(MlirModule module) {
1067  MlirContext context = mlirModuleGetContext(module);
1068  PyMlirContextRef contextRef = PyMlirContext::forContext(context);
1069 
1070  py::gil_scoped_acquire acquire;
1071  auto &liveModules = contextRef->liveModules;
1072  auto it = liveModules.find(module.ptr);
1073  if (it == liveModules.end()) {
1074  // Create.
1075  PyModule *unownedModule = new PyModule(std::move(contextRef), module);
1076  // Note that the default return value policy on cast is automatic_reference,
1077  // which does not take ownership (delete will not be called).
1078  // Just be explicit.
1079  py::object pyRef =
1080  py::cast(unownedModule, py::return_value_policy::take_ownership);
1081  unownedModule->handle = pyRef;
1082  liveModules[module.ptr] =
1083  std::make_pair(unownedModule->handle, unownedModule);
1084  return PyModuleRef(unownedModule, std::move(pyRef));
1085  }
1086  // Use existing.
1087  PyModule *existing = it->second.second;
1088  py::object pyRef = py::reinterpret_borrow<py::object>(it->second.first);
1089  return PyModuleRef(existing, std::move(pyRef));
1090 }
1091 
1092 py::object PyModule::createFromCapsule(py::object capsule) {
1093  MlirModule rawModule = mlirPythonCapsuleToModule(capsule.ptr());
1094  if (mlirModuleIsNull(rawModule))
1095  throw py::error_already_set();
1096  return forModule(rawModule).releaseObject();
1097 }
1098 
1099 py::object PyModule::getCapsule() {
1100  return py::reinterpret_steal<py::object>(mlirPythonModuleToCapsule(get()));
1101 }
1102 
1103 //------------------------------------------------------------------------------
1104 // PyOperation
1105 //------------------------------------------------------------------------------
1106 
1107 PyOperation::PyOperation(PyMlirContextRef contextRef, MlirOperation operation)
1108  : BaseContextObject(std::move(contextRef)), operation(operation) {}
1109 
1111  // If the operation has already been invalidated there is nothing to do.
1112  if (!valid)
1113  return;
1114  auto &liveOperations = getContext()->liveOperations;
1115  assert(liveOperations.count(operation.ptr) == 1 &&
1116  "destroying operation not in live map");
1117  liveOperations.erase(operation.ptr);
1118  if (!isAttached()) {
1119  mlirOperationDestroy(operation);
1120  }
1121 }
1122 
1123 PyOperationRef PyOperation::createInstance(PyMlirContextRef contextRef,
1124  MlirOperation operation,
1125  py::object parentKeepAlive) {
1126  auto &liveOperations = contextRef->liveOperations;
1127  // Create.
1128  PyOperation *unownedOperation =
1129  new PyOperation(std::move(contextRef), operation);
1130  // Note that the default return value policy on cast is automatic_reference,
1131  // which does not take ownership (delete will not be called).
1132  // Just be explicit.
1133  py::object pyRef =
1134  py::cast(unownedOperation, py::return_value_policy::take_ownership);
1135  unownedOperation->handle = pyRef;
1136  if (parentKeepAlive) {
1137  unownedOperation->parentKeepAlive = std::move(parentKeepAlive);
1138  }
1139  liveOperations[operation.ptr] = std::make_pair(pyRef, unownedOperation);
1140  return PyOperationRef(unownedOperation, std::move(pyRef));
1141 }
1142 
1144  MlirOperation operation,
1145  py::object parentKeepAlive) {
1146  auto &liveOperations = contextRef->liveOperations;
1147  auto it = liveOperations.find(operation.ptr);
1148  if (it == liveOperations.end()) {
1149  // Create.
1150  return createInstance(std::move(contextRef), operation,
1151  std::move(parentKeepAlive));
1152  }
1153  // Use existing.
1154  PyOperation *existing = it->second.second;
1155  py::object pyRef = py::reinterpret_borrow<py::object>(it->second.first);
1156  return PyOperationRef(existing, std::move(pyRef));
1157 }
1158 
1160  MlirOperation operation,
1161  py::object parentKeepAlive) {
1162  auto &liveOperations = contextRef->liveOperations;
1163  assert(liveOperations.count(operation.ptr) == 0 &&
1164  "cannot create detached operation that already exists");
1165  (void)liveOperations;
1166 
1167  PyOperationRef created = createInstance(std::move(contextRef), operation,
1168  std::move(parentKeepAlive));
1169  created->attached = false;
1170  return created;
1171 }
1172 
1174  const std::string &sourceStr,
1175  const std::string &sourceName) {
1176  PyMlirContext::ErrorCapture errors(contextRef);
1177  MlirOperation op =
1178  mlirOperationCreateParse(contextRef->get(), toMlirStringRef(sourceStr),
1179  toMlirStringRef(sourceName));
1180  if (mlirOperationIsNull(op))
1181  throw MLIRError("Unable to parse operation assembly", errors.take());
1182  return PyOperation::createDetached(std::move(contextRef), op);
1183 }
1184 
1186  if (!valid) {
1187  throw std::runtime_error("the operation has been invalidated");
1188  }
1189 }
1190 
1191 void PyOperationBase::print(std::optional<int64_t> largeElementsLimit,
1192  bool enableDebugInfo, bool prettyDebugInfo,
1193  bool printGenericOpForm, bool useLocalScope,
1194  bool assumeVerified, py::object fileObject,
1195  bool binary) {
1196  PyOperation &operation = getOperation();
1197  operation.checkValid();
1198  if (fileObject.is_none())
1199  fileObject = py::module::import("sys").attr("stdout");
1200 
1201  MlirOpPrintingFlags flags = mlirOpPrintingFlagsCreate();
1202  if (largeElementsLimit)
1203  mlirOpPrintingFlagsElideLargeElementsAttrs(flags, *largeElementsLimit);
1204  if (enableDebugInfo)
1205  mlirOpPrintingFlagsEnableDebugInfo(flags, /*enable=*/true,
1206  /*prettyForm=*/prettyDebugInfo);
1207  if (printGenericOpForm)
1209  if (useLocalScope)
1211  if (assumeVerified)
1213 
1214  PyFileAccumulator accum(fileObject, binary);
1215  mlirOperationPrintWithFlags(operation, flags, accum.getCallback(),
1216  accum.getUserData());
1218 }
1219 
1220 void PyOperationBase::print(PyAsmState &state, py::object fileObject,
1221  bool binary) {
1222  PyOperation &operation = getOperation();
1223  operation.checkValid();
1224  if (fileObject.is_none())
1225  fileObject = py::module::import("sys").attr("stdout");
1226  PyFileAccumulator accum(fileObject, binary);
1227  mlirOperationPrintWithState(operation, state.get(), accum.getCallback(),
1228  accum.getUserData());
1229 }
1230 
1231 void PyOperationBase::writeBytecode(const py::object &fileObject,
1232  std::optional<int64_t> bytecodeVersion) {
1233  PyOperation &operation = getOperation();
1234  operation.checkValid();
1235  PyFileAccumulator accum(fileObject, /*binary=*/true);
1236 
1237  if (!bytecodeVersion.has_value())
1238  return mlirOperationWriteBytecode(operation, accum.getCallback(),
1239  accum.getUserData());
1240 
1241  MlirBytecodeWriterConfig config = mlirBytecodeWriterConfigCreate();
1242  mlirBytecodeWriterConfigDesiredEmitVersion(config, *bytecodeVersion);
1244  operation, config, accum.getCallback(), accum.getUserData());
1246  if (mlirLogicalResultIsFailure(res))
1247  throw py::value_error((Twine("Unable to honor desired bytecode version ") +
1248  Twine(*bytecodeVersion))
1249  .str());
1250 }
1251 
1252 py::object PyOperationBase::getAsm(bool binary,
1253  std::optional<int64_t> largeElementsLimit,
1254  bool enableDebugInfo, bool prettyDebugInfo,
1255  bool printGenericOpForm, bool useLocalScope,
1256  bool assumeVerified) {
1257  py::object fileObject;
1258  if (binary) {
1259  fileObject = py::module::import("io").attr("BytesIO")();
1260  } else {
1261  fileObject = py::module::import("io").attr("StringIO")();
1262  }
1263  print(/*largeElementsLimit=*/largeElementsLimit,
1264  /*enableDebugInfo=*/enableDebugInfo,
1265  /*prettyDebugInfo=*/prettyDebugInfo,
1266  /*printGenericOpForm=*/printGenericOpForm,
1267  /*useLocalScope=*/useLocalScope,
1268  /*assumeVerified=*/assumeVerified,
1269  /*fileObject=*/fileObject,
1270  /*binary=*/binary);
1271 
1272  return fileObject.attr("getvalue")();
1273 }
1274 
1276  PyOperation &operation = getOperation();
1277  PyOperation &otherOp = other.getOperation();
1278  operation.checkValid();
1279  otherOp.checkValid();
1280  mlirOperationMoveAfter(operation, otherOp);
1281  operation.parentKeepAlive = otherOp.parentKeepAlive;
1282 }
1283 
1285  PyOperation &operation = getOperation();
1286  PyOperation &otherOp = other.getOperation();
1287  operation.checkValid();
1288  otherOp.checkValid();
1289  mlirOperationMoveBefore(operation, otherOp);
1290  operation.parentKeepAlive = otherOp.parentKeepAlive;
1291 }
1292 
1294  PyOperation &op = getOperation();
1296  if (!mlirOperationVerify(op.get()))
1297  throw MLIRError("Verification failed", errors.take());
1298  return true;
1299 }
1300 
1301 std::optional<PyOperationRef> PyOperation::getParentOperation() {
1302  checkValid();
1303  if (!isAttached())
1304  throw py::value_error("Detached operations have no parent");
1305  MlirOperation operation = mlirOperationGetParentOperation(get());
1306  if (mlirOperationIsNull(operation))
1307  return {};
1308  return PyOperation::forOperation(getContext(), operation);
1309 }
1310 
1312  checkValid();
1313  std::optional<PyOperationRef> parentOperation = getParentOperation();
1314  MlirBlock block = mlirOperationGetBlock(get());
1315  assert(!mlirBlockIsNull(block) && "Attached operation has null parent");
1316  assert(parentOperation && "Operation has no parent");
1317  return PyBlock{std::move(*parentOperation), block};
1318 }
1319 
1321  checkValid();
1322  return py::reinterpret_steal<py::object>(mlirPythonOperationToCapsule(get()));
1323 }
1324 
1325 py::object PyOperation::createFromCapsule(py::object capsule) {
1326  MlirOperation rawOperation = mlirPythonCapsuleToOperation(capsule.ptr());
1327  if (mlirOperationIsNull(rawOperation))
1328  throw py::error_already_set();
1329  MlirContext rawCtxt = mlirOperationGetContext(rawOperation);
1330  return forOperation(PyMlirContext::forContext(rawCtxt), rawOperation)
1331  .releaseObject();
1332 }
1333 
1335  const py::object &maybeIp) {
1336  // InsertPoint active?
1337  if (!maybeIp.is(py::cast(false))) {
1338  PyInsertionPoint *ip;
1339  if (maybeIp.is_none()) {
1341  } else {
1342  ip = py::cast<PyInsertionPoint *>(maybeIp);
1343  }
1344  if (ip)
1345  ip->insert(*op.get());
1346  }
1347 }
1348 
1349 py::object PyOperation::create(const std::string &name,
1350  std::optional<std::vector<PyType *>> results,
1351  std::optional<std::vector<PyValue *>> operands,
1352  std::optional<py::dict> attributes,
1353  std::optional<std::vector<PyBlock *>> successors,
1354  int regions, DefaultingPyLocation location,
1355  const py::object &maybeIp, bool inferType) {
1356  llvm::SmallVector<MlirValue, 4> mlirOperands;
1357  llvm::SmallVector<MlirType, 4> mlirResults;
1358  llvm::SmallVector<MlirBlock, 4> mlirSuccessors;
1360 
1361  // General parameter validation.
1362  if (regions < 0)
1363  throw py::value_error("number of regions must be >= 0");
1364 
1365  // Unpack/validate operands.
1366  if (operands) {
1367  mlirOperands.reserve(operands->size());
1368  for (PyValue *operand : *operands) {
1369  if (!operand)
1370  throw py::value_error("operand value cannot be None");
1371  mlirOperands.push_back(operand->get());
1372  }
1373  }
1374 
1375  // Unpack/validate results.
1376  if (results) {
1377  mlirResults.reserve(results->size());
1378  for (PyType *result : *results) {
1379  // TODO: Verify result type originate from the same context.
1380  if (!result)
1381  throw py::value_error("result type cannot be None");
1382  mlirResults.push_back(*result);
1383  }
1384  }
1385  // Unpack/validate attributes.
1386  if (attributes) {
1387  mlirAttributes.reserve(attributes->size());
1388  for (auto &it : *attributes) {
1389  std::string key;
1390  try {
1391  key = it.first.cast<std::string>();
1392  } catch (py::cast_error &err) {
1393  std::string msg = "Invalid attribute key (not a string) when "
1394  "attempting to create the operation \"" +
1395  name + "\" (" + err.what() + ")";
1396  throw py::cast_error(msg);
1397  }
1398  try {
1399  auto &attribute = it.second.cast<PyAttribute &>();
1400  // TODO: Verify attribute originates from the same context.
1401  mlirAttributes.emplace_back(std::move(key), attribute);
1402  } catch (py::reference_cast_error &) {
1403  // This exception seems thrown when the value is "None".
1404  std::string msg =
1405  "Found an invalid (`None`?) attribute value for the key \"" + key +
1406  "\" when attempting to create the operation \"" + name + "\"";
1407  throw py::cast_error(msg);
1408  } catch (py::cast_error &err) {
1409  std::string msg = "Invalid attribute value for the key \"" + key +
1410  "\" when attempting to create the operation \"" +
1411  name + "\" (" + err.what() + ")";
1412  throw py::cast_error(msg);
1413  }
1414  }
1415  }
1416  // Unpack/validate successors.
1417  if (successors) {
1418  mlirSuccessors.reserve(successors->size());
1419  for (auto *successor : *successors) {
1420  // TODO: Verify successor originate from the same context.
1421  if (!successor)
1422  throw py::value_error("successor block cannot be None");
1423  mlirSuccessors.push_back(successor->get());
1424  }
1425  }
1426 
1427  // Apply unpacked/validated to the operation state. Beyond this
1428  // point, exceptions cannot be thrown or else the state will leak.
1429  MlirOperationState state =
1430  mlirOperationStateGet(toMlirStringRef(name), location);
1431  if (!mlirOperands.empty())
1432  mlirOperationStateAddOperands(&state, mlirOperands.size(),
1433  mlirOperands.data());
1434  state.enableResultTypeInference = inferType;
1435  if (!mlirResults.empty())
1436  mlirOperationStateAddResults(&state, mlirResults.size(),
1437  mlirResults.data());
1438  if (!mlirAttributes.empty()) {
1439  // Note that the attribute names directly reference bytes in
1440  // mlirAttributes, so that vector must not be changed from here
1441  // on.
1442  llvm::SmallVector<MlirNamedAttribute, 4> mlirNamedAttributes;
1443  mlirNamedAttributes.reserve(mlirAttributes.size());
1444  for (auto &it : mlirAttributes)
1445  mlirNamedAttributes.push_back(mlirNamedAttributeGet(
1447  toMlirStringRef(it.first)),
1448  it.second));
1449  mlirOperationStateAddAttributes(&state, mlirNamedAttributes.size(),
1450  mlirNamedAttributes.data());
1451  }
1452  if (!mlirSuccessors.empty())
1453  mlirOperationStateAddSuccessors(&state, mlirSuccessors.size(),
1454  mlirSuccessors.data());
1455  if (regions) {
1457  mlirRegions.resize(regions);
1458  for (int i = 0; i < regions; ++i)
1459  mlirRegions[i] = mlirRegionCreate();
1460  mlirOperationStateAddOwnedRegions(&state, mlirRegions.size(),
1461  mlirRegions.data());
1462  }
1463 
1464  // Construct the operation.
1465  MlirOperation operation = mlirOperationCreate(&state);
1466  if (!operation.ptr)
1467  throw py::value_error("Operation creation failed");
1468  PyOperationRef created =
1469  PyOperation::createDetached(location->getContext(), operation);
1470  maybeInsertOperation(created, maybeIp);
1471 
1472  return created->createOpView();
1473 }
1474 
1475 py::object PyOperation::clone(const py::object &maybeIp) {
1476  MlirOperation clonedOperation = mlirOperationClone(operation);
1477  PyOperationRef cloned =
1478  PyOperation::createDetached(getContext(), clonedOperation);
1479  maybeInsertOperation(cloned, maybeIp);
1480 
1481  return cloned->createOpView();
1482 }
1483 
1485  checkValid();
1486  MlirIdentifier ident = mlirOperationGetName(get());
1487  MlirStringRef identStr = mlirIdentifierStr(ident);
1488  auto operationCls = PyGlobals::get().lookupOperationClass(
1489  StringRef(identStr.data, identStr.length));
1490  if (operationCls)
1491  return PyOpView::constructDerived(*operationCls, *getRef().get());
1492  return py::cast(PyOpView(getRef().getObject()));
1493 }
1494 
1496  checkValid();
1497  // TODO: Fix memory hazards when erasing a tree of operations for which a deep
1498  // Python reference to a child operation is live. All children should also
1499  // have their `valid` bit set to false.
1500  auto &liveOperations = getContext()->liveOperations;
1501  if (liveOperations.count(operation.ptr))
1502  liveOperations.erase(operation.ptr);
1503  mlirOperationDestroy(operation);
1504  valid = false;
1505 }
1506 
1507 //------------------------------------------------------------------------------
1508 // PyOpView
1509 //------------------------------------------------------------------------------
1510 
1511 static void populateResultTypes(StringRef name, py::list resultTypeList,
1512  const py::object &resultSegmentSpecObj,
1513  std::vector<int32_t> &resultSegmentLengths,
1514  std::vector<PyType *> &resultTypes) {
1515  resultTypes.reserve(resultTypeList.size());
1516  if (resultSegmentSpecObj.is_none()) {
1517  // Non-variadic result unpacking.
1518  for (const auto &it : llvm::enumerate(resultTypeList)) {
1519  try {
1520  resultTypes.push_back(py::cast<PyType *>(it.value()));
1521  if (!resultTypes.back())
1522  throw py::cast_error();
1523  } catch (py::cast_error &err) {
1524  throw py::value_error((llvm::Twine("Result ") +
1525  llvm::Twine(it.index()) + " of operation \"" +
1526  name + "\" must be a Type (" + err.what() + ")")
1527  .str());
1528  }
1529  }
1530  } else {
1531  // Sized result unpacking.
1532  auto resultSegmentSpec = py::cast<std::vector<int>>(resultSegmentSpecObj);
1533  if (resultSegmentSpec.size() != resultTypeList.size()) {
1534  throw py::value_error((llvm::Twine("Operation \"") + name +
1535  "\" requires " +
1536  llvm::Twine(resultSegmentSpec.size()) +
1537  " result segments but was provided " +
1538  llvm::Twine(resultTypeList.size()))
1539  .str());
1540  }
1541  resultSegmentLengths.reserve(resultTypeList.size());
1542  for (const auto &it :
1543  llvm::enumerate(llvm::zip(resultTypeList, resultSegmentSpec))) {
1544  int segmentSpec = std::get<1>(it.value());
1545  if (segmentSpec == 1 || segmentSpec == 0) {
1546  // Unpack unary element.
1547  try {
1548  auto *resultType = py::cast<PyType *>(std::get<0>(it.value()));
1549  if (resultType) {
1550  resultTypes.push_back(resultType);
1551  resultSegmentLengths.push_back(1);
1552  } else if (segmentSpec == 0) {
1553  // Allowed to be optional.
1554  resultSegmentLengths.push_back(0);
1555  } else {
1556  throw py::cast_error("was None and result is not optional");
1557  }
1558  } catch (py::cast_error &err) {
1559  throw py::value_error((llvm::Twine("Result ") +
1560  llvm::Twine(it.index()) + " of operation \"" +
1561  name + "\" must be a Type (" + err.what() +
1562  ")")
1563  .str());
1564  }
1565  } else if (segmentSpec == -1) {
1566  // Unpack sequence by appending.
1567  try {
1568  if (std::get<0>(it.value()).is_none()) {
1569  // Treat it as an empty list.
1570  resultSegmentLengths.push_back(0);
1571  } else {
1572  // Unpack the list.
1573  auto segment = py::cast<py::sequence>(std::get<0>(it.value()));
1574  for (py::object segmentItem : segment) {
1575  resultTypes.push_back(py::cast<PyType *>(segmentItem));
1576  if (!resultTypes.back()) {
1577  throw py::cast_error("contained a None item");
1578  }
1579  }
1580  resultSegmentLengths.push_back(segment.size());
1581  }
1582  } catch (std::exception &err) {
1583  // NOTE: Sloppy to be using a catch-all here, but there are at least
1584  // three different unrelated exceptions that can be thrown in the
1585  // above "casts". Just keep the scope above small and catch them all.
1586  throw py::value_error((llvm::Twine("Result ") +
1587  llvm::Twine(it.index()) + " of operation \"" +
1588  name + "\" must be a Sequence of Types (" +
1589  err.what() + ")")
1590  .str());
1591  }
1592  } else {
1593  throw py::value_error("Unexpected segment spec");
1594  }
1595  }
1596  }
1597 }
1598 
1600  const py::object &cls, std::optional<py::list> resultTypeList,
1601  py::list operandList, std::optional<py::dict> attributes,
1602  std::optional<std::vector<PyBlock *>> successors,
1603  std::optional<int> regions, DefaultingPyLocation location,
1604  const py::object &maybeIp) {
1605  PyMlirContextRef context = location->getContext();
1606  // Class level operation construction metadata.
1607  std::string name = py::cast<std::string>(cls.attr("OPERATION_NAME"));
1608  // Operand and result segment specs are either none, which does no
1609  // variadic unpacking, or a list of ints with segment sizes, where each
1610  // element is either a positive number (typically 1 for a scalar) or -1 to
1611  // indicate that it is derived from the length of the same-indexed operand
1612  // or result (implying that it is a list at that position).
1613  py::object operandSegmentSpecObj = cls.attr("_ODS_OPERAND_SEGMENTS");
1614  py::object resultSegmentSpecObj = cls.attr("_ODS_RESULT_SEGMENTS");
1615 
1616  std::vector<int32_t> operandSegmentLengths;
1617  std::vector<int32_t> resultSegmentLengths;
1618 
1619  // Validate/determine region count.
1620  auto opRegionSpec = py::cast<std::tuple<int, bool>>(cls.attr("_ODS_REGIONS"));
1621  int opMinRegionCount = std::get<0>(opRegionSpec);
1622  bool opHasNoVariadicRegions = std::get<1>(opRegionSpec);
1623  if (!regions) {
1624  regions = opMinRegionCount;
1625  }
1626  if (*regions < opMinRegionCount) {
1627  throw py::value_error(
1628  (llvm::Twine("Operation \"") + name + "\" requires a minimum of " +
1629  llvm::Twine(opMinRegionCount) +
1630  " regions but was built with regions=" + llvm::Twine(*regions))
1631  .str());
1632  }
1633  if (opHasNoVariadicRegions && *regions > opMinRegionCount) {
1634  throw py::value_error(
1635  (llvm::Twine("Operation \"") + name + "\" requires a maximum of " +
1636  llvm::Twine(opMinRegionCount) +
1637  " regions but was built with regions=" + llvm::Twine(*regions))
1638  .str());
1639  }
1640 
1641  // Unpack results.
1642  std::vector<PyType *> resultTypes;
1643  if (resultTypeList.has_value()) {
1644  populateResultTypes(name, *resultTypeList, resultSegmentSpecObj,
1645  resultSegmentLengths, resultTypes);
1646  }
1647 
1648  // Unpack operands.
1649  std::vector<PyValue *> operands;
1650  operands.reserve(operands.size());
1651  if (operandSegmentSpecObj.is_none()) {
1652  // Non-sized operand unpacking.
1653  for (const auto &it : llvm::enumerate(operandList)) {
1654  try {
1655  operands.push_back(py::cast<PyValue *>(it.value()));
1656  if (!operands.back())
1657  throw py::cast_error();
1658  } catch (py::cast_error &err) {
1659  throw py::value_error((llvm::Twine("Operand ") +
1660  llvm::Twine(it.index()) + " of operation \"" +
1661  name + "\" must be a Value (" + err.what() + ")")
1662  .str());
1663  }
1664  }
1665  } else {
1666  // Sized operand unpacking.
1667  auto operandSegmentSpec = py::cast<std::vector<int>>(operandSegmentSpecObj);
1668  if (operandSegmentSpec.size() != operandList.size()) {
1669  throw py::value_error((llvm::Twine("Operation \"") + name +
1670  "\" requires " +
1671  llvm::Twine(operandSegmentSpec.size()) +
1672  "operand segments but was provided " +
1673  llvm::Twine(operandList.size()))
1674  .str());
1675  }
1676  operandSegmentLengths.reserve(operandList.size());
1677  for (const auto &it :
1678  llvm::enumerate(llvm::zip(operandList, operandSegmentSpec))) {
1679  int segmentSpec = std::get<1>(it.value());
1680  if (segmentSpec == 1 || segmentSpec == 0) {
1681  // Unpack unary element.
1682  try {
1683  auto *operandValue = py::cast<PyValue *>(std::get<0>(it.value()));
1684  if (operandValue) {
1685  operands.push_back(operandValue);
1686  operandSegmentLengths.push_back(1);
1687  } else if (segmentSpec == 0) {
1688  // Allowed to be optional.
1689  operandSegmentLengths.push_back(0);
1690  } else {
1691  throw py::cast_error("was None and operand is not optional");
1692  }
1693  } catch (py::cast_error &err) {
1694  throw py::value_error((llvm::Twine("Operand ") +
1695  llvm::Twine(it.index()) + " of operation \"" +
1696  name + "\" must be a Value (" + err.what() +
1697  ")")
1698  .str());
1699  }
1700  } else if (segmentSpec == -1) {
1701  // Unpack sequence by appending.
1702  try {
1703  if (std::get<0>(it.value()).is_none()) {
1704  // Treat it as an empty list.
1705  operandSegmentLengths.push_back(0);
1706  } else {
1707  // Unpack the list.
1708  auto segment = py::cast<py::sequence>(std::get<0>(it.value()));
1709  for (py::object segmentItem : segment) {
1710  operands.push_back(py::cast<PyValue *>(segmentItem));
1711  if (!operands.back()) {
1712  throw py::cast_error("contained a None item");
1713  }
1714  }
1715  operandSegmentLengths.push_back(segment.size());
1716  }
1717  } catch (std::exception &err) {
1718  // NOTE: Sloppy to be using a catch-all here, but there are at least
1719  // three different unrelated exceptions that can be thrown in the
1720  // above "casts". Just keep the scope above small and catch them all.
1721  throw py::value_error((llvm::Twine("Operand ") +
1722  llvm::Twine(it.index()) + " of operation \"" +
1723  name + "\" must be a Sequence of Values (" +
1724  err.what() + ")")
1725  .str());
1726  }
1727  } else {
1728  throw py::value_error("Unexpected segment spec");
1729  }
1730  }
1731  }
1732 
1733  // Merge operand/result segment lengths into attributes if needed.
1734  if (!operandSegmentLengths.empty() || !resultSegmentLengths.empty()) {
1735  // Dup.
1736  if (attributes) {
1737  attributes = py::dict(*attributes);
1738  } else {
1739  attributes = py::dict();
1740  }
1741  if (attributes->contains("resultSegmentSizes") ||
1742  attributes->contains("operandSegmentSizes")) {
1743  throw py::value_error("Manually setting a 'resultSegmentSizes' or "
1744  "'operandSegmentSizes' attribute is unsupported. "
1745  "Use Operation.create for such low-level access.");
1746  }
1747 
1748  // Add resultSegmentSizes attribute.
1749  if (!resultSegmentLengths.empty()) {
1750  MlirAttribute segmentLengthAttr =
1751  mlirDenseI32ArrayGet(context->get(), resultSegmentLengths.size(),
1752  resultSegmentLengths.data());
1753  (*attributes)["resultSegmentSizes"] =
1754  PyAttribute(context, segmentLengthAttr);
1755  }
1756 
1757  // Add operandSegmentSizes attribute.
1758  if (!operandSegmentLengths.empty()) {
1759  MlirAttribute segmentLengthAttr =
1760  mlirDenseI32ArrayGet(context->get(), operandSegmentLengths.size(),
1761  operandSegmentLengths.data());
1762  (*attributes)["operandSegmentSizes"] =
1763  PyAttribute(context, segmentLengthAttr);
1764  }
1765  }
1766 
1767  // Delegate to create.
1768  return PyOperation::create(name,
1769  /*results=*/std::move(resultTypes),
1770  /*operands=*/std::move(operands),
1771  /*attributes=*/std::move(attributes),
1772  /*successors=*/std::move(successors),
1773  /*regions=*/*regions, location, maybeIp,
1774  !resultTypeList);
1775 }
1776 
1777 pybind11::object PyOpView::constructDerived(const pybind11::object &cls,
1778  const PyOperation &operation) {
1779  // TODO: pybind11 2.6 supports a more direct form.
1780  // Upgrade many years from now.
1781  // auto opViewType = py::type::of<PyOpView>();
1782  py::handle opViewType = py::detail::get_type_handle(typeid(PyOpView), true);
1783  py::object instance = cls.attr("__new__")(cls);
1784  opViewType.attr("__init__")(instance, operation);
1785  return instance;
1786 }
1787 
1788 PyOpView::PyOpView(const py::object &operationObject)
1789  // Casting through the PyOperationBase base-class and then back to the
1790  // Operation lets us accept any PyOperationBase subclass.
1791  : operation(py::cast<PyOperationBase &>(operationObject).getOperation()),
1792  operationObject(operation.getRef().getObject()) {}
1793 
1794 //------------------------------------------------------------------------------
1795 // PyInsertionPoint.
1796 //------------------------------------------------------------------------------
1797 
1799 
1801  : refOperation(beforeOperationBase.getOperation().getRef()),
1802  block((*refOperation)->getBlock()) {}
1803 
1805  PyOperation &operation = operationBase.getOperation();
1806  if (operation.isAttached())
1807  throw py::value_error(
1808  "Attempt to insert operation that is already attached");
1809  block.getParentOperation()->checkValid();
1810  MlirOperation beforeOp = {nullptr};
1811  if (refOperation) {
1812  // Insert before operation.
1813  (*refOperation)->checkValid();
1814  beforeOp = (*refOperation)->get();
1815  } else {
1816  // Insert at end (before null) is only valid if the block does not
1817  // already end in a known terminator (violating this will cause assertion
1818  // failures later).
1819  if (!mlirOperationIsNull(mlirBlockGetTerminator(block.get()))) {
1820  throw py::index_error("Cannot insert operation at the end of a block "
1821  "that already has a terminator. Did you mean to "
1822  "use 'InsertionPoint.at_block_terminator(block)' "
1823  "versus 'InsertionPoint(block)'?");
1824  }
1825  }
1826  mlirBlockInsertOwnedOperationBefore(block.get(), beforeOp, operation);
1827  operation.setAttached();
1828 }
1829 
1831  MlirOperation firstOp = mlirBlockGetFirstOperation(block.get());
1832  if (mlirOperationIsNull(firstOp)) {
1833  // Just insert at end.
1834  return PyInsertionPoint(block);
1835  }
1836 
1837  // Insert before first op.
1839  block.getParentOperation()->getContext(), firstOp);
1840  return PyInsertionPoint{block, std::move(firstOpRef)};
1841 }
1842 
1844  MlirOperation terminator = mlirBlockGetTerminator(block.get());
1845  if (mlirOperationIsNull(terminator))
1846  throw py::value_error("Block has no terminator");
1847  PyOperationRef terminatorOpRef = PyOperation::forOperation(
1848  block.getParentOperation()->getContext(), terminator);
1849  return PyInsertionPoint{block, std::move(terminatorOpRef)};
1850 }
1851 
1854 }
1855 
1856 void PyInsertionPoint::contextExit(const pybind11::object &excType,
1857  const pybind11::object &excVal,
1858  const pybind11::object &excTb) {
1860 }
1861 
1862 //------------------------------------------------------------------------------
1863 // PyAttribute.
1864 //------------------------------------------------------------------------------
1865 
1866 bool PyAttribute::operator==(const PyAttribute &other) const {
1867  return mlirAttributeEqual(attr, other.attr);
1868 }
1869 
1871  return py::reinterpret_steal<py::object>(mlirPythonAttributeToCapsule(*this));
1872 }
1873 
1875  MlirAttribute rawAttr = mlirPythonCapsuleToAttribute(capsule.ptr());
1876  if (mlirAttributeIsNull(rawAttr))
1877  throw py::error_already_set();
1878  return PyAttribute(
1880 }
1881 
1882 //------------------------------------------------------------------------------
1883 // PyNamedAttribute.
1884 //------------------------------------------------------------------------------
1885 
1886 PyNamedAttribute::PyNamedAttribute(MlirAttribute attr, std::string ownedName)
1887  : ownedName(new std::string(std::move(ownedName))) {
1890  toMlirStringRef(*this->ownedName)),
1891  attr);
1892 }
1893 
1894 //------------------------------------------------------------------------------
1895 // PyType.
1896 //------------------------------------------------------------------------------
1897 
1898 bool PyType::operator==(const PyType &other) const {
1899  return mlirTypeEqual(type, other.type);
1900 }
1901 
1902 py::object PyType::getCapsule() {
1903  return py::reinterpret_steal<py::object>(mlirPythonTypeToCapsule(*this));
1904 }
1905 
1906 PyType PyType::createFromCapsule(py::object capsule) {
1907  MlirType rawType = mlirPythonCapsuleToType(capsule.ptr());
1908  if (mlirTypeIsNull(rawType))
1909  throw py::error_already_set();
1911  rawType);
1912 }
1913 
1914 //------------------------------------------------------------------------------
1915 // PyTypeID.
1916 //------------------------------------------------------------------------------
1917 
1918 py::object PyTypeID::getCapsule() {
1919  return py::reinterpret_steal<py::object>(mlirPythonTypeIDToCapsule(*this));
1920 }
1921 
1923  MlirTypeID mlirTypeID = mlirPythonCapsuleToTypeID(capsule.ptr());
1924  if (mlirTypeIDIsNull(mlirTypeID))
1925  throw py::error_already_set();
1926  return PyTypeID(mlirTypeID);
1927 }
1928 bool PyTypeID::operator==(const PyTypeID &other) const {
1929  return mlirTypeIDEqual(typeID, other.typeID);
1930 }
1931 
1932 //------------------------------------------------------------------------------
1933 // PyValue and subclasses.
1934 //------------------------------------------------------------------------------
1935 
1936 pybind11::object PyValue::getCapsule() {
1937  return py::reinterpret_steal<py::object>(mlirPythonValueToCapsule(get()));
1938 }
1939 
1940 pybind11::object PyValue::maybeDownCast() {
1941  MlirType type = mlirValueGetType(get());
1942  MlirTypeID mlirTypeID = mlirTypeGetTypeID(type);
1943  assert(!mlirTypeIDIsNull(mlirTypeID) &&
1944  "mlirTypeID was expected to be non-null.");
1945  std::optional<pybind11::function> valueCaster =
1947  // py::return_value_policy::move means use std::move to move the return value
1948  // contents into a new instance that will be owned by Python.
1949  py::object thisObj = py::cast(this, py::return_value_policy::move);
1950  if (!valueCaster)
1951  return thisObj;
1952  return valueCaster.value()(thisObj);
1953 }
1954 
1955 PyValue PyValue::createFromCapsule(pybind11::object capsule) {
1956  MlirValue value = mlirPythonCapsuleToValue(capsule.ptr());
1957  if (mlirValueIsNull(value))
1958  throw py::error_already_set();
1959  MlirOperation owner;
1960  if (mlirValueIsAOpResult(value))
1961  owner = mlirOpResultGetOwner(value);
1962  if (mlirValueIsABlockArgument(value))
1964  if (mlirOperationIsNull(owner))
1965  throw py::error_already_set();
1966  MlirContext ctx = mlirOperationGetContext(owner);
1967  PyOperationRef ownerRef =
1969  return PyValue(ownerRef, value);
1970 }
1971 
1972 //------------------------------------------------------------------------------
1973 // PySymbolTable.
1974 //------------------------------------------------------------------------------
1975 
1977  : operation(operation.getOperation().getRef()) {
1978  symbolTable = mlirSymbolTableCreate(operation.getOperation().get());
1979  if (mlirSymbolTableIsNull(symbolTable)) {
1980  throw py::cast_error("Operation is not a Symbol Table.");
1981  }
1982 }
1983 
1984 py::object PySymbolTable::dunderGetItem(const std::string &name) {
1985  operation->checkValid();
1986  MlirOperation symbol = mlirSymbolTableLookup(
1987  symbolTable, mlirStringRefCreate(name.data(), name.length()));
1988  if (mlirOperationIsNull(symbol))
1989  throw py::key_error("Symbol '" + name + "' not in the symbol table.");
1990 
1991  return PyOperation::forOperation(operation->getContext(), symbol,
1992  operation.getObject())
1993  ->createOpView();
1994 }
1995 
1997  operation->checkValid();
1998  symbol.getOperation().checkValid();
1999  mlirSymbolTableErase(symbolTable, symbol.getOperation().get());
2000  // The operation is also erased, so we must invalidate it. There may be Python
2001  // references to this operation so we don't want to delete it from the list of
2002  // live operations here.
2003  symbol.getOperation().valid = false;
2004 }
2005 
2006 void PySymbolTable::dunderDel(const std::string &name) {
2007  py::object operation = dunderGetItem(name);
2008  erase(py::cast<PyOperationBase &>(operation));
2009 }
2010 
2011 MlirAttribute PySymbolTable::insert(PyOperationBase &symbol) {
2012  operation->checkValid();
2013  symbol.getOperation().checkValid();
2014  MlirAttribute symbolAttr = mlirOperationGetAttributeByName(
2016  if (mlirAttributeIsNull(symbolAttr))
2017  throw py::value_error("Expected operation to have a symbol name.");
2018  return mlirSymbolTableInsert(symbolTable, symbol.getOperation().get());
2019 }
2020 
2022  // Op must already be a symbol.
2023  PyOperation &operation = symbol.getOperation();
2024  operation.checkValid();
2026  MlirAttribute existingNameAttr =
2027  mlirOperationGetAttributeByName(operation.get(), attrName);
2028  if (mlirAttributeIsNull(existingNameAttr))
2029  throw py::value_error("Expected operation to have a symbol name.");
2030  return existingNameAttr;
2031 }
2032 
2034  const std::string &name) {
2035  // Op must already be a symbol.
2036  PyOperation &operation = symbol.getOperation();
2037  operation.checkValid();
2039  MlirAttribute existingNameAttr =
2040  mlirOperationGetAttributeByName(operation.get(), attrName);
2041  if (mlirAttributeIsNull(existingNameAttr))
2042  throw py::value_error("Expected operation to have a symbol name.");
2043  MlirAttribute newNameAttr =
2044  mlirStringAttrGet(operation.getContext()->get(), toMlirStringRef(name));
2045  mlirOperationSetAttributeByName(operation.get(), attrName, newNameAttr);
2046 }
2047 
2049  PyOperation &operation = symbol.getOperation();
2050  operation.checkValid();
2052  MlirAttribute existingVisAttr =
2053  mlirOperationGetAttributeByName(operation.get(), attrName);
2054  if (mlirAttributeIsNull(existingVisAttr))
2055  throw py::value_error("Expected operation to have a symbol visibility.");
2056  return existingVisAttr;
2057 }
2058 
2060  const std::string &visibility) {
2061  if (visibility != "public" && visibility != "private" &&
2062  visibility != "nested")
2063  throw py::value_error(
2064  "Expected visibility to be 'public', 'private' or 'nested'");
2065  PyOperation &operation = symbol.getOperation();
2066  operation.checkValid();
2068  MlirAttribute existingVisAttr =
2069  mlirOperationGetAttributeByName(operation.get(), attrName);
2070  if (mlirAttributeIsNull(existingVisAttr))
2071  throw py::value_error("Expected operation to have a symbol visibility.");
2072  MlirAttribute newVisAttr = mlirStringAttrGet(operation.getContext()->get(),
2073  toMlirStringRef(visibility));
2074  mlirOperationSetAttributeByName(operation.get(), attrName, newVisAttr);
2075 }
2076 
2077 void PySymbolTable::replaceAllSymbolUses(const std::string &oldSymbol,
2078  const std::string &newSymbol,
2079  PyOperationBase &from) {
2080  PyOperation &fromOperation = from.getOperation();
2081  fromOperation.checkValid();
2083  toMlirStringRef(oldSymbol), toMlirStringRef(newSymbol),
2084  from.getOperation())))
2085 
2086  throw py::value_error("Symbol rename failed");
2087 }
2088 
2090  bool allSymUsesVisible,
2091  py::object callback) {
2092  PyOperation &fromOperation = from.getOperation();
2093  fromOperation.checkValid();
2094  struct UserData {
2095  PyMlirContextRef context;
2096  py::object callback;
2097  bool gotException;
2098  std::string exceptionWhat;
2099  py::object exceptionType;
2100  };
2101  UserData userData{
2102  fromOperation.getContext(), std::move(callback), false, {}, {}};
2104  fromOperation.get(), allSymUsesVisible,
2105  [](MlirOperation foundOp, bool isVisible, void *calleeUserDataVoid) {
2106  UserData *calleeUserData = static_cast<UserData *>(calleeUserDataVoid);
2107  auto pyFoundOp =
2108  PyOperation::forOperation(calleeUserData->context, foundOp);
2109  if (calleeUserData->gotException)
2110  return;
2111  try {
2112  calleeUserData->callback(pyFoundOp.getObject(), isVisible);
2113  } catch (py::error_already_set &e) {
2114  calleeUserData->gotException = true;
2115  calleeUserData->exceptionWhat = e.what();
2116  calleeUserData->exceptionType = e.type();
2117  }
2118  },
2119  static_cast<void *>(&userData));
2120  if (userData.gotException) {
2121  std::string message("Exception raised in callback: ");
2122  message.append(userData.exceptionWhat);
2123  throw std::runtime_error(message);
2124  }
2125 }
2126 
2127 namespace {
2128 /// CRTP base class for Python MLIR values that subclass Value and should be
2129 /// castable from it. The value hierarchy is one level deep and is not supposed
2130 /// to accommodate other levels unless core MLIR changes.
2131 template <typename DerivedTy>
2132 class PyConcreteValue : public PyValue {
2133 public:
2134  // Derived classes must define statics for:
2135  // IsAFunctionTy isaFunction
2136  // const char *pyClassName
2137  // and redefine bindDerived.
2138  using ClassTy = py::class_<DerivedTy, PyValue>;
2139  using IsAFunctionTy = bool (*)(MlirValue);
2140 
2141  PyConcreteValue() = default;
2142  PyConcreteValue(PyOperationRef operationRef, MlirValue value)
2143  : PyValue(operationRef, value) {}
2144  PyConcreteValue(PyValue &orig)
2145  : PyConcreteValue(orig.getParentOperation(), castFrom(orig)) {}
2146 
2147  /// Attempts to cast the original value to the derived type and throws on
2148  /// type mismatches.
2149  static MlirValue castFrom(PyValue &orig) {
2150  if (!DerivedTy::isaFunction(orig.get())) {
2151  auto origRepr = py::repr(py::cast(orig)).cast<std::string>();
2152  throw py::value_error((Twine("Cannot cast value to ") +
2153  DerivedTy::pyClassName + " (from " + origRepr +
2154  ")")
2155  .str());
2156  }
2157  return orig.get();
2158  }
2159 
2160  /// Binds the Python module objects to functions of this class.
2161  static void bind(py::module &m) {
2162  auto cls = ClassTy(m, DerivedTy::pyClassName, py::module_local());
2163  cls.def(py::init<PyValue &>(), py::keep_alive<0, 1>(), py::arg("value"));
2164  cls.def_static(
2165  "isinstance",
2166  [](PyValue &otherValue) -> bool {
2167  return DerivedTy::isaFunction(otherValue);
2168  },
2169  py::arg("other_value"));
2171  [](DerivedTy &self) { return self.maybeDownCast(); });
2172  DerivedTy::bindDerived(cls);
2173  }
2174 
2175  /// Implemented by derived classes to add methods to the Python subclass.
2176  static void bindDerived(ClassTy &m) {}
2177 };
2178 
2179 /// Python wrapper for MlirBlockArgument.
2180 class PyBlockArgument : public PyConcreteValue<PyBlockArgument> {
2181 public:
2182  static constexpr IsAFunctionTy isaFunction = mlirValueIsABlockArgument;
2183  static constexpr const char *pyClassName = "BlockArgument";
2184  using PyConcreteValue::PyConcreteValue;
2185 
2186  static void bindDerived(ClassTy &c) {
2187  c.def_property_readonly("owner", [](PyBlockArgument &self) {
2188  return PyBlock(self.getParentOperation(),
2189  mlirBlockArgumentGetOwner(self.get()));
2190  });
2191  c.def_property_readonly("arg_number", [](PyBlockArgument &self) {
2192  return mlirBlockArgumentGetArgNumber(self.get());
2193  });
2194  c.def(
2195  "set_type",
2196  [](PyBlockArgument &self, PyType type) {
2197  return mlirBlockArgumentSetType(self.get(), type);
2198  },
2199  py::arg("type"));
2200  }
2201 };
2202 
2203 /// Python wrapper for MlirOpResult.
2204 class PyOpResult : public PyConcreteValue<PyOpResult> {
2205 public:
2206  static constexpr IsAFunctionTy isaFunction = mlirValueIsAOpResult;
2207  static constexpr const char *pyClassName = "OpResult";
2208  using PyConcreteValue::PyConcreteValue;
2209 
2210  static void bindDerived(ClassTy &c) {
2211  c.def_property_readonly("owner", [](PyOpResult &self) {
2212  assert(
2213  mlirOperationEqual(self.getParentOperation()->get(),
2214  mlirOpResultGetOwner(self.get())) &&
2215  "expected the owner of the value in Python to match that in the IR");
2216  return self.getParentOperation().getObject();
2217  });
2218  c.def_property_readonly("result_number", [](PyOpResult &self) {
2219  return mlirOpResultGetResultNumber(self.get());
2220  });
2221  }
2222 };
2223 
2224 /// Returns the list of types of the values held by container.
2225 template <typename Container>
2226 static std::vector<MlirType> getValueTypes(Container &container,
2227  PyMlirContextRef &context) {
2228  std::vector<MlirType> result;
2229  result.reserve(container.size());
2230  for (int i = 0, e = container.size(); i < e; ++i) {
2231  result.push_back(mlirValueGetType(container.getElement(i).get()));
2232  }
2233  return result;
2234 }
2235 
2236 /// A list of block arguments. Internally, these are stored as consecutive
2237 /// elements, random access is cheap. The argument list is associated with the
2238 /// operation that contains the block (detached blocks are not allowed in
2239 /// Python bindings) and extends its lifetime.
2240 class PyBlockArgumentList
2241  : public Sliceable<PyBlockArgumentList, PyBlockArgument> {
2242 public:
2243  static constexpr const char *pyClassName = "BlockArgumentList";
2245 
2246  PyBlockArgumentList(PyOperationRef operation, MlirBlock block,
2247  intptr_t startIndex = 0, intptr_t length = -1,
2248  intptr_t step = 1)
2249  : Sliceable(startIndex,
2250  length == -1 ? mlirBlockGetNumArguments(block) : length,
2251  step),
2252  operation(std::move(operation)), block(block) {}
2253 
2254  static void bindDerived(ClassTy &c) {
2255  c.def_property_readonly("types", [](PyBlockArgumentList &self) {
2256  return getValueTypes(self, self.operation->getContext());
2257  });
2258  }
2259 
2260 private:
2261  /// Give the parent CRTP class access to hook implementations below.
2262  friend class Sliceable<PyBlockArgumentList, PyBlockArgument>;
2263 
2264  /// Returns the number of arguments in the list.
2265  intptr_t getRawNumElements() {
2266  operation->checkValid();
2267  return mlirBlockGetNumArguments(block);
2268  }
2269 
2270  /// Returns `pos`-the element in the list.
2271  PyBlockArgument getRawElement(intptr_t pos) {
2272  MlirValue argument = mlirBlockGetArgument(block, pos);
2273  return PyBlockArgument(operation, argument);
2274  }
2275 
2276  /// Returns a sublist of this list.
2277  PyBlockArgumentList slice(intptr_t startIndex, intptr_t length,
2278  intptr_t step) {
2279  return PyBlockArgumentList(operation, block, startIndex, length, step);
2280  }
2281 
2282  PyOperationRef operation;
2283  MlirBlock block;
2284 };
2285 
2286 /// A list of operation operands. Internally, these are stored as consecutive
2287 /// elements, random access is cheap. The (returned) operand list is associated
2288 /// with the operation whose operands these are, and thus extends the lifetime
2289 /// of this operation.
2290 class PyOpOperandList : public Sliceable<PyOpOperandList, PyValue> {
2291 public:
2292  static constexpr const char *pyClassName = "OpOperandList";
2293  using SliceableT = Sliceable<PyOpOperandList, PyValue>;
2294 
2295  PyOpOperandList(PyOperationRef operation, intptr_t startIndex = 0,
2296  intptr_t length = -1, intptr_t step = 1)
2297  : Sliceable(startIndex,
2298  length == -1 ? mlirOperationGetNumOperands(operation->get())
2299  : length,
2300  step),
2301  operation(operation) {}
2302 
2303  void dunderSetItem(intptr_t index, PyValue value) {
2304  index = wrapIndex(index);
2305  mlirOperationSetOperand(operation->get(), index, value.get());
2306  }
2307 
2308  static void bindDerived(ClassTy &c) {
2309  c.def("__setitem__", &PyOpOperandList::dunderSetItem);
2310  }
2311 
2312 private:
2313  /// Give the parent CRTP class access to hook implementations below.
2314  friend class Sliceable<PyOpOperandList, PyValue>;
2315 
2316  intptr_t getRawNumElements() {
2317  operation->checkValid();
2318  return mlirOperationGetNumOperands(operation->get());
2319  }
2320 
2321  PyValue getRawElement(intptr_t pos) {
2322  MlirValue operand = mlirOperationGetOperand(operation->get(), pos);
2323  MlirOperation owner;
2324  if (mlirValueIsAOpResult(operand))
2325  owner = mlirOpResultGetOwner(operand);
2326  else if (mlirValueIsABlockArgument(operand))
2328  else
2329  assert(false && "Value must be an block arg or op result.");
2330  PyOperationRef pyOwner =
2331  PyOperation::forOperation(operation->getContext(), owner);
2332  return PyValue(pyOwner, operand);
2333  }
2334 
2335  PyOpOperandList slice(intptr_t startIndex, intptr_t length, intptr_t step) {
2336  return PyOpOperandList(operation, startIndex, length, step);
2337  }
2338 
2339  PyOperationRef operation;
2340 };
2341 
2342 /// A list of operation results. Internally, these are stored as consecutive
2343 /// elements, random access is cheap. The (returned) result list is associated
2344 /// with the operation whose results these are, and thus extends the lifetime of
2345 /// this operation.
2346 class PyOpResultList : public Sliceable<PyOpResultList, PyOpResult> {
2347 public:
2348  static constexpr const char *pyClassName = "OpResultList";
2349  using SliceableT = Sliceable<PyOpResultList, PyOpResult>;
2350 
2351  PyOpResultList(PyOperationRef operation, intptr_t startIndex = 0,
2352  intptr_t length = -1, intptr_t step = 1)
2353  : Sliceable(startIndex,
2354  length == -1 ? mlirOperationGetNumResults(operation->get())
2355  : length,
2356  step),
2357  operation(std::move(operation)) {}
2358 
2359  static void bindDerived(ClassTy &c) {
2360  c.def_property_readonly("types", [](PyOpResultList &self) {
2361  return getValueTypes(self, self.operation->getContext());
2362  });
2363  c.def_property_readonly("owner", [](PyOpResultList &self) {
2364  return self.operation->createOpView();
2365  });
2366  }
2367 
2368 private:
2369  /// Give the parent CRTP class access to hook implementations below.
2370  friend class Sliceable<PyOpResultList, PyOpResult>;
2371 
2372  intptr_t getRawNumElements() {
2373  operation->checkValid();
2374  return mlirOperationGetNumResults(operation->get());
2375  }
2376 
2377  PyOpResult getRawElement(intptr_t index) {
2378  PyValue value(operation, mlirOperationGetResult(operation->get(), index));
2379  return PyOpResult(value);
2380  }
2381 
2382  PyOpResultList slice(intptr_t startIndex, intptr_t length, intptr_t step) {
2383  return PyOpResultList(operation, startIndex, length, step);
2384  }
2385 
2386  PyOperationRef operation;
2387 };
2388 
2389 /// A list of operation successors. Internally, these are stored as consecutive
2390 /// elements, random access is cheap. The (returned) successor list is
2391 /// associated with the operation whose successors these are, and thus extends
2392 /// the lifetime of this operation.
2393 class PyOpSuccessors : public Sliceable<PyOpSuccessors, PyBlock> {
2394 public:
2395  static constexpr const char *pyClassName = "OpSuccessors";
2396 
2397  PyOpSuccessors(PyOperationRef operation, intptr_t startIndex = 0,
2398  intptr_t length = -1, intptr_t step = 1)
2399  : Sliceable(startIndex,
2400  length == -1 ? mlirOperationGetNumSuccessors(operation->get())
2401  : length,
2402  step),
2403  operation(operation) {}
2404 
2405  void dunderSetItem(intptr_t index, PyBlock block) {
2406  index = wrapIndex(index);
2407  mlirOperationSetSuccessor(operation->get(), index, block.get());
2408  }
2409 
2410  static void bindDerived(ClassTy &c) {
2411  c.def("__setitem__", &PyOpSuccessors::dunderSetItem);
2412  }
2413 
2414 private:
2415  /// Give the parent CRTP class access to hook implementations below.
2416  friend class Sliceable<PyOpSuccessors, PyBlock>;
2417 
2418  intptr_t getRawNumElements() {
2419  operation->checkValid();
2420  return mlirOperationGetNumSuccessors(operation->get());
2421  }
2422 
2423  PyBlock getRawElement(intptr_t pos) {
2424  MlirBlock block = mlirOperationGetSuccessor(operation->get(), pos);
2425  return PyBlock(operation, block);
2426  }
2427 
2428  PyOpSuccessors slice(intptr_t startIndex, intptr_t length, intptr_t step) {
2429  return PyOpSuccessors(operation, startIndex, length, step);
2430  }
2431 
2432  PyOperationRef operation;
2433 };
2434 
2435 /// A list of operation attributes. Can be indexed by name, producing
2436 /// attributes, or by index, producing named attributes.
2437 class PyOpAttributeMap {
2438 public:
2439  PyOpAttributeMap(PyOperationRef operation)
2440  : operation(std::move(operation)) {}
2441 
2442  MlirAttribute dunderGetItemNamed(const std::string &name) {
2443  MlirAttribute attr = mlirOperationGetAttributeByName(operation->get(),
2444  toMlirStringRef(name));
2445  if (mlirAttributeIsNull(attr)) {
2446  throw py::key_error("attempt to access a non-existent attribute");
2447  }
2448  return attr;
2449  }
2450 
2451  PyNamedAttribute dunderGetItemIndexed(intptr_t index) {
2452  if (index < 0 || index >= dunderLen()) {
2453  throw py::index_error("attempt to access out of bounds attribute");
2454  }
2455  MlirNamedAttribute namedAttr =
2456  mlirOperationGetAttribute(operation->get(), index);
2457  return PyNamedAttribute(
2458  namedAttr.attribute,
2459  std::string(mlirIdentifierStr(namedAttr.name).data,
2460  mlirIdentifierStr(namedAttr.name).length));
2461  }
2462 
2463  void dunderSetItem(const std::string &name, const PyAttribute &attr) {
2464  mlirOperationSetAttributeByName(operation->get(), toMlirStringRef(name),
2465  attr);
2466  }
2467 
2468  void dunderDelItem(const std::string &name) {
2469  int removed = mlirOperationRemoveAttributeByName(operation->get(),
2470  toMlirStringRef(name));
2471  if (!removed)
2472  throw py::key_error("attempt to delete a non-existent attribute");
2473  }
2474 
2475  intptr_t dunderLen() {
2476  return mlirOperationGetNumAttributes(operation->get());
2477  }
2478 
2479  bool dunderContains(const std::string &name) {
2481  operation->get(), toMlirStringRef(name)));
2482  }
2483 
2484  static void bind(py::module &m) {
2485  py::class_<PyOpAttributeMap>(m, "OpAttributeMap", py::module_local())
2486  .def("__contains__", &PyOpAttributeMap::dunderContains)
2487  .def("__len__", &PyOpAttributeMap::dunderLen)
2488  .def("__getitem__", &PyOpAttributeMap::dunderGetItemNamed)
2489  .def("__getitem__", &PyOpAttributeMap::dunderGetItemIndexed)
2490  .def("__setitem__", &PyOpAttributeMap::dunderSetItem)
2491  .def("__delitem__", &PyOpAttributeMap::dunderDelItem);
2492  }
2493 
2494 private:
2495  PyOperationRef operation;
2496 };
2497 
2498 } // namespace
2499 
2500 //------------------------------------------------------------------------------
2501 // Populates the core exports of the 'ir' submodule.
2502 //------------------------------------------------------------------------------
2503 
2504 void mlir::python::populateIRCore(py::module &m) {
2505  //----------------------------------------------------------------------------
2506  // Enums.
2507  //----------------------------------------------------------------------------
2508  py::enum_<MlirDiagnosticSeverity>(m, "DiagnosticSeverity", py::module_local())
2509  .value("ERROR", MlirDiagnosticError)
2510  .value("WARNING", MlirDiagnosticWarning)
2511  .value("NOTE", MlirDiagnosticNote)
2512  .value("REMARK", MlirDiagnosticRemark);
2513 
2514  //----------------------------------------------------------------------------
2515  // Mapping of Diagnostics.
2516  //----------------------------------------------------------------------------
2517  py::class_<PyDiagnostic>(m, "Diagnostic", py::module_local())
2518  .def_property_readonly("severity", &PyDiagnostic::getSeverity)
2519  .def_property_readonly("location", &PyDiagnostic::getLocation)
2520  .def_property_readonly("message", &PyDiagnostic::getMessage)
2521  .def_property_readonly("notes", &PyDiagnostic::getNotes)
2522  .def("__str__", [](PyDiagnostic &self) -> py::str {
2523  if (!self.isValid())
2524  return "<Invalid Diagnostic>";
2525  return self.getMessage();
2526  });
2527 
2528  py::class_<PyDiagnostic::DiagnosticInfo>(m, "DiagnosticInfo",
2529  py::module_local())
2530  .def(py::init<>([](PyDiagnostic diag) { return diag.getInfo(); }))
2531  .def_readonly("severity", &PyDiagnostic::DiagnosticInfo::severity)
2532  .def_readonly("location", &PyDiagnostic::DiagnosticInfo::location)
2533  .def_readonly("message", &PyDiagnostic::DiagnosticInfo::message)
2534  .def_readonly("notes", &PyDiagnostic::DiagnosticInfo::notes)
2535  .def("__str__",
2536  [](PyDiagnostic::DiagnosticInfo &self) { return self.message; });
2537 
2538  py::class_<PyDiagnosticHandler>(m, "DiagnosticHandler", py::module_local())
2539  .def("detach", &PyDiagnosticHandler::detach)
2540  .def_property_readonly("attached", &PyDiagnosticHandler::isAttached)
2541  .def_property_readonly("had_error", &PyDiagnosticHandler::getHadError)
2542  .def("__enter__", &PyDiagnosticHandler::contextEnter)
2543  .def("__exit__", &PyDiagnosticHandler::contextExit);
2544 
2545  //----------------------------------------------------------------------------
2546  // Mapping of MlirContext.
2547  // Note that this is exported as _BaseContext. The containing, Python level
2548  // __init__.py will subclass it with site-specific functionality and set a
2549  // "Context" attribute on this module.
2550  //----------------------------------------------------------------------------
2551  py::class_<PyMlirContext>(m, "_BaseContext", py::module_local())
2552  .def(py::init<>(&PyMlirContext::createNewContextForInit))
2553  .def_static("_get_live_count", &PyMlirContext::getLiveCount)
2554  .def("_get_context_again",
2555  [](PyMlirContext &self) {
2556  PyMlirContextRef ref = PyMlirContext::forContext(self.get());
2557  return ref.releaseObject();
2558  })
2559  .def("_get_live_operation_count", &PyMlirContext::getLiveOperationCount)
2560  .def("_get_live_operation_objects",
2561  &PyMlirContext::getLiveOperationObjects)
2562  .def("_clear_live_operations", &PyMlirContext::clearLiveOperations)
2563  .def("_clear_live_operations_inside",
2564  py::overload_cast<MlirOperation>(
2565  &PyMlirContext::clearOperationsInside))
2566  .def("_get_live_module_count", &PyMlirContext::getLiveModuleCount)
2567  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR,
2568  &PyMlirContext::getCapsule)
2569  .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyMlirContext::createFromCapsule)
2570  .def("__enter__", &PyMlirContext::contextEnter)
2571  .def("__exit__", &PyMlirContext::contextExit)
2572  .def_property_readonly_static(
2573  "current",
2574  [](py::object & /*class*/) {
2575  auto *context = PyThreadContextEntry::getDefaultContext();
2576  if (!context)
2577  return py::none().cast<py::object>();
2578  return py::cast(context);
2579  },
2580  "Gets the Context bound to the current thread or raises ValueError")
2581  .def_property_readonly(
2582  "dialects",
2583  [](PyMlirContext &self) { return PyDialects(self.getRef()); },
2584  "Gets a container for accessing dialects by name")
2585  .def_property_readonly(
2586  "d", [](PyMlirContext &self) { return PyDialects(self.getRef()); },
2587  "Alias for 'dialect'")
2588  .def(
2589  "get_dialect_descriptor",
2590  [=](PyMlirContext &self, std::string &name) {
2591  MlirDialect dialect = mlirContextGetOrLoadDialect(
2592  self.get(), {name.data(), name.size()});
2593  if (mlirDialectIsNull(dialect)) {
2594  throw py::value_error(
2595  (Twine("Dialect '") + name + "' not found").str());
2596  }
2597  return PyDialectDescriptor(self.getRef(), dialect);
2598  },
2599  py::arg("dialect_name"),
2600  "Gets or loads a dialect by name, returning its descriptor object")
2601  .def_property(
2602  "allow_unregistered_dialects",
2603  [](PyMlirContext &self) -> bool {
2605  },
2606  [](PyMlirContext &self, bool value) {
2608  })
2609  .def("attach_diagnostic_handler", &PyMlirContext::attachDiagnosticHandler,
2610  py::arg("callback"),
2611  "Attaches a diagnostic handler that will receive callbacks")
2612  .def(
2613  "enable_multithreading",
2614  [](PyMlirContext &self, bool enable) {
2615  mlirContextEnableMultithreading(self.get(), enable);
2616  },
2617  py::arg("enable"))
2618  .def(
2619  "is_registered_operation",
2620  [](PyMlirContext &self, std::string &name) {
2622  self.get(), MlirStringRef{name.data(), name.size()});
2623  },
2624  py::arg("operation_name"))
2625  .def(
2626  "append_dialect_registry",
2627  [](PyMlirContext &self, PyDialectRegistry &registry) {
2628  mlirContextAppendDialectRegistry(self.get(), registry);
2629  },
2630  py::arg("registry"))
2631  .def_property("emit_error_diagnostics", nullptr,
2632  &PyMlirContext::setEmitErrorDiagnostics,
2633  "Emit error diagnostics to diagnostic handlers. By default "
2634  "error diagnostics are captured and reported through "
2635  "MLIRError exceptions.")
2636  .def("load_all_available_dialects", [](PyMlirContext &self) {
2638  });
2639 
2640  //----------------------------------------------------------------------------
2641  // Mapping of PyDialectDescriptor
2642  //----------------------------------------------------------------------------
2643  py::class_<PyDialectDescriptor>(m, "DialectDescriptor", py::module_local())
2644  .def_property_readonly("namespace",
2645  [](PyDialectDescriptor &self) {
2646  MlirStringRef ns =
2647  mlirDialectGetNamespace(self.get());
2648  return py::str(ns.data, ns.length);
2649  })
2650  .def("__repr__", [](PyDialectDescriptor &self) {
2652  std::string repr("<DialectDescriptor ");
2653  repr.append(ns.data, ns.length);
2654  repr.append(">");
2655  return repr;
2656  });
2657 
2658  //----------------------------------------------------------------------------
2659  // Mapping of PyDialects
2660  //----------------------------------------------------------------------------
2661  py::class_<PyDialects>(m, "Dialects", py::module_local())
2662  .def("__getitem__",
2663  [=](PyDialects &self, std::string keyName) {
2664  MlirDialect dialect =
2665  self.getDialectForKey(keyName, /*attrError=*/false);
2666  py::object descriptor =
2667  py::cast(PyDialectDescriptor{self.getContext(), dialect});
2668  return createCustomDialectWrapper(keyName, std::move(descriptor));
2669  })
2670  .def("__getattr__", [=](PyDialects &self, std::string attrName) {
2671  MlirDialect dialect =
2672  self.getDialectForKey(attrName, /*attrError=*/true);
2673  py::object descriptor =
2674  py::cast(PyDialectDescriptor{self.getContext(), dialect});
2675  return createCustomDialectWrapper(attrName, std::move(descriptor));
2676  });
2677 
2678  //----------------------------------------------------------------------------
2679  // Mapping of PyDialect
2680  //----------------------------------------------------------------------------
2681  py::class_<PyDialect>(m, "Dialect", py::module_local())
2682  .def(py::init<py::object>(), py::arg("descriptor"))
2683  .def_property_readonly(
2684  "descriptor", [](PyDialect &self) { return self.getDescriptor(); })
2685  .def("__repr__", [](py::object self) {
2686  auto clazz = self.attr("__class__");
2687  return py::str("<Dialect ") +
2688  self.attr("descriptor").attr("namespace") + py::str(" (class ") +
2689  clazz.attr("__module__") + py::str(".") +
2690  clazz.attr("__name__") + py::str(")>");
2691  });
2692 
2693  //----------------------------------------------------------------------------
2694  // Mapping of PyDialectRegistry
2695  //----------------------------------------------------------------------------
2696  py::class_<PyDialectRegistry>(m, "DialectRegistry", py::module_local())
2697  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR,
2698  &PyDialectRegistry::getCapsule)
2699  .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyDialectRegistry::createFromCapsule)
2700  .def(py::init<>());
2701 
2702  //----------------------------------------------------------------------------
2703  // Mapping of Location
2704  //----------------------------------------------------------------------------
2705  py::class_<PyLocation>(m, "Location", py::module_local())
2706  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyLocation::getCapsule)
2707  .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyLocation::createFromCapsule)
2708  .def("__enter__", &PyLocation::contextEnter)
2709  .def("__exit__", &PyLocation::contextExit)
2710  .def("__eq__",
2711  [](PyLocation &self, PyLocation &other) -> bool {
2712  return mlirLocationEqual(self, other);
2713  })
2714  .def("__eq__", [](PyLocation &self, py::object other) { return false; })
2715  .def_property_readonly_static(
2716  "current",
2717  [](py::object & /*class*/) {
2718  auto *loc = PyThreadContextEntry::getDefaultLocation();
2719  if (!loc)
2720  throw py::value_error("No current Location");
2721  return loc;
2722  },
2723  "Gets the Location bound to the current thread or raises ValueError")
2724  .def_static(
2725  "unknown",
2726  [](DefaultingPyMlirContext context) {
2727  return PyLocation(context->getRef(),
2728  mlirLocationUnknownGet(context->get()));
2729  },
2730  py::arg("context") = py::none(),
2731  "Gets a Location representing an unknown location")
2732  .def_static(
2733  "callsite",
2734  [](PyLocation callee, const std::vector<PyLocation> &frames,
2735  DefaultingPyMlirContext context) {
2736  if (frames.empty())
2737  throw py::value_error("No caller frames provided");
2738  MlirLocation caller = frames.back().get();
2739  for (const PyLocation &frame :
2740  llvm::reverse(llvm::ArrayRef(frames).drop_back()))
2741  caller = mlirLocationCallSiteGet(frame.get(), caller);
2742  return PyLocation(context->getRef(),
2743  mlirLocationCallSiteGet(callee.get(), caller));
2744  },
2745  py::arg("callee"), py::arg("frames"), py::arg("context") = py::none(),
2747  .def_static(
2748  "file",
2749  [](std::string filename, int line, int col,
2750  DefaultingPyMlirContext context) {
2751  return PyLocation(
2752  context->getRef(),
2754  context->get(), toMlirStringRef(filename), line, col));
2755  },
2756  py::arg("filename"), py::arg("line"), py::arg("col"),
2757  py::arg("context") = py::none(), kContextGetFileLocationDocstring)
2758  .def_static(
2759  "fused",
2760  [](const std::vector<PyLocation> &pyLocations,
2761  std::optional<PyAttribute> metadata,
2762  DefaultingPyMlirContext context) {
2764  locations.reserve(pyLocations.size());
2765  for (auto &pyLocation : pyLocations)
2766  locations.push_back(pyLocation.get());
2767  MlirLocation location = mlirLocationFusedGet(
2768  context->get(), locations.size(), locations.data(),
2769  metadata ? metadata->get() : MlirAttribute{0});
2770  return PyLocation(context->getRef(), location);
2771  },
2772  py::arg("locations"), py::arg("metadata") = py::none(),
2773  py::arg("context") = py::none(), kContextGetFusedLocationDocstring)
2774  .def_static(
2775  "name",
2776  [](std::string name, std::optional<PyLocation> childLoc,
2777  DefaultingPyMlirContext context) {
2778  return PyLocation(
2779  context->getRef(),
2781  context->get(), toMlirStringRef(name),
2782  childLoc ? childLoc->get()
2783  : mlirLocationUnknownGet(context->get())));
2784  },
2785  py::arg("name"), py::arg("childLoc") = py::none(),
2786  py::arg("context") = py::none(), kContextGetNameLocationDocString)
2787  .def_static(
2788  "from_attr",
2789  [](PyAttribute &attribute, DefaultingPyMlirContext context) {
2790  return PyLocation(context->getRef(),
2791  mlirLocationFromAttribute(attribute));
2792  },
2793  py::arg("attribute"), py::arg("context") = py::none(),
2794  "Gets a Location from a LocationAttr")
2795  .def_property_readonly(
2796  "context",
2797  [](PyLocation &self) { return self.getContext().getObject(); },
2798  "Context that owns the Location")
2799  .def_property_readonly(
2800  "attr",
2801  [](PyLocation &self) { return mlirLocationGetAttribute(self); },
2802  "Get the underlying LocationAttr")
2803  .def(
2804  "emit_error",
2805  [](PyLocation &self, std::string message) {
2806  mlirEmitError(self, message.c_str());
2807  },
2808  py::arg("message"), "Emits an error at this location")
2809  .def("__repr__", [](PyLocation &self) {
2810  PyPrintAccumulator printAccum;
2811  mlirLocationPrint(self, printAccum.getCallback(),
2812  printAccum.getUserData());
2813  return printAccum.join();
2814  });
2815 
2816  //----------------------------------------------------------------------------
2817  // Mapping of Module
2818  //----------------------------------------------------------------------------
2819  py::class_<PyModule>(m, "Module", py::module_local())
2820  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyModule::getCapsule)
2821  .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyModule::createFromCapsule)
2822  .def_static(
2823  "parse",
2824  [](const std::string &moduleAsm, DefaultingPyMlirContext context) {
2825  PyMlirContext::ErrorCapture errors(context->getRef());
2826  MlirModule module = mlirModuleCreateParse(
2827  context->get(), toMlirStringRef(moduleAsm));
2828  if (mlirModuleIsNull(module))
2829  throw MLIRError("Unable to parse module assembly", errors.take());
2830  return PyModule::forModule(module).releaseObject();
2831  },
2832  py::arg("asm"), py::arg("context") = py::none(),
2834  .def_static(
2835  "create",
2836  [](DefaultingPyLocation loc) {
2837  MlirModule module = mlirModuleCreateEmpty(loc);
2838  return PyModule::forModule(module).releaseObject();
2839  },
2840  py::arg("loc") = py::none(), "Creates an empty module")
2841  .def_property_readonly(
2842  "context",
2843  [](PyModule &self) { return self.getContext().getObject(); },
2844  "Context that created the Module")
2845  .def_property_readonly(
2846  "operation",
2847  [](PyModule &self) {
2848  return PyOperation::forOperation(self.getContext(),
2849  mlirModuleGetOperation(self.get()),
2850  self.getRef().releaseObject())
2851  .releaseObject();
2852  },
2853  "Accesses the module as an operation")
2854  .def_property_readonly(
2855  "body",
2856  [](PyModule &self) {
2857  PyOperationRef moduleOp = PyOperation::forOperation(
2858  self.getContext(), mlirModuleGetOperation(self.get()),
2859  self.getRef().releaseObject());
2860  PyBlock returnBlock(moduleOp, mlirModuleGetBody(self.get()));
2861  return returnBlock;
2862  },
2863  "Return the block for this module")
2864  .def(
2865  "dump",
2866  [](PyModule &self) {
2868  },
2870  .def(
2871  "__str__",
2872  [](py::object self) {
2873  // Defer to the operation's __str__.
2874  return self.attr("operation").attr("__str__")();
2875  },
2877 
2878  //----------------------------------------------------------------------------
2879  // Mapping of Operation.
2880  //----------------------------------------------------------------------------
2881  py::class_<PyOperationBase>(m, "_OperationBase", py::module_local())
2882  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR,
2883  [](PyOperationBase &self) {
2884  return self.getOperation().getCapsule();
2885  })
2886  .def("__eq__",
2887  [](PyOperationBase &self, PyOperationBase &other) {
2888  return &self.getOperation() == &other.getOperation();
2889  })
2890  .def("__eq__",
2891  [](PyOperationBase &self, py::object other) { return false; })
2892  .def("__hash__",
2893  [](PyOperationBase &self) {
2894  return static_cast<size_t>(llvm::hash_value(&self.getOperation()));
2895  })
2896  .def_property_readonly("attributes",
2897  [](PyOperationBase &self) {
2898  return PyOpAttributeMap(
2899  self.getOperation().getRef());
2900  })
2901  .def_property_readonly(
2902  "context",
2903  [](PyOperationBase &self) {
2904  PyOperation &concreteOperation = self.getOperation();
2905  concreteOperation.checkValid();
2906  return concreteOperation.getContext().getObject();
2907  },
2908  "Context that owns the Operation")
2909  .def_property_readonly("name",
2910  [](PyOperationBase &self) {
2911  auto &concreteOperation = self.getOperation();
2912  concreteOperation.checkValid();
2913  MlirOperation operation =
2914  concreteOperation.get();
2916  mlirOperationGetName(operation));
2917  return py::str(name.data, name.length);
2918  })
2919  .def_property_readonly("operands",
2920  [](PyOperationBase &self) {
2921  return PyOpOperandList(
2922  self.getOperation().getRef());
2923  })
2924  .def_property_readonly("regions",
2925  [](PyOperationBase &self) {
2926  return PyRegionList(
2927  self.getOperation().getRef());
2928  })
2929  .def_property_readonly(
2930  "results",
2931  [](PyOperationBase &self) {
2932  return PyOpResultList(self.getOperation().getRef());
2933  },
2934  "Returns the list of Operation results.")
2935  .def_property_readonly(
2936  "result",
2937  [](PyOperationBase &self) {
2938  auto &operation = self.getOperation();
2939  auto numResults = mlirOperationGetNumResults(operation);
2940  if (numResults != 1) {
2941  auto name = mlirIdentifierStr(mlirOperationGetName(operation));
2942  throw py::value_error(
2943  (Twine("Cannot call .result on operation ") +
2944  StringRef(name.data, name.length) + " which has " +
2945  Twine(numResults) +
2946  " results (it is only valid for operations with a "
2947  "single result)")
2948  .str());
2949  }
2950  return PyOpResult(operation.getRef(),
2951  mlirOperationGetResult(operation, 0))
2952  .maybeDownCast();
2953  },
2954  "Shortcut to get an op result if it has only one (throws an error "
2955  "otherwise).")
2956  .def_property_readonly(
2957  "location",
2958  [](PyOperationBase &self) {
2959  PyOperation &operation = self.getOperation();
2960  return PyLocation(operation.getContext(),
2961  mlirOperationGetLocation(operation.get()));
2962  },
2963  "Returns the source location the operation was defined or derived "
2964  "from.")
2965  .def_property_readonly("parent",
2966  [](PyOperationBase &self) -> py::object {
2967  auto parent =
2968  self.getOperation().getParentOperation();
2969  if (parent)
2970  return parent->getObject();
2971  return py::none();
2972  })
2973  .def(
2974  "__str__",
2975  [](PyOperationBase &self) {
2976  return self.getAsm(/*binary=*/false,
2977  /*largeElementsLimit=*/std::nullopt,
2978  /*enableDebugInfo=*/false,
2979  /*prettyDebugInfo=*/false,
2980  /*printGenericOpForm=*/false,
2981  /*useLocalScope=*/false,
2982  /*assumeVerified=*/false);
2983  },
2984  "Returns the assembly form of the operation.")
2985  .def("print",
2986  py::overload_cast<PyAsmState &, pybind11::object, bool>(
2988  py::arg("state"), py::arg("file") = py::none(),
2989  py::arg("binary") = false, kOperationPrintStateDocstring)
2990  .def("print",
2991  py::overload_cast<std::optional<int64_t>, bool, bool, bool, bool,
2992  bool, py::object, bool>(
2994  // Careful: Lots of arguments must match up with print method.
2995  py::arg("large_elements_limit") = py::none(),
2996  py::arg("enable_debug_info") = false,
2997  py::arg("pretty_debug_info") = false,
2998  py::arg("print_generic_op_form") = false,
2999  py::arg("use_local_scope") = false,
3000  py::arg("assume_verified") = false, py::arg("file") = py::none(),
3001  py::arg("binary") = false, kOperationPrintDocstring)
3002  .def("write_bytecode", &PyOperationBase::writeBytecode, py::arg("file"),
3003  py::arg("desired_version") = py::none(),
3005  .def("get_asm", &PyOperationBase::getAsm,
3006  // Careful: Lots of arguments must match up with get_asm method.
3007  py::arg("binary") = false,
3008  py::arg("large_elements_limit") = py::none(),
3009  py::arg("enable_debug_info") = false,
3010  py::arg("pretty_debug_info") = false,
3011  py::arg("print_generic_op_form") = false,
3012  py::arg("use_local_scope") = false,
3013  py::arg("assume_verified") = false, kOperationGetAsmDocstring)
3014  .def("verify", &PyOperationBase::verify,
3015  "Verify the operation. Raises MLIRError if verification fails, and "
3016  "returns true otherwise.")
3017  .def("move_after", &PyOperationBase::moveAfter, py::arg("other"),
3018  "Puts self immediately after the other operation in its parent "
3019  "block.")
3020  .def("move_before", &PyOperationBase::moveBefore, py::arg("other"),
3021  "Puts self immediately before the other operation in its parent "
3022  "block.")
3023  .def(
3024  "clone",
3025  [](PyOperationBase &self, py::object ip) {
3026  return self.getOperation().clone(ip);
3027  },
3028  py::arg("ip") = py::none())
3029  .def(
3030  "detach_from_parent",
3031  [](PyOperationBase &self) {
3032  PyOperation &operation = self.getOperation();
3033  operation.checkValid();
3034  if (!operation.isAttached())
3035  throw py::value_error("Detached operation has no parent.");
3036 
3037  operation.detachFromParent();
3038  return operation.createOpView();
3039  },
3040  "Detaches the operation from its parent block.")
3041  .def("erase", [](PyOperationBase &self) { self.getOperation().erase(); });
3042 
3043  py::class_<PyOperation, PyOperationBase>(m, "Operation", py::module_local())
3044  .def_static("create", &PyOperation::create, py::arg("name"),
3045  py::arg("results") = py::none(),
3046  py::arg("operands") = py::none(),
3047  py::arg("attributes") = py::none(),
3048  py::arg("successors") = py::none(), py::arg("regions") = 0,
3049  py::arg("loc") = py::none(), py::arg("ip") = py::none(),
3050  py::arg("infer_type") = false, kOperationCreateDocstring)
3051  .def_static(
3052  "parse",
3053  [](const std::string &sourceStr, const std::string &sourceName,
3054  DefaultingPyMlirContext context) {
3055  return PyOperation::parse(context->getRef(), sourceStr, sourceName)
3056  ->createOpView();
3057  },
3058  py::arg("source"), py::kw_only(), py::arg("source_name") = "",
3059  py::arg("context") = py::none(),
3060  "Parses an operation. Supports both text assembly format and binary "
3061  "bytecode format.")
3062  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR,
3063  &PyOperation::getCapsule)
3064  .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyOperation::createFromCapsule)
3065  .def_property_readonly("operation", [](py::object self) { return self; })
3066  .def_property_readonly("opview", &PyOperation::createOpView)
3067  .def_property_readonly(
3068  "successors",
3069  [](PyOperationBase &self) {
3070  return PyOpSuccessors(self.getOperation().getRef());
3071  },
3072  "Returns the list of Operation successors.");
3073 
3074  auto opViewClass =
3075  py::class_<PyOpView, PyOperationBase>(m, "OpView", py::module_local())
3076  .def(py::init<py::object>(), py::arg("operation"))
3077  .def_property_readonly("operation", &PyOpView::getOperationObject)
3078  .def_property_readonly("opview", [](py::object self) { return self; })
3079  .def(
3080  "__str__",
3081  [](PyOpView &self) { return py::str(self.getOperationObject()); })
3082  .def_property_readonly(
3083  "successors",
3084  [](PyOperationBase &self) {
3085  return PyOpSuccessors(self.getOperation().getRef());
3086  },
3087  "Returns the list of Operation successors.");
3088  opViewClass.attr("_ODS_REGIONS") = py::make_tuple(0, true);
3089  opViewClass.attr("_ODS_OPERAND_SEGMENTS") = py::none();
3090  opViewClass.attr("_ODS_RESULT_SEGMENTS") = py::none();
3091  opViewClass.attr("build_generic") = classmethod(
3092  &PyOpView::buildGeneric, py::arg("cls"), py::arg("results") = py::none(),
3093  py::arg("operands") = py::none(), py::arg("attributes") = py::none(),
3094  py::arg("successors") = py::none(), py::arg("regions") = py::none(),
3095  py::arg("loc") = py::none(), py::arg("ip") = py::none(),
3096  "Builds a specific, generated OpView based on class level attributes.");
3097  opViewClass.attr("parse") = classmethod(
3098  [](const py::object &cls, const std::string &sourceStr,
3099  const std::string &sourceName, DefaultingPyMlirContext context) {
3100  PyOperationRef parsed =
3101  PyOperation::parse(context->getRef(), sourceStr, sourceName);
3102 
3103  // Check if the expected operation was parsed, and cast to to the
3104  // appropriate `OpView` subclass if successful.
3105  // NOTE: This accesses attributes that have been automatically added to
3106  // `OpView` subclasses, and is not intended to be used on `OpView`
3107  // directly.
3108  std::string clsOpName =
3109  py::cast<std::string>(cls.attr("OPERATION_NAME"));
3110  MlirStringRef identifier =
3112  std::string_view parsedOpName(identifier.data, identifier.length);
3113  if (clsOpName != parsedOpName)
3114  throw MLIRError(Twine("Expected a '") + clsOpName + "' op, got: '" +
3115  parsedOpName + "'");
3116  return PyOpView::constructDerived(cls, *parsed.get());
3117  },
3118  py::arg("cls"), py::arg("source"), py::kw_only(),
3119  py::arg("source_name") = "", py::arg("context") = py::none(),
3120  "Parses a specific, generated OpView based on class level attributes");
3121 
3122  //----------------------------------------------------------------------------
3123  // Mapping of PyRegion.
3124  //----------------------------------------------------------------------------
3125  py::class_<PyRegion>(m, "Region", py::module_local())
3126  .def_property_readonly(
3127  "blocks",
3128  [](PyRegion &self) {
3129  return PyBlockList(self.getParentOperation(), self.get());
3130  },
3131  "Returns a forward-optimized sequence of blocks.")
3132  .def_property_readonly(
3133  "owner",
3134  [](PyRegion &self) {
3135  return self.getParentOperation()->createOpView();
3136  },
3137  "Returns the operation owning this region.")
3138  .def(
3139  "__iter__",
3140  [](PyRegion &self) {
3141  self.checkValid();
3142  MlirBlock firstBlock = mlirRegionGetFirstBlock(self.get());
3143  return PyBlockIterator(self.getParentOperation(), firstBlock);
3144  },
3145  "Iterates over blocks in the region.")
3146  .def("__eq__",
3147  [](PyRegion &self, PyRegion &other) {
3148  return self.get().ptr == other.get().ptr;
3149  })
3150  .def("__eq__", [](PyRegion &self, py::object &other) { return false; });
3151 
3152  //----------------------------------------------------------------------------
3153  // Mapping of PyBlock.
3154  //----------------------------------------------------------------------------
3155  py::class_<PyBlock>(m, "Block", py::module_local())
3156  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyBlock::getCapsule)
3157  .def_property_readonly(
3158  "owner",
3159  [](PyBlock &self) {
3160  return self.getParentOperation()->createOpView();
3161  },
3162  "Returns the owning operation of this block.")
3163  .def_property_readonly(
3164  "region",
3165  [](PyBlock &self) {
3166  MlirRegion region = mlirBlockGetParentRegion(self.get());
3167  return PyRegion(self.getParentOperation(), region);
3168  },
3169  "Returns the owning region of this block.")
3170  .def_property_readonly(
3171  "arguments",
3172  [](PyBlock &self) {
3173  return PyBlockArgumentList(self.getParentOperation(), self.get());
3174  },
3175  "Returns a list of block arguments.")
3176  .def_property_readonly(
3177  "operations",
3178  [](PyBlock &self) {
3179  return PyOperationList(self.getParentOperation(), self.get());
3180  },
3181  "Returns a forward-optimized sequence of operations.")
3182  .def_static(
3183  "create_at_start",
3184  [](PyRegion &parent, const py::list &pyArgTypes,
3185  const std::optional<py::sequence> &pyArgLocs) {
3186  parent.checkValid();
3187  MlirBlock block = createBlock(pyArgTypes, pyArgLocs);
3188  mlirRegionInsertOwnedBlock(parent, 0, block);
3189  return PyBlock(parent.getParentOperation(), block);
3190  },
3191  py::arg("parent"), py::arg("arg_types") = py::list(),
3192  py::arg("arg_locs") = std::nullopt,
3193  "Creates and returns a new Block at the beginning of the given "
3194  "region (with given argument types and locations).")
3195  .def(
3196  "append_to",
3197  [](PyBlock &self, PyRegion &region) {
3198  MlirBlock b = self.get();
3200  mlirBlockDetach(b);
3201  mlirRegionAppendOwnedBlock(region.get(), b);
3202  },
3203  "Append this block to a region, transferring ownership if necessary")
3204  .def(
3205  "create_before",
3206  [](PyBlock &self, const py::args &pyArgTypes,
3207  const std::optional<py::sequence> &pyArgLocs) {
3208  self.checkValid();
3209  MlirBlock block = createBlock(pyArgTypes, pyArgLocs);
3210  MlirRegion region = mlirBlockGetParentRegion(self.get());
3211  mlirRegionInsertOwnedBlockBefore(region, self.get(), block);
3212  return PyBlock(self.getParentOperation(), block);
3213  },
3214  py::arg("arg_locs") = std::nullopt,
3215  "Creates and returns a new Block before this block "
3216  "(with given argument types and locations).")
3217  .def(
3218  "create_after",
3219  [](PyBlock &self, const py::args &pyArgTypes,
3220  const std::optional<py::sequence> &pyArgLocs) {
3221  self.checkValid();
3222  MlirBlock block = createBlock(pyArgTypes, pyArgLocs);
3223  MlirRegion region = mlirBlockGetParentRegion(self.get());
3224  mlirRegionInsertOwnedBlockAfter(region, self.get(), block);
3225  return PyBlock(self.getParentOperation(), block);
3226  },
3227  py::arg("arg_locs") = std::nullopt,
3228  "Creates and returns a new Block after this block "
3229  "(with given argument types and locations).")
3230  .def(
3231  "__iter__",
3232  [](PyBlock &self) {
3233  self.checkValid();
3234  MlirOperation firstOperation =
3236  return PyOperationIterator(self.getParentOperation(),
3237  firstOperation);
3238  },
3239  "Iterates over operations in the block.")
3240  .def("__eq__",
3241  [](PyBlock &self, PyBlock &other) {
3242  return self.get().ptr == other.get().ptr;
3243  })
3244  .def("__eq__", [](PyBlock &self, py::object &other) { return false; })
3245  .def("__hash__",
3246  [](PyBlock &self) {
3247  return static_cast<size_t>(llvm::hash_value(self.get().ptr));
3248  })
3249  .def(
3250  "__str__",
3251  [](PyBlock &self) {
3252  self.checkValid();
3253  PyPrintAccumulator printAccum;
3254  mlirBlockPrint(self.get(), printAccum.getCallback(),
3255  printAccum.getUserData());
3256  return printAccum.join();
3257  },
3258  "Returns the assembly form of the block.")
3259  .def(
3260  "append",
3261  [](PyBlock &self, PyOperationBase &operation) {
3262  if (operation.getOperation().isAttached())
3263  operation.getOperation().detachFromParent();
3264 
3265  MlirOperation mlirOperation = operation.getOperation().get();
3266  mlirBlockAppendOwnedOperation(self.get(), mlirOperation);
3267  operation.getOperation().setAttached(
3268  self.getParentOperation().getObject());
3269  },
3270  py::arg("operation"),
3271  "Appends an operation to this block. If the operation is currently "
3272  "in another block, it will be moved.");
3273 
3274  //----------------------------------------------------------------------------
3275  // Mapping of PyInsertionPoint.
3276  //----------------------------------------------------------------------------
3277 
3278  py::class_<PyInsertionPoint>(m, "InsertionPoint", py::module_local())
3279  .def(py::init<PyBlock &>(), py::arg("block"),
3280  "Inserts after the last operation but still inside the block.")
3281  .def("__enter__", &PyInsertionPoint::contextEnter)
3282  .def("__exit__", &PyInsertionPoint::contextExit)
3283  .def_property_readonly_static(
3284  "current",
3285  [](py::object & /*class*/) {
3286  auto *ip = PyThreadContextEntry::getDefaultInsertionPoint();
3287  if (!ip)
3288  throw py::value_error("No current InsertionPoint");
3289  return ip;
3290  },
3291  "Gets the InsertionPoint bound to the current thread or raises "
3292  "ValueError if none has been set")
3293  .def(py::init<PyOperationBase &>(), py::arg("beforeOperation"),
3294  "Inserts before a referenced operation.")
3295  .def_static("at_block_begin", &PyInsertionPoint::atBlockBegin,
3296  py::arg("block"), "Inserts at the beginning of the block.")
3297  .def_static("at_block_terminator", &PyInsertionPoint::atBlockTerminator,
3298  py::arg("block"), "Inserts before the block terminator.")
3299  .def("insert", &PyInsertionPoint::insert, py::arg("operation"),
3300  "Inserts an operation.")
3301  .def_property_readonly(
3302  "block", [](PyInsertionPoint &self) { return self.getBlock(); },
3303  "Returns the block that this InsertionPoint points to.")
3304  .def_property_readonly(
3305  "ref_operation",
3306  [](PyInsertionPoint &self) -> py::object {
3307  auto refOperation = self.getRefOperation();
3308  if (refOperation)
3309  return refOperation->getObject();
3310  return py::none();
3311  },
3312  "The reference operation before which new operations are "
3313  "inserted, or None if the insertion point is at the end of "
3314  "the block");
3315 
3316  //----------------------------------------------------------------------------
3317  // Mapping of PyAttribute.
3318  //----------------------------------------------------------------------------
3319  py::class_<PyAttribute>(m, "Attribute", py::module_local())
3320  // Delegate to the PyAttribute copy constructor, which will also lifetime
3321  // extend the backing context which owns the MlirAttribute.
3322  .def(py::init<PyAttribute &>(), py::arg("cast_from_type"),
3323  "Casts the passed attribute to the generic Attribute")
3324  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR,
3325  &PyAttribute::getCapsule)
3326  .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyAttribute::createFromCapsule)
3327  .def_static(
3328  "parse",
3329  [](const std::string &attrSpec, DefaultingPyMlirContext context) {
3330  PyMlirContext::ErrorCapture errors(context->getRef());
3331  MlirAttribute attr = mlirAttributeParseGet(
3332  context->get(), toMlirStringRef(attrSpec));
3333  if (mlirAttributeIsNull(attr))
3334  throw MLIRError("Unable to parse attribute", errors.take());
3335  return attr;
3336  },
3337  py::arg("asm"), py::arg("context") = py::none(),
3338  "Parses an attribute from an assembly form. Raises an MLIRError on "
3339  "failure.")
3340  .def_property_readonly(
3341  "context",
3342  [](PyAttribute &self) { return self.getContext().getObject(); },
3343  "Context that owns the Attribute")
3344  .def_property_readonly(
3345  "type", [](PyAttribute &self) { return mlirAttributeGetType(self); })
3346  .def(
3347  "get_named",
3348  [](PyAttribute &self, std::string name) {
3349  return PyNamedAttribute(self, std::move(name));
3350  },
3351  py::keep_alive<0, 1>(), "Binds a name to the attribute")
3352  .def("__eq__",
3353  [](PyAttribute &self, PyAttribute &other) { return self == other; })
3354  .def("__eq__", [](PyAttribute &self, py::object &other) { return false; })
3355  .def("__hash__",
3356  [](PyAttribute &self) {
3357  return static_cast<size_t>(llvm::hash_value(self.get().ptr));
3358  })
3359  .def(
3360  "dump", [](PyAttribute &self) { mlirAttributeDump(self); },
3362  .def(
3363  "__str__",
3364  [](PyAttribute &self) {
3365  PyPrintAccumulator printAccum;
3366  mlirAttributePrint(self, printAccum.getCallback(),
3367  printAccum.getUserData());
3368  return printAccum.join();
3369  },
3370  "Returns the assembly form of the Attribute.")
3371  .def("__repr__",
3372  [](PyAttribute &self) {
3373  // Generally, assembly formats are not printed for __repr__ because
3374  // this can cause exceptionally long debug output and exceptions.
3375  // However, attribute values are generally considered useful and
3376  // are printed. This may need to be re-evaluated if debug dumps end
3377  // up being excessive.
3378  PyPrintAccumulator printAccum;
3379  printAccum.parts.append("Attribute(");
3380  mlirAttributePrint(self, printAccum.getCallback(),
3381  printAccum.getUserData());
3382  printAccum.parts.append(")");
3383  return printAccum.join();
3384  })
3385  .def_property_readonly(
3386  "typeid",
3387  [](PyAttribute &self) -> MlirTypeID {
3388  MlirTypeID mlirTypeID = mlirAttributeGetTypeID(self);
3389  assert(!mlirTypeIDIsNull(mlirTypeID) &&
3390  "mlirTypeID was expected to be non-null.");
3391  return mlirTypeID;
3392  })
3394  MlirTypeID mlirTypeID = mlirAttributeGetTypeID(self);
3395  assert(!mlirTypeIDIsNull(mlirTypeID) &&
3396  "mlirTypeID was expected to be non-null.");
3397  std::optional<pybind11::function> typeCaster =
3398  PyGlobals::get().lookupTypeCaster(mlirTypeID,
3399  mlirAttributeGetDialect(self));
3400  if (!typeCaster)
3401  return py::cast(self);
3402  return typeCaster.value()(self);
3403  });
3404 
3405  //----------------------------------------------------------------------------
3406  // Mapping of PyNamedAttribute
3407  //----------------------------------------------------------------------------
3408  py::class_<PyNamedAttribute>(m, "NamedAttribute", py::module_local())
3409  .def("__repr__",
3410  [](PyNamedAttribute &self) {
3411  PyPrintAccumulator printAccum;
3412  printAccum.parts.append("NamedAttribute(");
3413  printAccum.parts.append(
3414  py::str(mlirIdentifierStr(self.namedAttr.name).data,
3415  mlirIdentifierStr(self.namedAttr.name).length));
3416  printAccum.parts.append("=");
3417  mlirAttributePrint(self.namedAttr.attribute,
3418  printAccum.getCallback(),
3419  printAccum.getUserData());
3420  printAccum.parts.append(")");
3421  return printAccum.join();
3422  })
3423  .def_property_readonly(
3424  "name",
3425  [](PyNamedAttribute &self) {
3426  return py::str(mlirIdentifierStr(self.namedAttr.name).data,
3427  mlirIdentifierStr(self.namedAttr.name).length);
3428  },
3429  "The name of the NamedAttribute binding")
3430  .def_property_readonly(
3431  "attr",
3432  [](PyNamedAttribute &self) { return self.namedAttr.attribute; },
3433  py::keep_alive<0, 1>(),
3434  "The underlying generic attribute of the NamedAttribute binding");
3435 
3436  //----------------------------------------------------------------------------
3437  // Mapping of PyType.
3438  //----------------------------------------------------------------------------
3439  py::class_<PyType>(m, "Type", py::module_local())
3440  // Delegate to the PyType copy constructor, which will also lifetime
3441  // extend the backing context which owns the MlirType.
3442  .def(py::init<PyType &>(), py::arg("cast_from_type"),
3443  "Casts the passed type to the generic Type")
3444  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyType::getCapsule)
3445  .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyType::createFromCapsule)
3446  .def_static(
3447  "parse",
3448  [](std::string typeSpec, DefaultingPyMlirContext context) {
3449  PyMlirContext::ErrorCapture errors(context->getRef());
3450  MlirType type =
3451  mlirTypeParseGet(context->get(), toMlirStringRef(typeSpec));
3452  if (mlirTypeIsNull(type))
3453  throw MLIRError("Unable to parse type", errors.take());
3454  return type;
3455  },
3456  py::arg("asm"), py::arg("context") = py::none(),
3458  .def_property_readonly(
3459  "context", [](PyType &self) { return self.getContext().getObject(); },
3460  "Context that owns the Type")
3461  .def("__eq__", [](PyType &self, PyType &other) { return self == other; })
3462  .def("__eq__", [](PyType &self, py::object &other) { return false; })
3463  .def("__hash__",
3464  [](PyType &self) {
3465  return static_cast<size_t>(llvm::hash_value(self.get().ptr));
3466  })
3467  .def(
3468  "dump", [](PyType &self) { mlirTypeDump(self); }, kDumpDocstring)
3469  .def(
3470  "__str__",
3471  [](PyType &self) {
3472  PyPrintAccumulator printAccum;
3473  mlirTypePrint(self, printAccum.getCallback(),
3474  printAccum.getUserData());
3475  return printAccum.join();
3476  },
3477  "Returns the assembly form of the type.")
3478  .def("__repr__",
3479  [](PyType &self) {
3480  // Generally, assembly formats are not printed for __repr__ because
3481  // this can cause exceptionally long debug output and exceptions.
3482  // However, types are an exception as they typically have compact
3483  // assembly forms and printing them is useful.
3484  PyPrintAccumulator printAccum;
3485  printAccum.parts.append("Type(");
3486  mlirTypePrint(self, printAccum.getCallback(),
3487  printAccum.getUserData());
3488  printAccum.parts.append(")");
3489  return printAccum.join();
3490  })
3492  [](PyType &self) {
3493  MlirTypeID mlirTypeID = mlirTypeGetTypeID(self);
3494  assert(!mlirTypeIDIsNull(mlirTypeID) &&
3495  "mlirTypeID was expected to be non-null.");
3496  std::optional<pybind11::function> typeCaster =
3497  PyGlobals::get().lookupTypeCaster(mlirTypeID,
3498  mlirTypeGetDialect(self));
3499  if (!typeCaster)
3500  return py::cast(self);
3501  return typeCaster.value()(self);
3502  })
3503  .def_property_readonly("typeid", [](PyType &self) -> MlirTypeID {
3504  MlirTypeID mlirTypeID = mlirTypeGetTypeID(self);
3505  if (!mlirTypeIDIsNull(mlirTypeID))
3506  return mlirTypeID;
3507  auto origRepr =
3508  pybind11::repr(pybind11::cast(self)).cast<std::string>();
3509  throw py::value_error(
3510  (origRepr + llvm::Twine(" has no typeid.")).str());
3511  });
3512 
3513  //----------------------------------------------------------------------------
3514  // Mapping of PyTypeID.
3515  //----------------------------------------------------------------------------
3516  py::class_<PyTypeID>(m, "TypeID", py::module_local())
3517  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyTypeID::getCapsule)
3518  .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyTypeID::createFromCapsule)
3519  // Note, this tests whether the underlying TypeIDs are the same,
3520  // not whether the wrapper MlirTypeIDs are the same, nor whether
3521  // the Python objects are the same (i.e., PyTypeID is a value type).
3522  .def("__eq__",
3523  [](PyTypeID &self, PyTypeID &other) { return self == other; })
3524  .def("__eq__",
3525  [](PyTypeID &self, const py::object &other) { return false; })
3526  // Note, this gives the hash value of the underlying TypeID, not the
3527  // hash value of the Python object, nor the hash value of the
3528  // MlirTypeID wrapper.
3529  .def("__hash__", [](PyTypeID &self) {
3530  return static_cast<size_t>(mlirTypeIDHashValue(self));
3531  });
3532 
3533  //----------------------------------------------------------------------------
3534  // Mapping of Value.
3535  //----------------------------------------------------------------------------
3536  py::class_<PyValue>(m, "Value", py::module_local())
3537  .def(py::init<PyValue &>(), py::keep_alive<0, 1>(), py::arg("value"))
3538  .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyValue::getCapsule)
3539  .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyValue::createFromCapsule)
3540  .def_property_readonly(
3541  "context",
3542  [](PyValue &self) { return self.getParentOperation()->getContext(); },
3543  "Context in which the value lives.")
3544  .def(
3545  "dump", [](PyValue &self) { mlirValueDump(self.get()); },
3547  .def_property_readonly(
3548  "owner",
3549  [](PyValue &self) -> py::object {
3550  MlirValue v = self.get();
3551  if (mlirValueIsAOpResult(v)) {
3552  assert(
3553  mlirOperationEqual(self.getParentOperation()->get(),
3554  mlirOpResultGetOwner(self.get())) &&
3555  "expected the owner of the value in Python to match that in "
3556  "the IR");
3557  return self.getParentOperation().getObject();
3558  }
3559 
3560  if (mlirValueIsABlockArgument(v)) {
3561  MlirBlock block = mlirBlockArgumentGetOwner(self.get());
3562  return py::cast(PyBlock(self.getParentOperation(), block));
3563  }
3564 
3565  assert(false && "Value must be a block argument or an op result");
3566  return py::none();
3567  })
3568  .def_property_readonly("uses",
3569  [](PyValue &self) {
3570  return PyOpOperandIterator(
3571  mlirValueGetFirstUse(self.get()));
3572  })
3573  .def("__eq__",
3574  [](PyValue &self, PyValue &other) {
3575  return self.get().ptr == other.get().ptr;
3576  })
3577  .def("__eq__", [](PyValue &self, py::object other) { return false; })
3578  .def("__hash__",
3579  [](PyValue &self) {
3580  return static_cast<size_t>(llvm::hash_value(self.get().ptr));
3581  })
3582  .def(
3583  "__str__",
3584  [](PyValue &self) {
3585  PyPrintAccumulator printAccum;
3586  printAccum.parts.append("Value(");
3587  mlirValuePrint(self.get(), printAccum.getCallback(),
3588  printAccum.getUserData());
3589  printAccum.parts.append(")");
3590  return printAccum.join();
3591  },
3593  .def(
3594  "get_name",
3595  [](PyValue &self, bool useLocalScope) {
3596  PyPrintAccumulator printAccum;
3597  MlirOpPrintingFlags flags = mlirOpPrintingFlagsCreate();
3598  if (useLocalScope)
3600  MlirAsmState valueState =
3601  mlirAsmStateCreateForValue(self.get(), flags);
3602  mlirValuePrintAsOperand(self.get(), valueState,
3603  printAccum.getCallback(),
3604  printAccum.getUserData());
3606  mlirAsmStateDestroy(valueState);
3607  return printAccum.join();
3608  },
3609  py::arg("use_local_scope") = false)
3610  .def(
3611  "get_name",
3612  [](PyValue &self, std::reference_wrapper<PyAsmState> state) {
3613  PyPrintAccumulator printAccum;
3614  MlirAsmState valueState = state.get().get();
3615  mlirValuePrintAsOperand(self.get(), valueState,
3616  printAccum.getCallback(),
3617  printAccum.getUserData());
3618  return printAccum.join();
3619  },
3620  py::arg("state"), kGetNameAsOperand)
3621  .def_property_readonly(
3622  "type", [](PyValue &self) { return mlirValueGetType(self.get()); })
3623  .def(
3624  "set_type",
3625  [](PyValue &self, const PyType &type) {
3626  return mlirValueSetType(self.get(), type);
3627  },
3628  py::arg("type"))
3629  .def(
3630  "replace_all_uses_with",
3631  [](PyValue &self, PyValue &with) {
3632  mlirValueReplaceAllUsesOfWith(self.get(), with.get());
3633  },
3636  [](PyValue &self) { return self.maybeDownCast(); });
3637  PyBlockArgument::bind(m);
3638  PyOpResult::bind(m);
3639  PyOpOperand::bind(m);
3640 
3641  py::class_<PyAsmState>(m, "AsmState", py::module_local())
3642  .def(py::init<PyValue &, bool>(), py::arg("value"),
3643  py::arg("use_local_scope") = false)
3644  .def(py::init<PyOperationBase &, bool>(), py::arg("op"),
3645  py::arg("use_local_scope") = false);
3646 
3647  //----------------------------------------------------------------------------
3648  // Mapping of SymbolTable.
3649  //----------------------------------------------------------------------------
3650  py::class_<PySymbolTable>(m, "SymbolTable", py::module_local())
3651  .def(py::init<PyOperationBase &>())
3652  .def("__getitem__", &PySymbolTable::dunderGetItem)
3653  .def("insert", &PySymbolTable::insert, py::arg("operation"))
3654  .def("erase", &PySymbolTable::erase, py::arg("operation"))
3655  .def("__delitem__", &PySymbolTable::dunderDel)
3656  .def("__contains__",
3657  [](PySymbolTable &table, const std::string &name) {
3659  table, mlirStringRefCreate(name.data(), name.length())));
3660  })
3661  // Static helpers.
3662  .def_static("set_symbol_name", &PySymbolTable::setSymbolName,
3663  py::arg("symbol"), py::arg("name"))
3664  .def_static("get_symbol_name", &PySymbolTable::getSymbolName,
3665  py::arg("symbol"))
3666  .def_static("get_visibility", &PySymbolTable::getVisibility,
3667  py::arg("symbol"))
3668  .def_static("set_visibility", &PySymbolTable::setVisibility,
3669  py::arg("symbol"), py::arg("visibility"))
3670  .def_static("replace_all_symbol_uses",
3671  &PySymbolTable::replaceAllSymbolUses, py::arg("old_symbol"),
3672  py::arg("new_symbol"), py::arg("from_op"))
3673  .def_static("walk_symbol_tables", &PySymbolTable::walkSymbolTables,
3674  py::arg("from_op"), py::arg("all_sym_uses_visible"),
3675  py::arg("callback"));
3676 
3677  // Container bindings.
3678  PyBlockArgumentList::bind(m);
3679  PyBlockIterator::bind(m);
3680  PyBlockList::bind(m);
3681  PyOperationIterator::bind(m);
3682  PyOperationList::bind(m);
3683  PyOpAttributeMap::bind(m);
3684  PyOpOperandIterator::bind(m);
3685  PyOpOperandList::bind(m);
3686  PyOpResultList::bind(m);
3687  PyOpSuccessors::bind(m);
3688  PyRegionIterator::bind(m);
3689  PyRegionList::bind(m);
3690 
3691  // Debug bindings.
3693 
3694  // Attribute builder getter.
3696 
3697  py::register_local_exception_translator([](std::exception_ptr p) {
3698  // We can't define exceptions with custom fields through pybind, so instead
3699  // the exception class is defined in python and imported here.
3700  try {
3701  if (p)
3702  std::rethrow_exception(p);
3703  } catch (const MLIRError &e) {
3704  py::object obj = py::module_::import(MAKE_MLIR_PYTHON_QUALNAME("ir"))
3705  .attr("MLIRError")(e.message, e.errorDiagnostics);
3706  PyErr_SetObject(PyExc_Exception, obj.ptr());
3707  }
3708  });
3709 }
MLIR_CAPI_EXPORTED bool mlirIsGlobalDebugEnabled()
Retuns true if the global debugging flag is set, false otherwise.
Definition: Debug.cpp:18
MLIR_CAPI_EXPORTED void mlirEnableGlobalDebug(bool enable)
Sets the global debugging flag.
Definition: Debug.cpp:16
static const char kOperationPrintStateDocstring[]
Definition: IRCore.cpp:113
static const char kValueReplaceAllUsesWithDocstring[]
Definition: IRCore.cpp:175
static py::object createCustomDialectWrapper(const std::string &dialectNamespace, py::object dialectDescriptor)
Definition: IRCore.cpp:192
static const char kContextGetNameLocationDocString[]
Definition: IRCore.cpp:57
static const char kGetNameAsOperand[]
Definition: IRCore.cpp:171
static MlirStringRef toMlirStringRef(const std::string &s)
Definition: IRCore.cpp:204
static const char kModuleParseDocstring[]
Definition: IRCore.cpp:60
static const char kOperationStrDunderDocstring[]
Definition: IRCore.cpp:145
static const char kOperationPrintDocstring[]
Definition: IRCore.cpp:87
static const char kContextGetFileLocationDocstring[]
Definition: IRCore.cpp:51
static const char kDumpDocstring[]
Definition: IRCore.cpp:153
static const char kAppendBlockDocstring[]
Definition: IRCore.cpp:156
static const char kContextGetFusedLocationDocstring[]
Definition: IRCore.cpp:54
static void maybeInsertOperation(PyOperationRef &op, const py::object &maybeIp)
Definition: IRCore.cpp:1334
static MlirBlock createBlock(const py::sequence &pyArgTypes, const std::optional< py::sequence > &pyArgLocs)
Create a block, using the current location context if no locations are specified.
Definition: IRCore.cpp:210
static const char kOperationPrintBytecodeDocstring[]
Definition: IRCore.cpp:135
static const char kOperationGetAsmDocstring[]
Definition: IRCore.cpp:122
static void populateResultTypes(StringRef name, py::list resultTypeList, const py::object &resultSegmentSpecObj, std::vector< int32_t > &resultSegmentLengths, std::vector< PyType * > &resultTypes)
Definition: IRCore.cpp:1511
static const char kOperationCreateDocstring[]
Definition: IRCore.cpp:68
static const char kContextParseTypeDocstring[]
Definition: IRCore.cpp:40
static const char kContextGetCallSiteLocationDocstring[]
Definition: IRCore.cpp:48
static const char kValueDunderStrDocstring[]
Definition: IRCore.cpp:163
py::object classmethod(Func f, Args... args)
Helper for creating an @classmethod.
Definition: IRCore.cpp:186
static MLIRContext * getContext(OpFoldResult val)
static PyObject * mlirPythonModuleToCapsule(MlirModule module)
Creates a capsule object encapsulating the raw C-API MlirModule.
Definition: Interop.h:272
#define MLIR_PYTHON_MAYBE_DOWNCAST_ATTR
Attribute on MLIR Python objects that expose a function for downcasting the corresponding Python obje...
Definition: Interop.h:117
static PyObject * mlirPythonTypeIDToCapsule(MlirTypeID typeID)
Creates a capsule object encapsulating the raw C-API MlirTypeID.
Definition: Interop.h:327
static MlirOperation mlirPythonCapsuleToOperation(PyObject *capsule)
Extracts an MlirOperations from a capsule as produced from mlirPythonOperationToCapsule.
Definition: Interop.h:317
#define MLIR_PYTHON_CAPI_PTR_ATTR
Attribute on MLIR Python objects that expose their C-API pointer.
Definition: Interop.h:96
static MlirAttribute mlirPythonCapsuleToAttribute(PyObject *capsule)
Extracts an MlirAttribute from a capsule as produced from mlirPythonAttributeToCapsule.
Definition: Interop.h:188
static PyObject * mlirPythonAttributeToCapsule(MlirAttribute attribute)
Creates a capsule object encapsulating the raw C-API MlirAttribute.
Definition: Interop.h:179
static PyObject * mlirPythonLocationToCapsule(MlirLocation loc)
Creates a capsule object encapsulating the raw C-API MlirLocation.
Definition: Interop.h:254
#define MLIR_PYTHON_CAPI_FACTORY_ATTR
Attribute on MLIR Python objects that exposes a factory function for constructing the corresponding P...
Definition: Interop.h:109
static MlirModule mlirPythonCapsuleToModule(PyObject *capsule)
Extracts an MlirModule from a capsule as produced from mlirPythonModuleToCapsule.
Definition: Interop.h:281
static MlirContext mlirPythonCapsuleToContext(PyObject *capsule)
Extracts a MlirContext from a capsule as produced from mlirPythonContextToCapsule.
Definition: Interop.h:223
static MlirTypeID mlirPythonCapsuleToTypeID(PyObject *capsule)
Extracts an MlirTypeID from a capsule as produced from mlirPythonTypeIDToCapsule.
Definition: Interop.h:336
static PyObject * mlirPythonDialectRegistryToCapsule(MlirDialectRegistry registry)
Creates a capsule object encapsulating the raw C-API MlirDialectRegistry.
Definition: Interop.h:234
static PyObject * mlirPythonTypeToCapsule(MlirType type)
Creates a capsule object encapsulating the raw C-API MlirType.
Definition: Interop.h:346
static MlirDialectRegistry mlirPythonCapsuleToDialectRegistry(PyObject *capsule)
Extracts an MlirDialectRegistry from a capsule as produced from mlirPythonDialectRegistryToCapsule.
Definition: Interop.h:244
#define MAKE_MLIR_PYTHON_QUALNAME(local)
Definition: Interop.h:56
static MlirType mlirPythonCapsuleToType(PyObject *capsule)
Extracts an MlirType from a capsule as produced from mlirPythonTypeToCapsule.
Definition: Interop.h:355
static MlirValue mlirPythonCapsuleToValue(PyObject *capsule)
Extracts an MlirValue from a capsule as produced from mlirPythonValueToCapsule.
Definition: Interop.h:433
static PyObject * mlirPythonBlockToCapsule(MlirBlock block)
Creates a capsule object encapsulating the raw C-API MlirBlock.
Definition: Interop.h:197
static PyObject * mlirPythonOperationToCapsule(MlirOperation operation)
Creates a capsule object encapsulating the raw C-API MlirOperation.
Definition: Interop.h:309
static MlirLocation mlirPythonCapsuleToLocation(PyObject *capsule)
Extracts an MlirLocation from a capsule as produced from mlirPythonLocationToCapsule.
Definition: Interop.h:263
static PyObject * mlirPythonValueToCapsule(MlirValue value)
Creates a capsule object encapsulating the raw C-API MlirValue.
Definition: Interop.h:424
static PyObject * mlirPythonContextToCapsule(MlirContext context)
Creates a capsule object encapsulating the raw C-API MlirContext.
Definition: Interop.h:215
static LogicalResult nextIndex(ArrayRef< int64_t > shape, MutableArrayRef< int64_t > index)
Walks over the indices of the elements of a tensor of a given shape by updating index in place to the...
static std::string diag(const llvm::Value &value)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static sycl::context getDefaultContext()
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:216
Accumulates int a python file-like object, either writing text (default) or binary.
Definition: PybindUtils.h:125
MlirStringCallback getCallback()
Definition: PybindUtils.h:132
A CRTP base class for pseudo-containers willing to support Python-type slicing access on top of index...
Definition: PybindUtils.h:209
Base class for all objects that directly or indirectly depend on an MlirContext.
Definition: IRModule.h:295
PyMlirContextRef & getContext()
Accesses the context reference.
Definition: IRModule.h:303
Used in function arguments when None should resolve to the current context manager set instance.
Definition: IRModule.h:510
static PyLocation & resolve()
Definition: IRCore.cpp:1039
Used in function arguments when None should resolve to the current context manager set instance.
Definition: IRModule.h:284
static PyMlirContext & resolve()
Definition: IRCore.cpp:763
ReferrentTy * get() const
Definition: PybindUtils.h:47
Wrapper around an MlirAsmState.
Definition: IRModule.h:772
Wrapper around the generic MlirAttribute.
Definition: IRModule.h:989
PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
Definition: IRModule.h:991
static PyAttribute createFromCapsule(pybind11::object capsule)
Creates a PyAttribute from the MlirAttribute wrapped by a capsule.
Definition: IRCore.cpp:1874
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirAttribute.
Definition: IRCore.cpp:1870
bool operator==(const PyAttribute &other) const
Definition: IRCore.cpp:1866
Wrapper around an MlirBlock.
Definition: IRModule.h:807
MlirBlock get()
Definition: IRModule.h:814
PyOperationRef & getParentOperation()
Definition: IRModule.h:815
Represents a diagnostic handler attached to the context.
Definition: IRModule.h:391
void detach()
Detaches the handler. Does nothing if not attached.
Definition: IRCore.cpp:925
PyDiagnosticHandler(MlirContext context, pybind11::object callback)
Definition: IRCore.cpp:919
Python class mirroring the C MlirDiagnostic struct.
Definition: IRModule.h:341
pybind11::str getMessage()
Definition: IRCore.cpp:955
PyLocation getLocation()
Definition: IRCore.cpp:948
DiagnosticInfo getInfo()
Definition: IRCore.cpp:976
PyDiagnostic(MlirDiagnostic diagnostic)
Definition: IRModule.h:343
MlirDiagnosticSeverity getSeverity()
Definition: IRCore.cpp:943
pybind11::tuple getNotes()
Definition: IRCore.cpp:963
Wrapper around an MlirDialect.
Definition: IRModule.h:446
Wrapper around an MlirDialectRegistry.
Definition: IRModule.h:483
static PyDialectRegistry createFromCapsule(pybind11::object capsule)
Definition: IRCore.cpp:1005
pybind11::object getCapsule()
Definition: IRCore.cpp:1000
User-level dialect object.
Definition: IRModule.h:470
User-level object for accessing dialects with dotted syntax such as: ctx.dialect.std.
Definition: IRModule.h:459
MlirDialect getDialectForKey(const std::string &key, bool attrError)
Definition: IRCore.cpp:987
static PyGlobals & get()
Most code should get the globals via this static accessor.
Definition: Globals.h:34
std::optional< pybind11::object > lookupOperationClass(llvm::StringRef operationName)
Looks up a registered operation class (deriving from OpView) by operation name.
Definition: IRModule.cpp:172
std::optional< pybind11::function > lookupValueCaster(MlirTypeID mlirTypeID, MlirDialect dialect)
Returns the custom value caster for MlirTypeID mlirTypeID.
Definition: IRModule.cpp:145
An insertion point maintains a pointer to a Block and a reference operation.
Definition: IRModule.h:831
static PyInsertionPoint atBlockTerminator(PyBlock &block)
Shortcut to create an insertion point before the block terminator.
Definition: IRCore.cpp:1843
PyInsertionPoint(PyBlock &block)
Creates an insertion point positioned after the last operation in the block, but still inside the blo...
Definition: IRCore.cpp:1798
static PyInsertionPoint atBlockBegin(PyBlock &block)
Shortcut to create an insertion point at the beginning of the block.
Definition: IRCore.cpp:1830
void insert(PyOperationBase &operationBase)
Inserts an operation.
Definition: IRCore.cpp:1804
void contextExit(const pybind11::object &excType, const pybind11::object &excVal, const pybind11::object &excTb)
Definition: IRCore.cpp:1856
pybind11::object contextEnter()
Enter and exit the context manager.
Definition: IRCore.cpp:1852
Wrapper around an MlirLocation.
Definition: IRModule.h:310
PyLocation(PyMlirContextRef contextRef, MlirLocation loc)
Definition: IRModule.h:312
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirLocation.
Definition: IRCore.cpp:1017
static PyLocation createFromCapsule(pybind11::object capsule)
Creates a PyLocation from the MlirLocation wrapped by a capsule.
Definition: IRCore.cpp:1021
void contextExit(const pybind11::object &excType, const pybind11::object &excVal, const pybind11::object &excTb)
Definition: IRCore.cpp:1033
pybind11::object contextEnter()
Enter and exit the context manager.
Definition: IRCore.cpp:1029
MlirLocation get() const
Definition: IRModule.h:316
pybind11::object attachDiagnosticHandler(pybind11::object callback)
Attaches a Python callback as a diagnostic handler, returning a registration object (internally a PyD...
Definition: IRCore.cpp:698
MlirContext get()
Accesses the underlying MlirContext.
Definition: IRModule.h:184
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:188
static pybind11::object createFromCapsule(pybind11::object capsule)
Creates a PyMlirContext from the MlirContext wrapped by a capsule.
Definition: IRCore.cpp:601
void clearOperationsInside(PyOperationBase &op)
Clears all operations nested inside the given op using clearOperation(MlirOperation).
Definition: IRCore.cpp:662
static size_t getLiveCount()
Gets the count of live context objects. Used for testing.
Definition: IRCore.cpp:635
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:608
size_t getLiveModuleCount()
Gets the count of live modules associated with this context.
Definition: IRCore.cpp:686
pybind11::object contextEnter()
Enter and exit the context manager.
Definition: IRCore.cpp:688
size_t clearLiveOperations()
Clears the live operations map, returning the number of entries which were invalidated.
Definition: IRCore.cpp:646
std::vector< PyOperation * > getLiveOperationObjects()
Get a list of Python objects which are still in the live context map.
Definition: IRCore.cpp:639
void contextExit(const pybind11::object &excType, const pybind11::object &excVal, const pybind11::object &excTb)
Definition: IRCore.cpp:692
void clearOperation(MlirOperation op)
Removes an operation from the live operations map and sets it invalid.
Definition: IRCore.cpp:654
static PyMlirContextRef forContext(MlirContext context)
Returns a context reference for the singleton PyMlirContext wrapper for the given context.
Definition: IRCore.cpp:613
size_t getLiveOperationCount()
Gets the count of live operations associated with this context.
Definition: IRCore.cpp:637
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirContext.
Definition: IRCore.cpp:597
MlirModule get()
Gets the backing MlirModule.
Definition: IRModule.h:533
static PyModuleRef forModule(MlirModule module)
Returns a PyModule reference for the given MlirModule.
Definition: IRCore.cpp:1066
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirModule.
Definition: IRCore.cpp:1099
static pybind11::object createFromCapsule(pybind11::object capsule)
Creates a PyModule from the MlirModule wrapped by a capsule.
Definition: IRCore.cpp:1092
PyModule(PyModule &)=delete
Represents a Python MlirNamedAttr, carrying an optional owned name.
Definition: IRModule.h:1013
PyNamedAttribute(MlirAttribute attr, std::string ownedName)
Constructs a PyNamedAttr that retains an owned name.
Definition: IRCore.cpp:1886
MlirNamedAttribute namedAttr
Definition: IRModule.h:1022
pybind11::object getObject()
Definition: IRModule.h:87
pybind11::object releaseObject()
Releases the object held by this instance, returning it.
Definition: IRModule.h:75
A PyOpView is equivalent to the C++ "Op" wrappers: these are the basis for providing more instance-sp...
Definition: IRModule.h:721
PyOpView(const pybind11::object &operationObject)
Definition: IRCore.cpp:1788
static pybind11::object buildGeneric(const pybind11::object &cls, std::optional< 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:1599
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:1777
Base class for PyOperation and PyOpView which exposes the primary, user visible methods for manipulat...
Definition: IRModule.h:563
virtual PyOperation & getOperation()=0
Each must provide access to the raw Operation.
void writeBytecode(const pybind11::object &fileObject, std::optional< int64_t > bytecodeVersion)
Definition: IRCore.cpp:1231
pybind11::object getAsm(bool binary, std::optional< int64_t > largeElementsLimit, bool enableDebugInfo, bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope, bool assumeVerified)
Definition: IRCore.cpp:1252
void moveAfter(PyOperationBase &other)
Moves the operation before or after the other operation.
Definition: IRCore.cpp:1275
void print(std::optional< int64_t > largeElementsLimit, bool enableDebugInfo, bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope, bool assumeVerified, py::object fileObject, bool binary)
Implements the bound 'print' method and helps with others.
Definition: IRCore.cpp:1191
void moveBefore(PyOperationBase &other)
Definition: IRCore.cpp:1284
bool verify()
Verify the operation.
Definition: IRCore.cpp:1293
pybind11::object clone(const pybind11::object &ip)
Clones this operation.
Definition: IRCore.cpp:1475
void detachFromParent()
Detaches the operation from its parent block and updates its state accordingly.
Definition: IRModule.h:627
void erase()
Erases the underlying MlirOperation, removes its pointer from the parent context's live operations ma...
Definition: IRCore.cpp:1495
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirOperation.
Definition: IRCore.cpp:1320
PyOperation & getOperation() override
Each must provide access to the raw Operation.
Definition: IRModule.h:605
PyOperationRef getRef()
Definition: IRModule.h:640
MlirOperation get() const
Definition: IRModule.h:635
void setAttached(const pybind11::object &parent=pybind11::object())
Definition: IRModule.h:646
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, bool inferType)
Creates an operation. See corresponding python docstring.
Definition: IRCore.cpp:1349
pybind11::object createOpView()
Creates an OpView suitable for this operation.
Definition: IRCore.cpp:1484
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:1143
std::optional< PyOperationRef > getParentOperation()
Gets the parent operation or raises an exception if the operation has no parent.
Definition: IRCore.cpp:1301
PyBlock getBlock()
Gets the owning block or raises an exception if the operation has no owning block.
Definition: IRCore.cpp:1311
static PyOperationRef createDetached(PyMlirContextRef contextRef, MlirOperation operation, pybind11::object parentKeepAlive=pybind11::object())
Creates a detached operation.
Definition: IRCore.cpp:1159
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:1173
static pybind11::object createFromCapsule(pybind11::object capsule)
Creates a PyOperation from the MlirOperation wrapped by a capsule.
Definition: IRCore.cpp:1325
void checkValid() const
Definition: IRCore.cpp:1185
Wrapper around an MlirRegion.
Definition: IRModule.h:753
PyOperationRef & getParentOperation()
Definition: IRModule.h:762
MlirRegion get()
Definition: IRModule.h:761
Bindings for MLIR symbol tables.
Definition: IRModule.h:1219
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:2006
static void replaceAllSymbolUses(const std::string &oldSymbol, const std::string &newSymbol, PyOperationBase &from)
Replaces all symbol uses within an operation.
Definition: IRCore.cpp:2077
static void setVisibility(PyOperationBase &symbol, const std::string &visibility)
Definition: IRCore.cpp:2059
static void setSymbolName(PyOperationBase &symbol, const std::string &name)
Definition: IRCore.cpp:2033
MlirAttribute insert(PyOperationBase &symbol)
Inserts the given operation into the symbol table.
Definition: IRCore.cpp:2011
void erase(PyOperationBase &symbol)
Removes the given operation from the symbol table and erases it.
Definition: IRCore.cpp:1996
PySymbolTable(PyOperationBase &operation)
Constructs a symbol table for the given operation.
Definition: IRCore.cpp:1976
static MlirAttribute getSymbolName(PyOperationBase &symbol)
Gets and sets the name of a symbol op.
Definition: IRCore.cpp:2021
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:1984
static MlirAttribute getVisibility(PyOperationBase &symbol)
Gets and sets the visibility of a symbol op.
Definition: IRCore.cpp:2048
static void walkSymbolTables(PyOperationBase &from, bool allSymUsesVisible, pybind11::object callback)
Walks all symbol tables under and including 'from'.
Definition: IRCore.cpp:2089
Tracks an entry in the thread context stack.
Definition: IRModule.h:106
static PyThreadContextEntry * getTopOfStack()
Stack management.
Definition: IRCore.cpp:783
static void popLocation(PyLocation &location)
Definition: IRCore.cpp:895
static pybind11::object pushContext(PyMlirContext &context)
Definition: IRCore.cpp:845
static PyLocation * getDefaultLocation()
Gets the top of stack location and returns nullptr if not defined.
Definition: IRCore.cpp:840
static void popInsertionPoint(PyInsertionPoint &insertionPoint)
Definition: IRCore.cpp:875
static void popContext(PyMlirContext &context)
Definition: IRCore.cpp:853
static PyInsertionPoint * getDefaultInsertionPoint()
Gets the top of stack insertion point and return nullptr if not defined.
Definition: IRCore.cpp:835
static pybind11::object pushInsertionPoint(PyInsertionPoint &insertionPoint)
Definition: IRCore.cpp:864
static pybind11::object pushLocation(PyLocation &location)
Definition: IRCore.cpp:886
PyMlirContext * getContext()
Definition: IRCore.cpp:812
static PyMlirContext * getDefaultContext()
Gets the top of stack context and return nullptr if not defined.
Definition: IRCore.cpp:830
static std::vector< PyThreadContextEntry > & getStack()
Gets the thread local stack.
Definition: IRCore.cpp:778
PyInsertionPoint * getInsertionPoint()
Definition: IRCore.cpp:818
A TypeID provides an efficient and unique identifier for a specific C++ type.
Definition: IRModule.h:891
bool operator==(const PyTypeID &other) const
Definition: IRCore.cpp:1928
static PyTypeID createFromCapsule(pybind11::object capsule)
Creates a PyTypeID from the MlirTypeID wrapped by a capsule.
Definition: IRCore.cpp:1922
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirTypeID.
Definition: IRCore.cpp:1918
PyTypeID(MlirTypeID typeID)
Definition: IRModule.h:893
Wrapper around the generic MlirType.
Definition: IRModule.h:867
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirType.
Definition: IRCore.cpp:1902
static PyType createFromCapsule(pybind11::object capsule)
Creates a PyType from the MlirType wrapped by a capsule.
Definition: IRCore.cpp:1906
PyType(PyMlirContextRef contextRef, MlirType type)
Definition: IRModule.h:869
bool operator==(const PyType &other) const
Definition: IRCore.cpp:1898
Wrapper around the generic MlirValue.
Definition: IRModule.h:1120
static PyValue createFromCapsule(pybind11::object capsule)
Creates a PyValue from the MlirValue wrapped by a capsule.
Definition: IRCore.cpp:1955
PyValue(PyOperationRef parentOperation, MlirValue value)
Definition: IRModule.h:1126
pybind11::object getCapsule()
Gets a capsule wrapping the void* within the MlirValue.
Definition: IRCore.cpp:1936
pybind11::object maybeDownCast()
Definition: IRCore.cpp:1940
MLIR_CAPI_EXPORTED intptr_t mlirDiagnosticGetNumNotes(MlirDiagnostic diagnostic)
Returns the number of notes attached to the diagnostic.
Definition: Diagnostics.cpp:44
MLIR_CAPI_EXPORTED MlirDiagnosticSeverity mlirDiagnosticGetSeverity(MlirDiagnostic diagnostic)
Returns the severity of the diagnostic.
Definition: Diagnostics.cpp:28
MLIR_CAPI_EXPORTED void mlirDiagnosticPrint(MlirDiagnostic diagnostic, MlirStringCallback callback, void *userData)
Prints a diagnostic using the provided callback.
Definition: Diagnostics.cpp:18
MlirDiagnosticSeverity
Severity of a diagnostic.
Definition: Diagnostics.h:32
@ MlirDiagnosticNote
Definition: Diagnostics.h:35
@ MlirDiagnosticRemark
Definition: Diagnostics.h:36
@ MlirDiagnosticWarning
Definition: Diagnostics.h:34
@ MlirDiagnosticError
Definition: Diagnostics.h:33
MLIR_CAPI_EXPORTED MlirDiagnostic mlirDiagnosticGetNote(MlirDiagnostic diagnostic, intptr_t pos)
Returns pos-th note attached to the diagnostic.
Definition: Diagnostics.cpp:50
MLIR_CAPI_EXPORTED void mlirEmitError(MlirLocation location, const char *message)
Emits an error at the given location through the diagnostics engine.
Definition: Diagnostics.cpp:78
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 MlirLocation mlirDiagnosticGetLocation(MlirDiagnostic diagnostic)
Returns the location at which the diagnostic is reported.
Definition: Diagnostics.cpp:24
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI32ArrayGet(MlirContext ctx, intptr_t size, int32_t const *values)
MLIR_CAPI_EXPORTED MlirAttribute mlirStringAttrGet(MlirContext ctx, MlirStringRef str)
Creates a string attribute in the given context containing the given string.
MLIR_CAPI_EXPORTED MlirAttribute mlirLocationGetAttribute(MlirLocation location)
Returns the underlying location attribute of this location.
Definition: IR.cpp:242
MLIR_CAPI_EXPORTED intptr_t mlirBlockArgumentGetArgNumber(MlirValue value)
Returns the position of the value in the argument list of its block.
Definition: IR.cpp:926
static bool mlirAttributeIsNull(MlirAttribute attr)
Checks whether an attribute is null.
Definition: IR.h:1011
MLIR_CAPI_EXPORTED void mlirOperationWriteBytecode(MlirOperation op, MlirStringCallback callback, void *userData)
Same as mlirOperationPrint but writing the bytecode format.
Definition: IR.cpp:691
MLIR_CAPI_EXPORTED MlirIdentifier mlirOperationGetName(MlirOperation op)
Gets the name of the operation as an identifier.
Definition: IR.cpp:519
MLIR_CAPI_EXPORTED MlirLocation mlirLocationFileLineColGet(MlirContext context, MlirStringRef filename, unsigned line, unsigned col)
Creates an File/Line/Column location owned by the given context.
Definition: IR.cpp:250
MLIR_CAPI_EXPORTED void mlirSymbolTableWalkSymbolTables(MlirOperation from, bool allSymUsesVisible, void(*callback)(MlirOperation, bool, void *userData), void *userData)
Walks all symbol table operations nested within, and including, op.
Definition: IR.cpp:1155
MLIR_CAPI_EXPORTED MlirStringRef mlirDialectGetNamespace(MlirDialect dialect)
Returns the namespace of the given dialect.
Definition: IR.cpp:126
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumResults(MlirOperation op)
Returns the number of results of the operation.
Definition: IR.cpp:578
MLIR_CAPI_EXPORTED MlirAttribute mlirSymbolTableInsert(MlirSymbolTable symbolTable, MlirOperation operation)
Inserts the given operation into the given symbol table.
Definition: IR.cpp:1134
@ MlirWalkPreOrder
Definition: IR.h:710
MLIR_CAPI_EXPORTED MlirNamedAttribute mlirOperationGetAttribute(MlirOperation op, intptr_t pos)
Return pos-th attribute of the operation.
Definition: IR.cpp:652
MLIR_CAPI_EXPORTED void mlirOperationStateAddOperands(MlirOperationState *state, intptr_t n, MlirValue const *operands)
Definition: IR.cpp:367
MLIR_CAPI_EXPORTED void mlirModuleDestroy(MlirModule module)
Takes a module owned by the caller and deletes it.
Definition: IR.cpp:320
MLIR_CAPI_EXPORTED MlirNamedAttribute mlirNamedAttributeGet(MlirIdentifier name, MlirAttribute attr)
Associates an attribute with the name. Takes ownership of neither.
Definition: IR.cpp:1082
MLIR_CAPI_EXPORTED void mlirSymbolTableErase(MlirSymbolTable symbolTable, MlirOperation operation)
Removes the given operation from the symbol table and erases it.
Definition: IR.cpp:1139
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsUseLocalScope(MlirOpPrintingFlags flags)
Use local scope when printing the operation.
Definition: IR.cpp:213
MLIR_CAPI_EXPORTED bool mlirValueIsABlockArgument(MlirValue value)
Returns 1 if the value is a block argument, 0 otherwise.
Definition: IR.cpp:914
MLIR_CAPI_EXPORTED void mlirContextAppendDialectRegistry(MlirContext ctx, MlirDialectRegistry registry)
Append the contents of the given dialect registry to the registry associated with the context.
Definition: IR.cpp:81
MLIR_CAPI_EXPORTED MlirStringRef mlirIdentifierStr(MlirIdentifier ident)
Gets the string value of the identifier.
Definition: IR.cpp:1103
void(* MlirOperationWalkCallback)(MlirOperation, void *userData)
Operation walker type.
Definition: IR.h:716
static bool mlirModuleIsNull(MlirModule module)
Checks whether a module is null.
Definition: IR.h:314
MLIR_CAPI_EXPORTED MlirType mlirTypeParseGet(MlirContext context, MlirStringRef type)
Parses a type. The type is owned by the context.
Definition: IR.cpp:1016
MLIR_CAPI_EXPORTED MlirOpOperand mlirOpOperandGetNextUse(MlirOpOperand opOperand)
Returns an op operand representing the next use of the value, or a null op operand if there is no nex...
Definition: IR.cpp:999
MLIR_CAPI_EXPORTED MlirType mlirAttributeGetType(MlirAttribute attribute)
Gets the type of this attribute.
Definition: IR.cpp:1055
MLIR_CAPI_EXPORTED void mlirContextSetAllowUnregisteredDialects(MlirContext context, bool allow)
Sets whether unregistered dialects are allowed in this context.
Definition: IR.cpp:70
MLIR_CAPI_EXPORTED void mlirRegionInsertOwnedBlockBefore(MlirRegion region, MlirBlock reference, MlirBlock block)
Takes a block owned by the caller and inserts it before the (non-owned) reference block in the given ...
Definition: IR.cpp:774
MLIR_CAPI_EXPORTED void mlirValueReplaceAllUsesOfWith(MlirValue of, MlirValue with)
Replace all uses of 'of' value with the 'with' value, updating anything in the IR that uses 'of' to u...
Definition: IR.cpp:977
MLIR_CAPI_EXPORTED MlirBlock mlirOperationGetSuccessor(MlirOperation op, intptr_t pos)
Returns pos-th successor of the operation.
Definition: IR.cpp:590
MLIR_CAPI_EXPORTED void mlirValuePrintAsOperand(MlirValue value, MlirAsmState state, MlirStringCallback callback, void *userData)
Prints a value as an operand (i.e., the ValueID).
Definition: IR.cpp:960
MLIR_CAPI_EXPORTED MlirLocation mlirLocationUnknownGet(MlirContext context)
Creates a location with unknown position owned by the given context.
Definition: IR.cpp:278
MLIR_CAPI_EXPORTED void mlirTypePrint(MlirType type, MlirStringCallback callback, void *userData)
Prints a location by sending chunks of the string representation and forwarding userData tocallback`.
Definition: IR.cpp:1036
MLIR_CAPI_EXPORTED void mlirOperationSetAttributeByName(MlirOperation op, MlirStringRef name, MlirAttribute attr)
Sets an attribute by name, replacing the existing if it exists or adding a new one otherwise.
Definition: IR.cpp:662
MLIR_CAPI_EXPORTED MlirOperation mlirOpOperandGetOwner(MlirOpOperand opOperand)
Returns the owner operation of an op operand.
Definition: IR.cpp:987
MLIR_CAPI_EXPORTED MlirDialect mlirAttributeGetDialect(MlirAttribute attribute)
Gets the dialect of the attribute.
Definition: IR.cpp:1066
MLIR_CAPI_EXPORTED void mlirAttributePrint(MlirAttribute attr, MlirStringCallback callback, void *userData)
Prints an attribute by sending chunks of the string representation and forwarding userData tocallback...
Definition: IR.cpp:1074
MLIR_CAPI_EXPORTED MlirRegion mlirBlockGetParentRegion(MlirBlock block)
Returns the region that contains this block.
Definition: IR.cpp:813
MLIR_CAPI_EXPORTED void mlirOperationMoveBefore(MlirOperation op, MlirOperation other)
Moves the given operation immediately before the other operation in its parent block.
Definition: IR.cpp:715
static bool mlirValueIsNull(MlirValue value)
Returns whether the value is null.
Definition: IR.h:875
MLIR_CAPI_EXPORTED void mlirOperationPrintWithState(MlirOperation op, MlirAsmState state, MlirStringCallback callback, void *userData)
Same as mlirOperationPrint but accepts AsmState controlling the printing behavior as well as caching ...
Definition: IR.cpp:683
MLIR_CAPI_EXPORTED void mlirRegionInsertOwnedBlock(MlirRegion region, intptr_t pos, MlirBlock block)
Takes a block owned by the caller and inserts it at pos to the given region.
Definition: IR.cpp:754
MLIR_CAPI_EXPORTED MlirAttribute mlirOperationGetAttributeByName(MlirOperation op, MlirStringRef name)
Returns an attribute attached to the operation given its name.
Definition: IR.cpp:657
static bool mlirTypeIsNull(MlirType type)
Checks whether a type is null.
Definition: IR.h:976
MLIR_CAPI_EXPORTED bool mlirContextIsRegisteredOperation(MlirContext context, MlirStringRef name)
Returns whether the given fully-qualified operation (i.e.
Definition: IR.cpp:97
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumSuccessors(MlirOperation op)
Returns the number of successor blocks of the operation.
Definition: IR.cpp:586
MLIR_CAPI_EXPORTED MlirOperation mlirOperationClone(MlirOperation op)
Creates a deep copy of an operation.
Definition: IR.cpp:493
MLIR_CAPI_EXPORTED intptr_t mlirBlockGetNumArguments(MlirBlock block)
Returns the number of arguments of the block.
Definition: IR.cpp:882
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsPrintGenericOpForm(MlirOpPrintingFlags flags)
Always print operations in the generic form.
Definition: IR.cpp:209
MLIR_CAPI_EXPORTED MlirLocation mlirLocationFusedGet(MlirContext ctx, intptr_t nLocations, MlirLocation const *locations, MlirAttribute metadata)
Creates a fused location with an array of locations and metadata.
Definition: IR.cpp:261
MLIR_CAPI_EXPORTED void mlirBlockInsertOwnedOperationBefore(MlirBlock block, MlirOperation reference, MlirOperation operation)
Takes an operation owned by the caller and inserts it before the (non-owned) reference operation in t...
Definition: IR.cpp:863
MLIR_CAPI_EXPORTED void mlirAsmStateDestroy(MlirAsmState state)
Destroys printing flags created with mlirAsmStateCreate.
Definition: IR.cpp:185
static bool mlirContextIsNull(MlirContext context)
Checks whether a context is null.
Definition: IR.h:104
MLIR_CAPI_EXPORTED MlirDialect mlirContextGetOrLoadDialect(MlirContext context, MlirStringRef name)
Gets the dialect instance owned by the given context using the dialect namespace to identify it,...
Definition: IR.cpp:92
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsElideLargeElementsAttrs(MlirOpPrintingFlags flags, intptr_t largeElementLimit)
Enables the elision of large elements attributes by printing a lexically valid but otherwise meaningl...
Definition: IR.cpp:199
MLIR_CAPI_EXPORTED void mlirRegionInsertOwnedBlockAfter(MlirRegion region, MlirBlock reference, MlirBlock block)
Takes a block owned by the caller and inserts it after the (non-owned) reference block in the given r...
Definition: IR.cpp:760
MLIR_CAPI_EXPORTED void mlirBlockArgumentSetType(MlirValue value, MlirType type)
Sets the type of the block argument to the given type.
Definition: IR.cpp:931
MLIR_CAPI_EXPORTED MlirContext mlirOperationGetContext(MlirOperation op)
Gets the context this operation is associated with.
Definition: IR.cpp:505
MLIR_CAPI_EXPORTED MlirBlock mlirBlockCreate(intptr_t nArgs, MlirType const *args, MlirLocation const *locs)
Creates a new empty block with the given argument types and transfers ownership to the caller.
Definition: IR.cpp:797
static bool mlirBlockIsNull(MlirBlock block)
Checks whether a block is null.
Definition: IR.h:797
MLIR_CAPI_EXPORTED void mlirBlockAppendOwnedOperation(MlirBlock block, MlirOperation operation)
Takes an operation owned by the caller and appends it to the block.
Definition: IR.cpp:838
MLIR_CAPI_EXPORTED MlirValue mlirBlockGetArgument(MlirBlock block, intptr_t pos)
Returns pos-th argument of the block.
Definition: IR.cpp:896
MLIR_CAPI_EXPORTED MlirOperation mlirSymbolTableLookup(MlirSymbolTable symbolTable, MlirStringRef name)
Looks up a symbol with the given name in the given symbol table and returns the operation that corres...
Definition: IR.cpp:1129
MLIR_CAPI_EXPORTED MlirContext mlirTypeGetContext(MlirType type)
Gets the context that a type was created with.
Definition: IR.cpp:1020
MLIR_CAPI_EXPORTED void mlirValueDump(MlirValue value)
Prints the value to the standard error stream.
Definition: IR.cpp:952
MLIR_CAPI_EXPORTED MlirModule mlirModuleCreateEmpty(MlirLocation location)
Creates a new, empty module and transfers ownership to the caller.
Definition: IR.cpp:300
MLIR_CAPI_EXPORTED bool mlirOpOperandIsNull(MlirOpOperand opOperand)
Returns whether the op operand is null.
Definition: IR.cpp:985
MLIR_CAPI_EXPORTED MlirSymbolTable mlirSymbolTableCreate(MlirOperation operation)
Creates a symbol table for the given operation.
Definition: IR.cpp:1119
MLIR_CAPI_EXPORTED bool mlirLocationEqual(MlirLocation l1, MlirLocation l2)
Checks if two locations are equal.
Definition: IR.cpp:282
MLIR_CAPI_EXPORTED MlirBlock mlirOperationGetBlock(MlirOperation op)
Gets the block that owns this operation, returning null if the operation is not owned.
Definition: IR.cpp:523
static bool mlirLocationIsNull(MlirLocation location)
Checks if the location is null.
Definition: IR.h:282
MLIR_CAPI_EXPORTED bool mlirOperationEqual(MlirOperation op, MlirOperation other)
Checks whether two operation handles point to the same operation.
Definition: IR.cpp:501
MLIR_CAPI_EXPORTED void mlirOperationPrintWithFlags(MlirOperation op, MlirOpPrintingFlags flags, MlirStringCallback callback, void *userData)
Same as mlirOperationPrint but accepts flags controlling the printing behavior.
Definition: IR.cpp:677
MLIR_CAPI_EXPORTED MlirOpOperand mlirValueGetFirstUse(MlirValue value)
Returns an op operand representing the first use of the value, or a null op operand if there are no u...
Definition: IR.cpp:967
MLIR_CAPI_EXPORTED void mlirLocationPrint(MlirLocation location, MlirStringCallback callback, void *userData)
Prints a location by sending chunks of the string representation and forwarding userData tocallback`.
Definition: IR.cpp:290
MLIR_CAPI_EXPORTED bool mlirOperationVerify(MlirOperation op)
Verify the operation and return true if it passes, false if it fails.
Definition: IR.cpp:707
MLIR_CAPI_EXPORTED MlirOperation mlirModuleGetOperation(MlirModule module)
Views the module as a generic operation.
Definition: IR.cpp:326
MLIR_CAPI_EXPORTED bool mlirTypeEqual(MlirType t1, MlirType t2)
Checks if two types are equal.
Definition: IR.cpp:1032
MLIR_CAPI_EXPORTED MlirOperationState mlirOperationStateGet(MlirStringRef name, MlirLocation loc)
Constructs an operation state from a name and a location.
Definition: IR.cpp:338
MLIR_CAPI_EXPORTED unsigned mlirOpOperandGetOperandNumber(MlirOpOperand opOperand)
Returns the operand number of an op operand.
Definition: IR.cpp:995
MLIR_CAPI_EXPORTED MlirOperation mlirBlockGetTerminator(MlirBlock block)
Returns the terminator operation in the block or null if no terminator.
Definition: IR.cpp:828
MLIR_CAPI_EXPORTED MlirOperation mlirOperationGetNextInBlock(MlirOperation op)
Returns an operation immediately following the given operation it its enclosing block.
Definition: IR.cpp:555
MLIR_CAPI_EXPORTED MlirOperation mlirOperationGetParentOperation(MlirOperation op)
Gets the operation that owns this operation, returning null if the operation is not owned.
Definition: IR.cpp:527
MLIR_CAPI_EXPORTED MlirContext mlirModuleGetContext(MlirModule module)
Gets the context that a module was created with.
Definition: IR.cpp:312
MLIR_CAPI_EXPORTED MlirLocation mlirLocationFromAttribute(MlirAttribute attribute)
Creates a location from a location attribute.
Definition: IR.cpp:246
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsAssumeVerified(MlirOpPrintingFlags flags)
Do not verify the operation when using custom operation printers.
Definition: IR.cpp:217
MLIR_CAPI_EXPORTED MlirTypeID mlirTypeGetTypeID(MlirType type)
Gets the type ID of the type.
Definition: IR.cpp:1024
MLIR_CAPI_EXPORTED MlirStringRef mlirSymbolTableGetVisibilityAttributeName(void)
Returns the name of the attribute used to store symbol visibility.
Definition: IR.cpp:1115
static bool mlirDialectIsNull(MlirDialect dialect)
Checks if the dialect is null.
Definition: IR.h:173
MLIR_CAPI_EXPORTED void mlirBytecodeWriterConfigDestroy(MlirBytecodeWriterConfig config)
Destroys printing flags created with mlirBytecodeWriterConfigCreate.
Definition: IR.cpp:229
MLIR_CAPI_EXPORTED MlirValue mlirOperationGetOperand(MlirOperation op, intptr_t pos)
Returns pos-th operand of the operation.
Definition: IR.cpp:563
MLIR_CAPI_EXPORTED void mlirOperationStateAddAttributes(MlirOperationState *state, intptr_t n, MlirNamedAttribute const *attributes)
Definition: IR.cpp:379
MLIR_CAPI_EXPORTED MlirBlock mlirBlockGetNextInRegion(MlirBlock block)
Returns the block immediately following the given block in its parent region.
Definition: IR.cpp:817
MLIR_CAPI_EXPORTED MlirLocation mlirLocationCallSiteGet(MlirLocation callee, MlirLocation caller)
Creates a call site location with a callee and a caller.
Definition: IR.cpp:257
MLIR_CAPI_EXPORTED MlirOperation mlirOpResultGetOwner(MlirValue value)
Returns an operation that produced this value as its result.
Definition: IR.cpp:935
MLIR_CAPI_EXPORTED bool mlirValueIsAOpResult(MlirValue value)
Returns 1 if the value is an operation result, 0 otherwise.
Definition: IR.cpp:918
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumOperands(MlirOperation op)
Returns the number of operands of the operation.
Definition: IR.cpp:559
static bool mlirDialectRegistryIsNull(MlirDialectRegistry registry)
Checks if the dialect registry is null.
Definition: IR.h:235
MLIR_CAPI_EXPORTED void mlirOperationWalk(MlirOperation op, MlirOperationWalkCallback callback, void *userData, MlirWalkOrder walkOrder)
Walks operation op in walkOrder and calls callback on that operation.
Definition: IR.cpp:719
MLIR_CAPI_EXPORTED MlirContext mlirContextCreateWithThreading(bool threadingEnabled)
Creates an MLIR context with an explicit setting of the multithreading setting and transfers its owne...
Definition: IR.cpp:52
MLIR_CAPI_EXPORTED MlirOperation mlirBlockGetParentOperation(MlirBlock)
Returns the closest surrounding operation that contains this block.
Definition: IR.cpp:809
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumRegions(MlirOperation op)
Returns the number of regions attached to the given operation.
Definition: IR.cpp:531
MLIR_CAPI_EXPORTED MlirContext mlirLocationGetContext(MlirLocation location)
Gets the context that a location was created with.
Definition: IR.cpp:286
MLIR_CAPI_EXPORTED bool mlirOperationRemoveAttributeByName(MlirOperation op, MlirStringRef name)
Removes an attribute by name.
Definition: IR.cpp:667
MLIR_CAPI_EXPORTED void mlirAttributeDump(MlirAttribute attr)
Prints the attribute to the standard error stream.
Definition: IR.cpp:1080
MLIR_CAPI_EXPORTED MlirLogicalResult mlirSymbolTableReplaceAllSymbolUses(MlirStringRef oldSymbol, MlirStringRef newSymbol, MlirOperation from)
Attempt to replace all uses that are nested within the given operation of the given symbol 'oldSymbol...
Definition: IR.cpp:1144
MLIR_CAPI_EXPORTED MlirAttribute mlirAttributeParseGet(MlirContext context, MlirStringRef attr)
Parses an attribute. The attribute is owned by the context.
Definition: IR.cpp:1047
MLIR_CAPI_EXPORTED MlirModule mlirModuleCreateParse(MlirContext context, MlirStringRef module)
Parses a module from the string and transfers ownership to the caller.
Definition: IR.cpp:304
MLIR_CAPI_EXPORTED void mlirRegionAppendOwnedBlock(MlirRegion region, MlirBlock block)
Takes a block owned by the caller and appends it to the given region.
Definition: IR.cpp:750
MLIR_CAPI_EXPORTED MlirOperation mlirBlockGetFirstOperation(MlirBlock block)
Returns the first operation in the block.
Definition: IR.cpp:821
MLIR_CAPI_EXPORTED void mlirTypeDump(MlirType type)
Prints the type to the standard error stream.
Definition: IR.cpp:1041
MLIR_CAPI_EXPORTED MlirValue mlirOperationGetResult(MlirOperation op, intptr_t pos)
Returns pos-th result of the operation.
Definition: IR.cpp:582
MLIR_CAPI_EXPORTED MlirBytecodeWriterConfig mlirBytecodeWriterConfigCreate(void)
Creates new printing flags with defaults, intended for customization.
Definition: IR.cpp:225
MLIR_CAPI_EXPORTED MlirContext mlirAttributeGetContext(MlirAttribute attribute)
Gets the context that an attribute was created with.
Definition: IR.cpp:1051
MLIR_CAPI_EXPORTED MlirBlock mlirBlockArgumentGetOwner(MlirValue value)
Returns the block in which this value is defined as an argument.
Definition: IR.cpp:922
static bool mlirRegionIsNull(MlirRegion region)
Checks whether a region is null.
Definition: IR.h:736
MLIR_CAPI_EXPORTED void mlirOperationDestroy(MlirOperation op)
Takes an operation owned by the caller and destroys it.
Definition: IR.cpp:497
MLIR_CAPI_EXPORTED MlirRegion mlirOperationGetRegion(MlirOperation op, intptr_t pos)
Returns pos-th region attached to the operation.
Definition: IR.cpp:535
MLIR_CAPI_EXPORTED MlirDialect mlirTypeGetDialect(MlirType type)
Gets the dialect a type belongs to.
Definition: IR.cpp:1028
MLIR_CAPI_EXPORTED MlirIdentifier mlirIdentifierGet(MlirContext context, MlirStringRef str)
Gets an identifier with the given string value.
Definition: IR.cpp:1091
MLIR_CAPI_EXPORTED void mlirOperationSetSuccessor(MlirOperation op, intptr_t pos, MlirBlock block)
Set pos-th successor of the operation.
Definition: IR.cpp:643
MLIR_CAPI_EXPORTED void mlirContextLoadAllAvailableDialects(MlirContext context)
Eagerly loads all available dialects registered with a context, making them available for use for IR ...
Definition: IR.cpp:105
MLIR_CAPI_EXPORTED void mlirOperationStateAddOwnedRegions(MlirOperationState *state, intptr_t n, MlirRegion const *regions)
Definition: IR.cpp:371
MLIR_CAPI_EXPORTED void mlirOperationStateAddSuccessors(MlirOperationState *state, intptr_t n, MlirBlock const *successors)
Definition: IR.cpp:375
MLIR_CAPI_EXPORTED MlirBlock mlirModuleGetBody(MlirModule module)
Gets the body of the module, i.e. the only block it contains.
Definition: IR.cpp:316
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsDestroy(MlirOpPrintingFlags flags)
Destroys printing flags created with mlirOpPrintingFlagsCreate.
Definition: IR.cpp:195
MLIR_CAPI_EXPORTED MlirLocation mlirLocationNameGet(MlirContext context, MlirStringRef name, MlirLocation childLoc)
Creates a name location owned by the given context.
Definition: IR.cpp:269
MLIR_CAPI_EXPORTED void mlirContextEnableMultithreading(MlirContext context, bool enable)
Set threading mode (must be set to false to mlir-print-ir-after-all).
Definition: IR.cpp:101
MLIR_CAPI_EXPORTED void mlirBlockPrint(MlirBlock block, MlirStringCallback callback, void *userData)
Prints a block by sending chunks of the string representation and forwarding userData tocallback`.
Definition: IR.cpp:900
MLIR_CAPI_EXPORTED void mlirBytecodeWriterConfigDesiredEmitVersion(MlirBytecodeWriterConfig flags, int64_t version)
Sets the version to emit in the writer config.
Definition: IR.cpp:233
MLIR_CAPI_EXPORTED MlirStringRef mlirSymbolTableGetSymbolAttributeName(void)
Returns the name of the attribute used to store symbol names compatible with symbol tables.
Definition: IR.cpp:1111
MLIR_CAPI_EXPORTED MlirRegion mlirRegionCreate(void)
Creates a new empty region and transfers ownership to the caller.
Definition: IR.cpp:737
MLIR_CAPI_EXPORTED void mlirBlockDetach(MlirBlock block)
Detach a block from the owning region and assume ownership.
Definition: IR.cpp:877
MLIR_CAPI_EXPORTED void mlirOperationStateAddResults(MlirOperationState *state, intptr_t n, MlirType const *results)
Adds a list of components to the operation state.
Definition: IR.cpp:362
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsEnableDebugInfo(MlirOpPrintingFlags flags, bool enable, bool prettyForm)
Enable or disable printing of debug information (based on enable).
Definition: IR.cpp:204
MLIR_CAPI_EXPORTED MlirLocation mlirOperationGetLocation(MlirOperation op)
Gets the location of the operation.
Definition: IR.cpp:509
MLIR_CAPI_EXPORTED MlirTypeID mlirAttributeGetTypeID(MlirAttribute attribute)
Gets the type id of the attribute.
Definition: IR.cpp:1062
MLIR_CAPI_EXPORTED void mlirOperationSetOperand(MlirOperation op, intptr_t pos, MlirValue newValue)
Sets the pos-th operand of the operation.
Definition: IR.cpp:567
MLIR_CAPI_EXPORTED void mlirOperationDump(MlirOperation op)
Prints an operation to stderr.
Definition: IR.cpp:705
MLIR_CAPI_EXPORTED intptr_t mlirOpResultGetResultNumber(MlirValue value)
Returns the position of the value in the list of results of the operation that produced it.
Definition: IR.cpp:939
MLIR_CAPI_EXPORTED MlirOpPrintingFlags mlirOpPrintingFlagsCreate(void)
Creates new printing flags with defaults, intended for customization.
Definition: IR.cpp:191
MLIR_CAPI_EXPORTED MlirAsmState mlirAsmStateCreateForValue(MlirValue value, MlirOpPrintingFlags flags)
Creates new AsmState from value.
Definition: IR.cpp:167
MLIR_CAPI_EXPORTED MlirOperation mlirOperationCreate(MlirOperationState *state)
Creates an operation and transfers ownership to the caller.
Definition: IR.cpp:447
static bool mlirSymbolTableIsNull(MlirSymbolTable symbolTable)
Returns true if the symbol table is null.
Definition: IR.h:1066
MLIR_CAPI_EXPORTED bool mlirContextGetAllowUnregisteredDialects(MlirContext context)
Returns whether the context allows unregistered dialects.
Definition: IR.cpp:74
MLIR_CAPI_EXPORTED void mlirOperationMoveAfter(MlirOperation op, MlirOperation other)
Moves the given operation immediately after the other operation in its parent block.
Definition: IR.cpp:711
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumAttributes(MlirOperation op)
Returns the number of attributes attached to the operation.
Definition: IR.cpp:648
MLIR_CAPI_EXPORTED void mlirValuePrint(MlirValue value, MlirStringCallback callback, void *userData)
Prints a value by sending chunks of the string representation and forwarding userData tocallback`.
Definition: IR.cpp:954
MLIR_CAPI_EXPORTED MlirLogicalResult mlirOperationWriteBytecodeWithConfig(MlirOperation op, MlirBytecodeWriterConfig config, MlirStringCallback callback, void *userData)
Same as mlirOperationWriteBytecode but with writer config and returns failure only if desired bytecod...
Definition: IR.cpp:698
MLIR_CAPI_EXPORTED void mlirValueSetType(MlirValue value, MlirType type)
Set the type of the value.
Definition: IR.cpp:948
MLIR_CAPI_EXPORTED MlirType mlirValueGetType(MlirValue value)
Returns the type of the value.
Definition: IR.cpp:944
MLIR_CAPI_EXPORTED void mlirContextDestroy(MlirContext context)
Takes an MLIR context owned by the caller and destroys it.
Definition: IR.cpp:68
MLIR_CAPI_EXPORTED MlirOperation mlirOperationCreateParse(MlirContext context, MlirStringRef sourceStr, MlirStringRef sourceName)
Parses an operation, giving ownership to the caller.
Definition: IR.cpp:484
MLIR_CAPI_EXPORTED bool mlirAttributeEqual(MlirAttribute a1, MlirAttribute a2)
Checks if two attributes are equal.
Definition: IR.cpp:1070
static bool mlirOperationIsNull(MlirOperation op)
Checks whether the underlying operation is null.
Definition: IR.h:507
MLIR_CAPI_EXPORTED MlirBlock mlirRegionGetFirstBlock(MlirRegion region)
Gets the first block in the region.
Definition: IR.cpp:743
static MlirStringRef mlirStringRefCreate(const char *str, size_t length)
Constructs a string reference from the pointer and length.
Definition: Support.h:82
static MlirLogicalResult mlirLogicalResultFailure(void)
Creates a logical result representing a failure.
Definition: Support.h:138
MLIR_CAPI_EXPORTED size_t mlirTypeIDHashValue(MlirTypeID typeID)
Returns the hash value of the type id.
Definition: Support.cpp:51
static MlirLogicalResult mlirLogicalResultSuccess(void)
Creates a logical result representing a success.
Definition: Support.h:132
static bool mlirLogicalResultIsFailure(MlirLogicalResult res)
Checks if the given logical result represents a failure.
Definition: Support.h:127
static bool mlirTypeIDIsNull(MlirTypeID typeID)
Checks whether a type id is null.
Definition: Support.h:163
MLIR_CAPI_EXPORTED bool mlirTypeIDEqual(MlirTypeID typeID1, MlirTypeID typeID2)
Checks if two type ids are equal.
Definition: Support.cpp:47
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:285
llvm::hash_code hash_value(const MPInt &x)
Redeclarations of friend declaration above to make it discoverable by lookups.
Definition: MPInt.cpp:17
PyObjectRef< PyMlirContext > PyMlirContextRef
Wrapper around MlirContext.
Definition: IRModule.h:161
PyObjectRef< PyModule > PyModuleRef
Definition: IRModule.h:522
void populateIRCore(pybind11::module &m)
PyObjectRef< PyOperation > PyOperationRef
Definition: IRModule.h:601
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Definition: Query.cpp:19
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:421
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
MlirAttribute attribute
Definition: IR.h:78
MlirIdentifier name
Definition: IR.h:77
An auxiliary class for constructing operations.
Definition: IR.h:340
A pointer to a sized fragment of a string, not necessarily null-terminated.
Definition: Support.h:73
const char * data
Pointer to the first symbol.
Definition: Support.h:74
size_t length
Length of the fragment.
Definition: Support.h:75
static bool dunderContains(const std::string &attributeKind)
Definition: IRCore.cpp:248
static void dundeSetItemNamed(const std::string &attributeKind, py::function func, bool replace)
Definition: IRCore.cpp:257
static py::function dundeGetItemNamed(const std::string &attributeKind)
Definition: IRCore.cpp:251
static void bind(py::module &m)
Definition: IRCore.cpp:263
Wrapper for the global LLVM debugging flag.
Definition: IRCore.cpp:234
static void bind(py::module &m)
Definition: IRCore.cpp:239
static bool get(const py::object &)
Definition: IRCore.cpp:237
static void set(py::object &o, bool enable)
Definition: IRCore.cpp:235
Accumulates into a python string from a method that accepts an MlirStringCallback.
Definition: PybindUtils.h:102
pybind11::list parts
Definition: PybindUtils.h:103
pybind11::str join()
Definition: PybindUtils.h:117
MlirStringCallback getCallback()
Definition: PybindUtils.h:107
Custom exception that allows access to error diagnostic information.
Definition: IRModule.h:1271
std::vector< PyDiagnostic::DiagnosticInfo > errorDiagnostics
Definition: IRModule.h:1276
Materialized diagnostic information.
Definition: IRModule.h:353
RAII object that captures any error diagnostics emitted to the provided context.
Definition: IRModule.h:419
std::vector< PyDiagnostic::DiagnosticInfo > take()
Definition: IRModule.h:429
ErrorCapture(PyMlirContextRef ctx)
Definition: IRModule.h:420