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