#include <Python.h>
#include "mlir-c/IR.h"
+#include "mlir-c/Pass.h"
#define MLIR_PYTHON_CAPSULE_CONTEXT "mlir.ir.Context._CAPIPtr"
#define MLIR_PYTHON_CAPSULE_MODULE "mlir.ir.Module._CAPIPtr"
+#define MLIR_PYTHON_CAPSULE_PASS_MANAGER "mlir.passmanager.PassManager._CAPIPtr"
/** Attribute on MLIR Python objects that expose their C-API pointer.
* This will be a type-specific capsule created as per one of the helpers
* delineated). */
#define MLIR_PYTHON_CAPI_FACTORY_ATTR "_CAPICreate"
+/// Gets a void* from a wrapped struct. Needed because const cast is different
+/// between C/C++.
+#ifdef __cplusplus
+#define MLIR_PYTHON_GET_WRAPPED_POINTER(object) const_cast<void *>(object.ptr)
+#else
+#define MLIR_PYTHON_GET_WRAPPED_POINTER(object) (void *)(object.ptr)
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
* The returned capsule does not extend or affect ownership of any Python
* objects that reference the context in any way.
*/
-inline PyObject *mlirPythonContextToCapsule(MlirContext context) {
+static inline PyObject *mlirPythonContextToCapsule(MlirContext context) {
return PyCapsule_New(context.ptr, MLIR_PYTHON_CAPSULE_CONTEXT, NULL);
}
* mlirPythonContextToCapsule. If the capsule is not of the right type, then
* a null context is returned (as checked via mlirContextIsNull). In such a
* case, the Python APIs will have already set an error. */
-inline MlirContext mlirPythonCapsuleToContext(PyObject *capsule) {
+static inline MlirContext mlirPythonCapsuleToContext(PyObject *capsule) {
void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_CONTEXT);
MlirContext context = {ptr};
return context;
/** Creates a capsule object encapsulating the raw C-API MlirModule.
* The returned capsule does not extend or affect ownership of any Python
* objects that reference the module in any way. */
-inline PyObject *mlirPythonModuleToCapsule(MlirModule module) {
-#ifdef __cplusplus
- void *ptr = const_cast<void *>(module.ptr);
-#else
- void *ptr = (void *)ptr;
-#endif
- return PyCapsule_New(ptr, MLIR_PYTHON_CAPSULE_MODULE, NULL);
+static inline PyObject *mlirPythonModuleToCapsule(MlirModule module) {
+ return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(module),
+ MLIR_PYTHON_CAPSULE_MODULE, NULL);
}
/** Extracts an MlirModule from a capsule as produced from
* mlirPythonModuleToCapsule. If the capsule is not of the right type, then
* a null module is returned (as checked via mlirModuleIsNull). In such a
* case, the Python APIs will have already set an error. */
-inline MlirModule mlirPythonCapsuleToModule(PyObject *capsule) {
+static inline MlirModule mlirPythonCapsuleToModule(PyObject *capsule) {
void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_MODULE);
MlirModule module = {ptr};
return module;
}
+/** Creates a capsule object encapsulating the raw C-API MlirPassManager.
+ * The returned capsule does not extend or affect ownership of any Python
+ * objects that reference the module in any way. */
+static inline PyObject *mlirPythonPassManagerToCapsule(MlirPassManager pm) {
+ return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(pm),
+ MLIR_PYTHON_CAPSULE_PASS_MANAGER, NULL);
+}
+
+/** Extracts an MlirPassManager from a capsule as produced from
+ * mlirPythonPassManagerToCapsule. If the capsule is not of the right type, then
+ * a null pass manager is returned (as checked via mlirPassManagerIsNull). */
+static inline MlirPassManager
+mlirPythonCapsuleToPassManager(PyObject *capsule) {
+ void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_PASS_MANAGER);
+ MlirPassManager pm = {ptr};
+ return pm;
+}
+
#ifdef __cplusplus
}
#endif
#include "Pass.h"
#include "IRModules.h"
+#include "mlir-c/Bindings/Python/Interop.h"
#include "mlir-c/Pass.h"
namespace py = pybind11;
class PyPassManager {
public:
PyPassManager(MlirPassManager passManager) : passManager(passManager) {}
- ~PyPassManager() { mlirPassManagerDestroy(passManager); }
+ PyPassManager(PyPassManager &&other) : passManager(other.passManager) {
+ other.passManager.ptr = nullptr;
+ }
+ ~PyPassManager() {
+ if (!mlirPassManagerIsNull(passManager))
+ mlirPassManagerDestroy(passManager);
+ }
MlirPassManager get() { return passManager; }
+ void release() { passManager.ptr = nullptr; }
+ pybind11::object getCapsule() {
+ return py::reinterpret_steal<py::object>(
+ mlirPythonPassManagerToCapsule(get()));
+ }
+
+ static pybind11::object createFromCapsule(pybind11::object capsule) {
+ MlirPassManager rawPm = mlirPythonCapsuleToPassManager(capsule.ptr());
+ if (mlirPassManagerIsNull(rawPm))
+ throw py::error_already_set();
+ return py::cast(PyPassManager(rawPm), py::return_value_policy::move);
+ }
+
private:
MlirPassManager passManager;
};
}),
py::arg("context") = py::none(),
"Create a new PassManager for the current (or provided) Context.")
+ .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR,
+ &PyPassManager::getCapsule)
+ .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyPassManager::createFromCapsule)
+ .def("_testing_release", &PyPassManager::release,
+ "Releases (leaks) the backing pass manager (testing)")
.def_static(
"parse",
[](const std::string pipeline, DefaultingPyMlirContext context) {