| //===-- mlir-c/Interop.h - Constants for Python/C-API interop -----*- C -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM |
| // Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This header declares constants and helpers necessary for C-level |
| // interop with the MLIR Python extension module. Since the Python bindings |
| // are a thin wrapper around the MLIR C-API, a further C-API is not provided |
| // specifically for the Python extension. Instead, simple facilities are |
| // provided for translating between Python types and corresponding MLIR C-API |
| // types. |
| // |
| // This header is standalone, requiring nothing beyond normal linking against |
| // the Python implementation. |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef MLIR_C_BINDINGS_PYTHON_INTEROP_H |
| #define MLIR_C_BINDINGS_PYTHON_INTEROP_H |
| |
| #include <Python.h> |
| |
| #include "mlir-c/AffineExpr.h" |
| #include "mlir-c/AffineMap.h" |
| #include "mlir-c/IR.h" |
| #include "mlir-c/Pass.h" |
| |
| #define MLIR_PYTHON_CAPSULE_AFFINE_EXPR "mlir.ir.AffineExpr._CAPIPtr" |
| #define MLIR_PYTHON_CAPSULE_AFFINE_MAP "mlir.ir.AffineMap._CAPIPtr" |
| #define MLIR_PYTHON_CAPSULE_ATTRIBUTE "mlir.ir.Attribute._CAPIPtr" |
| #define MLIR_PYTHON_CAPSULE_CONTEXT "mlir.ir.Context._CAPIPtr" |
| #define MLIR_PYTHON_CAPSULE_LOCATION "mlir.ir.Location._CAPIPtr" |
| #define MLIR_PYTHON_CAPSULE_MODULE "mlir.ir.Module._CAPIPtr" |
| #define MLIR_PYTHON_CAPSULE_OPERATION "mlir.ir.Operation._CAPIPtr" |
| #define MLIR_PYTHON_CAPSULE_TYPE "mlir.ir.Type._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 |
| * below. |
| * |
| * Ownership is not transferred by acquiring a capsule in this way: the |
| * validity of the pointer wrapped by the capsule will be bounded by the |
| * lifetime of the Python object that produced it. Only the name and pointer |
| * of the capsule are set. The caller is free to set a destructor and context |
| * as needed to manage anything further. */ |
| #define MLIR_PYTHON_CAPI_PTR_ATTR "_CAPIPtr" |
| |
| /** Attribute on MLIR Python objects that exposes a factory function for |
| * constructing the corresponding Python object from a type-specific |
| * capsule wrapping the C-API pointer. The signature of the function is: |
| * def _CAPICreate(capsule) -> object |
| * Calling such a function implies a transfer of ownership of the object the |
| * capsule wraps: after such a call, the capsule should be considered invalid, |
| * and its wrapped pointer must not be destroyed. |
| * |
| * Only a very small number of Python objects can be created in such a fashion |
| * (i.e. top-level types such as Context where the lifetime can be cleanly |
| * 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 |
| |
| /** Creates a capsule object encapsulating the raw C-API MlirAffineExpr. The |
| * returned capsule does not extend or affect ownership of any Python objects |
| * that reference the expression in any way. |
| */ |
| static inline PyObject *mlirPythonAffineExprToCapsule(MlirAffineExpr expr) { |
| return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(expr), |
| MLIR_PYTHON_CAPSULE_AFFINE_EXPR, NULL); |
| } |
| |
| /** Extracts an MlirAffineExpr from a capsule as produced from |
| * mlirPythonAffineExprToCapsule. If the capsule is not of the right type, then |
| * a null expression is returned (as checked via mlirAffineExprIsNull). In such |
| * a case, the Python APIs will have already set an error. */ |
| static inline MlirAffineExpr mlirPythonCapsuleToAffineExpr(PyObject *capsule) { |
| void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_AFFINE_EXPR); |
| MlirAffineExpr expr = {ptr}; |
| return expr; |
| } |
| |
| /** Creates a capsule object encapsulating the raw C-API MlirAttribute. |
| * The returned capsule does not extend or affect ownership of any Python |
| * objects that reference the attribute in any way. |
| */ |
| static inline PyObject *mlirPythonAttributeToCapsule(MlirAttribute attribute) { |
| return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(attribute), |
| MLIR_PYTHON_CAPSULE_ATTRIBUTE, NULL); |
| } |
| |
| /** Extracts an MlirAttribute from a capsule as produced from |
| * mlirPythonAttributeToCapsule. If the capsule is not of the right type, then |
| * a null attribute is returned (as checked via mlirAttributeIsNull). In such a |
| * case, the Python APIs will have already set an error. */ |
| static inline MlirAttribute mlirPythonCapsuleToAttribute(PyObject *capsule) { |
| void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_ATTRIBUTE); |
| MlirAttribute attr = {ptr}; |
| return attr; |
| } |
| |
| /** Creates a capsule object encapsulating the raw C-API MlirContext. |
| * The returned capsule does not extend or affect ownership of any Python |
| * objects that reference the context in any way. |
| */ |
| static inline PyObject *mlirPythonContextToCapsule(MlirContext context) { |
| return PyCapsule_New(context.ptr, MLIR_PYTHON_CAPSULE_CONTEXT, NULL); |
| } |
| |
| /** Extracts a MlirContext from a capsule as produced from |
| * 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. */ |
| 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 MlirLocation. |
| * The returned capsule does not extend or affect ownership of any Python |
| * objects that reference the location in any way. */ |
| static inline PyObject *mlirPythonLocationToCapsule(MlirLocation loc) { |
| return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(loc), |
| MLIR_PYTHON_CAPSULE_LOCATION, NULL); |
| } |
| |
| /** Extracts an MlirLocation from a capsule as produced from |
| * mlirPythonLocationToCapsule. If the capsule is not of the right type, then |
| * a null module is returned (as checked via mlirLocationIsNull). In such a |
| * case, the Python APIs will have already set an error. */ |
| static inline MlirLocation mlirPythonCapsuleToLocation(PyObject *capsule) { |
| void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_LOCATION); |
| MlirLocation loc = {ptr}; |
| return loc; |
| } |
| |
| /** 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. */ |
| 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. */ |
| 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; |
| } |
| |
| /** Creates a capsule object encapsulating the raw C-API MlirOperation. |
| * The returned capsule does not extend or affect ownership of any Python |
| * objects that reference the operation in any way. |
| */ |
| static inline PyObject *mlirPythonOperationToCapsule(MlirOperation operation) { |
| return PyCapsule_New(operation.ptr, MLIR_PYTHON_CAPSULE_OPERATION, NULL); |
| } |
| |
| /** Extracts an MlirOperations from a capsule as produced from |
| * mlirPythonOperationToCapsule. If the capsule is not of the right type, then |
| * a null type is returned (as checked via mlirOperationIsNull). In such a |
| * case, the Python APIs will have already set an error. */ |
| static inline MlirOperation mlirPythonCapsuleToOperation(PyObject *capsule) { |
| void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_OPERATION); |
| MlirOperation op = {ptr}; |
| return op; |
| } |
| |
| /** Creates a capsule object encapsulating the raw C-API MlirType. |
| * The returned capsule does not extend or affect ownership of any Python |
| * objects that reference the type in any way. |
| */ |
| static inline PyObject *mlirPythonTypeToCapsule(MlirType type) { |
| return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(type), |
| MLIR_PYTHON_CAPSULE_TYPE, NULL); |
| } |
| |
| /** Extracts an MlirType from a capsule as produced from |
| * mlirPythonTypeToCapsule. If the capsule is not of the right type, then |
| * a null type is returned (as checked via mlirTypeIsNull). In such a |
| * case, the Python APIs will have already set an error. */ |
| static inline MlirType mlirPythonCapsuleToType(PyObject *capsule) { |
| void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_TYPE); |
| MlirType type = {ptr}; |
| return type; |
| } |
| |
| /** Creates a capsule object encapsulating the raw C-API MlirAffineMap. |
| * The returned capsule does not extend or affect ownership of any Python |
| * objects that reference the type in any way. |
| */ |
| static inline PyObject *mlirPythonAffineMapToCapsule(MlirAffineMap affineMap) { |
| return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(affineMap), |
| MLIR_PYTHON_CAPSULE_AFFINE_MAP, NULL); |
| } |
| |
| /** Extracts an MlirAffineMap from a capsule as produced from |
| * mlirPythonAffineMapToCapsule. If the capsule is not of the right type, then |
| * a null type is returned (as checked via mlirAffineMapIsNull). In such a |
| * case, the Python APIs will have already set an error. */ |
| static inline MlirAffineMap mlirPythonCapsuleToAffineMap(PyObject *capsule) { |
| void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_AFFINE_MAP); |
| MlirAffineMap affineMap = {ptr}; |
| return affineMap; |
| } |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif // MLIR_C_BINDINGS_PYTHON_INTEROP_H |