20 #include "nanobind/nanobind.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/ADT/SmallVector.h"
27 using namespace nb::literals;
32 using llvm::StringRef;
40 R
"(Parses the assembly form of a type.
42 Returns a Type object or raises an MLIRError if the type cannot be parsed.
44 See also: https://mlir.llvm.org/docs/LangRef/#type-system
48 R
"(Gets a Location representing a caller and callsite)";
51 R
"(Gets a Location representing a file, line and column)";
54 R
"(Gets a Location representing a file, line and column range)";
57 R
"(Gets a Location representing a fused location with optional metadata)";
60 R
"(Gets a Location representing a named location with optional child location)";
63 R
"(Parses a module's assembly format from a string.
65 Returns a new MlirModule or raises an MLIRError if the parsing fails.
67 See also: https://mlir.llvm.org/docs/LangRef/
71 R
"(Creates a Module from a MlirModule wrapped by a capsule (i.e. module._CAPIPtr).
72 Note this returns a new object BUT _clear_mlir_module(module) must be called to
73 prevent double-frees (of the underlying mlir::Module).
77 R
"(Creates a new operation.
80 name: Operation name (e.g. "dialect.operation").
81 results: Sequence of Type representing op result types.
82 attributes: Dict of str:Attribute.
83 successors: List of Block for the operation's successors.
84 regions: Number of regions to create.
85 location: A Location object (defaults to resolve from context manager).
86 ip: An InsertionPoint (defaults to resolve from context manager or set to
87 False to disable insertion, even with an insertion point set in the
89 infer_type: Whether to infer result types.
91 A new "detached" Operation object. Detached operations can be added
92 to blocks, which causes them to become "attached."
96 R
"(Prints the assembly form of the operation to a file like object.
99 file: The file like object to write to. Defaults to sys.stdout.
100 binary: Whether to write bytes (True) or str (False). Defaults to False.
101 large_elements_limit: Whether to elide elements attributes above this
102 number of elements. Defaults to None (no limit).
103 large_resource_limit: Whether to elide resource attributes above this
104 number of characters. Defaults to None (no limit). If large_elements_limit
105 is set and this is None, the behavior will be to use large_elements_limit
106 as large_resource_limit.
107 enable_debug_info: Whether to print debug/location information. Defaults
109 pretty_debug_info: Whether to format debug information for easier reading
110 by a human (warning: the result is unparseable).
111 print_generic_op_form: Whether to print the generic assembly forms of all
112 ops. Defaults to False.
113 use_local_Scope: Whether to print in a way that is more optimized for
114 multi-threaded access but may not be consistent with how the overall
116 assume_verified: By default, if not printing generic form, the verifier
117 will be run and if it fails, generic form will be printed with a comment
118 about failed verification. While a reasonable default for interactive use,
119 for systematic use, it is often better for the caller to verify explicitly
120 and report failures in a more robust fashion. Set this to True if doing this
121 in order to avoid running a redundant verification. If the IR is actually
122 invalid, behavior is undefined.
123 skip_regions: Whether to skip printing regions. Defaults to False.
127 R
"(Prints the assembly form of the operation to a file like object.
130 file: The file like object to write to. Defaults to sys.stdout.
131 binary: Whether to write bytes (True) or str (False). Defaults to False.
132 state: AsmState capturing the operation numbering and flags.
136 R
"(Gets the assembly form of the operation with all options available.
139 binary: Whether to return a bytes (True) or str (False) object. Defaults to
141 ... others ...: See the print() method for common keyword arguments for
142 configuring the printout.
144 Either a bytes or str object, depending on the setting of the 'binary'
149 R
"(Write the bytecode form of the operation to a file like object.
152 file: The file like object to write to.
153 desired_version: The version of bytecode to emit.
155 The bytecode writer status.
159 R
"(Gets the assembly form of the operation with default options.
161 If more advanced control over the assembly formatting or I/O options is needed,
162 use the dedicated print or get_asm method, which supports keyword arguments to
167 R
"(Dumps a debug representation of the object to stderr.)";
170 R
"(Appends a new block, with argument types as positional args.
177 R
"(Returns the string form of the value.
179 If the value is a block argument, this is the assembly form of its type and the
180 position in the argument list. If the value is an operation result, this is
181 equivalent to printing the operation that produced it.
185 R
"(Returns the string form of value as an operand (i.e., the ValueID).
189 R
"(Replace all uses of value with the new value, updating anything in
190 the IR that uses 'self' to use the other value instead.
194 R
"("Replace all uses of this value with the 'with' value, except for those
195 in 'exceptions'. 'exceptions' can be either a single operation or a list of
204 template <
class Func,
typename... Args>
206 nb::object cf = nb::cpp_function(f, args...);
207 return nb::borrow<nb::object>((PyClassMethod_New(cf.ptr())));
212 nb::object dialectDescriptor) {
213 auto dialectClass =
PyGlobals::get().lookupDialectClass(dialectNamespace);
216 return nb::cast(
PyDialect(std::move(dialectDescriptor)));
220 return (*dialectClass)(std::move(dialectDescriptor));
238 const std::optional<nb::sequence> &pyArgLocs) {
240 argTypes.reserve(nb::len(pyArgTypes));
241 for (
const auto &pyType : pyArgTypes)
242 argTypes.push_back(nb::cast<PyType &>(pyType));
246 argLocs.reserve(nb::len(*pyArgLocs));
247 for (
const auto &pyLoc : *pyArgLocs)
248 argLocs.push_back(nb::cast<PyLocation &>(pyLoc));
249 }
else if (!argTypes.empty()) {
250 argLocs.assign(argTypes.size(), DefaultingPyLocation::resolve());
253 if (argTypes.size() != argLocs.size())
254 throw nb::value_error((
"Expected " + Twine(argTypes.size()) +
255 " locations, got: " + Twine(argLocs.size()))
258 return mlirBlockCreate(argTypes.size(), argTypes.data(), argLocs.data());
263 static void set(nb::object &o,
bool enable) {
264 nb::ft_lock_guard lock(mutex);
268 static bool get(
const nb::object &) {
269 nb::ft_lock_guard lock(mutex);
273 static void bind(nb::module_ &m) {
275 nb::class_<PyGlobalDebugFlag>(m,
"_GlobalDebug")
280 [](
const std::string &type) {
281 nb::ft_lock_guard lock(mutex);
284 "types"_a,
"Sets specific debug types to be produced by LLVM")
285 .def_static(
"set_types", [](
const std::vector<std::string> &types) {
286 std::vector<const char *> pointers;
287 pointers.reserve(types.size());
288 for (
const std::string &str : types)
289 pointers.push_back(str.c_str());
290 nb::ft_lock_guard lock(mutex);
296 static nb::ft_mutex mutex;
299 nb::ft_mutex PyGlobalDebugFlag::mutex;
303 return PyGlobals::get().lookupAttributeBuilder(attributeKind).has_value();
306 auto builder =
PyGlobals::get().lookupAttributeBuilder(attributeKind);
308 throw nb::key_error(attributeKind.c_str());
312 nb::callable func,
bool replace) {
313 PyGlobals::get().registerAttributeBuilder(attributeKind, std::move(func),
317 static void bind(nb::module_ &m) {
318 nb::class_<PyAttrBuilderMap>(m,
"AttrBuilder")
322 "attribute_kind"_a,
"attr_builder"_a,
"replace"_a =
false,
323 "Register an attribute builder for building MLIR "
324 "attributes from python values.");
332 nb::object PyBlock::getCapsule() {
342 class PyRegionIterator {
345 : operation(std::move(operation)) {}
347 PyRegionIterator &dunderIter() {
return *
this; }
352 throw nb::stop_iteration();
358 static void bind(nb::module_ &m) {
359 nb::class_<PyRegionIterator>(m,
"RegionIterator")
360 .def(
"__iter__", &PyRegionIterator::dunderIter)
361 .def(
"__next__", &PyRegionIterator::dunderNext);
371 class PyRegionList :
public Sliceable<PyRegionList, PyRegion> {
373 static constexpr
const char *pyClassName =
"RegionSequence";
376 intptr_t length = -1, intptr_t step = 1)
381 operation(std::move(operation)) {}
383 PyRegionIterator dunderIter() {
385 return PyRegionIterator(operation);
388 static void bindDerived(ClassTy &c) {
389 c.def(
"__iter__", &PyRegionList::dunderIter);
396 intptr_t getRawNumElements() {
401 PyRegion getRawElement(intptr_t pos) {
406 PyRegionList slice(intptr_t startIndex, intptr_t length, intptr_t step) {
407 return PyRegionList(operation, startIndex, length, step);
413 class PyBlockIterator {
416 : operation(std::move(operation)), next(next) {}
418 PyBlockIterator &dunderIter() {
return *
this; }
423 throw nb::stop_iteration();
426 PyBlock returnBlock(operation, next);
431 static void bind(nb::module_ &m) {
432 nb::class_<PyBlockIterator>(m,
"BlockIterator")
433 .def(
"__iter__", &PyBlockIterator::dunderIter)
434 .def(
"__next__", &PyBlockIterator::dunderNext);
448 : operation(std::move(operation)), region(region) {}
450 PyBlockIterator dunderIter() {
455 intptr_t dunderLen() {
456 operation->checkValid();
466 PyBlock dunderGetItem(intptr_t index) {
469 index += dunderLen();
472 throw nb::index_error(
"attempt to access out of bounds block");
477 return PyBlock(operation, block);
482 throw nb::index_error(
"attempt to access out of bounds block");
485 PyBlock appendBlock(
const nb::args &pyArgTypes,
486 const std::optional<nb::sequence> &pyArgLocs) {
489 createBlock(nb::cast<nb::sequence>(pyArgTypes), pyArgLocs);
491 return PyBlock(operation, block);
494 static void bind(nb::module_ &m) {
495 nb::class_<PyBlockList>(m,
"BlockList")
496 .def(
"__getitem__", &PyBlockList::dunderGetItem)
497 .def(
"__iter__", &PyBlockList::dunderIter)
498 .def(
"__len__", &PyBlockList::dunderLen)
500 nb::arg(
"args"), nb::kw_only(),
501 nb::arg(
"arg_locs") = std::nullopt);
509 class PyOperationIterator {
511 PyOperationIterator(
PyOperationRef parentOperation, MlirOperation next)
512 : parentOperation(std::move(parentOperation)), next(next) {}
514 PyOperationIterator &dunderIter() {
return *
this; }
516 nb::typed<nb::object, PyOpView> dunderNext() {
519 throw nb::stop_iteration();
523 PyOperation::forOperation(parentOperation->getContext(), next);
528 static void bind(nb::module_ &m) {
529 nb::class_<PyOperationIterator>(m,
"OperationIterator")
530 .def(
"__iter__", &PyOperationIterator::dunderIter)
531 .def(
"__next__", &PyOperationIterator::dunderNext);
543 class PyOperationList {
546 : parentOperation(std::move(parentOperation)), block(block) {}
548 PyOperationIterator dunderIter() {
550 return PyOperationIterator(parentOperation,
554 intptr_t dunderLen() {
555 parentOperation->checkValid();
565 nb::typed<nb::object, PyOpView> dunderGetItem(intptr_t index) {
566 parentOperation->checkValid();
568 index += dunderLen();
571 throw nb::index_error(
"attempt to access out of bounds operation");
576 return PyOperation::forOperation(parentOperation->getContext(), childOp)
582 throw nb::index_error(
"attempt to access out of bounds operation");
585 static void bind(nb::module_ &m) {
586 nb::class_<PyOperationList>(m,
"OperationList")
587 .def(
"__getitem__", &PyOperationList::dunderGetItem)
588 .def(
"__iter__", &PyOperationList::dunderIter)
589 .def(
"__len__", &PyOperationList::dunderLen);
599 PyOpOperand(MlirOpOperand opOperand) : opOperand(opOperand) {}
605 return PyOperation::forOperation(context, owner)->createOpView();
610 static void bind(nb::module_ &m) {
611 nb::class_<PyOpOperand>(m,
"OpOperand")
612 .def_prop_ro(
"owner", &PyOpOperand::getOwner)
613 .def_prop_ro(
"operand_number", &PyOpOperand::getOperandNumber);
617 MlirOpOperand opOperand;
620 class PyOpOperandIterator {
622 PyOpOperandIterator(MlirOpOperand opOperand) : opOperand(opOperand) {}
624 PyOpOperandIterator &dunderIter() {
return *
this; }
626 PyOpOperand dunderNext() {
628 throw nb::stop_iteration();
630 PyOpOperand returnOpOperand(opOperand);
632 return returnOpOperand;
635 static void bind(nb::module_ &m) {
636 nb::class_<PyOpOperandIterator>(m,
"OpOperandIterator")
637 .def(
"__iter__", &PyOpOperandIterator::dunderIter)
638 .def(
"__next__", &PyOpOperandIterator::dunderNext);
642 MlirOpOperand opOperand;
651 PyMlirContext::PyMlirContext(MlirContext context) : context(context) {
652 nb::gil_scoped_acquire acquire;
653 nb::ft_lock_guard lock(live_contexts_mutex);
654 auto &liveContexts = getLiveContexts();
655 liveContexts[context.ptr] =
this;
662 nb::gil_scoped_acquire acquire;
664 nb::ft_lock_guard lock(live_contexts_mutex);
665 getLiveContexts().erase(context.ptr);
677 throw nb::python_error();
682 nb::gil_scoped_acquire acquire;
683 nb::ft_lock_guard lock(live_contexts_mutex);
684 auto &liveContexts = getLiveContexts();
685 auto it = liveContexts.find(context.ptr);
686 if (it == liveContexts.end()) {
689 nb::object pyRef = nb::cast(unownedContextWrapper);
690 assert(pyRef &&
"cast to nb::object failed");
691 liveContexts[context.ptr] = unownedContextWrapper;
695 nb::object pyRef = nb::cast(it->second);
699 nb::ft_mutex PyMlirContext::live_contexts_mutex;
702 static LiveContextMap liveContexts;
707 nb::ft_lock_guard lock(live_contexts_mutex);
708 return getLiveContexts().size();
716 const nb::object &excVal,
717 const nb::object &excTb) {
726 nb::object pyHandlerObject =
727 nb::cast(pyHandler, nb::rv_policy::take_ownership);
728 (void)pyHandlerObject.inc_ref();
732 auto handlerCallback =
735 nb::object pyDiagnosticObject =
736 nb::cast(pyDiagnostic, nb::rv_policy::take_ownership);
743 nb::gil_scoped_acquire gil;
745 result = nb::cast<bool>(pyHandler->callback(pyDiagnostic));
746 }
catch (std::exception &e) {
747 fprintf(stderr,
"MLIR Python Diagnostic handler raised exception: %s\n",
749 pyHandler->hadError =
true;
756 auto deleteCallback = +[](
void *userData) {
758 assert(pyHandler->registeredID &&
"handler is not registered");
759 pyHandler->registeredID.reset();
762 nb::object pyHandlerObject = nb::cast(pyHandler, nb::rv_policy::reference);
763 pyHandlerObject.dec_ref();
767 get(), handlerCallback,
static_cast<void *
>(pyHandler), deleteCallback);
768 return pyHandlerObject;
775 if (self->ctx->emitErrorDiagnostics)
788 throw std::runtime_error(
789 "An MLIR function requires a Context but none was provided in the call "
790 "or from the surrounding environment. Either pass to the function with "
791 "a 'context=' argument or establish a default using 'with Context():'");
801 static thread_local std::vector<PyThreadContextEntry> stack;
806 auto &stack = getStack();
809 return &stack.back();
812 void PyThreadContextEntry::push(FrameKind frameKind, nb::object context,
813 nb::object insertionPoint,
814 nb::object location) {
815 auto &stack = getStack();
816 stack.emplace_back(frameKind, std::move(context), std::move(insertionPoint),
817 std::move(location));
821 if (stack.size() > 1) {
822 auto &prev = *(stack.rbegin() + 1);
823 auto ¤t = stack.back();
824 if (current.context.is(prev.context)) {
826 if (!current.insertionPoint)
827 current.insertionPoint = prev.insertionPoint;
828 if (!current.location)
829 current.location = prev.location;
837 return nb::cast<PyMlirContext *>(context);
843 return nb::cast<PyInsertionPoint *>(insertionPoint);
849 return nb::cast<PyLocation *>(location);
853 auto *tos = getTopOfStack();
854 return tos ? tos->getContext() :
nullptr;
858 auto *tos = getTopOfStack();
859 return tos ? tos->getInsertionPoint() :
nullptr;
863 auto *tos = getTopOfStack();
864 return tos ? tos->getLocation() :
nullptr;
868 push(FrameKind::Context, context,
875 auto &stack = getStack();
877 throw std::runtime_error(
"Unbalanced Context enter/exit");
878 auto &tos = stack.back();
879 if (tos.frameKind != FrameKind::Context && tos.getContext() != &context)
880 throw std::runtime_error(
"Unbalanced Context enter/exit");
887 nb::cast<PyInsertionPoint &>(insertionPointObj);
888 nb::object contextObj =
890 push(FrameKind::InsertionPoint,
894 return insertionPointObj;
898 auto &stack = getStack();
900 throw std::runtime_error(
"Unbalanced InsertionPoint enter/exit");
901 auto &tos = stack.back();
902 if (tos.frameKind != FrameKind::InsertionPoint &&
903 tos.getInsertionPoint() != &insertionPoint)
904 throw std::runtime_error(
"Unbalanced InsertionPoint enter/exit");
909 PyLocation &location = nb::cast<PyLocation &>(locationObj);
911 push(FrameKind::Location, contextObj,
918 auto &stack = getStack();
920 throw std::runtime_error(
"Unbalanced Location enter/exit");
921 auto &tos = stack.back();
922 if (tos.frameKind != FrameKind::Location && tos.getLocation() != &location)
923 throw std::runtime_error(
"Unbalanced Location enter/exit");
933 if (materializedNotes) {
934 for (nb::handle noteObject : *materializedNotes) {
935 PyDiagnostic *note = nb::cast<PyDiagnostic *>(noteObject);
943 : context(context), callback(std::move(callback)) {}
952 assert(!registeredID &&
"should have unregistered");
958 void PyDiagnostic::checkValid() {
960 throw std::invalid_argument(
961 "Diagnostic is invalid (used outside of callback)");
979 nb::object fileObject = nb::module_::import_(
"io").attr(
"StringIO")();
982 return nb::cast<nb::str>(fileObject.attr(
"getvalue")());
987 if (materializedNotes)
988 return *materializedNotes;
990 nb::tuple notes = nb::steal<nb::tuple>(PyTuple_New(numNotes));
991 for (intptr_t i = 0; i < numNotes; ++i) {
993 nb::object diagnostic = nb::cast(
PyDiagnostic(noteDiag));
994 PyTuple_SET_ITEM(notes.ptr(), i, diagnostic.release().ptr());
996 materializedNotes = std::move(notes);
998 return *materializedNotes;
1002 std::vector<DiagnosticInfo> notes;
1004 notes.emplace_back(nb::cast<PyDiagnostic>(n).
getInfo());
1016 {key.data(), key.size()});
1018 std::string msg = (Twine(
"Dialect '") + key +
"' not found").str();
1020 throw nb::attribute_error(msg.c_str());
1021 throw nb::index_error(msg.c_str());
1031 MlirDialectRegistry rawRegistry =
1034 throw nb::python_error();
1049 throw nb::python_error();
1059 const nb::object &excVal,
1060 const nb::object &excTb) {
1067 throw std::runtime_error(
1068 "An MLIR function requires a Location but none was provided in the "
1069 "call or from the surrounding environment. Either pass to the function "
1070 "with a 'loc=' argument or establish a default using 'with loc:'");
1083 nb::gil_scoped_acquire acquire;
1084 auto &liveModules =
getContext()->liveModules;
1085 assert(liveModules.count(module.ptr) == 1 &&
1086 "destroying module not in live map");
1087 liveModules.erase(module.ptr);
1095 nb::gil_scoped_acquire acquire;
1096 auto &liveModules = contextRef->liveModules;
1097 auto it = liveModules.find(module.ptr);
1098 if (it == liveModules.end()) {
1104 nb::object pyRef = nb::cast(unownedModule, nb::rv_policy::take_ownership);
1105 unownedModule->handle = pyRef;
1106 liveModules[module.ptr] =
1107 std::make_pair(unownedModule->handle, unownedModule);
1108 return PyModuleRef(unownedModule, std::move(pyRef));
1111 PyModule *existing = it->second.second;
1112 nb::object pyRef = nb::borrow<nb::object>(it->second.first);
1119 throw nb::python_error();
1151 template <
typename T,
class... Args>
1153 nb::handle type = nb::type<T>();
1154 nb::object instance = nb::inst_alloc(type);
1155 T *ptr = nb::inst_ptr<T>(instance);
1156 new (ptr) T(std::forward<Args>(args)...);
1157 nb::inst_mark_ready(instance);
1164 MlirOperation operation,
1165 nb::object parentKeepAlive) {
1168 makeObjectRef<PyOperation>(std::move(contextRef), operation);
1169 unownedOperation->handle = unownedOperation.
getObject();
1170 if (parentKeepAlive) {
1171 unownedOperation->parentKeepAlive = std::move(parentKeepAlive);
1173 return unownedOperation;
1177 MlirOperation operation,
1178 nb::object parentKeepAlive) {
1179 return createInstance(std::move(contextRef), operation,
1180 std::move(parentKeepAlive));
1184 MlirOperation operation,
1185 nb::object parentKeepAlive) {
1186 PyOperationRef created = createInstance(std::move(contextRef), operation,
1187 std::move(parentKeepAlive));
1188 created->attached =
false;
1193 const std::string &sourceStr,
1194 const std::string &sourceName) {
1200 throw MLIRError(
"Unable to parse operation assembly", errors.
take());
1206 throw std::runtime_error(
"the operation has been invalidated");
1211 std::optional<int64_t> largeResourceLimit,
1212 bool enableDebugInfo,
bool prettyDebugInfo,
1213 bool printGenericOpForm,
bool useLocalScope,
1214 bool useNameLocAsPrefix,
bool assumeVerified,
1215 nb::object fileObject,
bool binary,
1219 if (fileObject.is_none())
1220 fileObject = nb::module_::import_(
"sys").attr(
"stdout");
1223 if (largeElementsLimit)
1225 if (largeResourceLimit)
1227 if (enableDebugInfo)
1230 if (printGenericOpForm)
1238 if (useNameLocAsPrefix)
1243 accum.getUserData());
1251 if (fileObject.is_none())
1252 fileObject = nb::module_::import_(
"sys").attr(
"stdout");
1255 accum.getUserData());
1259 std::optional<int64_t> bytecodeVersion) {
1264 if (!bytecodeVersion.has_value())
1274 throw nb::value_error((Twine(
"Unable to honor desired bytecode version ") +
1275 Twine(*bytecodeVersion))
1288 std::string exceptionWhat;
1289 nb::object exceptionType;
1291 UserData userData{callback,
false, {}, {}};
1294 UserData *calleeUserData =
static_cast<UserData *
>(userData);
1296 return (calleeUserData->callback)(op);
1297 }
catch (nb::python_error &e) {
1298 calleeUserData->gotException =
true;
1299 calleeUserData->exceptionWhat = std::string(e.what());
1300 calleeUserData->exceptionType = nb::borrow(e.type());
1305 if (userData.gotException) {
1306 std::string message(
"Exception raised in callback: ");
1307 message.append(userData.exceptionWhat);
1308 throw std::runtime_error(message);
1313 std::optional<int64_t> largeElementsLimit,
1314 std::optional<int64_t> largeResourceLimit,
1315 bool enableDebugInfo,
bool prettyDebugInfo,
1316 bool printGenericOpForm,
bool useLocalScope,
1317 bool useNameLocAsPrefix,
bool assumeVerified,
1319 nb::object fileObject;
1321 fileObject = nb::module_::import_(
"io").attr(
"BytesIO")();
1323 fileObject = nb::module_::import_(
"io").attr(
"StringIO")();
1325 print(largeElementsLimit,
1337 return fileObject.attr(
"getvalue")();
1346 operation.parentKeepAlive = otherOp.parentKeepAlive;
1355 operation.parentKeepAlive = otherOp.parentKeepAlive;
1377 throw nb::value_error(
"Detached operations have no parent");
1388 assert(!
mlirBlockIsNull(block) &&
"Attached operation has null parent");
1389 assert(parentOperation &&
"Operation has no parent");
1390 return PyBlock{std::move(*parentOperation), block};
1401 throw nb::python_error();
1408 const nb::object &maybeIp) {
1410 if (!maybeIp.is(nb::cast(
false))) {
1412 if (maybeIp.is_none()) {
1415 ip = nb::cast<PyInsertionPoint *>(maybeIp);
1423 std::optional<std::vector<PyType *>> results,
1425 std::optional<nb::dict> attributes,
1426 std::optional<std::vector<PyBlock *>> successors,
1428 const nb::object &maybeIp,
bool inferType) {
1435 throw nb::value_error(
"number of regions must be >= 0");
1439 mlirResults.reserve(results->size());
1440 for (
PyType *result : *results) {
1443 throw nb::value_error(
"result type cannot be None");
1444 mlirResults.push_back(*result);
1449 mlirAttributes.reserve(attributes->size());
1450 for (std::pair<nb::handle, nb::handle> it : *attributes) {
1453 key = nb::cast<std::string>(it.first);
1454 }
catch (nb::cast_error &err) {
1455 std::string msg =
"Invalid attribute key (not a string) when "
1456 "attempting to create the operation \"" +
1457 std::string(name) +
"\" (" + err.what() +
")";
1458 throw nb::type_error(msg.c_str());
1461 auto &attribute = nb::cast<PyAttribute &>(it.second);
1463 mlirAttributes.emplace_back(std::move(key), attribute);
1464 }
catch (nb::cast_error &err) {
1465 std::string msg =
"Invalid attribute value for the key \"" + key +
1466 "\" when attempting to create the operation \"" +
1467 std::string(name) +
"\" (" + err.what() +
")";
1468 throw nb::type_error(msg.c_str());
1469 }
catch (std::runtime_error &) {
1472 "Found an invalid (`None`?) attribute value for the key \"" + key +
1473 "\" when attempting to create the operation \"" +
1474 std::string(name) +
"\"";
1475 throw std::runtime_error(msg);
1481 mlirSuccessors.reserve(successors->size());
1482 for (
auto *successor : *successors) {
1485 throw nb::value_error(
"successor block cannot be None");
1486 mlirSuccessors.push_back(successor->get());
1494 if (!operands.empty())
1496 state.enableResultTypeInference = inferType;
1497 if (!mlirResults.empty())
1499 mlirResults.data());
1500 if (!mlirAttributes.empty()) {
1505 mlirNamedAttributes.reserve(mlirAttributes.size());
1506 for (
auto &it : mlirAttributes)
1512 mlirNamedAttributes.data());
1514 if (!mlirSuccessors.empty())
1516 mlirSuccessors.data());
1519 mlirRegions.resize(regions);
1520 for (
int i = 0; i < regions; ++i)
1523 mlirRegions.data());
1529 throw nb::value_error(
"Operation creation failed");
1567 template <
typename DerivedTy>
1568 class PyConcreteValue :
public PyValue {
1574 using ClassTy = nb::class_<DerivedTy, PyValue>;
1575 using IsAFunctionTy = bool (*)(MlirValue);
1577 PyConcreteValue() =
default;
1579 :
PyValue(operationRef, value) {}
1580 PyConcreteValue(
PyValue &orig)
1581 : PyConcreteValue(orig.getParentOperation(), castFrom(orig)) {}
1585 static MlirValue castFrom(
PyValue &orig) {
1586 if (!DerivedTy::isaFunction(orig.
get())) {
1587 auto origRepr = nb::cast<std::string>(nb::repr(nb::cast(orig)));
1588 throw nb::value_error((Twine(
"Cannot cast value to ") +
1589 DerivedTy::pyClassName +
" (from " + origRepr +
1598 static void bind(nb::module_ &m) {
1599 auto cls = ClassTy(m, DerivedTy::pyClassName);
1600 cls.def(nb::init<PyValue &>(), nb::keep_alive<0, 1>(), nb::arg(
"value"));
1603 [](
PyValue &otherValue) ->
bool {
1604 return DerivedTy::isaFunction(otherValue);
1606 nb::arg(
"other_value"));
1608 [](
DerivedTy &
self) -> nb::typed<nb::object, DerivedTy> {
1609 return self.maybeDownCast();
1611 DerivedTy::bindDerived(cls);
1615 static void bindDerived(ClassTy &m) {}
1624 static constexpr
const char *pyClassName =
"OpResult";
1625 using PyConcreteValue::PyConcreteValue;
1629 "owner", [](
PyOpResult &
self) -> nb::typed<nb::object, PyOperation> {
1632 "expected the owner of the value in Python to match that in "
1634 return self.getParentOperation().getObject();
1636 c.def_prop_ro(
"result_number", [](
PyOpResult &
self) {
1643 template <
typename Container>
1644 static std::vector<nb::typed<nb::object, PyType>>
1646 std::vector<nb::typed<nb::object, PyType>> result;
1647 result.reserve(container.size());
1648 for (
int i = 0, e = container.size(); i < e; ++i) {
1662 static constexpr
const char *pyClassName =
"OpResultList";
1666 intptr_t length = -1, intptr_t step = 1)
1671 operation(std::move(operation)) {}
1677 c.def_prop_ro(
"owner",
1679 return self.operation->createOpView();
1689 intptr_t getRawNumElements() {
1699 PyOpResultList slice(intptr_t startIndex, intptr_t length, intptr_t step) {
1711 const nb::object &resultSegmentSpecObj,
1712 std::vector<int32_t> &resultSegmentLengths,
1713 std::vector<PyType *> &resultTypes) {
1714 resultTypes.reserve(resultTypeList.size());
1715 if (resultSegmentSpecObj.is_none()) {
1719 resultTypes.push_back(nb::cast<PyType *>(it.value()));
1720 if (!resultTypes.back())
1721 throw nb::cast_error();
1722 }
catch (nb::cast_error &err) {
1723 throw nb::value_error((llvm::Twine(
"Result ") +
1724 llvm::Twine(it.index()) +
" of operation \"" +
1725 name +
"\" must be a Type (" + err.what() +
")")
1732 auto resultSegmentSpec = nb::cast<std::vector<int>>(resultSegmentSpecObj);
1733 if (resultSegmentSpec.size() != resultTypeList.size()) {
1734 throw nb::value_error((llvm::Twine(
"Operation \"") + name +
1736 llvm::Twine(resultSegmentSpec.size()) +
1737 " result segments but was provided " +
1738 llvm::Twine(resultTypeList.size()))
1742 resultSegmentLengths.reserve(resultTypeList.size());
1743 for (
const auto &it :
1745 int segmentSpec = std::get<1>(it.value());
1746 if (segmentSpec == 1 || segmentSpec == 0) {
1749 auto *resultType = nb::cast<PyType *>(std::get<0>(it.value()));
1751 resultTypes.push_back(resultType);
1752 resultSegmentLengths.push_back(1);
1753 }
else if (segmentSpec == 0) {
1755 resultSegmentLengths.push_back(0);
1757 throw nb::value_error(
1758 (llvm::Twine(
"Result ") + llvm::Twine(it.index()) +
1759 " of operation \"" + name +
1760 "\" must be a Type (was None and result is not optional)")
1764 }
catch (nb::cast_error &err) {
1765 throw nb::value_error((llvm::Twine(
"Result ") +
1766 llvm::Twine(it.index()) +
" of operation \"" +
1767 name +
"\" must be a Type (" + err.what() +
1772 }
else if (segmentSpec == -1) {
1775 if (std::get<0>(it.value()).is_none()) {
1777 resultSegmentLengths.push_back(0);
1780 auto segment = nb::cast<nb::sequence>(std::get<0>(it.value()));
1781 for (nb::handle segmentItem : segment) {
1782 resultTypes.push_back(nb::cast<PyType *>(segmentItem));
1783 if (!resultTypes.back()) {
1784 throw nb::type_error(
"contained a None item");
1787 resultSegmentLengths.push_back(nb::len(segment));
1789 }
catch (std::exception &err) {
1793 throw nb::value_error((llvm::Twine(
"Result ") +
1794 llvm::Twine(it.index()) +
" of operation \"" +
1795 name +
"\" must be a Sequence of Types (" +
1801 throw nb::value_error(
"Unexpected segment spec");
1809 if (numResults != 1) {
1811 throw nb::value_error((Twine(
"Cannot call .result on operation ") +
1812 StringRef(name.data, name.length) +
" which has " +
1814 " results (it is only valid for operations with a "
1823 if (operand.is_none()) {
1824 throw nb::value_error(
"contained a None item");
1827 if (nb::try_cast<PyOperationBase *>(operand, op)) {
1831 if (nb::try_cast<PyOpResultList *>(operand, opResultList)) {
1835 if (nb::try_cast<PyValue *>(operand, value)) {
1836 return value->
get();
1838 throw nb::value_error(
"is not a Value");
1842 std::string_view name, std::tuple<int, bool> opRegionSpec,
1843 nb::object operandSegmentSpecObj, nb::object resultSegmentSpecObj,
1844 std::optional<nb::list> resultTypeList, nb::list operandList,
1845 std::optional<nb::dict> attributes,
1846 std::optional<std::vector<PyBlock *>> successors,
1847 std::optional<int> regions,
PyLocation &location,
1848 const nb::object &maybeIp) {
1857 std::vector<int32_t> operandSegmentLengths;
1858 std::vector<int32_t> resultSegmentLengths;
1861 int opMinRegionCount = std::get<0>(opRegionSpec);
1862 bool opHasNoVariadicRegions = std::get<1>(opRegionSpec);
1864 regions = opMinRegionCount;
1866 if (*regions < opMinRegionCount) {
1867 throw nb::value_error(
1868 (llvm::Twine(
"Operation \"") + name +
"\" requires a minimum of " +
1869 llvm::Twine(opMinRegionCount) +
1870 " regions but was built with regions=" + llvm::Twine(*regions))
1874 if (opHasNoVariadicRegions && *regions > opMinRegionCount) {
1875 throw nb::value_error(
1876 (llvm::Twine(
"Operation \"") + name +
"\" requires a maximum of " +
1877 llvm::Twine(opMinRegionCount) +
1878 " regions but was built with regions=" + llvm::Twine(*regions))
1884 std::vector<PyType *> resultTypes;
1885 if (resultTypeList.has_value()) {
1887 resultSegmentLengths, resultTypes);
1892 operands.reserve(operands.size());
1893 if (operandSegmentSpecObj.is_none()) {
1898 }
catch (nb::builtin_exception &err) {
1899 throw nb::value_error((llvm::Twine(
"Operand ") +
1900 llvm::Twine(it.index()) +
" of operation \"" +
1901 name +
"\" must be a Value (" + err.what() +
")")
1908 auto operandSegmentSpec = nb::cast<std::vector<int>>(operandSegmentSpecObj);
1909 if (operandSegmentSpec.size() != operandList.size()) {
1910 throw nb::value_error((llvm::Twine(
"Operation \"") + name +
1912 llvm::Twine(operandSegmentSpec.size()) +
1913 "operand segments but was provided " +
1914 llvm::Twine(operandList.size()))
1918 operandSegmentLengths.reserve(operandList.size());
1919 for (
const auto &it :
1921 int segmentSpec = std::get<1>(it.value());
1922 if (segmentSpec == 1 || segmentSpec == 0) {
1924 auto &operand = std::get<0>(it.value());
1925 if (!operand.is_none()) {
1929 }
catch (nb::builtin_exception &err) {
1930 throw nb::value_error((llvm::Twine(
"Operand ") +
1931 llvm::Twine(it.index()) +
1932 " of operation \"" + name +
1933 "\" must be a Value (" + err.what() +
")")
1938 operandSegmentLengths.push_back(1);
1939 }
else if (segmentSpec == 0) {
1941 operandSegmentLengths.push_back(0);
1943 throw nb::value_error(
1944 (llvm::Twine(
"Operand ") + llvm::Twine(it.index()) +
1945 " of operation \"" + name +
1946 "\" must be a Value (was None and operand is not optional)")
1950 }
else if (segmentSpec == -1) {
1953 if (std::get<0>(it.value()).is_none()) {
1955 operandSegmentLengths.push_back(0);
1958 auto segment = nb::cast<nb::sequence>(std::get<0>(it.value()));
1959 for (nb::handle segmentItem : segment) {
1962 operandSegmentLengths.push_back(nb::len(segment));
1964 }
catch (std::exception &err) {
1968 throw nb::value_error((llvm::Twine(
"Operand ") +
1969 llvm::Twine(it.index()) +
" of operation \"" +
1970 name +
"\" must be a Sequence of Values (" +
1976 throw nb::value_error(
"Unexpected segment spec");
1982 if (!operandSegmentLengths.empty() || !resultSegmentLengths.empty()) {
1985 attributes = nb::dict(*attributes);
1987 attributes = nb::dict();
1989 if (attributes->contains(
"resultSegmentSizes") ||
1990 attributes->contains(
"operandSegmentSizes")) {
1991 throw nb::value_error(
"Manually setting a 'resultSegmentSizes' or "
1992 "'operandSegmentSizes' attribute is unsupported. "
1993 "Use Operation.create for such low-level access.");
1997 if (!resultSegmentLengths.empty()) {
1998 MlirAttribute segmentLengthAttr =
2000 resultSegmentLengths.data());
2001 (*attributes)[
"resultSegmentSizes"] =
2006 if (!operandSegmentLengths.empty()) {
2007 MlirAttribute segmentLengthAttr =
2009 operandSegmentLengths.data());
2010 (*attributes)[
"operandSegmentSizes"] =
2017 std::move(resultTypes),
2019 std::move(attributes),
2020 std::move(successors),
2021 *regions, location, maybeIp,
2026 const nb::object &operation) {
2027 nb::handle opViewType = nb::type<PyOpView>();
2028 nb::object instance = cls.attr(
"__new__")(cls);
2029 opViewType.attr(
"__init__")(instance, operation);
2037 operationObject(operation.getRef().getObject()) {}
2046 : refOperation(beforeOperationBase.getOperation().getRef()),
2047 block((*refOperation)->getBlock()) {}
2050 : refOperation(beforeOperationRef), block((*refOperation)->getBlock()) {}
2055 throw nb::value_error(
2056 "Attempt to insert operation that is already attached");
2057 block.getParentOperation()->checkValid();
2058 MlirOperation beforeOp = {
nullptr};
2061 (*refOperation)->checkValid();
2062 beforeOp = (*refOperation)->get();
2068 throw nb::index_error(
"Cannot insert operation at the end of a block "
2069 "that already has a terminator. Did you mean to "
2070 "use 'InsertionPoint.at_block_terminator(block)' "
2071 "versus 'InsertionPoint(block)'?");
2094 throw nb::value_error(
"Block has no terminator");
2118 const nb::object &excVal,
2119 const nb::object &excTb) {
2138 throw nb::python_error();
2146 "mlirTypeID was expected to be non-null.");
2151 nb::object thisObj = nb::cast(
this, nb::rv_policy::move);
2154 return typeCaster.value()(thisObj);
2162 : ownedName(new std::string(std::move(ownedName))) {
2184 throw nb::python_error();
2192 "mlirTypeID was expected to be non-null.");
2197 nb::object thisObj = nb::cast(
this, nb::rv_policy::move);
2200 return typeCaster.value()(thisObj);
2214 throw nb::python_error();
2233 "mlirTypeID was expected to be non-null.");
2234 std::optional<nb::callable> valueCaster =
2238 nb::object thisObj = nb::cast(
this, nb::rv_policy::move);
2241 return valueCaster.value()(thisObj);
2247 throw nb::python_error();
2248 MlirOperation owner;
2254 throw nb::python_error();
2258 return PyValue(ownerRef, value);
2266 : operation(operation.getOperation().getRef()) {
2269 throw nb::type_error(
"Operation is not a Symbol Table.");
2278 throw nb::key_error(
2279 (
"Symbol '" + name +
"' not in the symbol table.").c_str());
2282 operation.getObject())
2298 erase(nb::cast<PyOperationBase &>(operation));
2307 throw nb::value_error(
"Expected operation to have a symbol name.");
2318 MlirAttribute existingNameAttr =
2321 throw nb::value_error(
"Expected operation to have a symbol name.");
2327 const std::string &name) {
2332 MlirAttribute existingNameAttr =
2335 throw nb::value_error(
"Expected operation to have a symbol name.");
2336 MlirAttribute newNameAttr =
2345 MlirAttribute existingVisAttr =
2348 throw nb::value_error(
"Expected operation to have a symbol visibility.");
2353 const std::string &visibility) {
2354 if (visibility !=
"public" && visibility !=
"private" &&
2355 visibility !=
"nested")
2356 throw nb::value_error(
2357 "Expected visibility to be 'public', 'private' or 'nested'");
2361 MlirAttribute existingVisAttr =
2364 throw nb::value_error(
"Expected operation to have a symbol visibility.");
2371 const std::string &newSymbol,
2379 throw nb::value_error(
"Symbol rename failed");
2383 bool allSymUsesVisible,
2384 nb::object callback) {
2389 nb::object callback;
2391 std::string exceptionWhat;
2392 nb::object exceptionType;
2395 fromOperation.
getContext(), std::move(callback),
false, {}, {}};
2397 fromOperation.
get(), allSymUsesVisible,
2398 [](MlirOperation foundOp,
bool isVisible,
void *calleeUserDataVoid) {
2399 UserData *calleeUserData = static_cast<UserData *>(calleeUserDataVoid);
2401 PyOperation::forOperation(calleeUserData->context, foundOp);
2402 if (calleeUserData->gotException)
2405 calleeUserData->callback(pyFoundOp.getObject(), isVisible);
2406 } catch (nb::python_error &e) {
2407 calleeUserData->gotException =
true;
2408 calleeUserData->exceptionWhat = e.what();
2409 calleeUserData->exceptionType = nb::borrow(e.type());
2412 static_cast<void *
>(&userData));
2413 if (userData.gotException) {
2414 std::string message(
"Exception raised in callback: ");
2415 message.append(userData.exceptionWhat);
2416 throw std::runtime_error(message);
2423 class PyBlockArgument :
public PyConcreteValue<PyBlockArgument> {
2426 static constexpr
const char *pyClassName =
"BlockArgument";
2427 using PyConcreteValue::PyConcreteValue;
2429 static void bindDerived(ClassTy &c) {
2430 c.def_prop_ro(
"owner", [](PyBlockArgument &
self) {
2431 return PyBlock(
self.getParentOperation(),
2434 c.def_prop_ro(
"arg_number", [](PyBlockArgument &
self) {
2439 [](PyBlockArgument &
self,
PyType type) {
2450 class PyBlockArgumentList
2451 :
public Sliceable<PyBlockArgumentList, PyBlockArgument> {
2453 static constexpr
const char *pyClassName =
"BlockArgumentList";
2457 intptr_t startIndex = 0, intptr_t length = -1,
2462 operation(std::move(operation)), block(block) {}
2464 static void bindDerived(ClassTy &c) {
2465 c.def_prop_ro(
"types", [](PyBlockArgumentList &
self) {
2472 friend class Sliceable<PyBlockArgumentList, PyBlockArgument>;
2475 intptr_t getRawNumElements() {
2481 PyBlockArgument getRawElement(intptr_t pos) {
2483 return PyBlockArgument(operation, argument);
2487 PyBlockArgumentList slice(intptr_t startIndex, intptr_t length,
2489 return PyBlockArgumentList(operation, block, startIndex, length, step);
2500 class PyOpOperandList :
public Sliceable<PyOpOperandList, PyValue> {
2502 static constexpr
const char *pyClassName =
"OpOperandList";
2505 PyOpOperandList(
PyOperationRef operation, intptr_t startIndex = 0,
2506 intptr_t length = -1, intptr_t step = 1)
2511 operation(operation) {}
2513 void dunderSetItem(intptr_t index,
PyValue value) {
2514 index = wrapIndex(index);
2518 static void bindDerived(ClassTy &c) {
2519 c.def(
"__setitem__", &PyOpOperandList::dunderSetItem);
2526 intptr_t getRawNumElements() {
2531 PyValue getRawElement(intptr_t pos) {
2533 MlirOperation owner;
2539 assert(
false &&
"Value must be an block arg or op result.");
2541 PyOperation::forOperation(operation->
getContext(), owner);
2542 return PyValue(pyOwner, operand);
2545 PyOpOperandList slice(intptr_t startIndex, intptr_t length, intptr_t step) {
2546 return PyOpOperandList(operation, startIndex, length, step);
2556 class PyOpSuccessors :
public Sliceable<PyOpSuccessors, PyBlock> {
2558 static constexpr
const char *pyClassName =
"OpSuccessors";
2560 PyOpSuccessors(
PyOperationRef operation, intptr_t startIndex = 0,
2561 intptr_t length = -1, intptr_t step = 1)
2566 operation(operation) {}
2568 void dunderSetItem(intptr_t index,
PyBlock block) {
2569 index = wrapIndex(index);
2573 static void bindDerived(ClassTy &c) {
2574 c.def(
"__setitem__", &PyOpSuccessors::dunderSetItem);
2581 intptr_t getRawNumElements() {
2586 PyBlock getRawElement(intptr_t pos) {
2588 return PyBlock(operation, block);
2591 PyOpSuccessors slice(intptr_t startIndex, intptr_t length, intptr_t step) {
2592 return PyOpSuccessors(operation, startIndex, length, step);
2602 class PyBlockSuccessors :
public Sliceable<PyBlockSuccessors, PyBlock> {
2604 static constexpr
const char *pyClassName =
"BlockSuccessors";
2607 intptr_t startIndex = 0, intptr_t length = -1,
2613 operation(operation), block(block) {}
2619 intptr_t getRawNumElements() {
2624 PyBlock getRawElement(intptr_t pos) {
2626 return PyBlock(operation, block);
2629 PyBlockSuccessors slice(intptr_t startIndex, intptr_t length, intptr_t step) {
2630 return PyBlockSuccessors(block, operation, startIndex, length, step);
2644 class PyBlockPredecessors :
public Sliceable<PyBlockPredecessors, PyBlock> {
2646 static constexpr
const char *pyClassName =
"BlockPredecessors";
2649 intptr_t startIndex = 0, intptr_t length = -1,
2655 operation(operation), block(block) {}
2661 intptr_t getRawNumElements() {
2666 PyBlock getRawElement(intptr_t pos) {
2668 return PyBlock(operation, block);
2671 PyBlockPredecessors slice(intptr_t startIndex, intptr_t length,
2673 return PyBlockPredecessors(block, operation, startIndex, length, step);
2682 class PyOpAttributeMap {
2685 : operation(std::move(operation)) {}
2687 nb::typed<nb::object, PyAttribute>
2688 dunderGetItemNamed(
const std::string &name) {
2692 throw nb::key_error(
"attempt to access a non-existent attribute");
2699 index += dunderLen();
2701 if (index < 0 || index >= dunderLen()) {
2702 throw nb::index_error(
"attempt to access out of bounds attribute");
2712 void dunderSetItem(
const std::string &name,
const PyAttribute &attr) {
2717 void dunderDelItem(
const std::string &name) {
2721 throw nb::key_error(
"attempt to delete a non-existent attribute");
2724 intptr_t dunderLen() {
2728 bool dunderContains(
const std::string &name) {
2733 static void bind(nb::module_ &m) {
2734 nb::class_<PyOpAttributeMap>(m,
"OpAttributeMap")
2735 .def(
"__contains__", &PyOpAttributeMap::dunderContains)
2736 .def(
"__len__", &PyOpAttributeMap::dunderLen)
2737 .def(
"__getitem__", &PyOpAttributeMap::dunderGetItemNamed)
2738 .def(
"__getitem__", &PyOpAttributeMap::dunderGetItemIndexed)
2739 .def(
"__setitem__", &PyOpAttributeMap::dunderSetItem)
2740 .def(
"__delitem__", &PyOpAttributeMap::dunderDelItem);
2751 #define _Py_CAST(type, expr) ((type)(expr))
2758 #if (defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L) || \
2759 (defined(__cplusplus) && __cplusplus >= 201103)
2760 #define _Py_NULL nullptr
2762 #define _Py_NULL NULL
2767 #if PY_VERSION_HEX < 0x030A00A3
2770 #if !defined(Py_XNewRef)
2771 [[maybe_unused]] PyObject *_Py_XNewRef(PyObject *obj) {
2775 #define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
2779 #if !defined(Py_NewRef)
2780 [[maybe_unused]] PyObject *_Py_NewRef(PyObject *obj) {
2784 #define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
2790 #if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
2793 PyFrameObject *PyThreadState_GetFrame(PyThreadState *tstate) {
2794 assert(tstate !=
_Py_NULL &&
"expected tstate != _Py_NULL");
2799 PyFrameObject *PyFrame_GetBack(PyFrameObject *frame) {
2800 assert(frame !=
_Py_NULL &&
"expected frame != _Py_NULL");
2805 PyCodeObject *PyFrame_GetCode(PyFrameObject *frame) {
2806 assert(frame !=
_Py_NULL &&
"expected frame != _Py_NULL");
2807 assert(frame->f_code !=
_Py_NULL &&
"expected frame->f_code != _Py_NULL");
2813 MlirLocation tracebackToLocation(MlirContext ctx) {
2814 size_t framesLimit =
2817 thread_local std::array<MlirLocation, PyGlobals::TracebackLoc::kMaxFrames>
2821 nb::gil_scoped_acquire acquire;
2822 PyThreadState *tstate = PyThreadState_GET();
2823 PyFrameObject *next;
2824 PyFrameObject *pyFrame = PyThreadState_GetFrame(tstate);
2830 for (; pyFrame !=
nullptr && count < framesLimit;
2831 next = PyFrame_GetBack(pyFrame), Py_XDECREF(pyFrame), pyFrame = next) {
2832 PyCodeObject *code = PyFrame_GetCode(pyFrame);
2834 nb::cast<std::string>(nb::borrow<nb::str>(code->co_filename));
2835 llvm::StringRef fileName(fileNameStr);
2836 if (!
PyGlobals::get().getTracebackLoc().isUserTracebackFilename(fileName))
2840 #if PY_VERSION_HEX < 0x030B00F0
2842 nb::cast<std::string>(nb::borrow<nb::str>(code->co_name));
2843 llvm::StringRef funcName(name);
2844 int startLine = PyFrame_GetLineNumber(pyFrame);
2849 nb::cast<std::string>(nb::borrow<nb::str>(code->co_qualname));
2850 llvm::StringRef funcName(name);
2851 int startLine, startCol, endLine, endCol;
2852 int lasti = PyFrame_GetLasti(pyFrame);
2853 if (!PyCode_Addr2Location(code, lasti, &startLine, &startCol, &endLine,
2855 throw nb::python_error();
2858 ctx,
wrap(fileName), startLine, startCol, endLine, endCol);
2866 Py_XDECREF(pyFrame);
2871 MlirLocation callee = frames[0];
2876 MlirLocation caller = frames[count - 1];
2878 for (
int i = count - 2; i >= 1; i--)
2885 maybeGetTracebackLocation(
const std::optional<PyLocation> &location) {
2886 if (location.has_value())
2887 return location.value();
2889 return DefaultingPyLocation::resolve();
2892 MlirLocation mlirLoc = tracebackToLocation(ctx.
get());
2894 return {ref, mlirLoc};
2905 nb::set_leak_warnings(
false);
2909 nb::enum_<MlirDiagnosticSeverity>(m,
"DiagnosticSeverity")
2915 nb::enum_<MlirWalkOrder>(m,
"WalkOrder")
2919 nb::enum_<MlirWalkResult>(m,
"WalkResult")
2927 nb::class_<PyDiagnostic>(m,
"Diagnostic")
2928 .def_prop_ro(
"severity", &PyDiagnostic::getSeverity)
2929 .def_prop_ro(
"location", &PyDiagnostic::getLocation)
2930 .def_prop_ro(
"message", &PyDiagnostic::getMessage)
2931 .def_prop_ro(
"notes", &PyDiagnostic::getNotes)
2933 if (!
self.isValid())
2934 return nb::str(
"<Invalid Diagnostic>");
2935 return self.getMessage();
2938 nb::class_<PyDiagnostic::DiagnosticInfo>(m,
"DiagnosticInfo")
2943 .def_ro(
"severity", &PyDiagnostic::DiagnosticInfo::severity)
2944 .def_ro(
"location", &PyDiagnostic::DiagnosticInfo::location)
2945 .def_ro(
"message", &PyDiagnostic::DiagnosticInfo::message)
2946 .def_ro(
"notes", &PyDiagnostic::DiagnosticInfo::notes)
2950 nb::class_<PyDiagnosticHandler>(m,
"DiagnosticHandler")
2951 .def(
"detach", &PyDiagnosticHandler::detach)
2952 .def_prop_ro(
"attached", &PyDiagnosticHandler::isAttached)
2953 .def_prop_ro(
"had_error", &PyDiagnosticHandler::getHadError)
2954 .def(
"__enter__", &PyDiagnosticHandler::contextEnter)
2955 .def(
"__exit__", &PyDiagnosticHandler::contextExit,
2956 nb::arg(
"exc_type").none(), nb::arg(
"exc_value").none(),
2957 nb::arg(
"traceback").none());
2960 nb::class_<PyThreadPool>(m,
"ThreadPool")
2962 .def(
"get_max_concurrency", &PyThreadPool::getMaxConcurrency)
2963 .def(
"_mlir_thread_pool_ptr", &PyThreadPool::_mlir_thread_pool_ptr);
2965 nb::class_<PyMlirContext>(m,
"Context")
2971 .def_static(
"_get_live_count", &PyMlirContext::getLiveCount)
2972 .def(
"_get_context_again",
2973 [](
PyMlirContext &
self) -> nb::typed<nb::object, PyMlirContext> {
2977 .def(
"_get_live_module_count", &PyMlirContext::getLiveModuleCount)
2980 &PyMlirContext::createFromCapsule)
2981 .def(
"__enter__", &PyMlirContext::contextEnter)
2982 .def(
"__exit__", &PyMlirContext::contextExit, nb::arg(
"exc_type").none(),
2983 nb::arg(
"exc_value").none(), nb::arg(
"traceback").none())
2984 .def_prop_ro_static(
2987 -> std::optional<nb::typed<nb::object, PyMlirContext>> {
2991 return nb::cast(context);
2993 nb::sig(
"def current(/) -> Context | None"),
2994 "Gets the Context bound to the current thread or raises ValueError")
2998 "Gets a container for accessing dialects by name")
3001 "Alias for 'dialect'")
3003 "get_dialect_descriptor",
3006 self.
get(), {name.data(), name.size()});
3008 throw nb::value_error(
3009 (Twine(
"Dialect '") + name +
"' not found").str().c_str());
3013 nb::arg(
"dialect_name"),
3014 "Gets or loads a dialect by name, returning its descriptor object")
3016 "allow_unregistered_dialects",
3023 .def(
"attach_diagnostic_handler", &PyMlirContext::attachDiagnosticHandler,
3024 nb::arg(
"callback"),
3025 "Attaches a diagnostic handler that will receive callbacks")
3027 "enable_multithreading",
3032 .def(
"set_thread_pool",
3040 .def(
"get_num_threads",
3044 .def(
"_mlir_thread_pool_ptr",
3047 std::stringstream ss;
3052 "is_registered_operation",
3057 nb::arg(
"operation_name"))
3059 "append_dialect_registry",
3063 nb::arg(
"registry"))
3064 .def_prop_rw(
"emit_error_diagnostics",
3065 &PyMlirContext::getEmitErrorDiagnostics,
3066 &PyMlirContext::setEmitErrorDiagnostics,
3067 "Emit error diagnostics to diagnostic handlers. By default "
3068 "error diagnostics are captured and reported through "
3069 "MLIRError exceptions.")
3070 .def(
"load_all_available_dialects", [](
PyMlirContext &
self) {
3077 nb::class_<PyDialectDescriptor>(m,
"DialectDescriptor")
3078 .def_prop_ro(
"namespace",
3087 std::string repr(
"<DialectDescriptor ");
3092 nb::sig(
"def __repr__(self) -> str"));
3097 nb::class_<PyDialects>(m,
"Dialects")
3100 MlirDialect dialect =
3101 self.getDialectForKey(keyName,
false);
3102 nb::object descriptor =
3106 .def(
"__getattr__", [=](
PyDialects &
self, std::string attrName) {
3107 MlirDialect dialect =
3108 self.getDialectForKey(attrName,
true);
3109 nb::object descriptor =
3117 nb::class_<PyDialect>(m,
"Dialect")
3118 .def(nb::init<nb::object>(), nb::arg(
"descriptor"))
3119 .def_prop_ro(
"descriptor",
3120 [](
PyDialect &
self) {
return self.getDescriptor(); })
3123 [](
const nb::object &
self) {
3124 auto clazz =
self.attr(
"__class__");
3125 return nb::str(
"<Dialect ") +
3126 self.attr(
"descriptor").attr(
"namespace") +
3127 nb::str(
" (class ") + clazz.attr(
"__module__") +
3128 nb::str(
".") + clazz.attr(
"__name__") + nb::str(
")>");
3130 nb::sig(
"def __repr__(self) -> str"));
3135 nb::class_<PyDialectRegistry>(m,
"DialectRegistry")
3138 &PyDialectRegistry::createFromCapsule)
3144 nb::class_<PyLocation>(m,
"Location")
3147 .def(
"__enter__", &PyLocation::contextEnter)
3148 .def(
"__exit__", &PyLocation::contextExit, nb::arg(
"exc_type").none(),
3149 nb::arg(
"exc_value").none(), nb::arg(
"traceback").none())
3154 .def(
"__eq__", [](
PyLocation &
self, nb::object other) {
return false; })
3155 .def_prop_ro_static(
3157 [](nb::object & ) -> std::optional<PyLocation *> {
3158 auto *loc = PyThreadContextEntry::getDefaultLocation();
3160 return std::nullopt;
3164 nb::sig(
"def current(/) -> Location | None"),
3166 "Gets the Location bound to the current thread or raises ValueError")
3173 nb::arg(
"context") = nb::none(),
3174 "Gets a Location representing an unknown location")
3177 [](
PyLocation callee,
const std::vector<PyLocation> &frames,
3180 throw nb::value_error(
"No caller frames provided");
3181 MlirLocation caller = frames.back().get();
3188 nb::arg(
"callee"), nb::arg(
"frames"), nb::arg(
"context") = nb::none(),
3191 .def_prop_ro(
"callee",
3196 .def_prop_ro(
"caller",
3203 [](std::string filename,
int line,
int col,
3210 nb::arg(
"filename"), nb::arg(
"line"), nb::arg(
"col"),
3214 [](std::string filename,
int startLine,
int startCol,
int endLine,
3219 startLine, startCol, endLine, endCol));
3221 nb::arg(
"filename"), nb::arg(
"start_line"), nb::arg(
"start_col"),
3222 nb::arg(
"end_line"), nb::arg(
"end_col"),
3225 .def_prop_ro(
"filename",
3226 [](MlirLocation loc) {
3236 [](
const std::vector<PyLocation> &pyLocations,
3237 std::optional<PyAttribute> metadata,
3240 locations.reserve(pyLocations.size());
3241 for (
auto &pyLocation : pyLocations)
3242 locations.push_back(pyLocation.get());
3244 context->
get(), locations.size(), locations.data(),
3245 metadata ? metadata->get() : MlirAttribute{0});
3246 return PyLocation(context->getRef(), location);
3248 nb::arg(
"locations"), nb::arg(
"metadata") = nb::none(),
3255 std::vector<MlirLocation> locations(numLocations);
3258 std::vector<PyLocation> pyLocations{};
3259 pyLocations.reserve(numLocations);
3260 for (
unsigned i = 0; i < numLocations; ++i)
3261 pyLocations.emplace_back(
self.getContext(), locations[i]);
3266 [](std::string name, std::optional<PyLocation> childLoc,
3272 childLoc ? childLoc->get()
3275 nb::arg(
"name"), nb::arg(
"childLoc") = nb::none(),
3278 .def_prop_ro(
"name_str",
3279 [](MlirLocation loc) {
3282 .def_prop_ro(
"child_loc",
3293 nb::arg(
"attribute"), nb::arg(
"context") = nb::none(),
3294 "Gets a Location from a LocationAttr")
3297 [](
PyLocation &
self) -> nb::typed<nb::object, PyMlirContext> {
3298 return self.getContext().getObject();
3300 "Context that owns the Location")
3307 "Get the underlying LocationAttr")
3313 nb::arg(
"message"),
"Emits an error at this location")
3318 return printAccum.
join();
3324 nb::class_<PyModule>(m,
"Module", nb::is_weak_referenceable())
3328 .def(
"_clear_mlir_module", &PyModule::clearMlirModule)
3332 -> nb::typed<nb::object, PyModule> {
3337 throw MLIRError(
"Unable to parse module assembly", errors.take());
3338 return PyModule::forModule(module).releaseObject();
3340 nb::arg(
"asm"), nb::arg(
"context") = nb::none(),
3345 -> nb::typed<nb::object, PyModule> {
3350 throw MLIRError(
"Unable to parse module assembly", errors.take());
3351 return PyModule::forModule(module).releaseObject();
3353 nb::arg(
"asm"), nb::arg(
"context") = nb::none(),
3358 -> nb::typed<nb::object, PyModule> {
3363 throw MLIRError(
"Unable to parse module assembly", errors.take());
3364 return PyModule::forModule(module).releaseObject();
3366 nb::arg(
"path"), nb::arg(
"context") = nb::none(),
3370 [](
const std::optional<PyLocation> &loc)
3371 -> nb::typed<nb::object, PyModule> {
3372 PyLocation pyLoc = maybeGetTracebackLocation(loc);
3374 return PyModule::forModule(module).releaseObject();
3376 nb::arg(
"loc") = nb::none(),
"Creates an empty module")
3379 [](
PyModule &
self) -> nb::typed<nb::object, PyMlirContext> {
3380 return self.getContext().getObject();
3382 "Context that created the Module")
3385 [](
PyModule &
self) -> nb::typed<nb::object, PyOperation> {
3386 return PyOperation::forOperation(
self.
getContext(),
3388 self.getRef().releaseObject())
3391 "Accesses the module as an operation")
3397 self.getRef().releaseObject());
3401 "Return the block for this module")
3410 [](
const nb::object &
self) {
3412 return self.attr(
"operation").attr(
"__str__")();
3427 nb::class_<PyOperationBase>(m,
"_OperationBase")
3430 return self.getOperation().getCapsule();
3443 .def_prop_ro(
"attributes",
3445 return PyOpAttributeMap(
self.getOperation().getRef());
3454 "Context that owns the Operation")
3455 .def_prop_ro(
"name",
3459 MlirOperation operation = concreteOperation.
get();
3462 .def_prop_ro(
"operands",
3464 return PyOpOperandList(
self.getOperation().getRef());
3466 .def_prop_ro(
"regions",
3468 return PyRegionList(
self.getOperation().getRef());
3475 "Returns the list of Operation results.")
3479 auto &operation =
self.getOperation();
3483 "Shortcut to get an op result if it has only one (throws an error "
3496 nb::for_getter(
"Returns the source location the operation was "
3497 "defined or derived from."),
3498 nb::for_setter(
"Sets the source location the operation was defined "
3499 "or derived from."))
3500 .def_prop_ro(
"parent",
3502 -> std::optional<nb::typed<nb::object, PyOperation>> {
3503 auto parent =
self.getOperation().getParentOperation();
3505 return parent->getObject();
3511 return self.getAsm(
false,
3522 nb::sig(
"def __str__(self) -> str"),
3523 "Returns the assembly form of the operation.")
3525 nb::overload_cast<PyAsmState &, nb::object, bool>(
3527 nb::arg(
"state"), nb::arg(
"file") = nb::none(),
3530 nb::overload_cast<std::optional<int64_t>, std::optional<int64_t>,
3531 bool,
bool,
bool,
bool,
bool,
bool, nb::object,
3534 nb::arg(
"large_elements_limit") = nb::none(),
3535 nb::arg(
"large_resource_limit") = nb::none(),
3536 nb::arg(
"enable_debug_info") =
false,
3537 nb::arg(
"pretty_debug_info") =
false,
3538 nb::arg(
"print_generic_op_form") =
false,
3539 nb::arg(
"use_local_scope") =
false,
3540 nb::arg(
"use_name_loc_as_prefix") =
false,
3541 nb::arg(
"assume_verified") =
false, nb::arg(
"file") = nb::none(),
3542 nb::arg(
"binary") =
false, nb::arg(
"skip_regions") =
false,
3544 .def(
"write_bytecode", &PyOperationBase::writeBytecode, nb::arg(
"file"),
3545 nb::arg(
"desired_version") = nb::none(),
3547 .def(
"get_asm", &PyOperationBase::getAsm,
3549 nb::arg(
"binary") =
false,
3550 nb::arg(
"large_elements_limit") = nb::none(),
3551 nb::arg(
"large_resource_limit") = nb::none(),
3552 nb::arg(
"enable_debug_info") =
false,
3553 nb::arg(
"pretty_debug_info") =
false,
3554 nb::arg(
"print_generic_op_form") =
false,
3555 nb::arg(
"use_local_scope") =
false,
3556 nb::arg(
"use_name_loc_as_prefix") =
false,
3557 nb::arg(
"assume_verified") =
false, nb::arg(
"skip_regions") =
false,
3560 "Verify the operation. Raises MLIRError if verification fails, and "
3561 "returns true otherwise.")
3562 .def(
"move_after", &PyOperationBase::moveAfter, nb::arg(
"other"),
3563 "Puts self immediately after the other operation in its parent "
3565 .def(
"move_before", &PyOperationBase::moveBefore, nb::arg(
"other"),
3566 "Puts self immediately before the other operation in its parent "
3570 "Given an operation 'other' that is within the same parent block, "
3572 "whether the current operation is before 'other' in the operation "
3574 "of the parent block.")
3578 const nb::object &ip) -> nb::typed<nb::object, PyOperation> {
3579 return self.getOperation().clone(ip);
3581 nb::arg(
"ip") = nb::none())
3583 "detach_from_parent",
3588 throw nb::value_error(
"Detached operation has no parent.");
3593 "Detaches the operation from its parent block.")
3601 "Reports if the operation is attached to its parent block.")
3602 .def(
"erase", [](
PyOperationBase &
self) {
self.getOperation().erase(); })
3606 nb::sig(
"def walk(self, callback: Callable[[Operation], WalkResult], walk_order: WalkOrder) -> None")
3610 nb::class_<PyOperation, PyOperationBase>(m,
"Operation")
3613 [](std::string_view name,
3614 std::optional<std::vector<PyType *>> results,
3615 std::optional<std::vector<PyValue *>> operands,
3616 std::optional<nb::dict> attributes,
3617 std::optional<std::vector<PyBlock *>> successors,
int regions,
3618 const std::optional<PyLocation> &location,
3619 const nb::object &maybeIp,
3620 bool inferType) -> nb::typed<nb::object, PyOperation> {
3624 mlirOperands.reserve(operands->size());
3625 for (
PyValue *operand : *operands) {
3627 throw nb::value_error(
"operand value cannot be None");
3628 mlirOperands.push_back(operand->get());
3632 PyLocation pyLoc = maybeGetTracebackLocation(location);
3633 return PyOperation::create(name, results, mlirOperands, attributes,
3634 successors, regions, pyLoc, maybeIp,
3637 nb::arg(
"name"), nb::arg(
"results") = nb::none(),
3638 nb::arg(
"operands") = nb::none(), nb::arg(
"attributes") = nb::none(),
3639 nb::arg(
"successors") = nb::none(), nb::arg(
"regions") = 0,
3640 nb::arg(
"loc") = nb::none(), nb::arg(
"ip") = nb::none(),
3644 [](
const std::string &sourceStr,
const std::string &sourceName,
3646 -> nb::typed<nb::object, PyOpView> {
3650 nb::arg(
"source"), nb::kw_only(), nb::arg(
"source_name") =
"",
3651 nb::arg(
"context") = nb::none(),
3652 "Parses an operation. Supports both text assembly format and binary "
3656 &PyOperation::createFromCapsule)
3657 .def_prop_ro(
"operation",
3658 [](nb::object
self) -> nb::typed<nb::object, PyOperation> {
3661 .def_prop_ro(
"opview",
3662 [](
PyOperation &
self) -> nb::typed<nb::object, PyOpView> {
3663 return self.createOpView();
3665 .def_prop_ro(
"block", &PyOperation::getBlock)
3669 return PyOpSuccessors(
self.getOperation().getRef());
3671 "Returns the list of Operation successors.")
3672 .def(
"_set_invalid", &PyOperation::setInvalid,
3673 "Invalidate the operation.");
3676 nb::class_<PyOpView, PyOperationBase>(m,
"OpView")
3677 .def(nb::init<nb::typed<nb::object, PyOperation>>(),
3678 nb::arg(
"operation"))
3681 [](
PyOpView *
self, std::string_view name,
3682 std::tuple<int, bool> opRegionSpec,
3683 nb::object operandSegmentSpecObj,
3684 nb::object resultSegmentSpecObj,
3685 std::optional<nb::list> resultTypeList, nb::list operandList,
3686 std::optional<nb::dict> attributes,
3687 std::optional<std::vector<PyBlock *>> successors,
3688 std::optional<int> regions,
3689 const std::optional<PyLocation> &location,
3690 const nb::object &maybeIp) {
3691 PyLocation pyLoc = maybeGetTracebackLocation(location);
3692 new (
self)
PyOpView(PyOpView::buildGeneric(
3693 name, opRegionSpec, operandSegmentSpecObj,
3694 resultSegmentSpecObj, resultTypeList, operandList,
3695 attributes, successors, regions, pyLoc, maybeIp));
3697 nb::arg(
"name"), nb::arg(
"opRegionSpec"),
3698 nb::arg(
"operandSegmentSpecObj") = nb::none(),
3699 nb::arg(
"resultSegmentSpecObj") = nb::none(),
3700 nb::arg(
"results") = nb::none(), nb::arg(
"operands") = nb::none(),
3701 nb::arg(
"attributes") = nb::none(),
3702 nb::arg(
"successors") = nb::none(),
3703 nb::arg(
"regions") = nb::none(), nb::arg(
"loc") = nb::none(),
3704 nb::arg(
"ip") = nb::none())
3707 [](
PyOpView &
self) -> nb::typed<nb::object, PyOperation> {
3708 return self.getOperationObject();
3710 .def_prop_ro(
"opview",
3711 [](nb::object
self) -> nb::typed<nb::object, PyOpView> {
3716 [](
PyOpView &
self) {
return nb::str(
self.getOperationObject()); })
3720 return PyOpSuccessors(
self.getOperation().getRef());
3722 "Returns the list of Operation successors.")
3725 [](
PyOpView &
self) {
self.getOperation().setInvalid(); },
3726 "Invalidate the operation.");
3727 opViewClass.attr(
"_ODS_REGIONS") = nb::make_tuple(0,
true);
3728 opViewClass.attr(
"_ODS_OPERAND_SEGMENTS") = nb::none();
3729 opViewClass.attr(
"_ODS_RESULT_SEGMENTS") = nb::none();
3734 [](nb::handle cls, std::optional<nb::list> resultTypeList,
3735 nb::list operandList, std::optional<nb::dict> attributes,
3736 std::optional<std::vector<PyBlock *>> successors,
3737 std::optional<int> regions, std::optional<PyLocation> location,
3738 const nb::object &maybeIp) {
3739 std::string name = nb::cast<std::string>(cls.attr(
"OPERATION_NAME"));
3740 std::tuple<int, bool> opRegionSpec =
3741 nb::cast<std::tuple<int, bool>>(cls.attr(
"_ODS_REGIONS"));
3742 nb::object operandSegmentSpec = cls.attr(
"_ODS_OPERAND_SEGMENTS");
3743 nb::object resultSegmentSpec = cls.attr(
"_ODS_RESULT_SEGMENTS");
3744 PyLocation pyLoc = maybeGetTracebackLocation(location);
3745 return PyOpView::buildGeneric(name, opRegionSpec, operandSegmentSpec,
3746 resultSegmentSpec, resultTypeList,
3747 operandList, attributes, successors,
3748 regions, pyLoc, maybeIp);
3750 nb::arg(
"cls"), nb::arg(
"results") = nb::none(),
3751 nb::arg(
"operands") = nb::none(), nb::arg(
"attributes") = nb::none(),
3752 nb::arg(
"successors") = nb::none(), nb::arg(
"regions") = nb::none(),
3753 nb::arg(
"loc") = nb::none(), nb::arg(
"ip") = nb::none(),
3754 "Builds a specific, generated OpView based on class level attributes.");
3756 [](
const nb::object &cls,
const std::string &sourceStr,
3757 const std::string &sourceName,
3767 std::string clsOpName =
3768 nb::cast<std::string>(cls.attr(
"OPERATION_NAME"));
3771 std::string_view parsedOpName(identifier.
data, identifier.
length);
3772 if (clsOpName != parsedOpName)
3773 throw MLIRError(Twine(
"Expected a '") + clsOpName +
"' op, got: '" +
3774 parsedOpName +
"'");
3775 return PyOpView::constructDerived(cls, parsed.
getObject());
3777 nb::arg(
"cls"), nb::arg(
"source"), nb::kw_only(),
3778 nb::arg(
"source_name") =
"", nb::arg(
"context") = nb::none(),
3779 "Parses a specific, generated OpView based on class level attributes");
3784 nb::class_<PyRegion>(m,
"Region")
3788 return PyBlockList(
self.getParentOperation(),
self.
get());
3790 "Returns a forward-optimized sequence of blocks.")
3793 [](
PyRegion &
self) -> nb::typed<nb::object, PyOpView> {
3794 return self.getParentOperation()->createOpView();
3796 "Returns the operation owning this region.")
3802 return PyBlockIterator(
self.getParentOperation(), firstBlock);
3804 "Iterates over blocks in the region.")
3807 return self.get().ptr == other.
get().ptr;
3809 .def(
"__eq__", [](
PyRegion &
self, nb::object &other) {
return false; });
3814 nb::class_<PyBlock>(m,
"Block")
3818 [](
PyBlock &
self) -> nb::typed<nb::object, PyOpView> {
3819 return self.getParentOperation()->createOpView();
3821 "Returns the owning operation of this block.")
3826 return PyRegion(
self.getParentOperation(), region);
3828 "Returns the owning region of this block.")
3832 return PyBlockArgumentList(
self.getParentOperation(),
self.
get());
3834 "Returns a list of block arguments.")
3838 return PyBlockArgument(
self.getParentOperation(),
3842 "Append an argument of the specified type to the block and returns "
3843 "the newly added argument.")
3846 [](
PyBlock &
self,
unsigned index) {
3849 "Erase the argument at 'index' and remove it from the argument list.")
3853 return PyOperationList(
self.getParentOperation(),
self.
get());
3855 "Returns a forward-optimized sequence of operations.")
3858 [](
PyRegion &parent,
const nb::sequence &pyArgTypes,
3859 const std::optional<nb::sequence> &pyArgLocs) {
3861 MlirBlock block =
createBlock(pyArgTypes, pyArgLocs);
3865 nb::arg(
"parent"), nb::arg(
"arg_types") = nb::list(),
3866 nb::arg(
"arg_locs") = std::nullopt,
3867 "Creates and returns a new Block at the beginning of the given "
3868 "region (with given argument types and locations).")
3872 MlirBlock b =
self.get();
3877 "Append this block to a region, transferring ownership if necessary")
3880 [](
PyBlock &
self,
const nb::args &pyArgTypes,
3881 const std::optional<nb::sequence> &pyArgLocs) {
3884 createBlock(nb::cast<nb::sequence>(pyArgTypes), pyArgLocs);
3887 return PyBlock(
self.getParentOperation(), block);
3889 nb::arg(
"arg_types"), nb::kw_only(),
3890 nb::arg(
"arg_locs") = std::nullopt,
3891 "Creates and returns a new Block before this block "
3892 "(with given argument types and locations).")
3895 [](
PyBlock &
self,
const nb::args &pyArgTypes,
3896 const std::optional<nb::sequence> &pyArgLocs) {
3899 createBlock(nb::cast<nb::sequence>(pyArgTypes), pyArgLocs);
3902 return PyBlock(
self.getParentOperation(), block);
3904 nb::arg(
"arg_types"), nb::kw_only(),
3905 nb::arg(
"arg_locs") = std::nullopt,
3906 "Creates and returns a new Block after this block "
3907 "(with given argument types and locations).")
3912 MlirOperation firstOperation =
3914 return PyOperationIterator(
self.getParentOperation(),
3917 "Iterates over operations in the block.")
3920 return self.get().ptr == other.
get().ptr;
3922 .def(
"__eq__", [](
PyBlock &
self, nb::object &other) {
return false; })
3934 return printAccum.
join();
3936 "Returns the assembly form of the block.")
3946 self.getParentOperation().getObject());
3948 nb::arg(
"operation"),
3949 "Appends an operation to this block. If the operation is currently "
3950 "in another block, it will be moved.")
3954 return PyBlockSuccessors(
self,
self.getParentOperation());
3956 "Returns the list of Block successors.")
3960 return PyBlockPredecessors(
self,
self.getParentOperation());
3962 "Returns the list of Block predecessors.");
3968 nb::class_<PyInsertionPoint>(m,
"InsertionPoint")
3969 .def(nb::init<PyBlock &>(), nb::arg(
"block"),
3970 "Inserts after the last operation but still inside the block.")
3971 .def(
"__enter__", &PyInsertionPoint::contextEnter)
3972 .def(
"__exit__", &PyInsertionPoint::contextExit,
3973 nb::arg(
"exc_type").none(), nb::arg(
"exc_value").none(),
3974 nb::arg(
"traceback").none())
3975 .def_prop_ro_static(
3978 auto *ip = PyThreadContextEntry::getDefaultInsertionPoint();
3980 throw nb::value_error(
"No current InsertionPoint");
3983 nb::sig(
"def current(/) -> InsertionPoint"),
3984 "Gets the InsertionPoint bound to the current thread or raises "
3985 "ValueError if none has been set")
3986 .def(nb::init<PyOperationBase &>(), nb::arg(
"beforeOperation"),
3987 "Inserts before a referenced operation.")
3988 .def_static(
"at_block_begin", &PyInsertionPoint::atBlockBegin,
3989 nb::arg(
"block"),
"Inserts at the beginning of the block.")
3990 .def_static(
"at_block_terminator", &PyInsertionPoint::atBlockTerminator,
3991 nb::arg(
"block"),
"Inserts before the block terminator.")
3992 .def_static(
"after", &PyInsertionPoint::after, nb::arg(
"operation"),
3993 "Inserts after the operation.")
3994 .def(
"insert", &PyInsertionPoint::insert, nb::arg(
"operation"),
3995 "Inserts an operation.")
3998 "Returns the block that this InsertionPoint points to.")
4002 -> std::optional<nb::typed<nb::object, PyOperation>> {
4003 auto refOperation =
self.getRefOperation();
4005 return refOperation->getObject();
4008 "The reference operation before which new operations are "
4009 "inserted, or None if the insertion point is at the end of "
4015 nb::class_<PyAttribute>(m,
"Attribute")
4018 .def(nb::init<PyAttribute &>(), nb::arg(
"cast_from_type"),
4019 "Casts the passed attribute to the generic Attribute")
4022 &PyAttribute::createFromCapsule)
4026 -> nb::typed<nb::object, PyAttribute> {
4031 throw MLIRError(
"Unable to parse attribute", errors.take());
4034 nb::arg(
"asm"), nb::arg(
"context") = nb::none(),
4035 "Parses an attribute from an assembly form. Raises an MLIRError on "
4039 [](
PyAttribute &
self) -> nb::typed<nb::object, PyMlirContext> {
4040 return self.getContext().getObject();
4042 "Context that owns the Attribute")
4043 .def_prop_ro(
"type",
4044 [](
PyAttribute &
self) -> nb::typed<nb::object, PyType> {
4054 nb::keep_alive<0, 1>(),
"Binds a name to the attribute")
4057 .def(
"__eq__", [](
PyAttribute &
self, nb::object &other) {
return false; })
4071 return printAccum.
join();
4073 "Returns the assembly form of the Attribute.")
4082 printAccum.
parts.append(
"Attribute(");
4085 printAccum.
parts.append(
")");
4086 return printAccum.
join();
4088 .def_prop_ro(
"typeid",
4092 "mlirTypeID was expected to be non-null.");
4096 [](
PyAttribute &
self) -> nb::typed<nb::object, PyAttribute> {
4097 return self.maybeDownCast();
4103 nb::class_<PyNamedAttribute>(m,
"NamedAttribute")
4107 printAccum.
parts.append(
"NamedAttribute(");
4108 printAccum.
parts.append(
4111 printAccum.
parts.append(
"=");
4115 printAccum.
parts.append(
")");
4116 return printAccum.
join();
4123 "The name of the NamedAttribute binding")
4127 nb::keep_alive<0, 1>(), nb::sig(
"def attr(self) -> Attribute"),
4128 "The underlying generic attribute of the NamedAttribute binding");
4133 nb::class_<PyType>(m,
"Type")
4136 .def(nb::init<PyType &>(), nb::arg(
"cast_from_type"),
4137 "Casts the passed type to the generic Type")
4142 [](std::string typeSpec,
4148 throw MLIRError(
"Unable to parse type", errors.take());
4151 nb::arg(
"asm"), nb::arg(
"context") = nb::none(),
4155 [](
PyType &
self) -> nb::typed<nb::object, PyMlirContext> {
4156 return self.getContext().getObject();
4158 "Context that owns the Type")
4159 .def(
"__eq__", [](
PyType &
self,
PyType &other) {
return self == other; })
4161 "__eq__", [](
PyType &
self, nb::object &other) {
return false; },
4162 nb::arg(
"other").none())
4175 return printAccum.
join();
4177 "Returns the assembly form of the type.")
4185 printAccum.
parts.append(
"Type(");
4188 printAccum.
parts.append(
")");
4189 return printAccum.
join();
4192 [](
PyType &
self) -> nb::typed<nb::object, PyType> {
4193 return self.maybeDownCast();
4195 .def_prop_ro(
"typeid", [](
PyType &
self) {
4199 auto origRepr = nb::cast<std::string>(nb::repr(nb::cast(
self)));
4200 throw nb::value_error(
4201 (origRepr + llvm::Twine(
" has no typeid.")).str().c_str());
4207 nb::class_<PyTypeID>(m,
"TypeID")
4216 [](
PyTypeID &
self,
const nb::object &other) {
return false; })
4220 .def(
"__hash__", [](
PyTypeID &
self) {
4227 nb::class_<PyValue>(m,
"Value")
4228 .def(nb::init<PyValue &>(), nb::keep_alive<0, 1>(), nb::arg(
"value"))
4233 [](
PyValue &
self) -> nb::typed<nb::object, PyMlirContext> {
4234 return self.getParentOperation()->
getContext().getObject();
4236 "Context in which the value lives.")
4242 [](
PyValue &
self) -> nb::object {
4243 MlirValue v =
self.get();
4247 "expected the owner of the value in Python to match "
4250 return self.getParentOperation().getObject();
4255 return nb::cast(
PyBlock(
self.getParentOperation(), block));
4258 assert(
false &&
"Value must be a block argument or an op result");
4262 nb::sig(
"def owner(self) -> Operation | Block | None"))
4264 .def_prop_ro(
"uses",
4266 return PyOpOperandIterator(
4271 return self.get().ptr == other.
get().ptr;
4273 .def(
"__eq__", [](
PyValue &
self, nb::object other) {
return false; })
4282 printAccum.
parts.append(
"Value(");
4285 printAccum.
parts.append(
")");
4286 return printAccum.
join();
4291 [](
PyValue &
self,
bool useLocalScope,
bool useNameLocAsPrefix) {
4296 if (useNameLocAsPrefix)
4298 MlirAsmState valueState =
4305 return printAccum.
join();
4307 nb::arg(
"use_local_scope") =
false,
4308 nb::arg(
"use_name_loc_as_prefix") =
false)
4313 MlirAsmState valueState = state.get();
4317 return printAccum.
join();
4320 .def_prop_ro(
"type",
4321 [](
PyValue &
self) -> nb::typed<nb::object, PyType> {
4333 "replace_all_uses_with",
4339 "replace_all_uses_except",
4341 MlirOperation exceptedUser = exception.
get();
4344 nb::arg(
"with_"), nb::arg(
"exceptions"),
4347 "replace_all_uses_except",
4351 for (nb::handle exception : exceptions) {
4352 exceptionOps.push_back(nb::cast<PyOperation &>(exception).
get());
4356 self, with,
static_cast<intptr_t
>(exceptionOps.size()),
4357 exceptionOps.data());
4359 nb::arg(
"with_"), nb::arg(
"exceptions"),
4362 "replace_all_uses_except",
4364 MlirOperation exceptedUser = exception.
get();
4367 nb::arg(
"with_"), nb::arg(
"exceptions"),
4370 "replace_all_uses_except",
4372 std::vector<PyOperation> &exceptions) {
4376 exceptionOps.push_back(exception);
4378 self, with,
static_cast<intptr_t
>(exceptionOps.size()),
4379 exceptionOps.data());
4381 nb::arg(
"with_"), nb::arg(
"exceptions"),
4384 [](
PyValue &
self) -> nb::typed<nb::object, PyValue> {
4385 return self.maybeDownCast();
4389 [](MlirValue
self) {
4394 "Returns the source location the value");
4396 PyBlockArgument::bind(m);
4397 PyOpResult::bind(m);
4398 PyOpOperand::bind(m);
4400 nb::class_<PyAsmState>(m,
"AsmState")
4401 .def(nb::init<PyValue &, bool>(), nb::arg(
"value"),
4402 nb::arg(
"use_local_scope") =
false)
4403 .def(nb::init<PyOperationBase &, bool>(), nb::arg(
"op"),
4404 nb::arg(
"use_local_scope") =
false);
4409 nb::class_<PySymbolTable>(m,
"SymbolTable")
4410 .def(nb::init<PyOperationBase &>())
4413 const std::string &name) -> nb::typed<nb::object, PyOpView> {
4414 return self.dunderGetItem(name);
4416 .def(
"insert", &PySymbolTable::insert, nb::arg(
"operation"))
4417 .def(
"erase", &PySymbolTable::erase, nb::arg(
"operation"))
4418 .def(
"__delitem__", &PySymbolTable::dunderDel)
4419 .def(
"__contains__",
4425 .def_static(
"set_symbol_name", &PySymbolTable::setSymbolName,
4426 nb::arg(
"symbol"), nb::arg(
"name"))
4427 .def_static(
"get_symbol_name", &PySymbolTable::getSymbolName,
4429 .def_static(
"get_visibility", &PySymbolTable::getVisibility,
4431 .def_static(
"set_visibility", &PySymbolTable::setVisibility,
4432 nb::arg(
"symbol"), nb::arg(
"visibility"))
4433 .def_static(
"replace_all_symbol_uses",
4434 &PySymbolTable::replaceAllSymbolUses, nb::arg(
"old_symbol"),
4435 nb::arg(
"new_symbol"), nb::arg(
"from_op"))
4436 .def_static(
"walk_symbol_tables", &PySymbolTable::walkSymbolTables,
4437 nb::arg(
"from_op"), nb::arg(
"all_sym_uses_visible"),
4438 nb::arg(
"callback"));
4441 PyBlockArgumentList::bind(m);
4442 PyBlockIterator::bind(m);
4443 PyBlockList::bind(m);
4444 PyBlockSuccessors::bind(m);
4445 PyBlockPredecessors::bind(m);
4446 PyOperationIterator::bind(m);
4447 PyOperationList::bind(m);
4448 PyOpAttributeMap::bind(m);
4449 PyOpOperandIterator::bind(m);
4450 PyOpOperandList::bind(m);
4452 PyOpSuccessors::bind(m);
4453 PyRegionIterator::bind(m);
4454 PyRegionList::bind(m);
4462 nb::register_exception_translator([](
const std::exception_ptr &p,
4468 std::rethrow_exception(p);
4472 PyErr_SetObject(PyExc_Exception, obj.ptr());
MLIR_CAPI_EXPORTED void mlirSetGlobalDebugType(const char *type)
Sets the current debug type, similarly to -debug-only=type in the command-line tools.
MLIR_CAPI_EXPORTED void mlirSetGlobalDebugTypes(const char **types, intptr_t n)
Sets multiple current debug types, similarly to `-debug-only=type1,type2" in the command-line tools.
MLIR_CAPI_EXPORTED bool mlirIsGlobalDebugEnabled()
Retuns true if the global debugging flag is set, false otherwise.
MLIR_CAPI_EXPORTED void mlirEnableGlobalDebug(bool enable)
Sets the global debugging flag.
static bool isBeforeInBlock(Block *block, Block::iterator a, Block::iterator b)
Given two iterators into the same block, return "true" if a is before `b.
static const char kOperationPrintStateDocstring[]
static const char kValueReplaceAllUsesWithDocstring[]
static const char kContextGetNameLocationDocString[]
static const char kGetNameAsOperand[]
static MlirStringRef toMlirStringRef(const std::string &s)
static const char kModuleParseDocstring[]
static const char kOperationStrDunderDocstring[]
static const char kOperationPrintDocstring[]
static nb::object classmethod(Func f, Args... args)
Helper for creating an @classmethod.
static MlirValue getUniqueResult(MlirOperation operation)
static const char kContextGetFileLocationDocstring[]
static const char kDumpDocstring[]
#define _Py_CAST(type, expr)
static const char kAppendBlockDocstring[]
static const char kModuleCAPICreate[]
static MlirValue getOpResultOrValue(nb::handle operand)
static std::vector< nb::typed< nb::object, PyType > > getValueTypes(Container &container, PyMlirContextRef &context)
Returns the list of types of the values held by container.
static const char kContextGetFusedLocationDocstring[]
static const char kContextGetFileRangeDocstring[]
static void maybeInsertOperation(PyOperationRef &op, const nb::object &maybeIp)
static nb::object createCustomDialectWrapper(const std::string &dialectNamespace, nb::object dialectDescriptor)
static const char kOperationPrintBytecodeDocstring[]
static const char kOperationGetAsmDocstring[]
static MlirBlock createBlock(const nb::sequence &pyArgTypes, const std::optional< nb::sequence > &pyArgLocs)
Create a block, using the current location context if no locations are specified.
static const char kOperationCreateDocstring[]
static const char kContextParseTypeDocstring[]
static void populateResultTypes(StringRef name, nb::list resultTypeList, const nb::object &resultSegmentSpecObj, std::vector< int32_t > &resultSegmentLengths, std::vector< PyType * > &resultTypes)
static const char kContextGetCallSiteLocationDocstring[]
static const char kValueDunderStrDocstring[]
static const char kValueReplaceAllUsesExceptDocstring[]
static MLIRContext * getContext(OpFoldResult val)
static PyObject * mlirPythonModuleToCapsule(MlirModule module)
Creates a capsule object encapsulating the raw C-API MlirModule.
#define MLIR_PYTHON_MAYBE_DOWNCAST_ATTR
Attribute on MLIR Python objects that expose a function for downcasting the corresponding Python obje...
static PyObject * mlirPythonTypeIDToCapsule(MlirTypeID typeID)
Creates a capsule object encapsulating the raw C-API MlirTypeID.
static MlirOperation mlirPythonCapsuleToOperation(PyObject *capsule)
Extracts an MlirOperations from a capsule as produced from mlirPythonOperationToCapsule.
#define MLIR_PYTHON_CAPI_PTR_ATTR
Attribute on MLIR Python objects that expose their C-API pointer.
static MlirAttribute mlirPythonCapsuleToAttribute(PyObject *capsule)
Extracts an MlirAttribute from a capsule as produced from mlirPythonAttributeToCapsule.
static PyObject * mlirPythonAttributeToCapsule(MlirAttribute attribute)
Creates a capsule object encapsulating the raw C-API MlirAttribute.
static PyObject * mlirPythonLocationToCapsule(MlirLocation loc)
Creates a capsule object encapsulating the raw C-API MlirLocation.
#define MLIR_PYTHON_CAPI_FACTORY_ATTR
Attribute on MLIR Python objects that exposes a factory function for constructing the corresponding P...
static MlirModule mlirPythonCapsuleToModule(PyObject *capsule)
Extracts an MlirModule from a capsule as produced from mlirPythonModuleToCapsule.
static MlirContext mlirPythonCapsuleToContext(PyObject *capsule)
Extracts a MlirContext from a capsule as produced from mlirPythonContextToCapsule.
static MlirTypeID mlirPythonCapsuleToTypeID(PyObject *capsule)
Extracts an MlirTypeID from a capsule as produced from mlirPythonTypeIDToCapsule.
static PyObject * mlirPythonDialectRegistryToCapsule(MlirDialectRegistry registry)
Creates a capsule object encapsulating the raw C-API MlirDialectRegistry.
static PyObject * mlirPythonTypeToCapsule(MlirType type)
Creates a capsule object encapsulating the raw C-API MlirType.
static MlirDialectRegistry mlirPythonCapsuleToDialectRegistry(PyObject *capsule)
Extracts an MlirDialectRegistry from a capsule as produced from mlirPythonDialectRegistryToCapsule.
#define MAKE_MLIR_PYTHON_QUALNAME(local)
static MlirType mlirPythonCapsuleToType(PyObject *capsule)
Extracts an MlirType from a capsule as produced from mlirPythonTypeToCapsule.
static MlirValue mlirPythonCapsuleToValue(PyObject *capsule)
Extracts an MlirValue from a capsule as produced from mlirPythonValueToCapsule.
static PyObject * mlirPythonBlockToCapsule(MlirBlock block)
Creates a capsule object encapsulating the raw C-API MlirBlock.
static PyObject * mlirPythonOperationToCapsule(MlirOperation operation)
Creates a capsule object encapsulating the raw C-API MlirOperation.
static MlirLocation mlirPythonCapsuleToLocation(PyObject *capsule)
Extracts an MlirLocation from a capsule as produced from mlirPythonLocationToCapsule.
static PyObject * mlirPythonValueToCapsule(MlirValue value)
Creates a capsule object encapsulating the raw C-API MlirValue.
static PyObject * mlirPythonContextToCapsule(MlirContext context)
Creates a capsule object encapsulating the raw C-API MlirContext.
static LogicalResult nextIndex(ArrayRef< int64_t > shape, MutableArrayRef< int64_t > index)
Walks over the indices of the elements of a tensor of a given shape by updating index in place to the...
static std::string diag(const llvm::Value &value)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static sycl::context getDefaultContext()
A list of operation results.
PyOperationRef & getOperation()
static void bindDerived(ClassTy &c)
PyOpResultList(PyOperationRef operation, intptr_t startIndex=0, intptr_t length=-1, intptr_t step=1)
Python wrapper for MlirOpResult.
static void bindDerived(ClassTy &c)
Accumulates into a file, either writing text (default) or binary.
MlirStringCallback getCallback()
A CRTP base class for pseudo-containers willing to support Python-type slicing access on top of index...
static void bind(nanobind::module_ &m)
Binds the indexing and length methods in the Python class.
nanobind::class_< PyOpResultList > ClassTy
Base class for all objects that directly or indirectly depend on an MlirContext.
PyMlirContextRef & getContext()
Accesses the context reference.
static PyLocation & resolve()
Used in function arguments when None should resolve to the current context manager set instance.
static PyMlirContext & resolve()
ReferrentTy * get() const
Wrapper around an MlirAsmState.
Wrapper around the generic MlirAttribute.
static PyAttribute createFromCapsule(const nanobind::object &capsule)
Creates a PyAttribute from the MlirAttribute wrapped by a capsule.
PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirAttribute.
nanobind::object maybeDownCast()
MlirAttribute get() const
bool operator==(const PyAttribute &other) const
Wrapper around an MlirBlock.
PyOperationRef & getParentOperation()
Represents a diagnostic handler attached to the context.
PyDiagnosticHandler(MlirContext context, nanobind::object callback)
void detach()
Detaches the handler. Does nothing if not attached.
Python class mirroring the C MlirDiagnostic struct.
nanobind::tuple getNotes()
nanobind::str getMessage()
PyDiagnostic(MlirDiagnostic diagnostic)
MlirDiagnosticSeverity getSeverity()
Wrapper around an MlirDialect.
Wrapper around an MlirDialectRegistry.
nanobind::object getCapsule()
static PyDialectRegistry createFromCapsule(nanobind::object capsule)
User-level dialect object.
User-level object for accessing dialects with dotted syntax such as: ctx.dialect.std.
MlirDialect getDialectForKey(const std::string &key, bool attrError)
std::optional< nanobind::callable > lookupValueCaster(MlirTypeID mlirTypeID, MlirDialect dialect)
Returns the custom value caster for MlirTypeID mlirTypeID.
std::optional< nanobind::object > lookupOperationClass(llvm::StringRef operationName)
Looks up a registered operation class (deriving from OpView) by operation name.
static PyGlobals & get()
Most code should get the globals via this static accessor.
std::optional< nanobind::callable > lookupTypeCaster(MlirTypeID mlirTypeID, MlirDialect dialect)
Returns the custom type caster for MlirTypeID mlirTypeID.
An insertion point maintains a pointer to a Block and a reference operation.
static PyInsertionPoint atBlockTerminator(PyBlock &block)
Shortcut to create an insertion point before the block terminator.
static PyInsertionPoint atBlockBegin(PyBlock &block)
Shortcut to create an insertion point at the beginning of the block.
void contextExit(const nanobind::object &excType, const nanobind::object &excVal, const nanobind::object &excTb)
static PyInsertionPoint after(PyOperationBase &op)
Shortcut to create an insertion point to the node after the specified operation.
PyInsertionPoint(const PyBlock &block)
Creates an insertion point positioned after the last operation in the block, but still inside the blo...
void insert(PyOperationBase &operationBase)
Inserts an operation.
static nanobind::object contextEnter(nanobind::object insertionPoint)
Enter and exit the context manager.
Wrapper around an MlirLocation.
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirLocation.
PyLocation(PyMlirContextRef contextRef, MlirLocation loc)
static PyLocation createFromCapsule(nanobind::object capsule)
Creates a PyLocation from the MlirLocation wrapped by a capsule.
void contextExit(const nanobind::object &excType, const nanobind::object &excVal, const nanobind::object &excTb)
static nanobind::object contextEnter(nanobind::object location)
Enter and exit the context manager.
MlirContext get()
Accesses the underlying MlirContext.
PyMlirContextRef getRef()
Gets a strong reference to this context, which will ensure it is kept alive for the life of the refer...
static size_t getLiveCount()
Gets the count of live context objects. Used for testing.
size_t getLiveModuleCount()
Gets the count of live modules associated with this context.
nanobind::object attachDiagnosticHandler(nanobind::object callback)
Attaches a Python callback as a diagnostic handler, returning a registration object (internally a PyD...
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirContext.
void contextExit(const nanobind::object &excType, const nanobind::object &excVal, const nanobind::object &excTb)
static PyMlirContextRef forContext(MlirContext context)
Returns a context reference for the singleton PyMlirContext wrapper for the given context.
static nanobind::object createFromCapsule(nanobind::object capsule)
Creates a PyMlirContext from the MlirContext wrapped by a capsule.
static nanobind::object contextEnter(nanobind::object context)
Enter and exit the context manager.
MlirModule get()
Gets the backing MlirModule.
static PyModuleRef forModule(MlirModule module)
Returns a PyModule reference for the given MlirModule.
static nanobind::object createFromCapsule(nanobind::object capsule)
Creates a PyModule from the MlirModule wrapped by a capsule.
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirModule.
PyModule(PyModule &)=delete
Represents a Python MlirNamedAttr, carrying an optional owned name.
PyNamedAttribute(MlirAttribute attr, std::string ownedName)
Constructs a PyNamedAttr that retains an owned name.
MlirNamedAttribute namedAttr
nanobind::object getObject()
nanobind::object releaseObject()
Releases the object held by this instance, returning it.
A PyOpView is equivalent to the C++ "Op" wrappers: these are the basis for providing more instance-sp...
static nanobind::object constructDerived(const nanobind::object &cls, const nanobind::object &operation)
Construct an instance of a class deriving from OpView, bypassing its __init__ method.
static nanobind::object buildGeneric(std::string_view name, std::tuple< int, bool > opRegionSpec, nanobind::object operandSegmentSpecObj, nanobind::object resultSegmentSpecObj, std::optional< nanobind::list > resultTypeList, nanobind::list operandList, std::optional< nanobind::dict > attributes, std::optional< std::vector< PyBlock * >> successors, std::optional< int > regions, PyLocation &location, const nanobind::object &maybeIp)
PyOpView(const nanobind::object &operationObject)
Base class for PyOperation and PyOpView which exposes the primary, user visible methods for manipulat...
void walk(std::function< MlirWalkResult(MlirOperation)> callback, MlirWalkOrder walkOrder)
bool isBeforeInBlock(PyOperationBase &other)
Given an operation 'other' that is within the same parent block, return whether the current operation...
virtual PyOperation & getOperation()=0
Each must provide access to the raw Operation.
nanobind::object getAsm(bool binary, std::optional< int64_t > largeElementsLimit, std::optional< int64_t > largeResourceLimit, bool enableDebugInfo, bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope, bool useNameLocAsPrefix, bool assumeVerified, bool skipRegions)
void moveAfter(PyOperationBase &other)
Moves the operation before or after the other operation.
void print(std::optional< int64_t > largeElementsLimit, std::optional< int64_t > largeResourceLimit, bool enableDebugInfo, bool prettyDebugInfo, bool printGenericOpForm, bool useLocalScope, bool useNameLocAsPrefix, bool assumeVerified, nanobind::object fileObject, bool binary, bool skipRegions)
Implements the bound 'print' method and helps with others.
void writeBytecode(const nanobind::object &fileObject, std::optional< int64_t > bytecodeVersion)
void moveBefore(PyOperationBase &other)
bool verify()
Verify the operation.
void detachFromParent()
Detaches the operation from its parent block and updates its state accordingly.
PyOperation(PyMlirContextRef contextRef, MlirOperation operation)
void erase()
Erases the underlying MlirOperation, removes its pointer from the parent context's live operations ma...
static nanobind::object createFromCapsule(const nanobind::object &capsule)
Creates a PyOperation from the MlirOperation wrapped by a capsule.
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirOperation.
static PyOperationRef createDetached(PyMlirContextRef contextRef, MlirOperation operation, nanobind::object parentKeepAlive=nanobind::object())
Creates a detached operation.
nanobind::object clone(const nanobind::object &ip)
Clones this operation.
PyOperation & getOperation() override
Each must provide access to the raw Operation.
MlirOperation get() const
static PyOperationRef forOperation(PyMlirContextRef contextRef, MlirOperation operation, nanobind::object parentKeepAlive=nanobind::object())
Returns a PyOperation for the given MlirOperation, optionally associating it with a parentKeepAlive.
void setAttached(const nanobind::object &parent=nanobind::object())
std::optional< PyOperationRef > getParentOperation()
Gets the parent operation or raises an exception if the operation has no parent.
static nanobind::object create(std::string_view name, std::optional< std::vector< PyType * >> results, llvm::ArrayRef< MlirValue > operands, std::optional< nanobind::dict > attributes, std::optional< std::vector< PyBlock * >> successors, int regions, PyLocation &location, const nanobind::object &ip, bool inferType)
Creates an operation. See corresponding python docstring.
nanobind::object createOpView()
Creates an OpView suitable for this operation.
PyBlock getBlock()
Gets the owning block or raises an exception if the operation has no owning block.
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.
void setInvalid()
Invalidate the operation.
Wrapper around an MlirRegion.
PyOperationRef & getParentOperation()
Bindings for MLIR symbol tables.
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 ...
static void walkSymbolTables(PyOperationBase &from, bool allSymUsesVisible, nanobind::object callback)
Walks all symbol tables under and including 'from'.
static void replaceAllSymbolUses(const std::string &oldSymbol, const std::string &newSymbol, PyOperationBase &from)
Replaces all symbol uses within an operation.
static void setVisibility(PyOperationBase &symbol, const std::string &visibility)
static void setSymbolName(PyOperationBase &symbol, const std::string &name)
PyStringAttribute insert(PyOperationBase &symbol)
Inserts the given operation into the symbol table.
void erase(PyOperationBase &symbol)
Removes the given operation from the symbol table and erases it.
PySymbolTable(PyOperationBase &operation)
Constructs a symbol table for the given operation.
static PyStringAttribute getSymbolName(PyOperationBase &symbol)
Gets and sets the name of a symbol op.
static PyStringAttribute getVisibility(PyOperationBase &symbol)
Gets and sets the visibility of a symbol op.
nanobind::object dunderGetItem(const std::string &name)
Returns the symbol (opview) with the given name, throws if there is no such symbol in the table.
Tracks an entry in the thread context stack.
static PyThreadContextEntry * getTopOfStack()
Stack management.
static void popLocation(PyLocation &location)
static nanobind::object pushLocation(nanobind::object location)
PyLocation * getLocation()
static nanobind::object pushContext(nanobind::object context)
static PyLocation * getDefaultLocation()
Gets the top of stack location and returns nullptr if not defined.
static void popInsertionPoint(PyInsertionPoint &insertionPoint)
static nanobind::object pushInsertionPoint(nanobind::object insertionPoint)
static void popContext(PyMlirContext &context)
static PyInsertionPoint * getDefaultInsertionPoint()
Gets the top of stack insertion point and return nullptr if not defined.
PyMlirContext * getContext()
static PyMlirContext * getDefaultContext()
Gets the top of stack context and return nullptr if not defined.
static std::vector< PyThreadContextEntry > & getStack()
Gets the thread local stack.
PyInsertionPoint * getInsertionPoint()
Wrapper around MlirLlvmThreadPool Python object owns the C++ thread pool.
A TypeID provides an efficient and unique identifier for a specific C++ type.
static PyTypeID createFromCapsule(nanobind::object capsule)
Creates a PyTypeID from the MlirTypeID wrapped by a capsule.
bool operator==(const PyTypeID &other) const
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirTypeID.
PyTypeID(MlirTypeID typeID)
Wrapper around the generic MlirType.
PyType(PyMlirContextRef contextRef, MlirType type)
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirType.
static PyType createFromCapsule(nanobind::object capsule)
Creates a PyType from the MlirType wrapped by a capsule.
nanobind::object maybeDownCast()
bool operator==(const PyType &other) const
Wrapper around the generic MlirValue.
PyValue(PyOperationRef parentOperation, MlirValue value)
static PyValue createFromCapsule(nanobind::object capsule)
Creates a PyValue from the MlirValue wrapped by a capsule.
nanobind::object maybeDownCast()
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirValue.
MLIR_CAPI_EXPORTED intptr_t mlirDiagnosticGetNumNotes(MlirDiagnostic diagnostic)
Returns the number of notes attached to the diagnostic.
MLIR_CAPI_EXPORTED MlirDiagnosticSeverity mlirDiagnosticGetSeverity(MlirDiagnostic diagnostic)
Returns the severity of the diagnostic.
MLIR_CAPI_EXPORTED void mlirDiagnosticPrint(MlirDiagnostic diagnostic, MlirStringCallback callback, void *userData)
Prints a diagnostic using the provided callback.
MlirDiagnosticSeverity
Severity of a diagnostic.
MLIR_CAPI_EXPORTED MlirDiagnostic mlirDiagnosticGetNote(MlirDiagnostic diagnostic, intptr_t pos)
Returns pos-th note attached to the diagnostic.
MLIR_CAPI_EXPORTED void mlirEmitError(MlirLocation location, const char *message)
Emits an error at the given location through the diagnostics engine.
MLIR_CAPI_EXPORTED MlirDiagnosticHandlerID mlirContextAttachDiagnosticHandler(MlirContext context, MlirDiagnosticHandler handler, void *userData, void(*deleteUserData)(void *))
Attaches the diagnostic handler to the context.
MLIR_CAPI_EXPORTED void mlirContextDetachDiagnosticHandler(MlirContext context, MlirDiagnosticHandlerID id)
Detaches an attached diagnostic handler from the context given its identifier.
uint64_t MlirDiagnosticHandlerID
Opaque identifier of a diagnostic handler, useful to detach a handler.
MLIR_CAPI_EXPORTED MlirLocation mlirDiagnosticGetLocation(MlirDiagnostic diagnostic)
Returns the location at which the diagnostic is reported.
MlirDiagnostic wrap(mlir::Diagnostic &diagnostic)
MLIR_CAPI_EXPORTED MlirAttribute mlirDenseI32ArrayGet(MlirContext ctx, intptr_t size, int32_t const *values)
MLIR_CAPI_EXPORTED MlirAttribute mlirStringAttrGet(MlirContext ctx, MlirStringRef str)
Creates a string attribute in the given context containing the given string.
MLIR_CAPI_EXPORTED MlirAttribute mlirLocationGetAttribute(MlirLocation location)
Returns the underlying location attribute of this location.
MLIR_CAPI_EXPORTED intptr_t mlirBlockArgumentGetArgNumber(MlirValue value)
Returns the position of the value in the argument list of its block.
static bool mlirAttributeIsNull(MlirAttribute attr)
Checks whether an attribute is null.
MlirWalkResult(* MlirOperationWalkCallback)(MlirOperation, void *userData)
Operation walker type.
MLIR_CAPI_EXPORTED MlirLocation mlirValueGetLocation(MlirValue v)
Gets the location of the value.
MLIR_CAPI_EXPORTED unsigned mlirContextGetNumThreads(MlirContext context)
Gets the number of threads of the thread pool of the context when multithreading is enabled.
MLIR_CAPI_EXPORTED void mlirOperationWriteBytecode(MlirOperation op, MlirStringCallback callback, void *userData)
Same as mlirOperationPrint but writing the bytecode format.
MLIR_CAPI_EXPORTED MlirIdentifier mlirOperationGetName(MlirOperation op)
Gets the name of the operation as an identifier.
MLIR_CAPI_EXPORTED MlirLocation mlirLocationFileLineColGet(MlirContext context, MlirStringRef filename, unsigned line, unsigned col)
Creates an File/Line/Column location owned by the given context.
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.
MLIR_CAPI_EXPORTED MlirStringRef mlirDialectGetNamespace(MlirDialect dialect)
Returns the namespace of the given dialect.
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumResults(MlirOperation op)
Returns the number of results of the operation.
MLIR_CAPI_EXPORTED int mlirLocationFileLineColRangeGetEndColumn(MlirLocation location)
Getter for end_column of FileLineColRange.
MLIR_CAPI_EXPORTED MlirAttribute mlirSymbolTableInsert(MlirSymbolTable symbolTable, MlirOperation operation)
Inserts the given operation into the given symbol table.
MlirWalkOrder
Traversal order for operation walk.
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsPrintNameLocAsPrefix(MlirOpPrintingFlags flags)
Print the name and location, if NamedLoc, as a prefix to the SSA ID.
MLIR_CAPI_EXPORTED MlirNamedAttribute mlirOperationGetAttribute(MlirOperation op, intptr_t pos)
Return pos-th attribute of the operation.
MLIR_CAPI_EXPORTED void mlirOperationStateAddOperands(MlirOperationState *state, intptr_t n, MlirValue const *operands)
MLIR_CAPI_EXPORTED void mlirModuleDestroy(MlirModule module)
Takes a module owned by the caller and deletes it.
MLIR_CAPI_EXPORTED MlirNamedAttribute mlirNamedAttributeGet(MlirIdentifier name, MlirAttribute attr)
Associates an attribute with the name. Takes ownership of neither.
MLIR_CAPI_EXPORTED MlirLocation mlirLocationNameGetChildLoc(MlirLocation location)
Getter for childLoc of Name.
MLIR_CAPI_EXPORTED void mlirSymbolTableErase(MlirSymbolTable symbolTable, MlirOperation operation)
Removes the given operation from the symbol table and erases it.
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsUseLocalScope(MlirOpPrintingFlags flags)
Use local scope when printing the operation.
MLIR_CAPI_EXPORTED bool mlirValueIsABlockArgument(MlirValue value)
Returns 1 if the value is a block argument, 0 otherwise.
MLIR_CAPI_EXPORTED void mlirContextAppendDialectRegistry(MlirContext ctx, MlirDialectRegistry registry)
Append the contents of the given dialect registry to the registry associated with the context.
MLIR_CAPI_EXPORTED MlirStringRef mlirIdentifierStr(MlirIdentifier ident)
Gets the string value of the identifier.
static bool mlirModuleIsNull(MlirModule module)
Checks whether a module is null.
MLIR_CAPI_EXPORTED MlirType mlirTypeParseGet(MlirContext context, MlirStringRef type)
Parses a type. The type is owned by the context.
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...
MLIR_CAPI_EXPORTED MlirType mlirAttributeGetType(MlirAttribute attribute)
Gets the type of this attribute.
MLIR_CAPI_EXPORTED void mlirContextSetAllowUnregisteredDialects(MlirContext context, bool allow)
Sets whether unregistered dialects are allowed in this context.
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 ...
MLIR_CAPI_EXPORTED bool mlirLocationIsAFileLineColRange(MlirLocation location)
Checks whether the given location is an FileLineColRange.
MLIR_CAPI_EXPORTED MlirBlock mlirBlockGetSuccessor(MlirBlock block, intptr_t pos)
Returns pos-th successor of the block.
MLIR_CAPI_EXPORTED unsigned mlirLocationFusedGetNumLocations(MlirLocation location)
Getter for number of locations fused together.
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...
MLIR_CAPI_EXPORTED MlirBlock mlirOperationGetSuccessor(MlirOperation op, intptr_t pos)
Returns pos-th successor of the operation.
MLIR_CAPI_EXPORTED void mlirValuePrintAsOperand(MlirValue value, MlirAsmState state, MlirStringCallback callback, void *userData)
Prints a value as an operand (i.e., the ValueID).
MLIR_CAPI_EXPORTED MlirLocation mlirLocationUnknownGet(MlirContext context)
Creates a location with unknown position owned by the given context.
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`.
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.
MLIR_CAPI_EXPORTED MlirOperation mlirOpOperandGetOwner(MlirOpOperand opOperand)
Returns the owner operation of an op operand.
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsElideLargeResourceString(MlirOpPrintingFlags flags, intptr_t largeResourceLimit)
Enables the elision of large resources strings by omitting them from the dialect_resources section.
MLIR_CAPI_EXPORTED MlirIdentifier mlirLocationFileLineColRangeGetFilename(MlirLocation location)
Getter for filename of FileLineColRange.
MLIR_CAPI_EXPORTED MlirDialect mlirAttributeGetDialect(MlirAttribute attribute)
Gets the dialect of the attribute.
MLIR_CAPI_EXPORTED void mlirLocationFusedGetLocations(MlirLocation location, MlirLocation *locationsCPtr)
Getter for locations of Fused.
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...
MLIR_CAPI_EXPORTED MlirRegion mlirBlockGetParentRegion(MlirBlock block)
Returns the region that contains this block.
MLIR_CAPI_EXPORTED void mlirOperationMoveBefore(MlirOperation op, MlirOperation other)
Moves the given operation immediately before the other operation in its parent block.
static bool mlirValueIsNull(MlirValue value)
Returns whether the value is null.
MLIR_CAPI_EXPORTED void mlirValueReplaceAllUsesExcept(MlirValue of, MlirValue with, intptr_t numExceptions, MlirOperation *exceptions)
Replace all uses of 'of' value with 'with' value, updating anything in the IR that uses 'of' to use '...
MLIR_CAPI_EXPORTED void mlirOperationPrintWithState(MlirOperation op, MlirAsmState state, MlirStringCallback callback, void *userData)
Same as mlirOperationPrint but accepts AsmState controlling the printing behavior as well as caching ...
MlirWalkResult
Operation walk result.
@ MlirWalkResultInterrupt
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.
MLIR_CAPI_EXPORTED MlirAttribute mlirOperationGetAttributeByName(MlirOperation op, MlirStringRef name)
Returns an attribute attached to the operation given its name.
static bool mlirTypeIsNull(MlirType type)
Checks whether a type is null.
MLIR_CAPI_EXPORTED MlirBlock mlirBlockGetPredecessor(MlirBlock block, intptr_t pos)
Returns pos-th predecessor of the block.
MLIR_CAPI_EXPORTED bool mlirContextIsRegisteredOperation(MlirContext context, MlirStringRef name)
Returns whether the given fully-qualified operation (i.e.
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumSuccessors(MlirOperation op)
Returns the number of successor blocks of the operation.
MLIR_CAPI_EXPORTED MlirOperation mlirOperationClone(MlirOperation op)
Creates a deep copy of an operation.
MLIR_CAPI_EXPORTED intptr_t mlirBlockGetNumArguments(MlirBlock block)
Returns the number of arguments of the block.
MLIR_CAPI_EXPORTED int mlirLocationFileLineColRangeGetStartLine(MlirLocation location)
Getter for start_line of FileLineColRange.
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsPrintGenericOpForm(MlirOpPrintingFlags flags)
Always print operations in the generic form.
MLIR_CAPI_EXPORTED bool mlirModuleEqual(MlirModule lhs, MlirModule rhs)
Checks if two modules are equal.
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.
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...
MLIR_CAPI_EXPORTED void mlirAsmStateDestroy(MlirAsmState state)
Destroys printing flags created with mlirAsmStateCreate.
static bool mlirContextIsNull(MlirContext context)
Checks whether a context is null.
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,...
MLIR_CAPI_EXPORTED bool mlirLocationIsACallSite(MlirLocation location)
Checks whether the given location is an CallSite.
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...
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...
MLIR_CAPI_EXPORTED void mlirBlockArgumentSetType(MlirValue value, MlirType type)
Sets the type of the block argument to the given type.
MLIR_CAPI_EXPORTED MlirContext mlirOperationGetContext(MlirOperation op)
Gets the context this operation is associated with.
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.
static bool mlirBlockIsNull(MlirBlock block)
Checks whether a block is null.
MLIR_CAPI_EXPORTED void mlirBlockAppendOwnedOperation(MlirBlock block, MlirOperation operation)
Takes an operation owned by the caller and appends it to the block.
MLIR_CAPI_EXPORTED MlirValue mlirBlockGetArgument(MlirBlock block, intptr_t pos)
Returns pos-th argument of the block.
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...
MLIR_CAPI_EXPORTED MlirContext mlirTypeGetContext(MlirType type)
Gets the context that a type was created with.
MLIR_CAPI_EXPORTED MlirLocation mlirLocationFileLineColRangeGet(MlirContext context, MlirStringRef filename, unsigned start_line, unsigned start_col, unsigned end_line, unsigned end_col)
Creates an File/Line/Column range location owned by the given context.
MLIR_CAPI_EXPORTED void mlirValueDump(MlirValue value)
Prints the value to the standard error stream.
MLIR_CAPI_EXPORTED MlirModule mlirModuleCreateEmpty(MlirLocation location)
Creates a new, empty module and transfers ownership to the caller.
MLIR_CAPI_EXPORTED bool mlirOpOperandIsNull(MlirOpOperand opOperand)
Returns whether the op operand is null.
MLIR_CAPI_EXPORTED MlirSymbolTable mlirSymbolTableCreate(MlirOperation operation)
Creates a symbol table for the given operation.
MLIR_CAPI_EXPORTED bool mlirLocationEqual(MlirLocation l1, MlirLocation l2)
Checks if two locations are equal.
MLIR_CAPI_EXPORTED int mlirLocationFileLineColRangeGetStartColumn(MlirLocation location)
Getter for start_column of FileLineColRange.
MLIR_CAPI_EXPORTED bool mlirLocationIsAFused(MlirLocation location)
Checks whether the given location is an Fused.
MLIR_CAPI_EXPORTED MlirBlock mlirOperationGetBlock(MlirOperation op)
Gets the block that owns this operation, returning null if the operation is not owned.
static bool mlirLocationIsNull(MlirLocation location)
Checks if the location is null.
MLIR_CAPI_EXPORTED intptr_t mlirBlockGetNumPredecessors(MlirBlock block)
Returns the number of predecessor blocks of the block.
MLIR_CAPI_EXPORTED bool mlirOperationEqual(MlirOperation op, MlirOperation other)
Checks whether two operation handles point to the same operation.
MLIR_CAPI_EXPORTED MlirValue mlirBlockAddArgument(MlirBlock block, MlirType type, MlirLocation loc)
Appends an argument of the specified type to the block.
MLIR_CAPI_EXPORTED void mlirOperationPrintWithFlags(MlirOperation op, MlirOpPrintingFlags flags, MlirStringCallback callback, void *userData)
Same as mlirOperationPrint but accepts flags controlling the printing behavior.
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...
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`.
MLIR_CAPI_EXPORTED void mlirContextSetThreadPool(MlirContext context, MlirLlvmThreadPool threadPool)
Sets the thread pool of the context explicitly, enabling multithreading in the process.
MLIR_CAPI_EXPORTED bool mlirOperationVerify(MlirOperation op)
Verify the operation and return true if it passes, false if it fails.
MLIR_CAPI_EXPORTED MlirOperation mlirModuleGetOperation(MlirModule module)
Views the module as a generic operation.
MLIR_CAPI_EXPORTED bool mlirTypeEqual(MlirType t1, MlirType t2)
Checks if two types are equal.
MLIR_CAPI_EXPORTED MlirOperationState mlirOperationStateGet(MlirStringRef name, MlirLocation loc)
Constructs an operation state from a name and a location.
MLIR_CAPI_EXPORTED unsigned mlirOpOperandGetOperandNumber(MlirOpOperand opOperand)
Returns the operand number of an op operand.
MLIR_CAPI_EXPORTED MlirLocation mlirLocationCallSiteGetCaller(MlirLocation location)
Getter for caller of CallSite.
MLIR_CAPI_EXPORTED MlirOperation mlirBlockGetTerminator(MlirBlock block)
Returns the terminator operation in the block or null if no terminator.
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsSkipRegions(MlirOpPrintingFlags flags)
Skip printing regions.
MLIR_CAPI_EXPORTED MlirIdentifier mlirLocationNameGetName(MlirLocation location)
Getter for name of Name.
MLIR_CAPI_EXPORTED MlirOperation mlirOperationGetNextInBlock(MlirOperation op)
Returns an operation immediately following the given operation it its enclosing block.
MLIR_CAPI_EXPORTED bool mlirOperationIsBeforeInBlock(MlirOperation op, MlirOperation other)
Given an operation 'other' that is within the same parent block, return whether the current operation...
MLIR_CAPI_EXPORTED MlirOperation mlirOperationGetParentOperation(MlirOperation op)
Gets the operation that owns this operation, returning null if the operation is not owned.
MLIR_CAPI_EXPORTED void mlirOperationSetLocation(MlirOperation op, MlirLocation loc)
Sets the location of the operation.
MLIR_CAPI_EXPORTED MlirContext mlirModuleGetContext(MlirModule module)
Gets the context that a module was created with.
MLIR_CAPI_EXPORTED MlirLocation mlirLocationFromAttribute(MlirAttribute attribute)
Creates a location from a location attribute.
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsAssumeVerified(MlirOpPrintingFlags flags)
Do not verify the operation when using custom operation printers.
MLIR_CAPI_EXPORTED MlirTypeID mlirTypeGetTypeID(MlirType type)
Gets the type ID of the type.
MLIR_CAPI_EXPORTED MlirStringRef mlirSymbolTableGetVisibilityAttributeName(void)
Returns the name of the attribute used to store symbol visibility.
static bool mlirDialectIsNull(MlirDialect dialect)
Checks if the dialect is null.
MLIR_CAPI_EXPORTED void mlirBytecodeWriterConfigDestroy(MlirBytecodeWriterConfig config)
Destroys printing flags created with mlirBytecodeWriterConfigCreate.
MLIR_CAPI_EXPORTED MlirValue mlirOperationGetOperand(MlirOperation op, intptr_t pos)
Returns pos-th operand of the operation.
MLIR_CAPI_EXPORTED void mlirOperationStateAddAttributes(MlirOperationState *state, intptr_t n, MlirNamedAttribute const *attributes)
MLIR_CAPI_EXPORTED MlirBlock mlirBlockGetNextInRegion(MlirBlock block)
Returns the block immediately following the given block in its parent region.
MLIR_CAPI_EXPORTED MlirLocation mlirLocationCallSiteGet(MlirLocation callee, MlirLocation caller)
Creates a call site location with a callee and a caller.
MLIR_CAPI_EXPORTED bool mlirLocationIsAName(MlirLocation location)
Checks whether the given location is an Name.
MLIR_CAPI_EXPORTED MlirOperation mlirOpResultGetOwner(MlirValue value)
Returns an operation that produced this value as its result.
MLIR_CAPI_EXPORTED bool mlirValueIsAOpResult(MlirValue value)
Returns 1 if the value is an operation result, 0 otherwise.
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumOperands(MlirOperation op)
Returns the number of operands of the operation.
static bool mlirDialectRegistryIsNull(MlirDialectRegistry registry)
Checks if the dialect registry is null.
MLIR_CAPI_EXPORTED void mlirOperationWalk(MlirOperation op, MlirOperationWalkCallback callback, void *userData, MlirWalkOrder walkOrder)
Walks operation op in walkOrder and calls callback on that operation.
MLIR_CAPI_EXPORTED MlirContext mlirContextCreateWithThreading(bool threadingEnabled)
Creates an MLIR context with an explicit setting of the multithreading setting and transfers its owne...
MLIR_CAPI_EXPORTED MlirOperation mlirBlockGetParentOperation(MlirBlock)
Returns the closest surrounding operation that contains this block.
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumRegions(MlirOperation op)
Returns the number of regions attached to the given operation.
MLIR_CAPI_EXPORTED MlirContext mlirLocationGetContext(MlirLocation location)
Gets the context that a location was created with.
MLIR_CAPI_EXPORTED void mlirBlockEraseArgument(MlirBlock block, unsigned index)
Erase the argument at 'index' and remove it from the argument list.
MLIR_CAPI_EXPORTED bool mlirOperationRemoveAttributeByName(MlirOperation op, MlirStringRef name)
Removes an attribute by name.
MLIR_CAPI_EXPORTED void mlirAttributeDump(MlirAttribute attr)
Prints the attribute to the standard error stream.
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...
MLIR_CAPI_EXPORTED MlirAttribute mlirAttributeParseGet(MlirContext context, MlirStringRef attr)
Parses an attribute. The attribute is owned by the context.
MLIR_CAPI_EXPORTED MlirModule mlirModuleCreateParse(MlirContext context, MlirStringRef module)
Parses a module from the string and transfers ownership to the caller.
MLIR_CAPI_EXPORTED size_t mlirOperationHashValue(MlirOperation op)
Compute a hash for the given operation.
MLIR_CAPI_EXPORTED void mlirRegionAppendOwnedBlock(MlirRegion region, MlirBlock block)
Takes a block owned by the caller and appends it to the given region.
MLIR_CAPI_EXPORTED MlirOperation mlirBlockGetFirstOperation(MlirBlock block)
Returns the first operation in the block.
MLIR_CAPI_EXPORTED void mlirTypeDump(MlirType type)
Prints the type to the standard error stream.
MLIR_CAPI_EXPORTED MlirValue mlirOperationGetResult(MlirOperation op, intptr_t pos)
Returns pos-th result of the operation.
MLIR_CAPI_EXPORTED MlirBytecodeWriterConfig mlirBytecodeWriterConfigCreate(void)
Creates new printing flags with defaults, intended for customization.
MLIR_CAPI_EXPORTED MlirContext mlirAttributeGetContext(MlirAttribute attribute)
Gets the context that an attribute was created with.
MLIR_CAPI_EXPORTED MlirBlock mlirBlockArgumentGetOwner(MlirValue value)
Returns the block in which this value is defined as an argument.
static bool mlirRegionIsNull(MlirRegion region)
Checks whether a region is null.
MLIR_CAPI_EXPORTED void mlirOperationDestroy(MlirOperation op)
Takes an operation owned by the caller and destroys it.
MLIR_CAPI_EXPORTED intptr_t mlirBlockGetNumSuccessors(MlirBlock block)
Returns the number of successor blocks of the block.
MLIR_CAPI_EXPORTED MlirRegion mlirOperationGetRegion(MlirOperation op, intptr_t pos)
Returns pos-th region attached to the operation.
MLIR_CAPI_EXPORTED MlirDialect mlirTypeGetDialect(MlirType type)
Gets the dialect a type belongs to.
MLIR_CAPI_EXPORTED MlirIdentifier mlirIdentifierGet(MlirContext context, MlirStringRef str)
Gets an identifier with the given string value.
MLIR_CAPI_EXPORTED void mlirOperationSetSuccessor(MlirOperation op, intptr_t pos, MlirBlock block)
Set pos-th successor of the operation.
MLIR_CAPI_EXPORTED void mlirContextLoadAllAvailableDialects(MlirContext context)
Eagerly loads all available dialects registered with a context, making them available for use for IR ...
MLIR_CAPI_EXPORTED void mlirOperationStateAddOwnedRegions(MlirOperationState *state, intptr_t n, MlirRegion const *regions)
MLIR_CAPI_EXPORTED void mlirOperationStateAddSuccessors(MlirOperationState *state, intptr_t n, MlirBlock const *successors)
MLIR_CAPI_EXPORTED MlirLlvmThreadPool mlirContextGetThreadPool(MlirContext context)
Gets the thread pool of the context when enabled multithreading, otherwise an assertion is raised.
MLIR_CAPI_EXPORTED MlirBlock mlirModuleGetBody(MlirModule module)
Gets the body of the module, i.e. the only block it contains.
MLIR_CAPI_EXPORTED int mlirLocationFileLineColRangeGetEndLine(MlirLocation location)
Getter for end_line of FileLineColRange.
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsDestroy(MlirOpPrintingFlags flags)
Destroys printing flags created with mlirOpPrintingFlagsCreate.
MLIR_CAPI_EXPORTED MlirLocation mlirLocationNameGet(MlirContext context, MlirStringRef name, MlirLocation childLoc)
Creates a name location owned by the given context.
MLIR_CAPI_EXPORTED void mlirContextEnableMultithreading(MlirContext context, bool enable)
Set threading mode (must be set to false to mlir-print-ir-after-all).
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`.
MLIR_CAPI_EXPORTED MlirLocation mlirLocationCallSiteGetCallee(MlirLocation location)
Getter for callee of CallSite.
MLIR_CAPI_EXPORTED MlirContext mlirValueGetContext(MlirValue v)
Gets the context that a value was created with.
MLIR_CAPI_EXPORTED void mlirBytecodeWriterConfigDesiredEmitVersion(MlirBytecodeWriterConfig flags, int64_t version)
Sets the version to emit in the writer config.
MLIR_CAPI_EXPORTED MlirStringRef mlirSymbolTableGetSymbolAttributeName(void)
Returns the name of the attribute used to store symbol names compatible with symbol tables.
MLIR_CAPI_EXPORTED MlirRegion mlirRegionCreate(void)
Creates a new empty region and transfers ownership to the caller.
MLIR_CAPI_EXPORTED MlirModule mlirModuleCreateParseFromFile(MlirContext context, MlirStringRef fileName)
Parses a module from file and transfers ownership to the caller.
MLIR_CAPI_EXPORTED void mlirBlockDetach(MlirBlock block)
Detach a block from the owning region and assume ownership.
MLIR_CAPI_EXPORTED void mlirOperationStateAddResults(MlirOperationState *state, intptr_t n, MlirType const *results)
Adds a list of components to the operation state.
MLIR_CAPI_EXPORTED void mlirOpPrintingFlagsEnableDebugInfo(MlirOpPrintingFlags flags, bool enable, bool prettyForm)
Enable or disable printing of debug information (based on enable).
MLIR_CAPI_EXPORTED MlirLocation mlirOperationGetLocation(MlirOperation op)
Gets the location of the operation.
MLIR_CAPI_EXPORTED MlirTypeID mlirAttributeGetTypeID(MlirAttribute attribute)
Gets the type id of the attribute.
MLIR_CAPI_EXPORTED void mlirOperationSetOperand(MlirOperation op, intptr_t pos, MlirValue newValue)
Sets the pos-th operand of the operation.
MLIR_CAPI_EXPORTED void mlirOperationDump(MlirOperation op)
Prints an operation to stderr.
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.
MLIR_CAPI_EXPORTED MlirOpPrintingFlags mlirOpPrintingFlagsCreate(void)
Creates new printing flags with defaults, intended for customization.
MLIR_CAPI_EXPORTED MlirAsmState mlirAsmStateCreateForValue(MlirValue value, MlirOpPrintingFlags flags)
Creates new AsmState from value.
MLIR_CAPI_EXPORTED MlirOperation mlirOperationCreate(MlirOperationState *state)
Creates an operation and transfers ownership to the caller.
static bool mlirSymbolTableIsNull(MlirSymbolTable symbolTable)
Returns true if the symbol table is null.
MLIR_CAPI_EXPORTED bool mlirContextGetAllowUnregisteredDialects(MlirContext context)
Returns whether the context allows unregistered dialects.
MLIR_CAPI_EXPORTED void mlirOperationMoveAfter(MlirOperation op, MlirOperation other)
Moves the given operation immediately after the other operation in its parent block.
MLIR_CAPI_EXPORTED intptr_t mlirOperationGetNumAttributes(MlirOperation op)
Returns the number of attributes attached to the operation.
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`.
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...
MLIR_CAPI_EXPORTED void mlirValueSetType(MlirValue value, MlirType type)
Set the type of the value.
MLIR_CAPI_EXPORTED MlirType mlirValueGetType(MlirValue value)
Returns the type of the value.
MLIR_CAPI_EXPORTED void mlirContextDestroy(MlirContext context)
Takes an MLIR context owned by the caller and destroys it.
MLIR_CAPI_EXPORTED size_t mlirModuleHashValue(MlirModule mod)
Compute a hash for the given module.
MLIR_CAPI_EXPORTED MlirOperation mlirOperationCreateParse(MlirContext context, MlirStringRef sourceStr, MlirStringRef sourceName)
Parses an operation, giving ownership to the caller.
MLIR_CAPI_EXPORTED bool mlirAttributeEqual(MlirAttribute a1, MlirAttribute a2)
Checks if two attributes are equal.
static bool mlirOperationIsNull(MlirOperation op)
Checks whether the underlying operation is null.
MLIR_CAPI_EXPORTED MlirBlock mlirRegionGetFirstBlock(MlirRegion region)
Gets the first block in the region.
static MlirStringRef mlirStringRefCreate(const char *str, size_t length)
Constructs a string reference from the pointer and length.
static MlirLogicalResult mlirLogicalResultFailure(void)
Creates a logical result representing a failure.
MLIR_CAPI_EXPORTED size_t mlirTypeIDHashValue(MlirTypeID typeID)
Returns the hash value of the type id.
static MlirLogicalResult mlirLogicalResultSuccess(void)
Creates a logical result representing a success.
static bool mlirLogicalResultIsFailure(MlirLogicalResult res)
Checks if the given logical result represents a failure.
static bool mlirTypeIDIsNull(MlirTypeID typeID)
Checks whether a type id is null.
MLIR_CAPI_EXPORTED bool mlirTypeIDEqual(MlirTypeID typeID1, MlirTypeID typeID2)
Checks if two type ids are equal.
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
PyObjectRef< PyMlirContext > PyMlirContextRef
Wrapper around MlirContext.
PyObjectRef< PyModule > PyModuleRef
void populateIRCore(nanobind::module_ &m)
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
llvm::hash_code hash_value(const StructType::MemberDecorationInfo &memberDecorationInfo)
Include the generated interface declarations.
const FrozenRewritePatternSet GreedyRewriteConfig config
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,...
An opaque reference to a diagnostic, always owned by the diagnostics engine (context).
A logical result value, essentially a boolean with named states.
An auxiliary class for constructing operations.
A pointer to a sized fragment of a string, not necessarily null-terminated.
const char * data
Pointer to the first symbol.
size_t length
Length of the fragment.
static bool dunderContains(const std::string &attributeKind)
static void dunderSetItemNamed(const std::string &attributeKind, nb::callable func, bool replace)
static nb::callable dunderGetItemNamed(const std::string &attributeKind)
static void bind(nb::module_ &m)
Wrapper for the global LLVM debugging flag.
static void bind(nb::module_ &m)
static void set(nb::object &o, bool enable)
static bool get(const nb::object &)
Accumulates into a python string from a method that accepts an MlirStringCallback.
MlirStringCallback getCallback()
Custom exception that allows access to error diagnostic information.
std::vector< PyDiagnostic::DiagnosticInfo > errorDiagnostics
Materialized diagnostic information.
RAII object that captures any error diagnostics emitted to the provided context.
std::vector< PyDiagnostic::DiagnosticInfo > take()
ErrorCapture(PyMlirContextRef ctx)