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