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 PyOpView::buildGeneric( 1111 const py::object &cls, py::list resultTypeList, py::list operandList, 1112 llvm::Optional<py::dict> attributes, 1113 llvm::Optional<std::vector<PyBlock *>> successors, 1114 llvm::Optional<int> regions, DefaultingPyLocation location, 1115 const py::object &maybeIp) { 1116 PyMlirContextRef context = location->getContext(); 1117 // Class level operation construction metadata. 1118 std::string name = py::cast<std::string>(cls.attr("OPERATION_NAME")); 1119 // Operand and result segment specs are either none, which does no 1120 // variadic unpacking, or a list of ints with segment sizes, where each 1121 // element is either a positive number (typically 1 for a scalar) or -1 to 1122 // indicate that it is derived from the length of the same-indexed operand 1123 // or result (implying that it is a list at that position). 1124 py::object operandSegmentSpecObj = cls.attr("_ODS_OPERAND_SEGMENTS"); 1125 py::object resultSegmentSpecObj = cls.attr("_ODS_RESULT_SEGMENTS"); 1126 1127 std::vector<uint32_t> operandSegmentLengths; 1128 std::vector<uint32_t> resultSegmentLengths; 1129 1130 // Validate/determine region count. 1131 auto opRegionSpec = py::cast<std::tuple<int, bool>>(cls.attr("_ODS_REGIONS")); 1132 int opMinRegionCount = std::get<0>(opRegionSpec); 1133 bool opHasNoVariadicRegions = std::get<1>(opRegionSpec); 1134 if (!regions) { 1135 regions = opMinRegionCount; 1136 } 1137 if (*regions < opMinRegionCount) { 1138 throw py::value_error( 1139 (llvm::Twine("Operation \"") + name + "\" requires a minimum of " + 1140 llvm::Twine(opMinRegionCount) + 1141 " regions but was built with regions=" + llvm::Twine(*regions)) 1142 .str()); 1143 } 1144 if (opHasNoVariadicRegions && *regions > opMinRegionCount) { 1145 throw py::value_error( 1146 (llvm::Twine("Operation \"") + name + "\" requires a maximum of " + 1147 llvm::Twine(opMinRegionCount) + 1148 " regions but was built with regions=" + llvm::Twine(*regions)) 1149 .str()); 1150 } 1151 1152 // Unpack results. 1153 std::vector<PyType *> resultTypes; 1154 resultTypes.reserve(resultTypeList.size()); 1155 if (resultSegmentSpecObj.is_none()) { 1156 // Non-variadic result unpacking. 1157 for (const auto &it : llvm::enumerate(resultTypeList)) { 1158 try { 1159 resultTypes.push_back(py::cast<PyType *>(it.value())); 1160 if (!resultTypes.back()) 1161 throw py::cast_error(); 1162 } catch (py::cast_error &err) { 1163 throw py::value_error((llvm::Twine("Result ") + 1164 llvm::Twine(it.index()) + " of operation \"" + 1165 name + "\" must be a Type (" + err.what() + ")") 1166 .str()); 1167 } 1168 } 1169 } else { 1170 // Sized result unpacking. 1171 auto resultSegmentSpec = py::cast<std::vector<int>>(resultSegmentSpecObj); 1172 if (resultSegmentSpec.size() != resultTypeList.size()) { 1173 throw py::value_error((llvm::Twine("Operation \"") + name + 1174 "\" requires " + 1175 llvm::Twine(resultSegmentSpec.size()) + 1176 " result segments but was provided " + 1177 llvm::Twine(resultTypeList.size())) 1178 .str()); 1179 } 1180 resultSegmentLengths.reserve(resultTypeList.size()); 1181 for (const auto &it : 1182 llvm::enumerate(llvm::zip(resultTypeList, resultSegmentSpec))) { 1183 int segmentSpec = std::get<1>(it.value()); 1184 if (segmentSpec == 1 || segmentSpec == 0) { 1185 // Unpack unary element. 1186 try { 1187 auto *resultType = py::cast<PyType *>(std::get<0>(it.value())); 1188 if (resultType) { 1189 resultTypes.push_back(resultType); 1190 resultSegmentLengths.push_back(1); 1191 } else if (segmentSpec == 0) { 1192 // Allowed to be optional. 1193 resultSegmentLengths.push_back(0); 1194 } else { 1195 throw py::cast_error("was None and result is not optional"); 1196 } 1197 } catch (py::cast_error &err) { 1198 throw py::value_error((llvm::Twine("Result ") + 1199 llvm::Twine(it.index()) + " of operation \"" + 1200 name + "\" must be a Type (" + err.what() + 1201 ")") 1202 .str()); 1203 } 1204 } else if (segmentSpec == -1) { 1205 // Unpack sequence by appending. 1206 try { 1207 if (std::get<0>(it.value()).is_none()) { 1208 // Treat it as an empty list. 1209 resultSegmentLengths.push_back(0); 1210 } else { 1211 // Unpack the list. 1212 auto segment = py::cast<py::sequence>(std::get<0>(it.value())); 1213 for (py::object segmentItem : segment) { 1214 resultTypes.push_back(py::cast<PyType *>(segmentItem)); 1215 if (!resultTypes.back()) { 1216 throw py::cast_error("contained a None item"); 1217 } 1218 } 1219 resultSegmentLengths.push_back(segment.size()); 1220 } 1221 } catch (std::exception &err) { 1222 // NOTE: Sloppy to be using a catch-all here, but there are at least 1223 // three different unrelated exceptions that can be thrown in the 1224 // above "casts". Just keep the scope above small and catch them all. 1225 throw py::value_error((llvm::Twine("Result ") + 1226 llvm::Twine(it.index()) + " of operation \"" + 1227 name + "\" must be a Sequence of Types (" + 1228 err.what() + ")") 1229 .str()); 1230 } 1231 } else { 1232 throw py::value_error("Unexpected segment spec"); 1233 } 1234 } 1235 } 1236 1237 // Unpack operands. 1238 std::vector<PyValue *> operands; 1239 operands.reserve(operands.size()); 1240 if (operandSegmentSpecObj.is_none()) { 1241 // Non-sized operand unpacking. 1242 for (const auto &it : llvm::enumerate(operandList)) { 1243 try { 1244 operands.push_back(py::cast<PyValue *>(it.value())); 1245 if (!operands.back()) 1246 throw py::cast_error(); 1247 } catch (py::cast_error &err) { 1248 throw py::value_error((llvm::Twine("Operand ") + 1249 llvm::Twine(it.index()) + " of operation \"" + 1250 name + "\" must be a Value (" + err.what() + ")") 1251 .str()); 1252 } 1253 } 1254 } else { 1255 // Sized operand unpacking. 1256 auto operandSegmentSpec = py::cast<std::vector<int>>(operandSegmentSpecObj); 1257 if (operandSegmentSpec.size() != operandList.size()) { 1258 throw py::value_error((llvm::Twine("Operation \"") + name + 1259 "\" requires " + 1260 llvm::Twine(operandSegmentSpec.size()) + 1261 "operand segments but was provided " + 1262 llvm::Twine(operandList.size())) 1263 .str()); 1264 } 1265 operandSegmentLengths.reserve(operandList.size()); 1266 for (const auto &it : 1267 llvm::enumerate(llvm::zip(operandList, operandSegmentSpec))) { 1268 int segmentSpec = std::get<1>(it.value()); 1269 if (segmentSpec == 1 || segmentSpec == 0) { 1270 // Unpack unary element. 1271 try { 1272 auto *operandValue = py::cast<PyValue *>(std::get<0>(it.value())); 1273 if (operandValue) { 1274 operands.push_back(operandValue); 1275 operandSegmentLengths.push_back(1); 1276 } else if (segmentSpec == 0) { 1277 // Allowed to be optional. 1278 operandSegmentLengths.push_back(0); 1279 } else { 1280 throw py::cast_error("was None and operand is not optional"); 1281 } 1282 } catch (py::cast_error &err) { 1283 throw py::value_error((llvm::Twine("Operand ") + 1284 llvm::Twine(it.index()) + " of operation \"" + 1285 name + "\" must be a Value (" + err.what() + 1286 ")") 1287 .str()); 1288 } 1289 } else if (segmentSpec == -1) { 1290 // Unpack sequence by appending. 1291 try { 1292 if (std::get<0>(it.value()).is_none()) { 1293 // Treat it as an empty list. 1294 operandSegmentLengths.push_back(0); 1295 } else { 1296 // Unpack the list. 1297 auto segment = py::cast<py::sequence>(std::get<0>(it.value())); 1298 for (py::object segmentItem : segment) { 1299 operands.push_back(py::cast<PyValue *>(segmentItem)); 1300 if (!operands.back()) { 1301 throw py::cast_error("contained a None item"); 1302 } 1303 } 1304 operandSegmentLengths.push_back(segment.size()); 1305 } 1306 } catch (std::exception &err) { 1307 // NOTE: Sloppy to be using a catch-all here, but there are at least 1308 // three different unrelated exceptions that can be thrown in the 1309 // above "casts". Just keep the scope above small and catch them all. 1310 throw py::value_error((llvm::Twine("Operand ") + 1311 llvm::Twine(it.index()) + " of operation \"" + 1312 name + "\" must be a Sequence of Values (" + 1313 err.what() + ")") 1314 .str()); 1315 } 1316 } else { 1317 throw py::value_error("Unexpected segment spec"); 1318 } 1319 } 1320 } 1321 1322 // Merge operand/result segment lengths into attributes if needed. 1323 if (!operandSegmentLengths.empty() || !resultSegmentLengths.empty()) { 1324 // Dup. 1325 if (attributes) { 1326 attributes = py::dict(*attributes); 1327 } else { 1328 attributes = py::dict(); 1329 } 1330 if (attributes->contains("result_segment_sizes") || 1331 attributes->contains("operand_segment_sizes")) { 1332 throw py::value_error("Manually setting a 'result_segment_sizes' or " 1333 "'operand_segment_sizes' attribute is unsupported. " 1334 "Use Operation.create for such low-level access."); 1335 } 1336 1337 // Add result_segment_sizes attribute. 1338 if (!resultSegmentLengths.empty()) { 1339 int64_t size = resultSegmentLengths.size(); 1340 MlirAttribute segmentLengthAttr = mlirDenseElementsAttrUInt32Get( 1341 mlirVectorTypeGet(1, &size, mlirIntegerTypeGet(context->get(), 32)), 1342 resultSegmentLengths.size(), resultSegmentLengths.data()); 1343 (*attributes)["result_segment_sizes"] = 1344 PyAttribute(context, segmentLengthAttr); 1345 } 1346 1347 // Add operand_segment_sizes attribute. 1348 if (!operandSegmentLengths.empty()) { 1349 int64_t size = operandSegmentLengths.size(); 1350 MlirAttribute segmentLengthAttr = mlirDenseElementsAttrUInt32Get( 1351 mlirVectorTypeGet(1, &size, mlirIntegerTypeGet(context->get(), 32)), 1352 operandSegmentLengths.size(), operandSegmentLengths.data()); 1353 (*attributes)["operand_segment_sizes"] = 1354 PyAttribute(context, segmentLengthAttr); 1355 } 1356 } 1357 1358 // Delegate to create. 1359 return PyOperation::create(name, 1360 /*results=*/std::move(resultTypes), 1361 /*operands=*/std::move(operands), 1362 /*attributes=*/std::move(attributes), 1363 /*successors=*/std::move(successors), 1364 /*regions=*/*regions, location, maybeIp); 1365 } 1366 1367 PyOpView::PyOpView(const py::object &operationObject) 1368 // Casting through the PyOperationBase base-class and then back to the 1369 // Operation lets us accept any PyOperationBase subclass. 1370 : operation(py::cast<PyOperationBase &>(operationObject).getOperation()), 1371 operationObject(operation.getRef().getObject()) {} 1372 1373 py::object PyOpView::createRawSubclass(const py::object &userClass) { 1374 // This is... a little gross. The typical pattern is to have a pure python 1375 // class that extends OpView like: 1376 // class AddFOp(_cext.ir.OpView): 1377 // def __init__(self, loc, lhs, rhs): 1378 // operation = loc.context.create_operation( 1379 // "addf", lhs, rhs, results=[lhs.type]) 1380 // super().__init__(operation) 1381 // 1382 // I.e. The goal of the user facing type is to provide a nice constructor 1383 // that has complete freedom for the op under construction. This is at odds 1384 // with our other desire to sometimes create this object by just passing an 1385 // operation (to initialize the base class). We could do *arg and **kwargs 1386 // munging to try to make it work, but instead, we synthesize a new class 1387 // on the fly which extends this user class (AddFOp in this example) and 1388 // *give it* the base class's __init__ method, thus bypassing the 1389 // intermediate subclass's __init__ method entirely. While slightly, 1390 // underhanded, this is safe/legal because the type hierarchy has not changed 1391 // (we just added a new leaf) and we aren't mucking around with __new__. 1392 // Typically, this new class will be stored on the original as "_Raw" and will 1393 // be used for casts and other things that need a variant of the class that 1394 // is initialized purely from an operation. 1395 py::object parentMetaclass = 1396 py::reinterpret_borrow<py::object>((PyObject *)&PyType_Type); 1397 py::dict attributes; 1398 // TODO: pybind11 2.6 supports a more direct form. Upgrade many years from 1399 // now. 1400 // auto opViewType = py::type::of<PyOpView>(); 1401 auto opViewType = py::detail::get_type_handle(typeid(PyOpView), true); 1402 attributes["__init__"] = opViewType.attr("__init__"); 1403 py::str origName = userClass.attr("__name__"); 1404 py::str newName = py::str("_") + origName; 1405 return parentMetaclass(newName, py::make_tuple(userClass), attributes); 1406 } 1407 1408 //------------------------------------------------------------------------------ 1409 // PyInsertionPoint. 1410 //------------------------------------------------------------------------------ 1411 1412 PyInsertionPoint::PyInsertionPoint(PyBlock &block) : block(block) {} 1413 1414 PyInsertionPoint::PyInsertionPoint(PyOperationBase &beforeOperationBase) 1415 : refOperation(beforeOperationBase.getOperation().getRef()), 1416 block((*refOperation)->getBlock()) {} 1417 1418 void PyInsertionPoint::insert(PyOperationBase &operationBase) { 1419 PyOperation &operation = operationBase.getOperation(); 1420 if (operation.isAttached()) 1421 throw SetPyError(PyExc_ValueError, 1422 "Attempt to insert operation that is already attached"); 1423 block.getParentOperation()->checkValid(); 1424 MlirOperation beforeOp = {nullptr}; 1425 if (refOperation) { 1426 // Insert before operation. 1427 (*refOperation)->checkValid(); 1428 beforeOp = (*refOperation)->get(); 1429 } else { 1430 // Insert at end (before null) is only valid if the block does not 1431 // already end in a known terminator (violating this will cause assertion 1432 // failures later). 1433 if (!mlirOperationIsNull(mlirBlockGetTerminator(block.get()))) { 1434 throw py::index_error("Cannot insert operation at the end of a block " 1435 "that already has a terminator. Did you mean to " 1436 "use 'InsertionPoint.at_block_terminator(block)' " 1437 "versus 'InsertionPoint(block)'?"); 1438 } 1439 } 1440 mlirBlockInsertOwnedOperationBefore(block.get(), beforeOp, operation); 1441 operation.setAttached(); 1442 } 1443 1444 PyInsertionPoint PyInsertionPoint::atBlockBegin(PyBlock &block) { 1445 MlirOperation firstOp = mlirBlockGetFirstOperation(block.get()); 1446 if (mlirOperationIsNull(firstOp)) { 1447 // Just insert at end. 1448 return PyInsertionPoint(block); 1449 } 1450 1451 // Insert before first op. 1452 PyOperationRef firstOpRef = PyOperation::forOperation( 1453 block.getParentOperation()->getContext(), firstOp); 1454 return PyInsertionPoint{block, std::move(firstOpRef)}; 1455 } 1456 1457 PyInsertionPoint PyInsertionPoint::atBlockTerminator(PyBlock &block) { 1458 MlirOperation terminator = mlirBlockGetTerminator(block.get()); 1459 if (mlirOperationIsNull(terminator)) 1460 throw SetPyError(PyExc_ValueError, "Block has no terminator"); 1461 PyOperationRef terminatorOpRef = PyOperation::forOperation( 1462 block.getParentOperation()->getContext(), terminator); 1463 return PyInsertionPoint{block, std::move(terminatorOpRef)}; 1464 } 1465 1466 py::object PyInsertionPoint::contextEnter() { 1467 return PyThreadContextEntry::pushInsertionPoint(*this); 1468 } 1469 1470 void PyInsertionPoint::contextExit(const pybind11::object &excType, 1471 const pybind11::object &excVal, 1472 const pybind11::object &excTb) { 1473 PyThreadContextEntry::popInsertionPoint(*this); 1474 } 1475 1476 //------------------------------------------------------------------------------ 1477 // PyAttribute. 1478 //------------------------------------------------------------------------------ 1479 1480 bool PyAttribute::operator==(const PyAttribute &other) { 1481 return mlirAttributeEqual(attr, other.attr); 1482 } 1483 1484 py::object PyAttribute::getCapsule() { 1485 return py::reinterpret_steal<py::object>(mlirPythonAttributeToCapsule(*this)); 1486 } 1487 1488 PyAttribute PyAttribute::createFromCapsule(py::object capsule) { 1489 MlirAttribute rawAttr = mlirPythonCapsuleToAttribute(capsule.ptr()); 1490 if (mlirAttributeIsNull(rawAttr)) 1491 throw py::error_already_set(); 1492 return PyAttribute( 1493 PyMlirContext::forContext(mlirAttributeGetContext(rawAttr)), rawAttr); 1494 } 1495 1496 //------------------------------------------------------------------------------ 1497 // PyNamedAttribute. 1498 //------------------------------------------------------------------------------ 1499 1500 PyNamedAttribute::PyNamedAttribute(MlirAttribute attr, std::string ownedName) 1501 : ownedName(new std::string(std::move(ownedName))) { 1502 namedAttr = mlirNamedAttributeGet( 1503 mlirIdentifierGet(mlirAttributeGetContext(attr), 1504 toMlirStringRef(*this->ownedName)), 1505 attr); 1506 } 1507 1508 //------------------------------------------------------------------------------ 1509 // PyType. 1510 //------------------------------------------------------------------------------ 1511 1512 bool PyType::operator==(const PyType &other) { 1513 return mlirTypeEqual(type, other.type); 1514 } 1515 1516 py::object PyType::getCapsule() { 1517 return py::reinterpret_steal<py::object>(mlirPythonTypeToCapsule(*this)); 1518 } 1519 1520 PyType PyType::createFromCapsule(py::object capsule) { 1521 MlirType rawType = mlirPythonCapsuleToType(capsule.ptr()); 1522 if (mlirTypeIsNull(rawType)) 1523 throw py::error_already_set(); 1524 return PyType(PyMlirContext::forContext(mlirTypeGetContext(rawType)), 1525 rawType); 1526 } 1527 1528 //------------------------------------------------------------------------------ 1529 // PyValue and subclases. 1530 //------------------------------------------------------------------------------ 1531 1532 pybind11::object PyValue::getCapsule() { 1533 return py::reinterpret_steal<py::object>(mlirPythonValueToCapsule(get())); 1534 } 1535 1536 PyValue PyValue::createFromCapsule(pybind11::object capsule) { 1537 MlirValue value = mlirPythonCapsuleToValue(capsule.ptr()); 1538 if (mlirValueIsNull(value)) 1539 throw py::error_already_set(); 1540 MlirOperation owner; 1541 if (mlirValueIsAOpResult(value)) 1542 owner = mlirOpResultGetOwner(value); 1543 if (mlirValueIsABlockArgument(value)) 1544 owner = mlirBlockGetParentOperation(mlirBlockArgumentGetOwner(value)); 1545 if (mlirOperationIsNull(owner)) 1546 throw py::error_already_set(); 1547 MlirContext ctx = mlirOperationGetContext(owner); 1548 PyOperationRef ownerRef = 1549 PyOperation::forOperation(PyMlirContext::forContext(ctx), owner); 1550 return PyValue(ownerRef, value); 1551 } 1552 1553 //------------------------------------------------------------------------------ 1554 // PySymbolTable. 1555 //------------------------------------------------------------------------------ 1556 1557 PySymbolTable::PySymbolTable(PyOperationBase &operation) 1558 : operation(operation.getOperation().getRef()) { 1559 symbolTable = mlirSymbolTableCreate(operation.getOperation().get()); 1560 if (mlirSymbolTableIsNull(symbolTable)) { 1561 throw py::cast_error("Operation is not a Symbol Table."); 1562 } 1563 } 1564 1565 py::object PySymbolTable::dunderGetItem(const std::string &name) { 1566 operation->checkValid(); 1567 MlirOperation symbol = mlirSymbolTableLookup( 1568 symbolTable, mlirStringRefCreate(name.data(), name.length())); 1569 if (mlirOperationIsNull(symbol)) 1570 throw py::key_error("Symbol '" + name + "' not in the symbol table."); 1571 1572 return PyOperation::forOperation(operation->getContext(), symbol, 1573 operation.getObject()) 1574 ->createOpView(); 1575 } 1576 1577 void PySymbolTable::erase(PyOperationBase &symbol) { 1578 operation->checkValid(); 1579 symbol.getOperation().checkValid(); 1580 mlirSymbolTableErase(symbolTable, symbol.getOperation().get()); 1581 // The operation is also erased, so we must invalidate it. There may be Python 1582 // references to this operation so we don't want to delete it from the list of 1583 // live operations here. 1584 symbol.getOperation().valid = false; 1585 } 1586 1587 void PySymbolTable::dunderDel(const std::string &name) { 1588 py::object operation = dunderGetItem(name); 1589 erase(py::cast<PyOperationBase &>(operation)); 1590 } 1591 1592 PyAttribute PySymbolTable::insert(PyOperationBase &symbol) { 1593 operation->checkValid(); 1594 symbol.getOperation().checkValid(); 1595 MlirAttribute symbolAttr = mlirOperationGetAttributeByName( 1596 symbol.getOperation().get(), mlirSymbolTableGetSymbolAttributeName()); 1597 if (mlirAttributeIsNull(symbolAttr)) 1598 throw py::value_error("Expected operation to have a symbol name."); 1599 return PyAttribute( 1600 symbol.getOperation().getContext(), 1601 mlirSymbolTableInsert(symbolTable, symbol.getOperation().get())); 1602 } 1603 1604 PyAttribute PySymbolTable::getSymbolName(PyOperationBase &symbol) { 1605 // Op must already be a symbol. 1606 PyOperation &operation = symbol.getOperation(); 1607 operation.checkValid(); 1608 MlirStringRef attrName = mlirSymbolTableGetSymbolAttributeName(); 1609 MlirAttribute existingNameAttr = 1610 mlirOperationGetAttributeByName(operation.get(), attrName); 1611 if (mlirAttributeIsNull(existingNameAttr)) 1612 throw py::value_error("Expected operation to have a symbol name."); 1613 return PyAttribute(symbol.getOperation().getContext(), existingNameAttr); 1614 } 1615 1616 void PySymbolTable::setSymbolName(PyOperationBase &symbol, 1617 const std::string &name) { 1618 // Op must already be a symbol. 1619 PyOperation &operation = symbol.getOperation(); 1620 operation.checkValid(); 1621 MlirStringRef attrName = mlirSymbolTableGetSymbolAttributeName(); 1622 MlirAttribute existingNameAttr = 1623 mlirOperationGetAttributeByName(operation.get(), attrName); 1624 if (mlirAttributeIsNull(existingNameAttr)) 1625 throw py::value_error("Expected operation to have a symbol name."); 1626 MlirAttribute newNameAttr = 1627 mlirStringAttrGet(operation.getContext()->get(), toMlirStringRef(name)); 1628 mlirOperationSetAttributeByName(operation.get(), attrName, newNameAttr); 1629 } 1630 1631 PyAttribute PySymbolTable::getVisibility(PyOperationBase &symbol) { 1632 PyOperation &operation = symbol.getOperation(); 1633 operation.checkValid(); 1634 MlirStringRef attrName = mlirSymbolTableGetVisibilityAttributeName(); 1635 MlirAttribute existingVisAttr = 1636 mlirOperationGetAttributeByName(operation.get(), attrName); 1637 if (mlirAttributeIsNull(existingVisAttr)) 1638 throw py::value_error("Expected operation to have a symbol visibility."); 1639 return PyAttribute(symbol.getOperation().getContext(), existingVisAttr); 1640 } 1641 1642 void PySymbolTable::setVisibility(PyOperationBase &symbol, 1643 const std::string &visibility) { 1644 if (visibility != "public" && visibility != "private" && 1645 visibility != "nested") 1646 throw py::value_error( 1647 "Expected visibility to be 'public', 'private' or 'nested'"); 1648 PyOperation &operation = symbol.getOperation(); 1649 operation.checkValid(); 1650 MlirStringRef attrName = mlirSymbolTableGetVisibilityAttributeName(); 1651 MlirAttribute existingVisAttr = 1652 mlirOperationGetAttributeByName(operation.get(), attrName); 1653 if (mlirAttributeIsNull(existingVisAttr)) 1654 throw py::value_error("Expected operation to have a symbol visibility."); 1655 MlirAttribute newVisAttr = mlirStringAttrGet(operation.getContext()->get(), 1656 toMlirStringRef(visibility)); 1657 mlirOperationSetAttributeByName(operation.get(), attrName, newVisAttr); 1658 } 1659 1660 void PySymbolTable::replaceAllSymbolUses(const std::string &oldSymbol, 1661 const std::string &newSymbol, 1662 PyOperationBase &from) { 1663 PyOperation &fromOperation = from.getOperation(); 1664 fromOperation.checkValid(); 1665 if (mlirLogicalResultIsFailure(mlirSymbolTableReplaceAllSymbolUses( 1666 toMlirStringRef(oldSymbol), toMlirStringRef(newSymbol), 1667 from.getOperation()))) 1668 1669 throw py::value_error("Symbol rename failed"); 1670 } 1671 1672 void PySymbolTable::walkSymbolTables(PyOperationBase &from, 1673 bool allSymUsesVisible, 1674 py::object callback) { 1675 PyOperation &fromOperation = from.getOperation(); 1676 fromOperation.checkValid(); 1677 struct UserData { 1678 PyMlirContextRef context; 1679 py::object callback; 1680 bool gotException; 1681 std::string exceptionWhat; 1682 py::object exceptionType; 1683 }; 1684 UserData userData{ 1685 fromOperation.getContext(), std::move(callback), false, {}, {}}; 1686 mlirSymbolTableWalkSymbolTables( 1687 fromOperation.get(), allSymUsesVisible, 1688 [](MlirOperation foundOp, bool isVisible, void *calleeUserDataVoid) { 1689 UserData *calleeUserData = static_cast<UserData *>(calleeUserDataVoid); 1690 auto pyFoundOp = 1691 PyOperation::forOperation(calleeUserData->context, foundOp); 1692 if (calleeUserData->gotException) 1693 return; 1694 try { 1695 calleeUserData->callback(pyFoundOp.getObject(), isVisible); 1696 } catch (py::error_already_set &e) { 1697 calleeUserData->gotException = true; 1698 calleeUserData->exceptionWhat = e.what(); 1699 calleeUserData->exceptionType = e.type(); 1700 } 1701 }, 1702 static_cast<void *>(&userData)); 1703 if (userData.gotException) { 1704 std::string message("Exception raised in callback: "); 1705 message.append(userData.exceptionWhat); 1706 throw std::runtime_error(message); 1707 } 1708 } 1709 1710 namespace { 1711 /// CRTP base class for Python MLIR values that subclass Value and should be 1712 /// castable from it. The value hierarchy is one level deep and is not supposed 1713 /// to accommodate other levels unless core MLIR changes. 1714 template <typename DerivedTy> 1715 class PyConcreteValue : public PyValue { 1716 public: 1717 // Derived classes must define statics for: 1718 // IsAFunctionTy isaFunction 1719 // const char *pyClassName 1720 // and redefine bindDerived. 1721 using ClassTy = py::class_<DerivedTy, PyValue>; 1722 using IsAFunctionTy = bool (*)(MlirValue); 1723 1724 PyConcreteValue() = default; 1725 PyConcreteValue(PyOperationRef operationRef, MlirValue value) 1726 : PyValue(operationRef, value) {} 1727 PyConcreteValue(PyValue &orig) 1728 : PyConcreteValue(orig.getParentOperation(), castFrom(orig)) {} 1729 1730 /// Attempts to cast the original value to the derived type and throws on 1731 /// type mismatches. 1732 static MlirValue castFrom(PyValue &orig) { 1733 if (!DerivedTy::isaFunction(orig.get())) { 1734 auto origRepr = py::repr(py::cast(orig)).cast<std::string>(); 1735 throw SetPyError(PyExc_ValueError, Twine("Cannot cast value to ") + 1736 DerivedTy::pyClassName + 1737 " (from " + origRepr + ")"); 1738 } 1739 return orig.get(); 1740 } 1741 1742 /// Binds the Python module objects to functions of this class. 1743 static void bind(py::module &m) { 1744 auto cls = ClassTy(m, DerivedTy::pyClassName, py::module_local()); 1745 cls.def(py::init<PyValue &>(), py::keep_alive<0, 1>(), py::arg("value")); 1746 cls.def_static( 1747 "isinstance", 1748 [](PyValue &otherValue) -> bool { 1749 return DerivedTy::isaFunction(otherValue); 1750 }, 1751 py::arg("other_value")); 1752 DerivedTy::bindDerived(cls); 1753 } 1754 1755 /// Implemented by derived classes to add methods to the Python subclass. 1756 static void bindDerived(ClassTy &m) {} 1757 }; 1758 1759 /// Python wrapper for MlirBlockArgument. 1760 class PyBlockArgument : public PyConcreteValue<PyBlockArgument> { 1761 public: 1762 static constexpr IsAFunctionTy isaFunction = mlirValueIsABlockArgument; 1763 static constexpr const char *pyClassName = "BlockArgument"; 1764 using PyConcreteValue::PyConcreteValue; 1765 1766 static void bindDerived(ClassTy &c) { 1767 c.def_property_readonly("owner", [](PyBlockArgument &self) { 1768 return PyBlock(self.getParentOperation(), 1769 mlirBlockArgumentGetOwner(self.get())); 1770 }); 1771 c.def_property_readonly("arg_number", [](PyBlockArgument &self) { 1772 return mlirBlockArgumentGetArgNumber(self.get()); 1773 }); 1774 c.def( 1775 "set_type", 1776 [](PyBlockArgument &self, PyType type) { 1777 return mlirBlockArgumentSetType(self.get(), type); 1778 }, 1779 py::arg("type")); 1780 } 1781 }; 1782 1783 /// Python wrapper for MlirOpResult. 1784 class PyOpResult : public PyConcreteValue<PyOpResult> { 1785 public: 1786 static constexpr IsAFunctionTy isaFunction = mlirValueIsAOpResult; 1787 static constexpr const char *pyClassName = "OpResult"; 1788 using PyConcreteValue::PyConcreteValue; 1789 1790 static void bindDerived(ClassTy &c) { 1791 c.def_property_readonly("owner", [](PyOpResult &self) { 1792 assert( 1793 mlirOperationEqual(self.getParentOperation()->get(), 1794 mlirOpResultGetOwner(self.get())) && 1795 "expected the owner of the value in Python to match that in the IR"); 1796 return self.getParentOperation().getObject(); 1797 }); 1798 c.def_property_readonly("result_number", [](PyOpResult &self) { 1799 return mlirOpResultGetResultNumber(self.get()); 1800 }); 1801 } 1802 }; 1803 1804 /// Returns the list of types of the values held by container. 1805 template <typename Container> 1806 static std::vector<PyType> getValueTypes(Container &container, 1807 PyMlirContextRef &context) { 1808 std::vector<PyType> result; 1809 result.reserve(container.getNumElements()); 1810 for (int i = 0, e = container.getNumElements(); i < e; ++i) { 1811 result.push_back( 1812 PyType(context, mlirValueGetType(container.getElement(i).get()))); 1813 } 1814 return result; 1815 } 1816 1817 /// A list of block arguments. Internally, these are stored as consecutive 1818 /// elements, random access is cheap. The argument list is associated with the 1819 /// operation that contains the block (detached blocks are not allowed in 1820 /// Python bindings) and extends its lifetime. 1821 class PyBlockArgumentList 1822 : public Sliceable<PyBlockArgumentList, PyBlockArgument> { 1823 public: 1824 static constexpr const char *pyClassName = "BlockArgumentList"; 1825 1826 PyBlockArgumentList(PyOperationRef operation, MlirBlock block, 1827 intptr_t startIndex = 0, intptr_t length = -1, 1828 intptr_t step = 1) 1829 : Sliceable(startIndex, 1830 length == -1 ? mlirBlockGetNumArguments(block) : length, 1831 step), 1832 operation(std::move(operation)), block(block) {} 1833 1834 /// Returns the number of arguments in the list. 1835 intptr_t getNumElements() { 1836 operation->checkValid(); 1837 return mlirBlockGetNumArguments(block); 1838 } 1839 1840 /// Returns `pos`-the element in the list. Asserts on out-of-bounds. 1841 PyBlockArgument getElement(intptr_t pos) { 1842 MlirValue argument = mlirBlockGetArgument(block, pos); 1843 return PyBlockArgument(operation, argument); 1844 } 1845 1846 /// Returns a sublist of this list. 1847 PyBlockArgumentList slice(intptr_t startIndex, intptr_t length, 1848 intptr_t step) { 1849 return PyBlockArgumentList(operation, block, startIndex, length, step); 1850 } 1851 1852 static void bindDerived(ClassTy &c) { 1853 c.def_property_readonly("types", [](PyBlockArgumentList &self) { 1854 return getValueTypes(self, self.operation->getContext()); 1855 }); 1856 } 1857 1858 private: 1859 PyOperationRef operation; 1860 MlirBlock block; 1861 }; 1862 1863 /// A list of operation operands. Internally, these are stored as consecutive 1864 /// elements, random access is cheap. The result list is associated with the 1865 /// operation whose results these are, and extends the lifetime of this 1866 /// operation. 1867 class PyOpOperandList : public Sliceable<PyOpOperandList, PyValue> { 1868 public: 1869 static constexpr const char *pyClassName = "OpOperandList"; 1870 1871 PyOpOperandList(PyOperationRef operation, intptr_t startIndex = 0, 1872 intptr_t length = -1, intptr_t step = 1) 1873 : Sliceable(startIndex, 1874 length == -1 ? mlirOperationGetNumOperands(operation->get()) 1875 : length, 1876 step), 1877 operation(operation) {} 1878 1879 intptr_t getNumElements() { 1880 operation->checkValid(); 1881 return mlirOperationGetNumOperands(operation->get()); 1882 } 1883 1884 PyValue getElement(intptr_t pos) { 1885 MlirValue operand = mlirOperationGetOperand(operation->get(), pos); 1886 MlirOperation owner; 1887 if (mlirValueIsAOpResult(operand)) 1888 owner = mlirOpResultGetOwner(operand); 1889 else if (mlirValueIsABlockArgument(operand)) 1890 owner = mlirBlockGetParentOperation(mlirBlockArgumentGetOwner(operand)); 1891 else 1892 assert(false && "Value must be an block arg or op result."); 1893 PyOperationRef pyOwner = 1894 PyOperation::forOperation(operation->getContext(), owner); 1895 return PyValue(pyOwner, operand); 1896 } 1897 1898 PyOpOperandList slice(intptr_t startIndex, intptr_t length, intptr_t step) { 1899 return PyOpOperandList(operation, startIndex, length, step); 1900 } 1901 1902 void dunderSetItem(intptr_t index, PyValue value) { 1903 index = wrapIndex(index); 1904 mlirOperationSetOperand(operation->get(), index, value.get()); 1905 } 1906 1907 static void bindDerived(ClassTy &c) { 1908 c.def("__setitem__", &PyOpOperandList::dunderSetItem); 1909 } 1910 1911 private: 1912 PyOperationRef operation; 1913 }; 1914 1915 /// A list of operation results. Internally, these are stored as consecutive 1916 /// elements, random access is cheap. The result list is associated with the 1917 /// operation whose results these are, and extends the lifetime of this 1918 /// operation. 1919 class PyOpResultList : public Sliceable<PyOpResultList, PyOpResult> { 1920 public: 1921 static constexpr const char *pyClassName = "OpResultList"; 1922 1923 PyOpResultList(PyOperationRef operation, intptr_t startIndex = 0, 1924 intptr_t length = -1, intptr_t step = 1) 1925 : Sliceable(startIndex, 1926 length == -1 ? mlirOperationGetNumResults(operation->get()) 1927 : length, 1928 step), 1929 operation(operation) {} 1930 1931 intptr_t getNumElements() { 1932 operation->checkValid(); 1933 return mlirOperationGetNumResults(operation->get()); 1934 } 1935 1936 PyOpResult getElement(intptr_t index) { 1937 PyValue value(operation, mlirOperationGetResult(operation->get(), index)); 1938 return PyOpResult(value); 1939 } 1940 1941 PyOpResultList slice(intptr_t startIndex, intptr_t length, intptr_t step) { 1942 return PyOpResultList(operation, startIndex, length, step); 1943 } 1944 1945 static void bindDerived(ClassTy &c) { 1946 c.def_property_readonly("types", [](PyOpResultList &self) { 1947 return getValueTypes(self, self.operation->getContext()); 1948 }); 1949 } 1950 1951 private: 1952 PyOperationRef operation; 1953 }; 1954 1955 /// A list of operation attributes. Can be indexed by name, producing 1956 /// attributes, or by index, producing named attributes. 1957 class PyOpAttributeMap { 1958 public: 1959 PyOpAttributeMap(PyOperationRef operation) 1960 : operation(std::move(operation)) {} 1961 1962 PyAttribute dunderGetItemNamed(const std::string &name) { 1963 MlirAttribute attr = mlirOperationGetAttributeByName(operation->get(), 1964 toMlirStringRef(name)); 1965 if (mlirAttributeIsNull(attr)) { 1966 throw SetPyError(PyExc_KeyError, 1967 "attempt to access a non-existent attribute"); 1968 } 1969 return PyAttribute(operation->getContext(), attr); 1970 } 1971 1972 PyNamedAttribute dunderGetItemIndexed(intptr_t index) { 1973 if (index < 0 || index >= dunderLen()) { 1974 throw SetPyError(PyExc_IndexError, 1975 "attempt to access out of bounds attribute"); 1976 } 1977 MlirNamedAttribute namedAttr = 1978 mlirOperationGetAttribute(operation->get(), index); 1979 return PyNamedAttribute( 1980 namedAttr.attribute, 1981 std::string(mlirIdentifierStr(namedAttr.name).data, 1982 mlirIdentifierStr(namedAttr.name).length)); 1983 } 1984 1985 void dunderSetItem(const std::string &name, const PyAttribute &attr) { 1986 mlirOperationSetAttributeByName(operation->get(), toMlirStringRef(name), 1987 attr); 1988 } 1989 1990 void dunderDelItem(const std::string &name) { 1991 int removed = mlirOperationRemoveAttributeByName(operation->get(), 1992 toMlirStringRef(name)); 1993 if (!removed) 1994 throw SetPyError(PyExc_KeyError, 1995 "attempt to delete a non-existent attribute"); 1996 } 1997 1998 intptr_t dunderLen() { 1999 return mlirOperationGetNumAttributes(operation->get()); 2000 } 2001 2002 bool dunderContains(const std::string &name) { 2003 return !mlirAttributeIsNull(mlirOperationGetAttributeByName( 2004 operation->get(), toMlirStringRef(name))); 2005 } 2006 2007 static void bind(py::module &m) { 2008 py::class_<PyOpAttributeMap>(m, "OpAttributeMap", py::module_local()) 2009 .def("__contains__", &PyOpAttributeMap::dunderContains) 2010 .def("__len__", &PyOpAttributeMap::dunderLen) 2011 .def("__getitem__", &PyOpAttributeMap::dunderGetItemNamed) 2012 .def("__getitem__", &PyOpAttributeMap::dunderGetItemIndexed) 2013 .def("__setitem__", &PyOpAttributeMap::dunderSetItem) 2014 .def("__delitem__", &PyOpAttributeMap::dunderDelItem); 2015 } 2016 2017 private: 2018 PyOperationRef operation; 2019 }; 2020 2021 } // namespace 2022 2023 //------------------------------------------------------------------------------ 2024 // Populates the core exports of the 'ir' submodule. 2025 //------------------------------------------------------------------------------ 2026 2027 void mlir::python::populateIRCore(py::module &m) { 2028 //---------------------------------------------------------------------------- 2029 // Mapping of MlirContext. 2030 //---------------------------------------------------------------------------- 2031 py::class_<PyMlirContext>(m, "Context", py::module_local()) 2032 .def(py::init<>(&PyMlirContext::createNewContextForInit)) 2033 .def_static("_get_live_count", &PyMlirContext::getLiveCount) 2034 .def("_get_context_again", 2035 [](PyMlirContext &self) { 2036 PyMlirContextRef ref = PyMlirContext::forContext(self.get()); 2037 return ref.releaseObject(); 2038 }) 2039 .def("_get_live_operation_count", &PyMlirContext::getLiveOperationCount) 2040 .def("_get_live_module_count", &PyMlirContext::getLiveModuleCount) 2041 .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, 2042 &PyMlirContext::getCapsule) 2043 .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyMlirContext::createFromCapsule) 2044 .def("__enter__", &PyMlirContext::contextEnter) 2045 .def("__exit__", &PyMlirContext::contextExit) 2046 .def_property_readonly_static( 2047 "current", 2048 [](py::object & /*class*/) { 2049 auto *context = PyThreadContextEntry::getDefaultContext(); 2050 if (!context) 2051 throw SetPyError(PyExc_ValueError, "No current Context"); 2052 return context; 2053 }, 2054 "Gets the Context bound to the current thread or raises ValueError") 2055 .def_property_readonly( 2056 "dialects", 2057 [](PyMlirContext &self) { return PyDialects(self.getRef()); }, 2058 "Gets a container for accessing dialects by name") 2059 .def_property_readonly( 2060 "d", [](PyMlirContext &self) { return PyDialects(self.getRef()); }, 2061 "Alias for 'dialect'") 2062 .def( 2063 "get_dialect_descriptor", 2064 [=](PyMlirContext &self, std::string &name) { 2065 MlirDialect dialect = mlirContextGetOrLoadDialect( 2066 self.get(), {name.data(), name.size()}); 2067 if (mlirDialectIsNull(dialect)) { 2068 throw SetPyError(PyExc_ValueError, 2069 Twine("Dialect '") + name + "' not found"); 2070 } 2071 return PyDialectDescriptor(self.getRef(), dialect); 2072 }, 2073 py::arg("dialect_name"), 2074 "Gets or loads a dialect by name, returning its descriptor object") 2075 .def_property( 2076 "allow_unregistered_dialects", 2077 [](PyMlirContext &self) -> bool { 2078 return mlirContextGetAllowUnregisteredDialects(self.get()); 2079 }, 2080 [](PyMlirContext &self, bool value) { 2081 mlirContextSetAllowUnregisteredDialects(self.get(), value); 2082 }) 2083 .def( 2084 "enable_multithreading", 2085 [](PyMlirContext &self, bool enable) { 2086 mlirContextEnableMultithreading(self.get(), enable); 2087 }, 2088 py::arg("enable")) 2089 .def( 2090 "is_registered_operation", 2091 [](PyMlirContext &self, std::string &name) { 2092 return mlirContextIsRegisteredOperation( 2093 self.get(), MlirStringRef{name.data(), name.size()}); 2094 }, 2095 py::arg("operation_name")); 2096 2097 //---------------------------------------------------------------------------- 2098 // Mapping of PyDialectDescriptor 2099 //---------------------------------------------------------------------------- 2100 py::class_<PyDialectDescriptor>(m, "DialectDescriptor", py::module_local()) 2101 .def_property_readonly("namespace", 2102 [](PyDialectDescriptor &self) { 2103 MlirStringRef ns = 2104 mlirDialectGetNamespace(self.get()); 2105 return py::str(ns.data, ns.length); 2106 }) 2107 .def("__repr__", [](PyDialectDescriptor &self) { 2108 MlirStringRef ns = mlirDialectGetNamespace(self.get()); 2109 std::string repr("<DialectDescriptor "); 2110 repr.append(ns.data, ns.length); 2111 repr.append(">"); 2112 return repr; 2113 }); 2114 2115 //---------------------------------------------------------------------------- 2116 // Mapping of PyDialects 2117 //---------------------------------------------------------------------------- 2118 py::class_<PyDialects>(m, "Dialects", py::module_local()) 2119 .def("__getitem__", 2120 [=](PyDialects &self, std::string keyName) { 2121 MlirDialect dialect = 2122 self.getDialectForKey(keyName, /*attrError=*/false); 2123 py::object descriptor = 2124 py::cast(PyDialectDescriptor{self.getContext(), dialect}); 2125 return createCustomDialectWrapper(keyName, std::move(descriptor)); 2126 }) 2127 .def("__getattr__", [=](PyDialects &self, std::string attrName) { 2128 MlirDialect dialect = 2129 self.getDialectForKey(attrName, /*attrError=*/true); 2130 py::object descriptor = 2131 py::cast(PyDialectDescriptor{self.getContext(), dialect}); 2132 return createCustomDialectWrapper(attrName, std::move(descriptor)); 2133 }); 2134 2135 //---------------------------------------------------------------------------- 2136 // Mapping of PyDialect 2137 //---------------------------------------------------------------------------- 2138 py::class_<PyDialect>(m, "Dialect", py::module_local()) 2139 .def(py::init<py::object>(), py::arg("descriptor")) 2140 .def_property_readonly( 2141 "descriptor", [](PyDialect &self) { return self.getDescriptor(); }) 2142 .def("__repr__", [](py::object self) { 2143 auto clazz = self.attr("__class__"); 2144 return py::str("<Dialect ") + 2145 self.attr("descriptor").attr("namespace") + py::str(" (class ") + 2146 clazz.attr("__module__") + py::str(".") + 2147 clazz.attr("__name__") + py::str(")>"); 2148 }); 2149 2150 //---------------------------------------------------------------------------- 2151 // Mapping of Location 2152 //---------------------------------------------------------------------------- 2153 py::class_<PyLocation>(m, "Location", py::module_local()) 2154 .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyLocation::getCapsule) 2155 .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyLocation::createFromCapsule) 2156 .def("__enter__", &PyLocation::contextEnter) 2157 .def("__exit__", &PyLocation::contextExit) 2158 .def("__eq__", 2159 [](PyLocation &self, PyLocation &other) -> bool { 2160 return mlirLocationEqual(self, other); 2161 }) 2162 .def("__eq__", [](PyLocation &self, py::object other) { return false; }) 2163 .def_property_readonly_static( 2164 "current", 2165 [](py::object & /*class*/) { 2166 auto *loc = PyThreadContextEntry::getDefaultLocation(); 2167 if (!loc) 2168 throw SetPyError(PyExc_ValueError, "No current Location"); 2169 return loc; 2170 }, 2171 "Gets the Location bound to the current thread or raises ValueError") 2172 .def_static( 2173 "unknown", 2174 [](DefaultingPyMlirContext context) { 2175 return PyLocation(context->getRef(), 2176 mlirLocationUnknownGet(context->get())); 2177 }, 2178 py::arg("context") = py::none(), 2179 "Gets a Location representing an unknown location") 2180 .def_static( 2181 "callsite", 2182 [](PyLocation callee, const std::vector<PyLocation> &frames, 2183 DefaultingPyMlirContext context) { 2184 if (frames.empty()) 2185 throw py::value_error("No caller frames provided"); 2186 MlirLocation caller = frames.back().get(); 2187 for (const PyLocation &frame : 2188 llvm::reverse(llvm::makeArrayRef(frames).drop_back())) 2189 caller = mlirLocationCallSiteGet(frame.get(), caller); 2190 return PyLocation(context->getRef(), 2191 mlirLocationCallSiteGet(callee.get(), caller)); 2192 }, 2193 py::arg("callee"), py::arg("frames"), py::arg("context") = py::none(), 2194 kContextGetCallSiteLocationDocstring) 2195 .def_static( 2196 "file", 2197 [](std::string filename, int line, int col, 2198 DefaultingPyMlirContext context) { 2199 return PyLocation( 2200 context->getRef(), 2201 mlirLocationFileLineColGet( 2202 context->get(), toMlirStringRef(filename), line, col)); 2203 }, 2204 py::arg("filename"), py::arg("line"), py::arg("col"), 2205 py::arg("context") = py::none(), kContextGetFileLocationDocstring) 2206 .def_static( 2207 "fused", 2208 [](const std::vector<PyLocation> &pyLocations, llvm::Optional<PyAttribute> metadata, 2209 DefaultingPyMlirContext context) { 2210 if (pyLocations.empty()) 2211 throw py::value_error("No locations provided"); 2212 llvm::SmallVector<MlirLocation, 4> locations; 2213 locations.reserve(pyLocations.size()); 2214 for (auto &pyLocation : pyLocations) 2215 locations.push_back(pyLocation.get()); 2216 MlirLocation location = mlirLocationFusedGet( 2217 context->get(), locations.size(), locations.data(), 2218 metadata ? metadata->get() : MlirAttribute{0}); 2219 return PyLocation(context->getRef(), location); 2220 }, 2221 py::arg("locations"), py::arg("metadata") = py::none(), 2222 py::arg("context") = py::none(), kContextGetFusedLocationDocstring) 2223 .def_static( 2224 "name", 2225 [](std::string name, llvm::Optional<PyLocation> childLoc, 2226 DefaultingPyMlirContext context) { 2227 return PyLocation( 2228 context->getRef(), 2229 mlirLocationNameGet( 2230 context->get(), toMlirStringRef(name), 2231 childLoc ? childLoc->get() 2232 : mlirLocationUnknownGet(context->get()))); 2233 }, 2234 py::arg("name"), py::arg("childLoc") = py::none(), 2235 py::arg("context") = py::none(), kContextGetNameLocationDocString) 2236 .def_property_readonly( 2237 "context", 2238 [](PyLocation &self) { return self.getContext().getObject(); }, 2239 "Context that owns the Location") 2240 .def("__repr__", [](PyLocation &self) { 2241 PyPrintAccumulator printAccum; 2242 mlirLocationPrint(self, printAccum.getCallback(), 2243 printAccum.getUserData()); 2244 return printAccum.join(); 2245 }); 2246 2247 //---------------------------------------------------------------------------- 2248 // Mapping of Module 2249 //---------------------------------------------------------------------------- 2250 py::class_<PyModule>(m, "Module", py::module_local()) 2251 .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyModule::getCapsule) 2252 .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyModule::createFromCapsule) 2253 .def_static( 2254 "parse", 2255 [](const std::string moduleAsm, DefaultingPyMlirContext context) { 2256 MlirModule module = mlirModuleCreateParse( 2257 context->get(), toMlirStringRef(moduleAsm)); 2258 // TODO: Rework error reporting once diagnostic engine is exposed 2259 // in C API. 2260 if (mlirModuleIsNull(module)) { 2261 throw SetPyError( 2262 PyExc_ValueError, 2263 "Unable to parse module assembly (see diagnostics)"); 2264 } 2265 return PyModule::forModule(module).releaseObject(); 2266 }, 2267 py::arg("asm"), py::arg("context") = py::none(), 2268 kModuleParseDocstring) 2269 .def_static( 2270 "create", 2271 [](DefaultingPyLocation loc) { 2272 MlirModule module = mlirModuleCreateEmpty(loc); 2273 return PyModule::forModule(module).releaseObject(); 2274 }, 2275 py::arg("loc") = py::none(), "Creates an empty module") 2276 .def_property_readonly( 2277 "context", 2278 [](PyModule &self) { return self.getContext().getObject(); }, 2279 "Context that created the Module") 2280 .def_property_readonly( 2281 "operation", 2282 [](PyModule &self) { 2283 return PyOperation::forOperation(self.getContext(), 2284 mlirModuleGetOperation(self.get()), 2285 self.getRef().releaseObject()) 2286 .releaseObject(); 2287 }, 2288 "Accesses the module as an operation") 2289 .def_property_readonly( 2290 "body", 2291 [](PyModule &self) { 2292 PyOperationRef moduleOp = PyOperation::forOperation( 2293 self.getContext(), mlirModuleGetOperation(self.get()), 2294 self.getRef().releaseObject()); 2295 PyBlock returnBlock(moduleOp, mlirModuleGetBody(self.get())); 2296 return returnBlock; 2297 }, 2298 "Return the block for this module") 2299 .def( 2300 "dump", 2301 [](PyModule &self) { 2302 mlirOperationDump(mlirModuleGetOperation(self.get())); 2303 }, 2304 kDumpDocstring) 2305 .def( 2306 "__str__", 2307 [](py::object self) { 2308 // Defer to the operation's __str__. 2309 return self.attr("operation").attr("__str__")(); 2310 }, 2311 kOperationStrDunderDocstring); 2312 2313 //---------------------------------------------------------------------------- 2314 // Mapping of Operation. 2315 //---------------------------------------------------------------------------- 2316 py::class_<PyOperationBase>(m, "_OperationBase", py::module_local()) 2317 .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, 2318 [](PyOperationBase &self) { 2319 return self.getOperation().getCapsule(); 2320 }) 2321 .def("__eq__", 2322 [](PyOperationBase &self, PyOperationBase &other) { 2323 return &self.getOperation() == &other.getOperation(); 2324 }) 2325 .def("__eq__", 2326 [](PyOperationBase &self, py::object other) { return false; }) 2327 .def("__hash__", 2328 [](PyOperationBase &self) { 2329 return static_cast<size_t>(llvm::hash_value(&self.getOperation())); 2330 }) 2331 .def_property_readonly("attributes", 2332 [](PyOperationBase &self) { 2333 return PyOpAttributeMap( 2334 self.getOperation().getRef()); 2335 }) 2336 .def_property_readonly("operands", 2337 [](PyOperationBase &self) { 2338 return PyOpOperandList( 2339 self.getOperation().getRef()); 2340 }) 2341 .def_property_readonly("regions", 2342 [](PyOperationBase &self) { 2343 return PyRegionList( 2344 self.getOperation().getRef()); 2345 }) 2346 .def_property_readonly( 2347 "results", 2348 [](PyOperationBase &self) { 2349 return PyOpResultList(self.getOperation().getRef()); 2350 }, 2351 "Returns the list of Operation results.") 2352 .def_property_readonly( 2353 "result", 2354 [](PyOperationBase &self) { 2355 auto &operation = self.getOperation(); 2356 auto numResults = mlirOperationGetNumResults(operation); 2357 if (numResults != 1) { 2358 auto name = mlirIdentifierStr(mlirOperationGetName(operation)); 2359 throw SetPyError( 2360 PyExc_ValueError, 2361 Twine("Cannot call .result on operation ") + 2362 StringRef(name.data, name.length) + " which has " + 2363 Twine(numResults) + 2364 " results (it is only valid for operations with a " 2365 "single result)"); 2366 } 2367 return PyOpResult(operation.getRef(), 2368 mlirOperationGetResult(operation, 0)); 2369 }, 2370 "Shortcut to get an op result if it has only one (throws an error " 2371 "otherwise).") 2372 .def_property_readonly( 2373 "location", 2374 [](PyOperationBase &self) { 2375 PyOperation &operation = self.getOperation(); 2376 return PyLocation(operation.getContext(), 2377 mlirOperationGetLocation(operation.get())); 2378 }, 2379 "Returns the source location the operation was defined or derived " 2380 "from.") 2381 .def( 2382 "__str__", 2383 [](PyOperationBase &self) { 2384 return self.getAsm(/*binary=*/false, 2385 /*largeElementsLimit=*/llvm::None, 2386 /*enableDebugInfo=*/false, 2387 /*prettyDebugInfo=*/false, 2388 /*printGenericOpForm=*/false, 2389 /*useLocalScope=*/false, 2390 /*assumeVerified=*/false); 2391 }, 2392 "Returns the assembly form of the operation.") 2393 .def("print", &PyOperationBase::print, 2394 // Careful: Lots of arguments must match up with print method. 2395 py::arg("file") = py::none(), py::arg("binary") = false, 2396 py::arg("large_elements_limit") = py::none(), 2397 py::arg("enable_debug_info") = false, 2398 py::arg("pretty_debug_info") = false, 2399 py::arg("print_generic_op_form") = false, 2400 py::arg("use_local_scope") = false, 2401 py::arg("assume_verified") = false, kOperationPrintDocstring) 2402 .def("get_asm", &PyOperationBase::getAsm, 2403 // Careful: Lots of arguments must match up with get_asm method. 2404 py::arg("binary") = false, 2405 py::arg("large_elements_limit") = py::none(), 2406 py::arg("enable_debug_info") = false, 2407 py::arg("pretty_debug_info") = false, 2408 py::arg("print_generic_op_form") = false, 2409 py::arg("use_local_scope") = false, 2410 py::arg("assume_verified") = false, kOperationGetAsmDocstring) 2411 .def( 2412 "verify", 2413 [](PyOperationBase &self) { 2414 return mlirOperationVerify(self.getOperation()); 2415 }, 2416 "Verify the operation and return true if it passes, false if it " 2417 "fails.") 2418 .def("move_after", &PyOperationBase::moveAfter, py::arg("other"), 2419 "Puts self immediately after the other operation in its parent " 2420 "block.") 2421 .def("move_before", &PyOperationBase::moveBefore, py::arg("other"), 2422 "Puts self immediately before the other operation in its parent " 2423 "block.") 2424 .def( 2425 "detach_from_parent", 2426 [](PyOperationBase &self) { 2427 PyOperation &operation = self.getOperation(); 2428 operation.checkValid(); 2429 if (!operation.isAttached()) 2430 throw py::value_error("Detached operation has no parent."); 2431 2432 operation.detachFromParent(); 2433 return operation.createOpView(); 2434 }, 2435 "Detaches the operation from its parent block."); 2436 2437 py::class_<PyOperation, PyOperationBase>(m, "Operation", py::module_local()) 2438 .def_static("create", &PyOperation::create, py::arg("name"), 2439 py::arg("results") = py::none(), 2440 py::arg("operands") = py::none(), 2441 py::arg("attributes") = py::none(), 2442 py::arg("successors") = py::none(), py::arg("regions") = 0, 2443 py::arg("loc") = py::none(), py::arg("ip") = py::none(), 2444 kOperationCreateDocstring) 2445 .def_property_readonly("parent", 2446 [](PyOperation &self) -> py::object { 2447 auto parent = self.getParentOperation(); 2448 if (parent) 2449 return parent->getObject(); 2450 return py::none(); 2451 }) 2452 .def("erase", &PyOperation::erase) 2453 .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, 2454 &PyOperation::getCapsule) 2455 .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyOperation::createFromCapsule) 2456 .def_property_readonly("name", 2457 [](PyOperation &self) { 2458 self.checkValid(); 2459 MlirOperation operation = self.get(); 2460 MlirStringRef name = mlirIdentifierStr( 2461 mlirOperationGetName(operation)); 2462 return py::str(name.data, name.length); 2463 }) 2464 .def_property_readonly( 2465 "context", 2466 [](PyOperation &self) { 2467 self.checkValid(); 2468 return self.getContext().getObject(); 2469 }, 2470 "Context that owns the Operation") 2471 .def_property_readonly("opview", &PyOperation::createOpView); 2472 2473 auto opViewClass = 2474 py::class_<PyOpView, PyOperationBase>(m, "OpView", py::module_local()) 2475 .def(py::init<py::object>(), py::arg("operation")) 2476 .def_property_readonly("operation", &PyOpView::getOperationObject) 2477 .def_property_readonly( 2478 "context", 2479 [](PyOpView &self) { 2480 return self.getOperation().getContext().getObject(); 2481 }, 2482 "Context that owns the Operation") 2483 .def("__str__", [](PyOpView &self) { 2484 return py::str(self.getOperationObject()); 2485 }); 2486 opViewClass.attr("_ODS_REGIONS") = py::make_tuple(0, true); 2487 opViewClass.attr("_ODS_OPERAND_SEGMENTS") = py::none(); 2488 opViewClass.attr("_ODS_RESULT_SEGMENTS") = py::none(); 2489 opViewClass.attr("build_generic") = classmethod( 2490 &PyOpView::buildGeneric, py::arg("cls"), py::arg("results") = py::none(), 2491 py::arg("operands") = py::none(), py::arg("attributes") = py::none(), 2492 py::arg("successors") = py::none(), py::arg("regions") = py::none(), 2493 py::arg("loc") = py::none(), py::arg("ip") = py::none(), 2494 "Builds a specific, generated OpView based on class level attributes."); 2495 2496 //---------------------------------------------------------------------------- 2497 // Mapping of PyRegion. 2498 //---------------------------------------------------------------------------- 2499 py::class_<PyRegion>(m, "Region", py::module_local()) 2500 .def_property_readonly( 2501 "blocks", 2502 [](PyRegion &self) { 2503 return PyBlockList(self.getParentOperation(), self.get()); 2504 }, 2505 "Returns a forward-optimized sequence of blocks.") 2506 .def_property_readonly( 2507 "owner", 2508 [](PyRegion &self) { 2509 return self.getParentOperation()->createOpView(); 2510 }, 2511 "Returns the operation owning this region.") 2512 .def( 2513 "__iter__", 2514 [](PyRegion &self) { 2515 self.checkValid(); 2516 MlirBlock firstBlock = mlirRegionGetFirstBlock(self.get()); 2517 return PyBlockIterator(self.getParentOperation(), firstBlock); 2518 }, 2519 "Iterates over blocks in the region.") 2520 .def("__eq__", 2521 [](PyRegion &self, PyRegion &other) { 2522 return self.get().ptr == other.get().ptr; 2523 }) 2524 .def("__eq__", [](PyRegion &self, py::object &other) { return false; }); 2525 2526 //---------------------------------------------------------------------------- 2527 // Mapping of PyBlock. 2528 //---------------------------------------------------------------------------- 2529 py::class_<PyBlock>(m, "Block", py::module_local()) 2530 .def_property_readonly( 2531 "owner", 2532 [](PyBlock &self) { 2533 return self.getParentOperation()->createOpView(); 2534 }, 2535 "Returns the owning operation of this block.") 2536 .def_property_readonly( 2537 "region", 2538 [](PyBlock &self) { 2539 MlirRegion region = mlirBlockGetParentRegion(self.get()); 2540 return PyRegion(self.getParentOperation(), region); 2541 }, 2542 "Returns the owning region of this block.") 2543 .def_property_readonly( 2544 "arguments", 2545 [](PyBlock &self) { 2546 return PyBlockArgumentList(self.getParentOperation(), self.get()); 2547 }, 2548 "Returns a list of block arguments.") 2549 .def_property_readonly( 2550 "operations", 2551 [](PyBlock &self) { 2552 return PyOperationList(self.getParentOperation(), self.get()); 2553 }, 2554 "Returns a forward-optimized sequence of operations.") 2555 .def_static( 2556 "create_at_start", 2557 [](PyRegion &parent, py::list pyArgTypes) { 2558 parent.checkValid(); 2559 llvm::SmallVector<MlirType, 4> argTypes; 2560 argTypes.reserve(pyArgTypes.size()); 2561 for (auto &pyArg : pyArgTypes) { 2562 argTypes.push_back(pyArg.cast<PyType &>()); 2563 } 2564 2565 MlirBlock block = mlirBlockCreate(argTypes.size(), argTypes.data()); 2566 mlirRegionInsertOwnedBlock(parent, 0, block); 2567 return PyBlock(parent.getParentOperation(), block); 2568 }, 2569 py::arg("parent"), py::arg("arg_types") = py::list(), 2570 "Creates and returns a new Block at the beginning of the given " 2571 "region (with given argument types).") 2572 .def( 2573 "create_before", 2574 [](PyBlock &self, py::args pyArgTypes) { 2575 self.checkValid(); 2576 llvm::SmallVector<MlirType, 4> argTypes; 2577 argTypes.reserve(pyArgTypes.size()); 2578 for (auto &pyArg : pyArgTypes) { 2579 argTypes.push_back(pyArg.cast<PyType &>()); 2580 } 2581 2582 MlirBlock block = mlirBlockCreate(argTypes.size(), argTypes.data()); 2583 MlirRegion region = mlirBlockGetParentRegion(self.get()); 2584 mlirRegionInsertOwnedBlockBefore(region, self.get(), block); 2585 return PyBlock(self.getParentOperation(), block); 2586 }, 2587 "Creates and returns a new Block before this block " 2588 "(with given argument types).") 2589 .def( 2590 "create_after", 2591 [](PyBlock &self, py::args pyArgTypes) { 2592 self.checkValid(); 2593 llvm::SmallVector<MlirType, 4> argTypes; 2594 argTypes.reserve(pyArgTypes.size()); 2595 for (auto &pyArg : pyArgTypes) { 2596 argTypes.push_back(pyArg.cast<PyType &>()); 2597 } 2598 2599 MlirBlock block = mlirBlockCreate(argTypes.size(), argTypes.data()); 2600 MlirRegion region = mlirBlockGetParentRegion(self.get()); 2601 mlirRegionInsertOwnedBlockAfter(region, self.get(), block); 2602 return PyBlock(self.getParentOperation(), block); 2603 }, 2604 "Creates and returns a new Block after this block " 2605 "(with given argument types).") 2606 .def( 2607 "__iter__", 2608 [](PyBlock &self) { 2609 self.checkValid(); 2610 MlirOperation firstOperation = 2611 mlirBlockGetFirstOperation(self.get()); 2612 return PyOperationIterator(self.getParentOperation(), 2613 firstOperation); 2614 }, 2615 "Iterates over operations in the block.") 2616 .def("__eq__", 2617 [](PyBlock &self, PyBlock &other) { 2618 return self.get().ptr == other.get().ptr; 2619 }) 2620 .def("__eq__", [](PyBlock &self, py::object &other) { return false; }) 2621 .def( 2622 "__str__", 2623 [](PyBlock &self) { 2624 self.checkValid(); 2625 PyPrintAccumulator printAccum; 2626 mlirBlockPrint(self.get(), printAccum.getCallback(), 2627 printAccum.getUserData()); 2628 return printAccum.join(); 2629 }, 2630 "Returns the assembly form of the block.") 2631 .def( 2632 "append", 2633 [](PyBlock &self, PyOperationBase &operation) { 2634 if (operation.getOperation().isAttached()) 2635 operation.getOperation().detachFromParent(); 2636 2637 MlirOperation mlirOperation = operation.getOperation().get(); 2638 mlirBlockAppendOwnedOperation(self.get(), mlirOperation); 2639 operation.getOperation().setAttached( 2640 self.getParentOperation().getObject()); 2641 }, 2642 py::arg("operation"), 2643 "Appends an operation to this block. If the operation is currently " 2644 "in another block, it will be moved."); 2645 2646 //---------------------------------------------------------------------------- 2647 // Mapping of PyInsertionPoint. 2648 //---------------------------------------------------------------------------- 2649 2650 py::class_<PyInsertionPoint>(m, "InsertionPoint", py::module_local()) 2651 .def(py::init<PyBlock &>(), py::arg("block"), 2652 "Inserts after the last operation but still inside the block.") 2653 .def("__enter__", &PyInsertionPoint::contextEnter) 2654 .def("__exit__", &PyInsertionPoint::contextExit) 2655 .def_property_readonly_static( 2656 "current", 2657 [](py::object & /*class*/) { 2658 auto *ip = PyThreadContextEntry::getDefaultInsertionPoint(); 2659 if (!ip) 2660 throw SetPyError(PyExc_ValueError, "No current InsertionPoint"); 2661 return ip; 2662 }, 2663 "Gets the InsertionPoint bound to the current thread or raises " 2664 "ValueError if none has been set") 2665 .def(py::init<PyOperationBase &>(), py::arg("beforeOperation"), 2666 "Inserts before a referenced operation.") 2667 .def_static("at_block_begin", &PyInsertionPoint::atBlockBegin, 2668 py::arg("block"), "Inserts at the beginning of the block.") 2669 .def_static("at_block_terminator", &PyInsertionPoint::atBlockTerminator, 2670 py::arg("block"), "Inserts before the block terminator.") 2671 .def("insert", &PyInsertionPoint::insert, py::arg("operation"), 2672 "Inserts an operation.") 2673 .def_property_readonly( 2674 "block", [](PyInsertionPoint &self) { return self.getBlock(); }, 2675 "Returns the block that this InsertionPoint points to."); 2676 2677 //---------------------------------------------------------------------------- 2678 // Mapping of PyAttribute. 2679 //---------------------------------------------------------------------------- 2680 py::class_<PyAttribute>(m, "Attribute", py::module_local()) 2681 // Delegate to the PyAttribute copy constructor, which will also lifetime 2682 // extend the backing context which owns the MlirAttribute. 2683 .def(py::init<PyAttribute &>(), py::arg("cast_from_type"), 2684 "Casts the passed attribute to the generic Attribute") 2685 .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, 2686 &PyAttribute::getCapsule) 2687 .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyAttribute::createFromCapsule) 2688 .def_static( 2689 "parse", 2690 [](std::string attrSpec, DefaultingPyMlirContext context) { 2691 MlirAttribute type = mlirAttributeParseGet( 2692 context->get(), toMlirStringRef(attrSpec)); 2693 // TODO: Rework error reporting once diagnostic engine is exposed 2694 // in C API. 2695 if (mlirAttributeIsNull(type)) { 2696 throw SetPyError(PyExc_ValueError, 2697 Twine("Unable to parse attribute: '") + 2698 attrSpec + "'"); 2699 } 2700 return PyAttribute(context->getRef(), type); 2701 }, 2702 py::arg("asm"), py::arg("context") = py::none(), 2703 "Parses an attribute from an assembly form") 2704 .def_property_readonly( 2705 "context", 2706 [](PyAttribute &self) { return self.getContext().getObject(); }, 2707 "Context that owns the Attribute") 2708 .def_property_readonly("type", 2709 [](PyAttribute &self) { 2710 return PyType(self.getContext()->getRef(), 2711 mlirAttributeGetType(self)); 2712 }) 2713 .def( 2714 "get_named", 2715 [](PyAttribute &self, std::string name) { 2716 return PyNamedAttribute(self, std::move(name)); 2717 }, 2718 py::keep_alive<0, 1>(), "Binds a name to the attribute") 2719 .def("__eq__", 2720 [](PyAttribute &self, PyAttribute &other) { return self == other; }) 2721 .def("__eq__", [](PyAttribute &self, py::object &other) { return false; }) 2722 .def("__hash__", 2723 [](PyAttribute &self) { 2724 return static_cast<size_t>(llvm::hash_value(self.get().ptr)); 2725 }) 2726 .def( 2727 "dump", [](PyAttribute &self) { mlirAttributeDump(self); }, 2728 kDumpDocstring) 2729 .def( 2730 "__str__", 2731 [](PyAttribute &self) { 2732 PyPrintAccumulator printAccum; 2733 mlirAttributePrint(self, printAccum.getCallback(), 2734 printAccum.getUserData()); 2735 return printAccum.join(); 2736 }, 2737 "Returns the assembly form of the Attribute.") 2738 .def("__repr__", [](PyAttribute &self) { 2739 // Generally, assembly formats are not printed for __repr__ because 2740 // this can cause exceptionally long debug output and exceptions. 2741 // However, attribute values are generally considered useful and are 2742 // printed. This may need to be re-evaluated if debug dumps end up 2743 // being excessive. 2744 PyPrintAccumulator printAccum; 2745 printAccum.parts.append("Attribute("); 2746 mlirAttributePrint(self, printAccum.getCallback(), 2747 printAccum.getUserData()); 2748 printAccum.parts.append(")"); 2749 return printAccum.join(); 2750 }); 2751 2752 //---------------------------------------------------------------------------- 2753 // Mapping of PyNamedAttribute 2754 //---------------------------------------------------------------------------- 2755 py::class_<PyNamedAttribute>(m, "NamedAttribute", py::module_local()) 2756 .def("__repr__", 2757 [](PyNamedAttribute &self) { 2758 PyPrintAccumulator printAccum; 2759 printAccum.parts.append("NamedAttribute("); 2760 printAccum.parts.append( 2761 py::str(mlirIdentifierStr(self.namedAttr.name).data, 2762 mlirIdentifierStr(self.namedAttr.name).length)); 2763 printAccum.parts.append("="); 2764 mlirAttributePrint(self.namedAttr.attribute, 2765 printAccum.getCallback(), 2766 printAccum.getUserData()); 2767 printAccum.parts.append(")"); 2768 return printAccum.join(); 2769 }) 2770 .def_property_readonly( 2771 "name", 2772 [](PyNamedAttribute &self) { 2773 return py::str(mlirIdentifierStr(self.namedAttr.name).data, 2774 mlirIdentifierStr(self.namedAttr.name).length); 2775 }, 2776 "The name of the NamedAttribute binding") 2777 .def_property_readonly( 2778 "attr", 2779 [](PyNamedAttribute &self) { 2780 // TODO: When named attribute is removed/refactored, also remove 2781 // this constructor (it does an inefficient table lookup). 2782 auto contextRef = PyMlirContext::forContext( 2783 mlirAttributeGetContext(self.namedAttr.attribute)); 2784 return PyAttribute(std::move(contextRef), self.namedAttr.attribute); 2785 }, 2786 py::keep_alive<0, 1>(), 2787 "The underlying generic attribute of the NamedAttribute binding"); 2788 2789 //---------------------------------------------------------------------------- 2790 // Mapping of PyType. 2791 //---------------------------------------------------------------------------- 2792 py::class_<PyType>(m, "Type", py::module_local()) 2793 // Delegate to the PyType copy constructor, which will also lifetime 2794 // extend the backing context which owns the MlirType. 2795 .def(py::init<PyType &>(), py::arg("cast_from_type"), 2796 "Casts the passed type to the generic Type") 2797 .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyType::getCapsule) 2798 .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyType::createFromCapsule) 2799 .def_static( 2800 "parse", 2801 [](std::string typeSpec, DefaultingPyMlirContext context) { 2802 MlirType type = 2803 mlirTypeParseGet(context->get(), toMlirStringRef(typeSpec)); 2804 // TODO: Rework error reporting once diagnostic engine is exposed 2805 // in C API. 2806 if (mlirTypeIsNull(type)) { 2807 throw SetPyError(PyExc_ValueError, 2808 Twine("Unable to parse type: '") + typeSpec + 2809 "'"); 2810 } 2811 return PyType(context->getRef(), type); 2812 }, 2813 py::arg("asm"), py::arg("context") = py::none(), 2814 kContextParseTypeDocstring) 2815 .def_property_readonly( 2816 "context", [](PyType &self) { return self.getContext().getObject(); }, 2817 "Context that owns the Type") 2818 .def("__eq__", [](PyType &self, PyType &other) { return self == other; }) 2819 .def("__eq__", [](PyType &self, py::object &other) { return false; }) 2820 .def("__hash__", 2821 [](PyType &self) { 2822 return static_cast<size_t>(llvm::hash_value(self.get().ptr)); 2823 }) 2824 .def( 2825 "dump", [](PyType &self) { mlirTypeDump(self); }, kDumpDocstring) 2826 .def( 2827 "__str__", 2828 [](PyType &self) { 2829 PyPrintAccumulator printAccum; 2830 mlirTypePrint(self, printAccum.getCallback(), 2831 printAccum.getUserData()); 2832 return printAccum.join(); 2833 }, 2834 "Returns the assembly form of the type.") 2835 .def("__repr__", [](PyType &self) { 2836 // Generally, assembly formats are not printed for __repr__ because 2837 // this can cause exceptionally long debug output and exceptions. 2838 // However, types are an exception as they typically have compact 2839 // assembly forms and printing them is useful. 2840 PyPrintAccumulator printAccum; 2841 printAccum.parts.append("Type("); 2842 mlirTypePrint(self, printAccum.getCallback(), printAccum.getUserData()); 2843 printAccum.parts.append(")"); 2844 return printAccum.join(); 2845 }); 2846 2847 //---------------------------------------------------------------------------- 2848 // Mapping of Value. 2849 //---------------------------------------------------------------------------- 2850 py::class_<PyValue>(m, "Value", py::module_local()) 2851 .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyValue::getCapsule) 2852 .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyValue::createFromCapsule) 2853 .def_property_readonly( 2854 "context", 2855 [](PyValue &self) { return self.getParentOperation()->getContext(); }, 2856 "Context in which the value lives.") 2857 .def( 2858 "dump", [](PyValue &self) { mlirValueDump(self.get()); }, 2859 kDumpDocstring) 2860 .def_property_readonly( 2861 "owner", 2862 [](PyValue &self) { 2863 assert(mlirOperationEqual(self.getParentOperation()->get(), 2864 mlirOpResultGetOwner(self.get())) && 2865 "expected the owner of the value in Python to match that in " 2866 "the IR"); 2867 return self.getParentOperation().getObject(); 2868 }) 2869 .def("__eq__", 2870 [](PyValue &self, PyValue &other) { 2871 return self.get().ptr == other.get().ptr; 2872 }) 2873 .def("__eq__", [](PyValue &self, py::object other) { return false; }) 2874 .def("__hash__", 2875 [](PyValue &self) { 2876 return static_cast<size_t>(llvm::hash_value(self.get().ptr)); 2877 }) 2878 .def( 2879 "__str__", 2880 [](PyValue &self) { 2881 PyPrintAccumulator printAccum; 2882 printAccum.parts.append("Value("); 2883 mlirValuePrint(self.get(), printAccum.getCallback(), 2884 printAccum.getUserData()); 2885 printAccum.parts.append(")"); 2886 return printAccum.join(); 2887 }, 2888 kValueDunderStrDocstring) 2889 .def_property_readonly("type", [](PyValue &self) { 2890 return PyType(self.getParentOperation()->getContext(), 2891 mlirValueGetType(self.get())); 2892 }); 2893 PyBlockArgument::bind(m); 2894 PyOpResult::bind(m); 2895 2896 //---------------------------------------------------------------------------- 2897 // Mapping of SymbolTable. 2898 //---------------------------------------------------------------------------- 2899 py::class_<PySymbolTable>(m, "SymbolTable", py::module_local()) 2900 .def(py::init<PyOperationBase &>()) 2901 .def("__getitem__", &PySymbolTable::dunderGetItem) 2902 .def("insert", &PySymbolTable::insert, py::arg("operation")) 2903 .def("erase", &PySymbolTable::erase, py::arg("operation")) 2904 .def("__delitem__", &PySymbolTable::dunderDel) 2905 .def("__contains__", 2906 [](PySymbolTable &table, const std::string &name) { 2907 return !mlirOperationIsNull(mlirSymbolTableLookup( 2908 table, mlirStringRefCreate(name.data(), name.length()))); 2909 }) 2910 // Static helpers. 2911 .def_static("set_symbol_name", &PySymbolTable::setSymbolName, 2912 py::arg("symbol"), py::arg("name")) 2913 .def_static("get_symbol_name", &PySymbolTable::getSymbolName, 2914 py::arg("symbol")) 2915 .def_static("get_visibility", &PySymbolTable::getVisibility, 2916 py::arg("symbol")) 2917 .def_static("set_visibility", &PySymbolTable::setVisibility, 2918 py::arg("symbol"), py::arg("visibility")) 2919 .def_static("replace_all_symbol_uses", 2920 &PySymbolTable::replaceAllSymbolUses, py::arg("old_symbol"), 2921 py::arg("new_symbol"), py::arg("from_op")) 2922 .def_static("walk_symbol_tables", &PySymbolTable::walkSymbolTables, 2923 py::arg("from_op"), py::arg("all_sym_uses_visible"), 2924 py::arg("callback")); 2925 2926 // Container bindings. 2927 PyBlockArgumentList::bind(m); 2928 PyBlockIterator::bind(m); 2929 PyBlockList::bind(m); 2930 PyOperationIterator::bind(m); 2931 PyOperationList::bind(m); 2932 PyOpAttributeMap::bind(m); 2933 PyOpOperandList::bind(m); 2934 PyOpResultList::bind(m); 2935 PyRegionIterator::bind(m); 2936 PyRegionList::bind(m); 2937 2938 // Debug bindings. 2939 PyGlobalDebugFlag::bind(m); 2940 } 2941