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 new operation.
74 name: Operation name (e.g. "dialect.operation").
75 results: Sequence of Type representing op result types.
76 attributes: Dict of str:Attribute.
77 successors: List of Block for the operation's successors.
78 regions: Number of regions to create.
79 location: A Location object (defaults to resolve from context manager).
80 ip: An InsertionPoint (defaults to resolve from context manager or set to
81 False to disable insertion, even with an insertion point set in the
83 infer_type: Whether to infer result types.
85 A new "detached" Operation object. Detached operations can be added
86 to blocks, which causes them to become "attached."
90 R
"(Prints the assembly form of the operation to a file like object.
93 file: The file like object to write to. Defaults to sys.stdout.
94 binary: Whether to write bytes (True) or str (False). Defaults to False.
95 large_elements_limit: Whether to elide elements attributes above this
96 number of elements. Defaults to None (no limit).
97 large_resource_limit: Whether to elide resource attributes above this
98 number of characters. Defaults to None (no limit). If large_elements_limit
99 is set and this is None, the behavior will be to use large_elements_limit
100 as large_resource_limit.
101 enable_debug_info: Whether to print debug/location information. Defaults
103 pretty_debug_info: Whether to format debug information for easier reading
104 by a human (warning: the result is unparseable).
105 print_generic_op_form: Whether to print the generic assembly forms of all
106 ops. Defaults to False.
107 use_local_Scope: Whether to print in a way that is more optimized for
108 multi-threaded access but may not be consistent with how the overall
110 assume_verified: By default, if not printing generic form, the verifier
111 will be run and if it fails, generic form will be printed with a comment
112 about failed verification. While a reasonable default for interactive use,
113 for systematic use, it is often better for the caller to verify explicitly
114 and report failures in a more robust fashion. Set this to True if doing this
115 in order to avoid running a redundant verification. If the IR is actually
116 invalid, behavior is undefined.
117 skip_regions: Whether to skip printing regions. Defaults to False.
121 R
"(Prints the assembly form of the operation to a file like object.
124 file: The file like object to write to. Defaults to sys.stdout.
125 binary: Whether to write bytes (True) or str (False). Defaults to False.
126 state: AsmState capturing the operation numbering and flags.
130 R
"(Gets the assembly form of the operation with all options available.
133 binary: Whether to return a bytes (True) or str (False) object. Defaults to
135 ... others ...: See the print() method for common keyword arguments for
136 configuring the printout.
138 Either a bytes or str object, depending on the setting of the 'binary'
143 R
"(Write the bytecode form of the operation to a file like object.
146 file: The file like object to write to.
147 desired_version: The version of bytecode to emit.
149 The bytecode writer status.
153 R
"(Gets the assembly form of the operation with default options.
155 If more advanced control over the assembly formatting or I/O options is needed,
156 use the dedicated print or get_asm method, which supports keyword arguments to
161 R
"(Dumps a debug representation of the object to stderr.)";
164 R
"(Appends a new block, with argument types as positional args.
171 R
"(Returns the string form of the value.
173 If the value is a block argument, this is the assembly form of its type and the
174 position in the argument list. If the value is an operation result, this is
175 equivalent to printing the operation that produced it.
179 R
"(Returns the string form of value as an operand (i.e., the ValueID).
183 R
"(Replace all uses of value with the new value, updating anything in
184 the IR that uses 'self' to use the other value instead.
188 R
"("Replace all uses of this value with the 'with' value, except for those
189 in 'exceptions'. 'exceptions' can be either a single operation or a list of
198 template <
class Func,
typename... Args>
200 nb::object cf = nb::cpp_function(f, args...);
201 return nb::borrow<nb::object>((PyClassMethod_New(cf.ptr())));
206 nb::object dialectDescriptor) {
207 auto dialectClass =
PyGlobals::get().lookupDialectClass(dialectNamespace);
210 return nb::cast(
PyDialect(std::move(dialectDescriptor)));
214 return (*dialectClass)(std::move(dialectDescriptor));
232 const std::optional<nb::sequence> &pyArgLocs) {
234 argTypes.reserve(nb::len(pyArgTypes));
235 for (
const auto &pyType : pyArgTypes)
236 argTypes.push_back(nb::cast<PyType &>(pyType));
240 argLocs.reserve(nb::len(*pyArgLocs));
241 for (
const auto &pyLoc : *pyArgLocs)
242 argLocs.push_back(nb::cast<PyLocation &>(pyLoc));
243 }
else if (!argTypes.empty()) {
244 argLocs.assign(argTypes.size(), DefaultingPyLocation::resolve());
247 if (argTypes.size() != argLocs.size())
248 throw nb::value_error((
"Expected " + Twine(argTypes.size()) +
249 " locations, got: " + Twine(argLocs.size()))
252 return mlirBlockCreate(argTypes.size(), argTypes.data(), argLocs.data());
257 static void set(nb::object &o,
bool enable) {
258 nb::ft_lock_guard lock(mutex);
262 static bool get(
const nb::object &) {
263 nb::ft_lock_guard lock(mutex);
267 static void bind(nb::module_ &m) {
269 nb::class_<PyGlobalDebugFlag>(m,
"_GlobalDebug")
274 [](
const std::string &type) {
275 nb::ft_lock_guard lock(mutex);
278 "types"_a,
"Sets specific debug types to be produced by LLVM")
279 .def_static(
"set_types", [](
const std::vector<std::string> &types) {
280 std::vector<const char *> pointers;
281 pointers.reserve(types.size());
282 for (
const std::string &str : types)
283 pointers.push_back(str.c_str());
284 nb::ft_lock_guard lock(mutex);
290 static nb::ft_mutex mutex;
293 nb::ft_mutex PyGlobalDebugFlag::mutex;
297 return PyGlobals::get().lookupAttributeBuilder(attributeKind).has_value();
300 auto builder =
PyGlobals::get().lookupAttributeBuilder(attributeKind);
302 throw nb::key_error(attributeKind.c_str());
306 nb::callable func,
bool replace) {
307 PyGlobals::get().registerAttributeBuilder(attributeKind, std::move(func),
311 static void bind(nb::module_ &m) {
312 nb::class_<PyAttrBuilderMap>(m,
"AttrBuilder")
316 "attribute_kind"_a,
"attr_builder"_a,
"replace"_a =
false,
317 "Register an attribute builder for building MLIR "
318 "attributes from python values.");
326 nb::object PyBlock::getCapsule() {
336 class PyRegionIterator {
339 : operation(std::move(operation)) {}
341 PyRegionIterator &dunderIter() {
return *
this; }
346 throw nb::stop_iteration();
352 static void bind(nb::module_ &m) {
353 nb::class_<PyRegionIterator>(m,
"RegionIterator")
354 .def(
"__iter__", &PyRegionIterator::dunderIter)
355 .def(
"__next__", &PyRegionIterator::dunderNext);
365 class PyRegionList :
public Sliceable<PyRegionList, PyRegion> {
367 static constexpr
const char *pyClassName =
"RegionSequence";
370 intptr_t length = -1, intptr_t step = 1)
375 operation(std::move(operation)) {}
377 PyRegionIterator dunderIter() {
379 return PyRegionIterator(operation);
382 static void bindDerived(ClassTy &c) {
383 c.def(
"__iter__", &PyRegionList::dunderIter);
390 intptr_t getRawNumElements() {
395 PyRegion getRawElement(intptr_t pos) {
400 PyRegionList slice(intptr_t startIndex, intptr_t length, intptr_t step) {
401 return PyRegionList(operation, startIndex, length, step);
407 class PyBlockIterator {
410 : operation(std::move(operation)), next(next) {}
412 PyBlockIterator &dunderIter() {
return *
this; }
417 throw nb::stop_iteration();
420 PyBlock returnBlock(operation, next);
425 static void bind(nb::module_ &m) {
426 nb::class_<PyBlockIterator>(m,
"BlockIterator")
427 .def(
"__iter__", &PyBlockIterator::dunderIter)
428 .def(
"__next__", &PyBlockIterator::dunderNext);
442 : operation(std::move(operation)), region(region) {}
444 PyBlockIterator dunderIter() {
449 intptr_t dunderLen() {
450 operation->checkValid();
460 PyBlock dunderGetItem(intptr_t index) {
463 index += dunderLen();
466 throw nb::index_error(
"attempt to access out of bounds block");
471 return PyBlock(operation, block);
476 throw nb::index_error(
"attempt to access out of bounds block");
479 PyBlock appendBlock(
const nb::args &pyArgTypes,
480 const std::optional<nb::sequence> &pyArgLocs) {
483 createBlock(nb::cast<nb::sequence>(pyArgTypes), pyArgLocs);
485 return PyBlock(operation, block);
488 static void bind(nb::module_ &m) {
489 nb::class_<PyBlockList>(m,
"BlockList")
490 .def(
"__getitem__", &PyBlockList::dunderGetItem)
491 .def(
"__iter__", &PyBlockList::dunderIter)
492 .def(
"__len__", &PyBlockList::dunderLen)
494 nb::arg(
"args"), nb::kw_only(),
495 nb::arg(
"arg_locs") = std::nullopt);
503 class PyOperationIterator {
505 PyOperationIterator(
PyOperationRef parentOperation, MlirOperation next)
506 : parentOperation(std::move(parentOperation)), next(next) {}
508 PyOperationIterator &dunderIter() {
return *
this; }
510 nb::object dunderNext() {
513 throw nb::stop_iteration();
517 PyOperation::forOperation(parentOperation->getContext(), next);
522 static void bind(nb::module_ &m) {
523 nb::class_<PyOperationIterator>(m,
"OperationIterator")
524 .def(
"__iter__", &PyOperationIterator::dunderIter)
525 .def(
"__next__", &PyOperationIterator::dunderNext);
537 class PyOperationList {
540 : parentOperation(std::move(parentOperation)), block(block) {}
542 PyOperationIterator dunderIter() {
544 return PyOperationIterator(parentOperation,
548 intptr_t dunderLen() {
549 parentOperation->checkValid();
559 nb::object dunderGetItem(intptr_t index) {
560 parentOperation->checkValid();
562 index += dunderLen();
565 throw nb::index_error(
"attempt to access out of bounds operation");
570 return PyOperation::forOperation(parentOperation->getContext(), childOp)
576 throw nb::index_error(
"attempt to access out of bounds operation");
579 static void bind(nb::module_ &m) {
580 nb::class_<PyOperationList>(m,
"OperationList")
581 .def(
"__getitem__", &PyOperationList::dunderGetItem)
582 .def(
"__iter__", &PyOperationList::dunderIter)
583 .def(
"__len__", &PyOperationList::dunderLen);
593 PyOpOperand(MlirOpOperand opOperand) : opOperand(opOperand) {}
595 nb::object getOwner() {
599 return PyOperation::forOperation(context, owner)->createOpView();
604 static void bind(nb::module_ &m) {
605 nb::class_<PyOpOperand>(m,
"OpOperand")
606 .def_prop_ro(
"owner", &PyOpOperand::getOwner)
607 .def_prop_ro(
"operand_number", &PyOpOperand::getOperandNumber);
611 MlirOpOperand opOperand;
614 class PyOpOperandIterator {
616 PyOpOperandIterator(MlirOpOperand opOperand) : opOperand(opOperand) {}
618 PyOpOperandIterator &dunderIter() {
return *
this; }
620 PyOpOperand dunderNext() {
622 throw nb::stop_iteration();
624 PyOpOperand returnOpOperand(opOperand);
626 return returnOpOperand;
629 static void bind(nb::module_ &m) {
630 nb::class_<PyOpOperandIterator>(m,
"OpOperandIterator")
631 .def(
"__iter__", &PyOpOperandIterator::dunderIter)
632 .def(
"__next__", &PyOpOperandIterator::dunderNext);
636 MlirOpOperand opOperand;
645 PyMlirContext::PyMlirContext(MlirContext context) : context(context) {
646 nb::gil_scoped_acquire acquire;
647 nb::ft_lock_guard lock(live_contexts_mutex);
648 auto &liveContexts = getLiveContexts();
649 liveContexts[context.ptr] =
this;
656 nb::gil_scoped_acquire acquire;
658 nb::ft_lock_guard lock(live_contexts_mutex);
659 getLiveContexts().erase(context.ptr);
671 throw nb::python_error();
676 nb::gil_scoped_acquire acquire;
677 nb::ft_lock_guard lock(live_contexts_mutex);
678 auto &liveContexts = getLiveContexts();
679 auto it = liveContexts.find(context.ptr);
680 if (it == liveContexts.end()) {
683 nb::object pyRef = nb::cast(unownedContextWrapper);
684 assert(pyRef &&
"cast to nb::object failed");
685 liveContexts[context.ptr] = unownedContextWrapper;
689 nb::object pyRef = nb::cast(it->second);
693 nb::ft_mutex PyMlirContext::live_contexts_mutex;
696 static LiveContextMap liveContexts;
701 nb::ft_lock_guard lock(live_contexts_mutex);
702 return getLiveContexts().size();
706 nb::ft_lock_guard lock(liveOperationsMutex);
707 return liveOperations.size();
711 std::vector<PyOperation *> liveObjects;
712 nb::ft_lock_guard lock(liveOperationsMutex);
713 for (
auto &entry : liveOperations)
714 liveObjects.push_back(entry.second.second);
722 nb::ft_lock_guard lock(liveOperationsMutex);
723 std::swap(operations, liveOperations);
725 for (
auto &op : operations)
726 op.second.second->setInvalid();
727 size_t numInvalidated = operations.size();
728 return numInvalidated;
734 nb::ft_lock_guard lock(liveOperationsMutex);
735 auto it = liveOperations.find(op.ptr);
736 if (it == liveOperations.end()) {
739 pyOp = it->second.second;
740 liveOperations.erase(it);
746 using callBackData =
struct {
755 callBackData *data =
static_cast<callBackData *
>(userData);
756 if (LLVM_LIKELY(data->rootSeen))
757 data->rootOp.getOperation().getContext()->clearOperation(op);
759 data->rootSeen =
true;
788 const nb::object &excVal,
789 const nb::object &excTb) {
798 nb::object pyHandlerObject =
799 nb::cast(pyHandler, nb::rv_policy::take_ownership);
800 pyHandlerObject.inc_ref();
804 auto handlerCallback =
807 nb::object pyDiagnosticObject =
808 nb::cast(pyDiagnostic, nb::rv_policy::take_ownership);
815 nb::gil_scoped_acquire gil;
817 result = nb::cast<bool>(pyHandler->callback(pyDiagnostic));
818 }
catch (std::exception &e) {
819 fprintf(stderr,
"MLIR Python Diagnostic handler raised exception: %s\n",
821 pyHandler->hadError =
true;
828 auto deleteCallback = +[](
void *userData) {
830 assert(pyHandler->registeredID &&
"handler is not registered");
831 pyHandler->registeredID.reset();
834 nb::object pyHandlerObject = nb::cast(pyHandler, nb::rv_policy::reference);
835 pyHandlerObject.dec_ref();
839 get(), handlerCallback,
static_cast<void *
>(pyHandler), deleteCallback);
840 return pyHandlerObject;
847 if (self->ctx->emitErrorDiagnostics)
860 throw std::runtime_error(
861 "An MLIR function requires a Context but none was provided in the call "
862 "or from the surrounding environment. Either pass to the function with "
863 "a 'context=' argument or establish a default using 'with Context():'");
873 static thread_local std::vector<PyThreadContextEntry> stack;
878 auto &stack = getStack();
881 return &stack.back();
884 void PyThreadContextEntry::push(FrameKind frameKind, nb::object context,
885 nb::object insertionPoint,
886 nb::object location) {
887 auto &stack = getStack();
888 stack.emplace_back(frameKind, std::move(context), std::move(insertionPoint),
889 std::move(location));
893 if (stack.size() > 1) {
894 auto &prev = *(stack.rbegin() + 1);
895 auto ¤t = stack.back();
896 if (current.context.is(prev.context)) {
898 if (!current.insertionPoint)
899 current.insertionPoint = prev.insertionPoint;
900 if (!current.location)
901 current.location = prev.location;
909 return nb::cast<PyMlirContext *>(context);
915 return nb::cast<PyInsertionPoint *>(insertionPoint);
921 return nb::cast<PyLocation *>(location);
925 auto *tos = getTopOfStack();
926 return tos ? tos->getContext() :
nullptr;
930 auto *tos = getTopOfStack();
931 return tos ? tos->getInsertionPoint() :
nullptr;
935 auto *tos = getTopOfStack();
936 return tos ? tos->getLocation() :
nullptr;
940 push(FrameKind::Context, context,
947 auto &stack = getStack();
949 throw std::runtime_error(
"Unbalanced Context enter/exit");
950 auto &tos = stack.back();
951 if (tos.frameKind != FrameKind::Context && tos.getContext() != &context)
952 throw std::runtime_error(
"Unbalanced Context enter/exit");
959 nb::cast<PyInsertionPoint &>(insertionPointObj);
960 nb::object contextObj =
962 push(FrameKind::InsertionPoint,
966 return insertionPointObj;
970 auto &stack = getStack();
972 throw std::runtime_error(
"Unbalanced InsertionPoint enter/exit");
973 auto &tos = stack.back();
974 if (tos.frameKind != FrameKind::InsertionPoint &&
975 tos.getInsertionPoint() != &insertionPoint)
976 throw std::runtime_error(
"Unbalanced InsertionPoint enter/exit");
981 PyLocation &location = nb::cast<PyLocation &>(locationObj);
983 push(FrameKind::Location, contextObj,
990 auto &stack = getStack();
992 throw std::runtime_error(
"Unbalanced Location enter/exit");
993 auto &tos = stack.back();
994 if (tos.frameKind != FrameKind::Location && tos.getLocation() != &location)
995 throw std::runtime_error(
"Unbalanced Location enter/exit");
1005 if (materializedNotes) {
1006 for (nb::handle noteObject : *materializedNotes) {
1007 PyDiagnostic *note = nb::cast<PyDiagnostic *>(noteObject);
1014 nb::object callback)
1015 : context(context), callback(std::move(callback)) {}
1024 assert(!registeredID &&
"should have unregistered");
1027 context = {
nullptr};
1030 void PyDiagnostic::checkValid() {
1032 throw std::invalid_argument(
1033 "Diagnostic is invalid (used outside of callback)");
1051 nb::object fileObject = nb::module_::import_(
"io").attr(
"StringIO")();
1054 return nb::cast<nb::str>(fileObject.attr(
"getvalue")());
1059 if (materializedNotes)
1060 return *materializedNotes;
1062 nb::tuple notes = nb::steal<nb::tuple>(PyTuple_New(numNotes));
1063 for (intptr_t i = 0; i < numNotes; ++i) {
1065 nb::object diagnostic = nb::cast(
PyDiagnostic(noteDiag));
1066 PyTuple_SET_ITEM(notes.ptr(), i, diagnostic.release().ptr());
1068 materializedNotes = std::move(notes);
1070 return *materializedNotes;
1074 std::vector<DiagnosticInfo> notes;
1076 notes.emplace_back(nb::cast<PyDiagnostic>(n).
getInfo());
1088 {key.data(), key.size()});
1090 std::string msg = (Twine(
"Dialect '") + key +
"' not found").str();
1092 throw nb::attribute_error(msg.c_str());
1093 throw nb::index_error(msg.c_str());
1103 MlirDialectRegistry rawRegistry =
1106 throw nb::python_error();
1121 throw nb::python_error();
1131 const nb::object &excVal,
1132 const nb::object &excTb) {
1139 throw std::runtime_error(
1140 "An MLIR function requires a Location but none was provided in the "
1141 "call or from the surrounding environment. Either pass to the function "
1142 "with a 'loc=' argument or establish a default using 'with loc:'");
1155 nb::gil_scoped_acquire acquire;
1156 auto &liveModules =
getContext()->liveModules;
1157 assert(liveModules.count(module.ptr) == 1 &&
1158 "destroying module not in live map");
1159 liveModules.erase(module.ptr);
1167 nb::gil_scoped_acquire acquire;
1168 auto &liveModules = contextRef->liveModules;
1169 auto it = liveModules.find(module.ptr);
1170 if (it == liveModules.end()) {
1176 nb::object pyRef = nb::cast(unownedModule, nb::rv_policy::take_ownership);
1177 unownedModule->handle = pyRef;
1178 liveModules[module.ptr] =
1179 std::make_pair(unownedModule->handle, unownedModule);
1180 return PyModuleRef(unownedModule, std::move(pyRef));
1183 PyModule *existing = it->second.second;
1184 nb::object pyRef = nb::borrow<nb::object>(it->second.first);
1191 throw nb::python_error();
1227 template <
typename T,
class... Args>
1229 nb::handle type = nb::type<T>();
1230 nb::object instance = nb::inst_alloc(type);
1231 T *ptr = nb::inst_ptr<T>(instance);
1232 new (ptr) T(std::forward<Args>(args)...);
1233 nb::inst_mark_ready(instance);
1240 MlirOperation operation,
1241 nb::object parentKeepAlive) {
1244 makeObjectRef<PyOperation>(std::move(contextRef), operation);
1245 unownedOperation->handle = unownedOperation.
getObject();
1246 if (parentKeepAlive) {
1247 unownedOperation->parentKeepAlive = std::move(parentKeepAlive);
1249 return unownedOperation;
1253 MlirOperation operation,
1254 nb::object parentKeepAlive) {
1255 nb::ft_lock_guard lock(contextRef->liveOperationsMutex);
1256 auto &liveOperations = contextRef->liveOperations;
1257 auto it = liveOperations.find(operation.ptr);
1258 if (it == liveOperations.end()) {
1260 PyOperationRef result = createInstance(std::move(contextRef), operation,
1261 std::move(parentKeepAlive));
1262 liveOperations[operation.ptr] =
1268 nb::object pyRef = nb::borrow<nb::object>(it->second.first);
1273 MlirOperation operation,
1274 nb::object parentKeepAlive) {
1275 nb::ft_lock_guard lock(contextRef->liveOperationsMutex);
1276 auto &liveOperations = contextRef->liveOperations;
1277 assert(liveOperations.count(operation.ptr) == 0 &&
1278 "cannot create detached operation that already exists");
1279 (void)liveOperations;
1280 PyOperationRef created = createInstance(std::move(contextRef), operation,
1281 std::move(parentKeepAlive));
1282 liveOperations[operation.ptr] =
1284 created->attached =
false;
1289 const std::string &sourceStr,
1290 const std::string &sourceName) {
1296 throw MLIRError(
"Unable to parse operation assembly", errors.
take());
1302 throw std::runtime_error(
"the operation has been invalidated");
1307 std::optional<int64_t> largeResourceLimit,
1308 bool enableDebugInfo,
bool prettyDebugInfo,
1309 bool printGenericOpForm,
bool useLocalScope,
1310 bool useNameLocAsPrefix,
bool assumeVerified,
1311 nb::object fileObject,
bool binary,
1315 if (fileObject.is_none())
1316 fileObject = nb::module_::import_(
"sys").attr(
"stdout");
1319 if (largeElementsLimit)
1321 if (largeResourceLimit)
1323 if (enableDebugInfo)
1326 if (printGenericOpForm)
1334 if (useNameLocAsPrefix)
1339 accum.getUserData());
1347 if (fileObject.is_none())
1348 fileObject = nb::module_::import_(
"sys").attr(
"stdout");
1351 accum.getUserData());
1355 std::optional<int64_t> bytecodeVersion) {
1360 if (!bytecodeVersion.has_value())
1370 throw nb::value_error((Twine(
"Unable to honor desired bytecode version ") +
1371 Twine(*bytecodeVersion))
1384 std::string exceptionWhat;
1385 nb::object exceptionType;
1387 UserData userData{callback,
false, {}, {}};
1390 UserData *calleeUserData =
static_cast<UserData *
>(userData);
1392 return (calleeUserData->callback)(op);
1393 }
catch (nb::python_error &e) {
1394 calleeUserData->gotException =
true;
1395 calleeUserData->exceptionWhat = std::string(e.what());
1396 calleeUserData->exceptionType = nb::borrow(e.type());
1401 if (userData.gotException) {
1402 std::string message(
"Exception raised in callback: ");
1403 message.append(userData.exceptionWhat);
1404 throw std::runtime_error(message);
1409 std::optional<int64_t> largeElementsLimit,
1410 std::optional<int64_t> largeResourceLimit,
1411 bool enableDebugInfo,
bool prettyDebugInfo,
1412 bool printGenericOpForm,
bool useLocalScope,
1413 bool useNameLocAsPrefix,
bool assumeVerified,
1415 nb::object fileObject;
1417 fileObject = nb::module_::import_(
"io").attr(
"BytesIO")();
1419 fileObject = nb::module_::import_(
"io").attr(
"StringIO")();
1421 print(largeElementsLimit,
1433 return fileObject.attr(
"getvalue")();
1442 operation.parentKeepAlive = otherOp.parentKeepAlive;
1451 operation.parentKeepAlive = otherOp.parentKeepAlive;
1473 throw nb::value_error(
"Detached operations have no parent");
1484 assert(!
mlirBlockIsNull(block) &&
"Attached operation has null parent");
1485 assert(parentOperation &&
"Operation has no parent");
1486 return PyBlock{std::move(*parentOperation), block};
1497 throw nb::python_error();
1504 const nb::object &maybeIp) {
1506 if (!maybeIp.is(nb::cast(
false))) {
1508 if (maybeIp.is_none()) {
1511 ip = nb::cast<PyInsertionPoint *>(maybeIp);
1519 std::optional<std::vector<PyType *>> results,
1521 std::optional<nb::dict> attributes,
1522 std::optional<std::vector<PyBlock *>> successors,
1524 const nb::object &maybeIp,
bool inferType) {
1531 throw nb::value_error(
"number of regions must be >= 0");
1535 mlirResults.reserve(results->size());
1536 for (
PyType *result : *results) {
1539 throw nb::value_error(
"result type cannot be None");
1540 mlirResults.push_back(*result);
1545 mlirAttributes.reserve(attributes->size());
1546 for (std::pair<nb::handle, nb::handle> it : *attributes) {
1549 key = nb::cast<std::string>(it.first);
1550 }
catch (nb::cast_error &err) {
1551 std::string msg =
"Invalid attribute key (not a string) when "
1552 "attempting to create the operation \"" +
1553 std::string(name) +
"\" (" + err.what() +
")";
1554 throw nb::type_error(msg.c_str());
1557 auto &attribute = nb::cast<PyAttribute &>(it.second);
1559 mlirAttributes.emplace_back(std::move(key), attribute);
1560 }
catch (nb::cast_error &err) {
1561 std::string msg =
"Invalid attribute value for the key \"" + key +
1562 "\" when attempting to create the operation \"" +
1563 std::string(name) +
"\" (" + err.what() +
")";
1564 throw nb::type_error(msg.c_str());
1565 }
catch (std::runtime_error &) {
1568 "Found an invalid (`None`?) attribute value for the key \"" + key +
1569 "\" when attempting to create the operation \"" +
1570 std::string(name) +
"\"";
1571 throw std::runtime_error(msg);
1577 mlirSuccessors.reserve(successors->size());
1578 for (
auto *successor : *successors) {
1581 throw nb::value_error(
"successor block cannot be None");
1582 mlirSuccessors.push_back(successor->get());
1590 if (!operands.empty())
1592 state.enableResultTypeInference = inferType;
1593 if (!mlirResults.empty())
1595 mlirResults.data());
1596 if (!mlirAttributes.empty()) {
1601 mlirNamedAttributes.reserve(mlirAttributes.size());
1602 for (
auto &it : mlirAttributes)
1608 mlirNamedAttributes.data());
1610 if (!mlirSuccessors.empty())
1612 mlirSuccessors.data());
1615 mlirRegions.resize(regions);
1616 for (
int i = 0; i < regions; ++i)
1619 mlirRegions.data());
1625 throw nb::value_error(
"Operation creation failed");
1663 template <
typename DerivedTy>
1664 class PyConcreteValue :
public PyValue {
1670 using ClassTy = nb::class_<DerivedTy, PyValue>;
1671 using IsAFunctionTy = bool (*)(MlirValue);
1673 PyConcreteValue() =
default;
1675 :
PyValue(operationRef, value) {}
1676 PyConcreteValue(
PyValue &orig)
1677 : PyConcreteValue(orig.getParentOperation(), castFrom(orig)) {}
1681 static MlirValue castFrom(
PyValue &orig) {
1682 if (!DerivedTy::isaFunction(orig.
get())) {
1683 auto origRepr = nb::cast<std::string>(nb::repr(nb::cast(orig)));
1684 throw nb::value_error((Twine(
"Cannot cast value to ") +
1685 DerivedTy::pyClassName +
" (from " + origRepr +
1694 static void bind(nb::module_ &m) {
1695 auto cls = ClassTy(m, DerivedTy::pyClassName);
1696 cls.def(nb::init<PyValue &>(), nb::keep_alive<0, 1>(), nb::arg(
"value"));
1699 [](
PyValue &otherValue) ->
bool {
1700 return DerivedTy::isaFunction(otherValue);
1702 nb::arg(
"other_value"));
1704 [](
DerivedTy &
self) {
return self.maybeDownCast(); });
1705 DerivedTy::bindDerived(cls);
1709 static void bindDerived(ClassTy &m) {}
1718 static constexpr
const char *pyClassName =
"OpResult";
1719 using PyConcreteValue::PyConcreteValue;
1722 c.def_prop_ro(
"owner", [](
PyOpResult &
self) {
1726 "expected the owner of the value in Python to match that in the IR");
1727 return self.getParentOperation().getObject();
1729 c.def_prop_ro(
"result_number", [](
PyOpResult &
self) {
1736 template <
typename Container>
1739 std::vector<MlirType> result;
1740 result.reserve(container.size());
1741 for (
int i = 0, e = container.size(); i < e; ++i) {
1753 static constexpr
const char *pyClassName =
"OpResultList";
1757 intptr_t length = -1, intptr_t step = 1)
1762 operation(std::move(operation)) {}
1769 return self.operation->createOpView();
1779 intptr_t getRawNumElements() {
1789 PyOpResultList slice(intptr_t startIndex, intptr_t length, intptr_t step) {
1801 const nb::object &resultSegmentSpecObj,
1802 std::vector<int32_t> &resultSegmentLengths,
1803 std::vector<PyType *> &resultTypes) {
1804 resultTypes.reserve(resultTypeList.size());
1805 if (resultSegmentSpecObj.is_none()) {
1809 resultTypes.push_back(nb::cast<PyType *>(it.value()));
1810 if (!resultTypes.back())
1811 throw nb::cast_error();
1812 }
catch (nb::cast_error &err) {
1813 throw nb::value_error((llvm::Twine(
"Result ") +
1814 llvm::Twine(it.index()) +
" of operation \"" +
1815 name +
"\" must be a Type (" + err.what() +
")")
1822 auto resultSegmentSpec = nb::cast<std::vector<int>>(resultSegmentSpecObj);
1823 if (resultSegmentSpec.size() != resultTypeList.size()) {
1824 throw nb::value_error((llvm::Twine(
"Operation \"") + name +
1826 llvm::Twine(resultSegmentSpec.size()) +
1827 " result segments but was provided " +
1828 llvm::Twine(resultTypeList.size()))
1832 resultSegmentLengths.reserve(resultTypeList.size());
1833 for (
const auto &it :
1835 int segmentSpec = std::get<1>(it.value());
1836 if (segmentSpec == 1 || segmentSpec == 0) {
1839 auto *resultType = nb::cast<PyType *>(std::get<0>(it.value()));
1841 resultTypes.push_back(resultType);
1842 resultSegmentLengths.push_back(1);
1843 }
else if (segmentSpec == 0) {
1845 resultSegmentLengths.push_back(0);
1847 throw nb::value_error(
1848 (llvm::Twine(
"Result ") + llvm::Twine(it.index()) +
1849 " of operation \"" + name +
1850 "\" must be a Type (was None and result is not optional)")
1854 }
catch (nb::cast_error &err) {
1855 throw nb::value_error((llvm::Twine(
"Result ") +
1856 llvm::Twine(it.index()) +
" of operation \"" +
1857 name +
"\" must be a Type (" + err.what() +
1862 }
else if (segmentSpec == -1) {
1865 if (std::get<0>(it.value()).is_none()) {
1867 resultSegmentLengths.push_back(0);
1870 auto segment = nb::cast<nb::sequence>(std::get<0>(it.value()));
1871 for (nb::handle segmentItem : segment) {
1872 resultTypes.push_back(nb::cast<PyType *>(segmentItem));
1873 if (!resultTypes.back()) {
1874 throw nb::type_error(
"contained a None item");
1877 resultSegmentLengths.push_back(nb::len(segment));
1879 }
catch (std::exception &err) {
1883 throw nb::value_error((llvm::Twine(
"Result ") +
1884 llvm::Twine(it.index()) +
" of operation \"" +
1885 name +
"\" must be a Sequence of Types (" +
1891 throw nb::value_error(
"Unexpected segment spec");
1899 if (numResults != 1) {
1901 throw nb::value_error((Twine(
"Cannot call .result on operation ") +
1902 StringRef(name.data, name.length) +
" which has " +
1904 " results (it is only valid for operations with a "
1913 if (operand.is_none()) {
1914 throw nb::value_error(
"contained a None item");
1917 if (nb::try_cast<PyOperationBase *>(operand, op)) {
1921 if (nb::try_cast<PyOpResultList *>(operand, opResultList)) {
1925 if (nb::try_cast<PyValue *>(operand, value)) {
1926 return value->
get();
1928 throw nb::value_error(
"is not a Value");
1932 std::string_view name, std::tuple<int, bool> opRegionSpec,
1933 nb::object operandSegmentSpecObj, nb::object resultSegmentSpecObj,
1934 std::optional<nb::list> resultTypeList, nb::list operandList,
1935 std::optional<nb::dict> attributes,
1936 std::optional<std::vector<PyBlock *>> successors,
1937 std::optional<int> regions,
PyLocation &location,
1938 const nb::object &maybeIp) {
1947 std::vector<int32_t> operandSegmentLengths;
1948 std::vector<int32_t> resultSegmentLengths;
1951 int opMinRegionCount = std::get<0>(opRegionSpec);
1952 bool opHasNoVariadicRegions = std::get<1>(opRegionSpec);
1954 regions = opMinRegionCount;
1956 if (*regions < opMinRegionCount) {
1957 throw nb::value_error(
1958 (llvm::Twine(
"Operation \"") + name +
"\" requires a minimum of " +
1959 llvm::Twine(opMinRegionCount) +
1960 " regions but was built with regions=" + llvm::Twine(*regions))
1964 if (opHasNoVariadicRegions && *regions > opMinRegionCount) {
1965 throw nb::value_error(
1966 (llvm::Twine(
"Operation \"") + name +
"\" requires a maximum of " +
1967 llvm::Twine(opMinRegionCount) +
1968 " regions but was built with regions=" + llvm::Twine(*regions))
1974 std::vector<PyType *> resultTypes;
1975 if (resultTypeList.has_value()) {
1977 resultSegmentLengths, resultTypes);
1982 operands.reserve(operands.size());
1983 if (operandSegmentSpecObj.is_none()) {
1988 }
catch (nb::builtin_exception &err) {
1989 throw nb::value_error((llvm::Twine(
"Operand ") +
1990 llvm::Twine(it.index()) +
" of operation \"" +
1991 name +
"\" must be a Value (" + err.what() +
")")
1998 auto operandSegmentSpec = nb::cast<std::vector<int>>(operandSegmentSpecObj);
1999 if (operandSegmentSpec.size() != operandList.size()) {
2000 throw nb::value_error((llvm::Twine(
"Operation \"") + name +
2002 llvm::Twine(operandSegmentSpec.size()) +
2003 "operand segments but was provided " +
2004 llvm::Twine(operandList.size()))
2008 operandSegmentLengths.reserve(operandList.size());
2009 for (
const auto &it :
2011 int segmentSpec = std::get<1>(it.value());
2012 if (segmentSpec == 1 || segmentSpec == 0) {
2014 auto &operand = std::get<0>(it.value());
2015 if (!operand.is_none()) {
2019 }
catch (nb::builtin_exception &err) {
2020 throw nb::value_error((llvm::Twine(
"Operand ") +
2021 llvm::Twine(it.index()) +
2022 " of operation \"" + name +
2023 "\" must be a Value (" + err.what() +
")")
2028 operandSegmentLengths.push_back(1);
2029 }
else if (segmentSpec == 0) {
2031 operandSegmentLengths.push_back(0);
2033 throw nb::value_error(
2034 (llvm::Twine(
"Operand ") + llvm::Twine(it.index()) +
2035 " of operation \"" + name +
2036 "\" must be a Value (was None and operand is not optional)")
2040 }
else if (segmentSpec == -1) {
2043 if (std::get<0>(it.value()).is_none()) {
2045 operandSegmentLengths.push_back(0);
2048 auto segment = nb::cast<nb::sequence>(std::get<0>(it.value()));
2049 for (nb::handle segmentItem : segment) {
2052 operandSegmentLengths.push_back(nb::len(segment));
2054 }
catch (std::exception &err) {
2058 throw nb::value_error((llvm::Twine(
"Operand ") +
2059 llvm::Twine(it.index()) +
" of operation \"" +
2060 name +
"\" must be a Sequence of Values (" +
2066 throw nb::value_error(
"Unexpected segment spec");
2072 if (!operandSegmentLengths.empty() || !resultSegmentLengths.empty()) {
2075 attributes = nb::dict(*attributes);
2077 attributes = nb::dict();
2079 if (attributes->contains(
"resultSegmentSizes") ||
2080 attributes->contains(
"operandSegmentSizes")) {
2081 throw nb::value_error(
"Manually setting a 'resultSegmentSizes' or "
2082 "'operandSegmentSizes' attribute is unsupported. "
2083 "Use Operation.create for such low-level access.");
2087 if (!resultSegmentLengths.empty()) {
2088 MlirAttribute segmentLengthAttr =
2090 resultSegmentLengths.data());
2091 (*attributes)[
"resultSegmentSizes"] =
2096 if (!operandSegmentLengths.empty()) {
2097 MlirAttribute segmentLengthAttr =
2099 operandSegmentLengths.data());
2100 (*attributes)[
"operandSegmentSizes"] =
2107 std::move(resultTypes),
2109 std::move(attributes),
2110 std::move(successors),
2111 *regions, location, maybeIp,
2116 const nb::object &operation) {
2117 nb::handle opViewType = nb::type<PyOpView>();
2118 nb::object instance = cls.attr(
"__new__")(cls);
2119 opViewType.attr(
"__init__")(instance, operation);
2127 operationObject(operation.getRef().getObject()) {}
2136 : refOperation(beforeOperationBase.getOperation().getRef()),
2137 block((*refOperation)->getBlock()) {}
2142 throw nb::value_error(
2143 "Attempt to insert operation that is already attached");
2144 block.getParentOperation()->checkValid();
2145 MlirOperation beforeOp = {
nullptr};
2148 (*refOperation)->checkValid();
2149 beforeOp = (*refOperation)->get();
2155 throw nb::index_error(
"Cannot insert operation at the end of a block "
2156 "that already has a terminator. Did you mean to "
2157 "use 'InsertionPoint.at_block_terminator(block)' "
2158 "versus 'InsertionPoint(block)'?");
2181 throw nb::value_error(
"Block has no terminator");
2192 const nb::object &excVal,
2193 const nb::object &excTb) {
2212 throw nb::python_error();
2222 : ownedName(new std::string(std::move(ownedName))) {
2244 throw nb::python_error();
2260 throw nb::python_error();
2279 "mlirTypeID was expected to be non-null.");
2280 std::optional<nb::callable> valueCaster =
2284 nb::object thisObj = nb::cast(
this, nb::rv_policy::move);
2287 return valueCaster.value()(thisObj);
2293 throw nb::python_error();
2294 MlirOperation owner;
2300 throw nb::python_error();
2304 return PyValue(ownerRef, value);
2312 : operation(operation.getOperation().getRef()) {
2315 throw nb::type_error(
"Operation is not a Symbol Table.");
2324 throw nb::key_error(
2325 (
"Symbol '" + name +
"' not in the symbol table.").c_str());
2328 operation.getObject())
2344 erase(nb::cast<PyOperationBase &>(operation));
2353 throw nb::value_error(
"Expected operation to have a symbol name.");
2362 MlirAttribute existingNameAttr =
2365 throw nb::value_error(
"Expected operation to have a symbol name.");
2366 return existingNameAttr;
2370 const std::string &name) {
2375 MlirAttribute existingNameAttr =
2378 throw nb::value_error(
"Expected operation to have a symbol name.");
2379 MlirAttribute newNameAttr =
2388 MlirAttribute existingVisAttr =
2391 throw nb::value_error(
"Expected operation to have a symbol visibility.");
2392 return existingVisAttr;
2396 const std::string &visibility) {
2397 if (visibility !=
"public" && visibility !=
"private" &&
2398 visibility !=
"nested")
2399 throw nb::value_error(
2400 "Expected visibility to be 'public', 'private' or 'nested'");
2404 MlirAttribute existingVisAttr =
2407 throw nb::value_error(
"Expected operation to have a symbol visibility.");
2414 const std::string &newSymbol,
2422 throw nb::value_error(
"Symbol rename failed");
2426 bool allSymUsesVisible,
2427 nb::object callback) {
2432 nb::object callback;
2434 std::string exceptionWhat;
2435 nb::object exceptionType;
2438 fromOperation.
getContext(), std::move(callback),
false, {}, {}};
2440 fromOperation.
get(), allSymUsesVisible,
2441 [](MlirOperation foundOp,
bool isVisible,
void *calleeUserDataVoid) {
2442 UserData *calleeUserData = static_cast<UserData *>(calleeUserDataVoid);
2444 PyOperation::forOperation(calleeUserData->context, foundOp);
2445 if (calleeUserData->gotException)
2448 calleeUserData->callback(pyFoundOp.getObject(), isVisible);
2449 } catch (nb::python_error &e) {
2450 calleeUserData->gotException =
true;
2451 calleeUserData->exceptionWhat = e.what();
2452 calleeUserData->exceptionType = nb::borrow(e.type());
2455 static_cast<void *
>(&userData));
2456 if (userData.gotException) {
2457 std::string message(
"Exception raised in callback: ");
2458 message.append(userData.exceptionWhat);
2459 throw std::runtime_error(message);
2466 class PyBlockArgument :
public PyConcreteValue<PyBlockArgument> {
2469 static constexpr
const char *pyClassName =
"BlockArgument";
2470 using PyConcreteValue::PyConcreteValue;
2472 static void bindDerived(ClassTy &c) {
2473 c.def_prop_ro(
"owner", [](PyBlockArgument &
self) {
2474 return PyBlock(
self.getParentOperation(),
2477 c.def_prop_ro(
"arg_number", [](PyBlockArgument &
self) {
2482 [](PyBlockArgument &
self,
PyType type) {
2493 class PyBlockArgumentList
2494 :
public Sliceable<PyBlockArgumentList, PyBlockArgument> {
2496 static constexpr
const char *pyClassName =
"BlockArgumentList";
2500 intptr_t startIndex = 0, intptr_t length = -1,
2505 operation(std::move(operation)), block(block) {}
2507 static void bindDerived(ClassTy &c) {
2508 c.def_prop_ro(
"types", [](PyBlockArgumentList &
self) {
2515 friend class Sliceable<PyBlockArgumentList, PyBlockArgument>;
2518 intptr_t getRawNumElements() {
2524 PyBlockArgument getRawElement(intptr_t pos) {
2526 return PyBlockArgument(operation, argument);
2530 PyBlockArgumentList slice(intptr_t startIndex, intptr_t length,
2532 return PyBlockArgumentList(operation, block, startIndex, length, step);
2543 class PyOpOperandList :
public Sliceable<PyOpOperandList, PyValue> {
2545 static constexpr
const char *pyClassName =
"OpOperandList";
2548 PyOpOperandList(
PyOperationRef operation, intptr_t startIndex = 0,
2549 intptr_t length = -1, intptr_t step = 1)
2554 operation(operation) {}
2556 void dunderSetItem(intptr_t index,
PyValue value) {
2557 index = wrapIndex(index);
2561 static void bindDerived(ClassTy &c) {
2562 c.def(
"__setitem__", &PyOpOperandList::dunderSetItem);
2569 intptr_t getRawNumElements() {
2574 PyValue getRawElement(intptr_t pos) {
2576 MlirOperation owner;
2582 assert(
false &&
"Value must be an block arg or op result.");
2584 PyOperation::forOperation(operation->
getContext(), owner);
2585 return PyValue(pyOwner, operand);
2588 PyOpOperandList slice(intptr_t startIndex, intptr_t length, intptr_t step) {
2589 return PyOpOperandList(operation, startIndex, length, step);
2599 class PyOpSuccessors :
public Sliceable<PyOpSuccessors, PyBlock> {
2601 static constexpr
const char *pyClassName =
"OpSuccessors";
2603 PyOpSuccessors(
PyOperationRef operation, intptr_t startIndex = 0,
2604 intptr_t length = -1, intptr_t step = 1)
2609 operation(operation) {}
2611 void dunderSetItem(intptr_t index,
PyBlock block) {
2612 index = wrapIndex(index);
2616 static void bindDerived(ClassTy &c) {
2617 c.def(
"__setitem__", &PyOpSuccessors::dunderSetItem);
2624 intptr_t getRawNumElements() {
2629 PyBlock getRawElement(intptr_t pos) {
2631 return PyBlock(operation, block);
2634 PyOpSuccessors slice(intptr_t startIndex, intptr_t length, intptr_t step) {
2635 return PyOpSuccessors(operation, startIndex, length, step);
2645 class PyBlockSuccessors :
public Sliceable<PyBlockSuccessors, PyBlock> {
2647 static constexpr
const char *pyClassName =
"BlockSuccessors";
2650 intptr_t startIndex = 0, intptr_t length = -1,
2656 operation(operation), block(block) {}
2662 intptr_t getRawNumElements() {
2667 PyBlock getRawElement(intptr_t pos) {
2669 return PyBlock(operation, block);
2672 PyBlockSuccessors slice(intptr_t startIndex, intptr_t length, intptr_t step) {
2673 return PyBlockSuccessors(block, operation, startIndex, length, step);
2687 class PyBlockPredecessors :
public Sliceable<PyBlockPredecessors, PyBlock> {
2689 static constexpr
const char *pyClassName =
"BlockPredecessors";
2692 intptr_t startIndex = 0, intptr_t length = -1,
2698 operation(operation), block(block) {}
2704 intptr_t getRawNumElements() {
2709 PyBlock getRawElement(intptr_t pos) {
2711 return PyBlock(operation, block);
2714 PyBlockPredecessors slice(intptr_t startIndex, intptr_t length,
2716 return PyBlockPredecessors(block, operation, startIndex, length, step);
2725 class PyOpAttributeMap {
2728 : operation(std::move(operation)) {}
2730 MlirAttribute dunderGetItemNamed(
const std::string &name) {
2734 throw nb::key_error(
"attempt to access a non-existent attribute");
2741 index += dunderLen();
2743 if (index < 0 || index >= dunderLen()) {
2744 throw nb::index_error(
"attempt to access out of bounds attribute");
2754 void dunderSetItem(
const std::string &name,
const PyAttribute &attr) {
2759 void dunderDelItem(
const std::string &name) {
2763 throw nb::key_error(
"attempt to delete a non-existent attribute");
2766 intptr_t dunderLen() {
2770 bool dunderContains(
const std::string &name) {
2775 static void bind(nb::module_ &m) {
2776 nb::class_<PyOpAttributeMap>(m,
"OpAttributeMap")
2777 .def(
"__contains__", &PyOpAttributeMap::dunderContains)
2778 .def(
"__len__", &PyOpAttributeMap::dunderLen)
2779 .def(
"__getitem__", &PyOpAttributeMap::dunderGetItemNamed)
2780 .def(
"__getitem__", &PyOpAttributeMap::dunderGetItemIndexed)
2781 .def(
"__setitem__", &PyOpAttributeMap::dunderSetItem)
2782 .def(
"__delitem__", &PyOpAttributeMap::dunderDelItem);
2793 #define _Py_CAST(type, expr) ((type)(expr))
2800 #if (defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L) || \
2801 (defined(__cplusplus) && __cplusplus >= 201103)
2802 #define _Py_NULL nullptr
2804 #define _Py_NULL NULL
2809 #if PY_VERSION_HEX < 0x030A00A3
2812 #if !defined(Py_XNewRef)
2813 [[maybe_unused]] PyObject *_Py_XNewRef(PyObject *obj) {
2817 #define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
2821 #if !defined(Py_NewRef)
2822 [[maybe_unused]] PyObject *_Py_NewRef(PyObject *obj) {
2826 #define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
2832 #if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
2835 PyFrameObject *PyThreadState_GetFrame(PyThreadState *tstate) {
2836 assert(tstate !=
_Py_NULL &&
"expected tstate != _Py_NULL");
2841 PyFrameObject *PyFrame_GetBack(PyFrameObject *frame) {
2842 assert(frame !=
_Py_NULL &&
"expected frame != _Py_NULL");
2847 PyCodeObject *PyFrame_GetCode(PyFrameObject *frame) {
2848 assert(frame !=
_Py_NULL &&
"expected frame != _Py_NULL");
2849 assert(frame->f_code !=
_Py_NULL &&
"expected frame->f_code != _Py_NULL");
2855 MlirLocation tracebackToLocation(MlirContext ctx) {
2856 size_t framesLimit =
2859 thread_local std::array<MlirLocation, PyGlobals::TracebackLoc::kMaxFrames>
2863 nb::gil_scoped_acquire acquire;
2864 PyThreadState *tstate = PyThreadState_GET();
2865 PyFrameObject *next;
2866 PyFrameObject *pyFrame = PyThreadState_GetFrame(tstate);
2872 for (; pyFrame !=
nullptr && count < framesLimit;
2873 next = PyFrame_GetBack(pyFrame), Py_XDECREF(pyFrame), pyFrame = next) {
2874 PyCodeObject *code = PyFrame_GetCode(pyFrame);
2876 nb::cast<std::string>(nb::borrow<nb::str>(code->co_filename));
2877 llvm::StringRef fileName(fileNameStr);
2878 if (!
PyGlobals::get().getTracebackLoc().isUserTracebackFilename(fileName))
2882 #if PY_VERSION_HEX < 0x030B00F0
2884 nb::cast<std::string>(nb::borrow<nb::str>(code->co_name));
2885 llvm::StringRef funcName(name);
2886 int startLine = PyFrame_GetLineNumber(pyFrame);
2891 nb::cast<std::string>(nb::borrow<nb::str>(code->co_qualname));
2892 llvm::StringRef funcName(name);
2893 int startLine, startCol, endLine, endCol;
2894 int lasti = PyFrame_GetLasti(pyFrame);
2895 if (!PyCode_Addr2Location(code, lasti, &startLine, &startCol, &endLine,
2897 throw nb::python_error();
2900 ctx,
wrap(fileName), startLine, startCol, endLine, endCol);
2908 Py_XDECREF(pyFrame);
2913 MlirLocation callee = frames[0];
2918 MlirLocation caller = frames[count - 1];
2920 for (
int i = count - 2; i >= 1; i--)
2927 maybeGetTracebackLocation(
const std::optional<PyLocation> &location) {
2928 if (location.has_value())
2929 return location.value();
2931 return DefaultingPyLocation::resolve();
2934 MlirLocation mlirLoc = tracebackToLocation(ctx.
get());
2936 return {ref, mlirLoc};
2947 nb::set_leak_warnings(
false);
2951 nb::enum_<MlirDiagnosticSeverity>(m,
"DiagnosticSeverity")
2957 nb::enum_<MlirWalkOrder>(m,
"WalkOrder")
2961 nb::enum_<MlirWalkResult>(m,
"WalkResult")
2969 nb::class_<PyDiagnostic>(m,
"Diagnostic")
2970 .def_prop_ro(
"severity", &PyDiagnostic::getSeverity)
2971 .def_prop_ro(
"location", &PyDiagnostic::getLocation)
2972 .def_prop_ro(
"message", &PyDiagnostic::getMessage)
2973 .def_prop_ro(
"notes", &PyDiagnostic::getNotes)
2975 if (!
self.isValid())
2976 return nb::str(
"<Invalid Diagnostic>");
2977 return self.getMessage();
2980 nb::class_<PyDiagnostic::DiagnosticInfo>(m,
"DiagnosticInfo")
2985 .def_ro(
"severity", &PyDiagnostic::DiagnosticInfo::severity)
2986 .def_ro(
"location", &PyDiagnostic::DiagnosticInfo::location)
2987 .def_ro(
"message", &PyDiagnostic::DiagnosticInfo::message)
2988 .def_ro(
"notes", &PyDiagnostic::DiagnosticInfo::notes)
2992 nb::class_<PyDiagnosticHandler>(m,
"DiagnosticHandler")
2993 .def(
"detach", &PyDiagnosticHandler::detach)
2994 .def_prop_ro(
"attached", &PyDiagnosticHandler::isAttached)
2995 .def_prop_ro(
"had_error", &PyDiagnosticHandler::getHadError)
2996 .def(
"__enter__", &PyDiagnosticHandler::contextEnter)
2997 .def(
"__exit__", &PyDiagnosticHandler::contextExit,
2998 nb::arg(
"exc_type").none(), nb::arg(
"exc_value").none(),
2999 nb::arg(
"traceback").none());
3009 nb::class_<PyThreadPool>(m,
"ThreadPool")
3011 .def(
"get_max_concurrency", &PyThreadPool::getMaxConcurrency)
3012 .def(
"_mlir_thread_pool_ptr", &PyThreadPool::_mlir_thread_pool_ptr);
3014 nb::class_<PyMlirContext>(m,
"_BaseContext")
3020 .def_static(
"_get_live_count", &PyMlirContext::getLiveCount)
3021 .def(
"_get_context_again",
3026 .def(
"_get_live_operation_count", &PyMlirContext::getLiveOperationCount)
3027 .def(
"_get_live_operation_objects",
3028 &PyMlirContext::getLiveOperationObjects)
3029 .def(
"_clear_live_operations", &PyMlirContext::clearLiveOperations)
3030 .def(
"_clear_live_operations_inside",
3031 nb::overload_cast<MlirOperation>(
3032 &PyMlirContext::clearOperationsInside))
3033 .def(
"_get_live_module_count", &PyMlirContext::getLiveModuleCount)
3036 .def(
"__enter__", &PyMlirContext::contextEnter)
3037 .def(
"__exit__", &PyMlirContext::contextExit, nb::arg(
"exc_type").none(),
3038 nb::arg(
"exc_value").none(), nb::arg(
"traceback").none())
3039 .def_prop_ro_static(
3045 return nb::cast(context);
3047 "Gets the Context bound to the current thread or raises ValueError")
3051 "Gets a container for accessing dialects by name")
3054 "Alias for 'dialect'")
3056 "get_dialect_descriptor",
3059 self.
get(), {name.data(), name.size()});
3061 throw nb::value_error(
3062 (Twine(
"Dialect '") + name +
"' not found").str().c_str());
3066 nb::arg(
"dialect_name"),
3067 "Gets or loads a dialect by name, returning its descriptor object")
3069 "allow_unregistered_dialects",
3076 .def(
"attach_diagnostic_handler", &PyMlirContext::attachDiagnosticHandler,
3077 nb::arg(
"callback"),
3078 "Attaches a diagnostic handler that will receive callbacks")
3080 "enable_multithreading",
3085 .def(
"set_thread_pool",
3093 .def(
"get_num_threads",
3097 .def(
"_mlir_thread_pool_ptr",
3100 std::stringstream ss;
3105 "is_registered_operation",
3110 nb::arg(
"operation_name"))
3112 "append_dialect_registry",
3116 nb::arg(
"registry"))
3117 .def_prop_rw(
"emit_error_diagnostics",
nullptr,
3118 &PyMlirContext::setEmitErrorDiagnostics,
3119 "Emit error diagnostics to diagnostic handlers. By default "
3120 "error diagnostics are captured and reported through "
3121 "MLIRError exceptions.")
3122 .def(
"load_all_available_dialects", [](
PyMlirContext &
self) {
3129 nb::class_<PyDialectDescriptor>(m,
"DialectDescriptor")
3130 .def_prop_ro(
"namespace",
3137 std::string repr(
"<DialectDescriptor ");
3146 nb::class_<PyDialects>(m,
"Dialects")
3149 MlirDialect dialect =
3150 self.getDialectForKey(keyName,
false);
3151 nb::object descriptor =
3155 .def(
"__getattr__", [=](
PyDialects &
self, std::string attrName) {
3156 MlirDialect dialect =
3157 self.getDialectForKey(attrName,
true);
3158 nb::object descriptor =
3166 nb::class_<PyDialect>(m,
"Dialect")
3167 .def(nb::init<nb::object>(), nb::arg(
"descriptor"))
3168 .def_prop_ro(
"descriptor",
3169 [](
PyDialect &
self) {
return self.getDescriptor(); })
3170 .def(
"__repr__", [](nb::object
self) {
3171 auto clazz =
self.attr(
"__class__");
3172 return nb::str(
"<Dialect ") +
3173 self.attr(
"descriptor").attr(
"namespace") + nb::str(
" (class ") +
3174 clazz.attr(
"__module__") + nb::str(
".") +
3175 clazz.attr(
"__name__") + nb::str(
")>");
3181 nb::class_<PyDialectRegistry>(m,
"DialectRegistry")
3189 nb::class_<PyLocation>(m,
"Location")
3192 .def(
"__enter__", &PyLocation::contextEnter)
3193 .def(
"__exit__", &PyLocation::contextExit, nb::arg(
"exc_type").none(),
3194 nb::arg(
"exc_value").none(), nb::arg(
"traceback").none())
3199 .def(
"__eq__", [](
PyLocation &
self, nb::object other) {
return false; })
3200 .def_prop_ro_static(
3202 [](nb::object & ) -> std::optional<PyLocation *> {
3203 auto *loc = PyThreadContextEntry::getDefaultLocation();
3205 return std::nullopt;
3208 "Gets the Location bound to the current thread or raises ValueError")
3215 nb::arg(
"context").none() = nb::none(),
3216 "Gets a Location representing an unknown location")
3219 [](
PyLocation callee,
const std::vector<PyLocation> &frames,
3222 throw nb::value_error(
"No caller frames provided");
3223 MlirLocation caller = frames.back().get();
3230 nb::arg(
"callee"), nb::arg(
"frames"),
3231 nb::arg(
"context").none() = nb::none(),
3238 [](std::string filename,
int line,
int col,
3245 nb::arg(
"filename"), nb::arg(
"line"), nb::arg(
"col"),
3246 nb::arg(
"context").none() = nb::none(),
3250 [](std::string filename,
int startLine,
int startCol,
int endLine,
3255 startLine, startCol, endLine, endCol));
3257 nb::arg(
"filename"), nb::arg(
"start_line"), nb::arg(
"start_col"),
3258 nb::arg(
"end_line"), nb::arg(
"end_col"),
3261 .def_prop_ro(
"filename",
3262 [](MlirLocation loc) {
3272 [](
const std::vector<PyLocation> &pyLocations,
3273 std::optional<PyAttribute> metadata,
3276 locations.reserve(pyLocations.size());
3277 for (
auto &pyLocation : pyLocations)
3278 locations.push_back(pyLocation.get());
3280 context->
get(), locations.size(), locations.data(),
3281 metadata ? metadata->get() : MlirAttribute{0});
3282 return PyLocation(context->getRef(), location);
3284 nb::arg(
"locations"), nb::arg(
"metadata").none() = nb::none(),
3285 nb::arg(
"context").none() = nb::none(),
3288 .def_prop_ro(
"locations",
3289 [](MlirLocation loc) {
3290 unsigned numLocations =
3292 std::vector<MlirLocation> locations(numLocations);
3299 [](std::string name, std::optional<PyLocation> childLoc,
3305 childLoc ? childLoc->get()
3308 nb::arg(
"name"), nb::arg(
"childLoc").none() = nb::none(),
3309 nb::arg(
"context").none() = nb::none(),
3312 .def_prop_ro(
"name_str",
3313 [](MlirLocation loc) {
3323 nb::arg(
"attribute"), nb::arg(
"context").none() = nb::none(),
3324 "Gets a Location from a LocationAttr")
3327 [](
PyLocation &
self) {
return self.getContext().getObject(); },
3328 "Context that owns the Location")
3332 "Get the underlying LocationAttr")
3338 nb::arg(
"message"),
"Emits an error at this location")
3343 return printAccum.
join();
3349 nb::class_<PyModule>(m,
"Module", nb::is_weak_referenceable())
3359 throw MLIRError(
"Unable to parse module assembly", errors.take());
3360 return PyModule::forModule(module).releaseObject();
3362 nb::arg(
"asm"), nb::arg(
"context").none() = nb::none(),
3371 throw MLIRError(
"Unable to parse module assembly", errors.take());
3372 return PyModule::forModule(module).releaseObject();
3374 nb::arg(
"asm"), nb::arg(
"context").none() = nb::none(),
3383 throw MLIRError(
"Unable to parse module assembly", errors.take());
3384 return PyModule::forModule(module).releaseObject();
3386 nb::arg(
"path"), nb::arg(
"context").none() = nb::none(),
3390 [](
const std::optional<PyLocation> &loc) {
3391 PyLocation pyLoc = maybeGetTracebackLocation(loc);
3393 return PyModule::forModule(module).releaseObject();
3395 nb::arg(
"loc").none() = nb::none(),
"Creates an empty module")
3398 [](
PyModule &
self) {
return self.getContext().getObject(); },
3399 "Context that created the Module")
3403 return PyOperation::forOperation(
self.
getContext(),
3405 self.getRef().releaseObject())
3408 "Accesses the module as an operation")
3414 self.getRef().releaseObject());
3418 "Return the block for this module")
3427 [](nb::object
self) {
3429 return self.attr(
"operation").attr(
"__str__")();
3436 nb::class_<PyOperationBase>(m,
"_OperationBase")
3439 return self.getOperation().getCapsule();
3451 .def_prop_ro(
"attributes",
3453 return PyOpAttributeMap(
self.getOperation().getRef());
3462 "Context that owns the Operation")
3463 .def_prop_ro(
"name",
3467 MlirOperation operation = concreteOperation.
get();
3470 .def_prop_ro(
"operands",
3472 return PyOpOperandList(
self.getOperation().getRef());
3474 .def_prop_ro(
"regions",
3476 return PyRegionList(
self.getOperation().getRef());
3483 "Returns the list of Operation results.")
3487 auto &operation =
self.getOperation();
3491 "Shortcut to get an op result if it has only one (throws an error "
3500 "Returns the source location the operation was defined or derived "
3502 .def_prop_ro(
"parent",
3504 auto parent =
self.getOperation().getParentOperation();
3506 return parent->getObject();
3512 return self.getAsm(
false,
3523 "Returns the assembly form of the operation.")
3525 nb::overload_cast<PyAsmState &, nb::object, bool>(
3527 nb::arg(
"state"), nb::arg(
"file").none() = 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").none() = nb::none(),
3535 nb::arg(
"large_resource_limit").none() = 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,
3542 nb::arg(
"file").none() = nb::none(), nb::arg(
"binary") =
false,
3544 .def(
"write_bytecode", &PyOperationBase::writeBytecode, nb::arg(
"file"),
3545 nb::arg(
"desired_version").none() = nb::none(),
3547 .def(
"get_asm", &PyOperationBase::getAsm,
3549 nb::arg(
"binary") =
false,
3550 nb::arg(
"large_elements_limit").none() = nb::none(),
3551 nb::arg(
"large_resource_limit").none() = 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 return self.getOperation().clone(ip);
3580 nb::arg(
"ip").none() = nb::none())
3582 "detach_from_parent",
3587 throw nb::value_error(
"Detached operation has no parent.");
3592 "Detaches the operation from its parent block.")
3600 "Reports if the operation is attached to its parent block.")
3601 .def(
"erase", [](
PyOperationBase &
self) {
self.getOperation().erase(); })
3605 nb::class_<PyOperation, PyOperationBase>(m,
"Operation")
3608 [](std::string_view name,
3609 std::optional<std::vector<PyType *>> results,
3610 std::optional<std::vector<PyValue *>> operands,
3611 std::optional<nb::dict> attributes,
3612 std::optional<std::vector<PyBlock *>> successors,
int regions,
3613 const std::optional<PyLocation> &location,
3614 const nb::object &maybeIp,
bool inferType) {
3618 mlirOperands.reserve(operands->size());
3619 for (
PyValue *operand : *operands) {
3621 throw nb::value_error(
"operand value cannot be None");
3622 mlirOperands.push_back(operand->get());
3626 PyLocation pyLoc = maybeGetTracebackLocation(location);
3627 return PyOperation::create(name, results, mlirOperands, attributes,
3628 successors, regions, pyLoc, maybeIp,
3631 nb::arg(
"name"), nb::arg(
"results").none() = nb::none(),
3632 nb::arg(
"operands").none() = nb::none(),
3633 nb::arg(
"attributes").none() = nb::none(),
3634 nb::arg(
"successors").none() = nb::none(), nb::arg(
"regions") = 0,
3635 nb::arg(
"loc").none() = nb::none(), nb::arg(
"ip").none() = nb::none(),
3639 [](
const std::string &sourceStr,
const std::string &sourceName,
3644 nb::arg(
"source"), nb::kw_only(), nb::arg(
"source_name") =
"",
3645 nb::arg(
"context").none() = nb::none(),
3646 "Parses an operation. Supports both text assembly format and binary "
3650 .def_prop_ro(
"operation", [](nb::object
self) {
return self; })
3651 .def_prop_ro(
"opview", &PyOperation::createOpView)
3652 .def_prop_ro(
"block", &PyOperation::getBlock)
3656 return PyOpSuccessors(
self.getOperation().getRef());
3658 "Returns the list of Operation successors.");
3661 nb::class_<PyOpView, PyOperationBase>(m,
"OpView")
3662 .def(nb::init<nb::object>(), nb::arg(
"operation"))
3665 [](
PyOpView *
self, std::string_view name,
3666 std::tuple<int, bool> opRegionSpec,
3667 nb::object operandSegmentSpecObj,
3668 nb::object resultSegmentSpecObj,
3669 std::optional<nb::list> resultTypeList, nb::list operandList,
3670 std::optional<nb::dict> attributes,
3671 std::optional<std::vector<PyBlock *>> successors,
3672 std::optional<int> regions,
3673 const std::optional<PyLocation> &location,
3674 const nb::object &maybeIp) {
3675 PyLocation pyLoc = maybeGetTracebackLocation(location);
3676 new (
self)
PyOpView(PyOpView::buildGeneric(
3677 name, opRegionSpec, operandSegmentSpecObj,
3678 resultSegmentSpecObj, resultTypeList, operandList,
3679 attributes, successors, regions, pyLoc, maybeIp));
3681 nb::arg(
"name"), nb::arg(
"opRegionSpec"),
3682 nb::arg(
"operandSegmentSpecObj").none() = nb::none(),
3683 nb::arg(
"resultSegmentSpecObj").none() = nb::none(),
3684 nb::arg(
"results").none() = nb::none(),
3685 nb::arg(
"operands").none() = nb::none(),
3686 nb::arg(
"attributes").none() = nb::none(),
3687 nb::arg(
"successors").none() = nb::none(),
3688 nb::arg(
"regions").none() = nb::none(),
3689 nb::arg(
"loc").none() = nb::none(),
3690 nb::arg(
"ip").none() = nb::none())
3692 .def_prop_ro(
"operation", &PyOpView::getOperationObject)
3693 .def_prop_ro(
"opview", [](nb::object
self) {
return self; })
3696 [](
PyOpView &
self) {
return nb::str(
self.getOperationObject()); })
3700 return PyOpSuccessors(
self.getOperation().getRef());
3702 "Returns the list of Operation successors.");
3703 opViewClass.attr(
"_ODS_REGIONS") = nb::make_tuple(0,
true);
3704 opViewClass.attr(
"_ODS_OPERAND_SEGMENTS") = nb::none();
3705 opViewClass.attr(
"_ODS_RESULT_SEGMENTS") = nb::none();
3710 [](nb::handle cls, std::optional<nb::list> resultTypeList,
3711 nb::list operandList, std::optional<nb::dict> attributes,
3712 std::optional<std::vector<PyBlock *>> successors,
3713 std::optional<int> regions, std::optional<PyLocation> location,
3714 const nb::object &maybeIp) {
3715 std::string name = nb::cast<std::string>(cls.attr(
"OPERATION_NAME"));
3716 std::tuple<int, bool> opRegionSpec =
3717 nb::cast<std::tuple<int, bool>>(cls.attr(
"_ODS_REGIONS"));
3718 nb::object operandSegmentSpec = cls.attr(
"_ODS_OPERAND_SEGMENTS");
3719 nb::object resultSegmentSpec = cls.attr(
"_ODS_RESULT_SEGMENTS");
3720 PyLocation pyLoc = maybeGetTracebackLocation(location);
3721 return PyOpView::buildGeneric(name, opRegionSpec, operandSegmentSpec,
3722 resultSegmentSpec, resultTypeList,
3723 operandList, attributes, successors,
3724 regions, pyLoc, maybeIp);
3726 nb::arg(
"cls"), nb::arg(
"results").none() = nb::none(),
3727 nb::arg(
"operands").none() = nb::none(),
3728 nb::arg(
"attributes").none() = nb::none(),
3729 nb::arg(
"successors").none() = nb::none(),
3730 nb::arg(
"regions").none() = nb::none(),
3731 nb::arg(
"loc").none() = nb::none(), nb::arg(
"ip").none() = nb::none(),
3732 "Builds a specific, generated OpView based on class level attributes.");
3734 [](
const nb::object &cls,
const std::string &sourceStr,
3744 std::string clsOpName =
3745 nb::cast<std::string>(cls.attr(
"OPERATION_NAME"));
3748 std::string_view parsedOpName(identifier.
data, identifier.
length);
3749 if (clsOpName != parsedOpName)
3750 throw MLIRError(Twine(
"Expected a '") + clsOpName +
"' op, got: '" +
3751 parsedOpName +
"'");
3752 return PyOpView::constructDerived(cls, parsed.
getObject());
3754 nb::arg(
"cls"), nb::arg(
"source"), nb::kw_only(),
3755 nb::arg(
"source_name") =
"", nb::arg(
"context").none() = nb::none(),
3756 "Parses a specific, generated OpView based on class level attributes");
3761 nb::class_<PyRegion>(m,
"Region")
3765 return PyBlockList(
self.getParentOperation(),
self.
get());
3767 "Returns a forward-optimized sequence of blocks.")
3771 return self.getParentOperation()->createOpView();
3773 "Returns the operation owning this region.")
3779 return PyBlockIterator(
self.getParentOperation(), firstBlock);
3781 "Iterates over blocks in the region.")
3784 return self.get().ptr == other.
get().ptr;
3786 .def(
"__eq__", [](
PyRegion &
self, nb::object &other) {
return false; });
3791 nb::class_<PyBlock>(m,
"Block")
3796 return self.getParentOperation()->createOpView();
3798 "Returns the owning operation of this block.")
3803 return PyRegion(
self.getParentOperation(), region);
3805 "Returns the owning region of this block.")
3809 return PyBlockArgumentList(
self.getParentOperation(),
self.
get());
3811 "Returns a list of block arguments.")
3817 "Append an argument of the specified type to the block and returns "
3818 "the newly added argument.")
3821 [](
PyBlock &
self,
unsigned index) {
3824 "Erase the argument at 'index' and remove it from the argument list.")
3828 return PyOperationList(
self.getParentOperation(),
self.
get());
3830 "Returns a forward-optimized sequence of operations.")
3833 [](
PyRegion &parent,
const nb::sequence &pyArgTypes,
3834 const std::optional<nb::sequence> &pyArgLocs) {
3836 MlirBlock block =
createBlock(pyArgTypes, pyArgLocs);
3840 nb::arg(
"parent"), nb::arg(
"arg_types") = nb::list(),
3841 nb::arg(
"arg_locs") = std::nullopt,
3842 "Creates and returns a new Block at the beginning of the given "
3843 "region (with given argument types and locations).")
3847 MlirBlock b =
self.get();
3852 "Append this block to a region, transferring ownership if necessary")
3855 [](
PyBlock &
self,
const nb::args &pyArgTypes,
3856 const std::optional<nb::sequence> &pyArgLocs) {
3859 createBlock(nb::cast<nb::sequence>(pyArgTypes), pyArgLocs);
3862 return PyBlock(
self.getParentOperation(), block);
3864 nb::arg(
"arg_types"), nb::kw_only(),
3865 nb::arg(
"arg_locs") = std::nullopt,
3866 "Creates and returns a new Block before this block "
3867 "(with given argument types and locations).")
3870 [](
PyBlock &
self,
const nb::args &pyArgTypes,
3871 const std::optional<nb::sequence> &pyArgLocs) {
3874 createBlock(nb::cast<nb::sequence>(pyArgTypes), pyArgLocs);
3877 return PyBlock(
self.getParentOperation(), block);
3879 nb::arg(
"arg_types"), nb::kw_only(),
3880 nb::arg(
"arg_locs") = std::nullopt,
3881 "Creates and returns a new Block after this block "
3882 "(with given argument types and locations).")
3887 MlirOperation firstOperation =
3889 return PyOperationIterator(
self.getParentOperation(),
3892 "Iterates over operations in the block.")
3895 return self.get().ptr == other.
get().ptr;
3897 .def(
"__eq__", [](
PyBlock &
self, nb::object &other) {
return false; })
3909 return printAccum.
join();
3911 "Returns the assembly form of the block.")
3921 self.getParentOperation().getObject());
3923 nb::arg(
"operation"),
3924 "Appends an operation to this block. If the operation is currently "
3925 "in another block, it will be moved.")
3929 return PyBlockSuccessors(
self,
self.getParentOperation());
3931 "Returns the list of Block successors.")
3935 return PyBlockPredecessors(
self,
self.getParentOperation());
3937 "Returns the list of Block predecessors.");
3943 nb::class_<PyInsertionPoint>(m,
"InsertionPoint")
3944 .def(nb::init<PyBlock &>(), nb::arg(
"block"),
3945 "Inserts after the last operation but still inside the block.")
3946 .def(
"__enter__", &PyInsertionPoint::contextEnter)
3947 .def(
"__exit__", &PyInsertionPoint::contextExit,
3948 nb::arg(
"exc_type").none(), nb::arg(
"exc_value").none(),
3949 nb::arg(
"traceback").none())
3950 .def_prop_ro_static(
3953 auto *ip = PyThreadContextEntry::getDefaultInsertionPoint();
3955 throw nb::value_error(
"No current InsertionPoint");
3958 "Gets the InsertionPoint bound to the current thread or raises "
3959 "ValueError if none has been set")
3960 .def(nb::init<PyOperationBase &>(), nb::arg(
"beforeOperation"),
3961 "Inserts before a referenced operation.")
3962 .def_static(
"at_block_begin", &PyInsertionPoint::atBlockBegin,
3963 nb::arg(
"block"),
"Inserts at the beginning of the block.")
3964 .def_static(
"at_block_terminator", &PyInsertionPoint::atBlockTerminator,
3965 nb::arg(
"block"),
"Inserts before the block terminator.")
3966 .def(
"insert", &PyInsertionPoint::insert, nb::arg(
"operation"),
3967 "Inserts an operation.")
3970 "Returns the block that this InsertionPoint points to.")
3974 auto refOperation =
self.getRefOperation();
3976 return refOperation->getObject();
3979 "The reference operation before which new operations are "
3980 "inserted, or None if the insertion point is at the end of "
3986 nb::class_<PyAttribute>(m,
"Attribute")
3989 .def(nb::init<PyAttribute &>(), nb::arg(
"cast_from_type"),
3990 "Casts the passed attribute to the generic Attribute")
4000 throw MLIRError(
"Unable to parse attribute", errors.take());
4003 nb::arg(
"asm"), nb::arg(
"context").none() = nb::none(),
4004 "Parses an attribute from an assembly form. Raises an MLIRError on "
4008 [](
PyAttribute &
self) {
return self.getContext().getObject(); },
4009 "Context that owns the Attribute")
4010 .def_prop_ro(
"type",
4017 nb::keep_alive<0, 1>(),
"Binds a name to the attribute")
4020 .def(
"__eq__", [](
PyAttribute &
self, nb::object &other) {
return false; })
4034 return printAccum.
join();
4036 "Returns the assembly form of the Attribute.")
4045 printAccum.
parts.append(
"Attribute(");
4048 printAccum.
parts.append(
")");
4049 return printAccum.
join();
4051 .def_prop_ro(
"typeid",
4055 "mlirTypeID was expected to be non-null.");
4061 "mlirTypeID was expected to be non-null.");
4062 std::optional<nb::callable> typeCaster =
4066 return nb::cast(
self);
4067 return typeCaster.value()(
self);
4073 nb::class_<PyNamedAttribute>(m,
"NamedAttribute")
4077 printAccum.
parts.append(
"NamedAttribute(");
4078 printAccum.
parts.append(
4081 printAccum.
parts.append(
"=");
4085 printAccum.
parts.append(
")");
4086 return printAccum.
join();
4093 "The name of the NamedAttribute binding")
4097 nb::keep_alive<0, 1>(),
4098 "The underlying generic attribute of the NamedAttribute binding");
4103 nb::class_<PyType>(m,
"Type")
4106 .def(nb::init<PyType &>(), nb::arg(
"cast_from_type"),
4107 "Casts the passed type to the generic Type")
4117 throw MLIRError(
"Unable to parse type", errors.take());
4120 nb::arg(
"asm"), nb::arg(
"context").none() = nb::none(),
4123 "context", [](
PyType &
self) {
return self.getContext().getObject(); },
4124 "Context that owns the Type")
4125 .def(
"__eq__", [](
PyType &
self,
PyType &other) {
return self == other; })
4127 "__eq__", [](
PyType &
self, nb::object &other) {
return false; },
4128 nb::arg(
"other").none())
4141 return printAccum.
join();
4143 "Returns the assembly form of the type.")
4151 printAccum.
parts.append(
"Type(");
4154 printAccum.
parts.append(
")");
4155 return printAccum.
join();
4161 "mlirTypeID was expected to be non-null.");
4162 std::optional<nb::callable> typeCaster =
4166 return nb::cast(
self);
4167 return typeCaster.value()(
self);
4169 .def_prop_ro(
"typeid", [](
PyType &
self) -> MlirTypeID {
4173 auto origRepr = nb::cast<std::string>(nb::repr(nb::cast(
self)));
4174 throw nb::value_error(
4175 (origRepr + llvm::Twine(
" has no typeid.")).str().c_str());
4181 nb::class_<PyTypeID>(m,
"TypeID")
4190 [](
PyTypeID &
self,
const nb::object &other) {
return false; })
4194 .def(
"__hash__", [](
PyTypeID &
self) {
4201 nb::class_<PyValue>(m,
"Value")
4202 .def(nb::init<PyValue &>(), nb::keep_alive<0, 1>(), nb::arg(
"value"))
4208 "Context in which the value lives.")
4214 [](
PyValue &
self) -> nb::object {
4215 MlirValue v =
self.get();
4220 "expected the owner of the value in Python to match that in "
4222 return self.getParentOperation().getObject();
4227 return nb::cast(
PyBlock(
self.getParentOperation(), block));
4230 assert(
false &&
"Value must be a block argument or an op result");
4233 .def_prop_ro(
"uses",
4235 return PyOpOperandIterator(
4240 return self.get().ptr == other.
get().ptr;
4242 .def(
"__eq__", [](
PyValue &
self, nb::object other) {
return false; })
4251 printAccum.
parts.append(
"Value(");
4254 printAccum.
parts.append(
")");
4255 return printAccum.
join();
4260 [](
PyValue &
self,
bool useLocalScope,
bool useNameLocAsPrefix) {
4265 if (useNameLocAsPrefix)
4267 MlirAsmState valueState =
4274 return printAccum.
join();
4276 nb::arg(
"use_local_scope") =
false,
4277 nb::arg(
"use_name_loc_as_prefix") =
false)
4282 MlirAsmState valueState = state.get();
4286 return printAccum.
join();
4289 .def_prop_ro(
"type",
4298 "replace_all_uses_with",
4304 "replace_all_uses_except",
4305 [](MlirValue
self, MlirValue with,
PyOperation &exception) {
4306 MlirOperation exceptedUser = exception.
get();
4309 nb::arg(
"with"), nb::arg(
"exceptions"),
4312 "replace_all_uses_except",
4313 [](MlirValue
self, MlirValue with, nb::list exceptions) {
4316 for (nb::handle exception : exceptions) {
4317 exceptionOps.push_back(nb::cast<PyOperation &>(exception).
get());
4321 self, with,
static_cast<intptr_t
>(exceptionOps.size()),
4322 exceptionOps.data());
4324 nb::arg(
"with"), nb::arg(
"exceptions"),
4327 [](
PyValue &
self) {
return self.maybeDownCast(); })
4330 [](MlirValue
self) {
4335 "Returns the source location the value");
4337 PyBlockArgument::bind(m);
4338 PyOpResult::bind(m);
4339 PyOpOperand::bind(m);
4341 nb::class_<PyAsmState>(m,
"AsmState")
4342 .def(nb::init<PyValue &, bool>(), nb::arg(
"value"),
4343 nb::arg(
"use_local_scope") =
false)
4344 .def(nb::init<PyOperationBase &, bool>(), nb::arg(
"op"),
4345 nb::arg(
"use_local_scope") =
false);
4350 nb::class_<PySymbolTable>(m,
"SymbolTable")
4351 .def(nb::init<PyOperationBase &>())
4352 .def(
"__getitem__", &PySymbolTable::dunderGetItem)
4353 .def(
"insert", &PySymbolTable::insert, nb::arg(
"operation"))
4354 .def(
"erase", &PySymbolTable::erase, nb::arg(
"operation"))
4355 .def(
"__delitem__", &PySymbolTable::dunderDel)
4356 .def(
"__contains__",
4362 .def_static(
"set_symbol_name", &PySymbolTable::setSymbolName,
4363 nb::arg(
"symbol"), nb::arg(
"name"))
4364 .def_static(
"get_symbol_name", &PySymbolTable::getSymbolName,
4366 .def_static(
"get_visibility", &PySymbolTable::getVisibility,
4368 .def_static(
"set_visibility", &PySymbolTable::setVisibility,
4369 nb::arg(
"symbol"), nb::arg(
"visibility"))
4370 .def_static(
"replace_all_symbol_uses",
4371 &PySymbolTable::replaceAllSymbolUses, nb::arg(
"old_symbol"),
4372 nb::arg(
"new_symbol"), nb::arg(
"from_op"))
4373 .def_static(
"walk_symbol_tables", &PySymbolTable::walkSymbolTables,
4374 nb::arg(
"from_op"), nb::arg(
"all_sym_uses_visible"),
4375 nb::arg(
"callback"));
4378 PyBlockArgumentList::bind(m);
4379 PyBlockIterator::bind(m);
4380 PyBlockList::bind(m);
4381 PyBlockSuccessors::bind(m);
4382 PyBlockPredecessors::bind(m);
4383 PyOperationIterator::bind(m);
4384 PyOperationList::bind(m);
4385 PyOpAttributeMap::bind(m);
4386 PyOpOperandIterator::bind(m);
4387 PyOpOperandList::bind(m);
4389 PyOpSuccessors::bind(m);
4390 PyRegionIterator::bind(m);
4391 PyRegionList::bind(m);
4399 nb::register_exception_translator([](
const std::exception_ptr &p,
4405 std::rethrow_exception(p);
4409 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 MlirValue getOpResultOrValue(nb::handle operand)
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 std::vector< MlirType > getValueTypes(Container &container, PyMlirContextRef &context)
Returns the list of types of the values held by container.
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.
PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirAttribute.
static PyAttribute createFromCapsule(nanobind::object capsule)
Creates a PyAttribute from the MlirAttribute wrapped by a capsule.
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.
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.
PyInsertionPoint(PyBlock &block)
Creates an insertion point positioned after the last operation in the block, but still inside the blo...
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)
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...
void clearOperationsInside(PyOperationBase &op)
Clears all operations nested inside the given op using clearOperation(MlirOperation).
static size_t getLiveCount()
Gets the count of live context objects. Used for testing.
void clearOperationAndInside(PyOperationBase &op)
Clears the operaiton and all operations inside using clearOperation(MlirOperation).
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...
size_t clearLiveOperations()
Clears the live operations map, returning the number of entries which were invalidated.
nanobind::object getCapsule()
Gets a capsule wrapping the void* within the MlirContext.
std::vector< PyOperation * > getLiveOperationObjects()
Get a list of Python objects which are still in the live context map.
void contextExit(const nanobind::object &excType, const nanobind::object &excVal, const nanobind::object &excTb)
void clearOperation(MlirOperation op)
Removes an operation from the live operations map and sets it invalid.
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.
size_t getLiveOperationCount()
Gets the count of live operations associated with this context.
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...
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.
static nanobind::object createFromCapsule(nanobind::object capsule)
Creates a PyOperation from the MlirOperation wrapped by a capsule.
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)
MlirAttribute 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 MlirAttribute getSymbolName(PyOperationBase &symbol)
Gets and sets the name 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.
static MlirAttribute getVisibility(PyOperationBase &symbol)
Gets and sets the visibility of a symbol op.
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.
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 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 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 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 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)
PyObjectRef< PyOperation > PyOperationRef
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)