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