1 //===-- mlir-c/Interop.h - Constants for Python/C-API interop -----*- C -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 4 // Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This header declares constants and helpers necessary for C-level 11 // interop with the MLIR Python extension module. Since the Python bindings 12 // are a thin wrapper around the MLIR C-API, a further C-API is not provided 13 // specifically for the Python extension. Instead, simple facilities are 14 // provided for translating between Python types and corresponding MLIR C-API 15 // types. 16 // 17 // This header is standalone, requiring nothing beyond normal linking against 18 // the Python implementation. 19 //===----------------------------------------------------------------------===// 20 21 #ifndef MLIR_C_BINDINGS_PYTHON_INTEROP_H 22 #define MLIR_C_BINDINGS_PYTHON_INTEROP_H 23 24 #include <Python.h> 25 26 #include "mlir-c/AffineExpr.h" 27 #include "mlir-c/AffineMap.h" 28 #include "mlir-c/ExecutionEngine.h" 29 #include "mlir-c/IR.h" 30 #include "mlir-c/IntegerSet.h" 31 #include "mlir-c/Pass.h" 32 33 #define MLIR_PYTHON_CAPSULE_AFFINE_EXPR "mlir.ir.AffineExpr._CAPIPtr" 34 #define MLIR_PYTHON_CAPSULE_AFFINE_MAP "mlir.ir.AffineMap._CAPIPtr" 35 #define MLIR_PYTHON_CAPSULE_ATTRIBUTE "mlir.ir.Attribute._CAPIPtr" 36 #define MLIR_PYTHON_CAPSULE_CONTEXT "mlir.ir.Context._CAPIPtr" 37 #define MLIR_PYTHON_CAPSULE_EXECUTION_ENGINE \ 38 "mlir.execution_engine.ExecutionEngine._CAPIPtr" 39 #define MLIR_PYTHON_CAPSULE_INTEGER_SET "mlir.ir.IntegerSet._CAPIPtr" 40 #define MLIR_PYTHON_CAPSULE_LOCATION "mlir.ir.Location._CAPIPtr" 41 #define MLIR_PYTHON_CAPSULE_MODULE "mlir.ir.Module._CAPIPtr" 42 #define MLIR_PYTHON_CAPSULE_OPERATION "mlir.ir.Operation._CAPIPtr" 43 #define MLIR_PYTHON_CAPSULE_TYPE "mlir.ir.Type._CAPIPtr" 44 #define MLIR_PYTHON_CAPSULE_PASS_MANAGER "mlir.passmanager.PassManager._CAPIPtr" 45 #define MLIR_PYTHON_CAPSULE_VALUE "mlir.ir.Value._CAPIPtr" 46 47 /** Attribute on MLIR Python objects that expose their C-API pointer. 48 * This will be a type-specific capsule created as per one of the helpers 49 * below. 50 * 51 * Ownership is not transferred by acquiring a capsule in this way: the 52 * validity of the pointer wrapped by the capsule will be bounded by the 53 * lifetime of the Python object that produced it. Only the name and pointer 54 * of the capsule are set. The caller is free to set a destructor and context 55 * as needed to manage anything further. */ 56 #define MLIR_PYTHON_CAPI_PTR_ATTR "_CAPIPtr" 57 58 /** Attribute on MLIR Python objects that exposes a factory function for 59 * constructing the corresponding Python object from a type-specific 60 * capsule wrapping the C-API pointer. The signature of the function is: 61 * def _CAPICreate(capsule) -> object 62 * Calling such a function implies a transfer of ownership of the object the 63 * capsule wraps: after such a call, the capsule should be considered invalid, 64 * and its wrapped pointer must not be destroyed. 65 * 66 * Only a very small number of Python objects can be created in such a fashion 67 * (i.e. top-level types such as Context where the lifetime can be cleanly 68 * delineated). */ 69 #define MLIR_PYTHON_CAPI_FACTORY_ATTR "_CAPICreate" 70 71 /// Gets a void* from a wrapped struct. Needed because const cast is different 72 /// between C/C++. 73 #ifdef __cplusplus 74 #define MLIR_PYTHON_GET_WRAPPED_POINTER(object) const_cast<void *>(object.ptr) 75 #else 76 #define MLIR_PYTHON_GET_WRAPPED_POINTER(object) (void *)(object.ptr) 77 #endif 78 79 #ifdef __cplusplus 80 extern "C" { 81 #endif 82 83 /** Creates a capsule object encapsulating the raw C-API MlirAffineExpr. The 84 * returned capsule does not extend or affect ownership of any Python objects 85 * that reference the expression in any way. 86 */ 87 static inline PyObject *mlirPythonAffineExprToCapsule(MlirAffineExpr expr) { 88 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(expr), 89 MLIR_PYTHON_CAPSULE_AFFINE_EXPR, NULL); 90 } 91 92 /** Extracts an MlirAffineExpr from a capsule as produced from 93 * mlirPythonAffineExprToCapsule. If the capsule is not of the right type, then 94 * a null expression is returned (as checked via mlirAffineExprIsNull). In such 95 * a case, the Python APIs will have already set an error. */ 96 static inline MlirAffineExpr mlirPythonCapsuleToAffineExpr(PyObject *capsule) { 97 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_AFFINE_EXPR); 98 MlirAffineExpr expr = {ptr}; 99 return expr; 100 } 101 102 /** Creates a capsule object encapsulating the raw C-API MlirAttribute. 103 * The returned capsule does not extend or affect ownership of any Python 104 * objects that reference the attribute in any way. 105 */ 106 static inline PyObject *mlirPythonAttributeToCapsule(MlirAttribute attribute) { 107 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(attribute), 108 MLIR_PYTHON_CAPSULE_ATTRIBUTE, NULL); 109 } 110 111 /** Extracts an MlirAttribute from a capsule as produced from 112 * mlirPythonAttributeToCapsule. If the capsule is not of the right type, then 113 * a null attribute is returned (as checked via mlirAttributeIsNull). In such a 114 * case, the Python APIs will have already set an error. */ 115 static inline MlirAttribute mlirPythonCapsuleToAttribute(PyObject *capsule) { 116 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_ATTRIBUTE); 117 MlirAttribute attr = {ptr}; 118 return attr; 119 } 120 121 /** Creates a capsule object encapsulating the raw C-API MlirContext. 122 * The returned capsule does not extend or affect ownership of any Python 123 * objects that reference the context in any way. 124 */ 125 static inline PyObject *mlirPythonContextToCapsule(MlirContext context) { 126 return PyCapsule_New(context.ptr, MLIR_PYTHON_CAPSULE_CONTEXT, NULL); 127 } 128 129 /** Extracts a MlirContext from a capsule as produced from 130 * mlirPythonContextToCapsule. If the capsule is not of the right type, then 131 * a null context is returned (as checked via mlirContextIsNull). In such a 132 * case, the Python APIs will have already set an error. */ 133 static inline MlirContext mlirPythonCapsuleToContext(PyObject *capsule) { 134 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_CONTEXT); 135 MlirContext context = {ptr}; 136 return context; 137 } 138 139 /** Creates a capsule object encapsulating the raw C-API MlirLocation. 140 * The returned capsule does not extend or affect ownership of any Python 141 * objects that reference the location in any way. */ 142 static inline PyObject *mlirPythonLocationToCapsule(MlirLocation loc) { 143 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(loc), 144 MLIR_PYTHON_CAPSULE_LOCATION, NULL); 145 } 146 147 /** Extracts an MlirLocation from a capsule as produced from 148 * mlirPythonLocationToCapsule. If the capsule is not of the right type, then 149 * a null module is returned (as checked via mlirLocationIsNull). In such a 150 * case, the Python APIs will have already set an error. */ 151 static inline MlirLocation mlirPythonCapsuleToLocation(PyObject *capsule) { 152 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_LOCATION); 153 MlirLocation loc = {ptr}; 154 return loc; 155 } 156 157 /** Creates a capsule object encapsulating the raw C-API MlirModule. 158 * The returned capsule does not extend or affect ownership of any Python 159 * objects that reference the module in any way. */ 160 static inline PyObject *mlirPythonModuleToCapsule(MlirModule module) { 161 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(module), 162 MLIR_PYTHON_CAPSULE_MODULE, NULL); 163 } 164 165 /** Extracts an MlirModule from a capsule as produced from 166 * mlirPythonModuleToCapsule. If the capsule is not of the right type, then 167 * a null module is returned (as checked via mlirModuleIsNull). In such a 168 * case, the Python APIs will have already set an error. */ 169 static inline MlirModule mlirPythonCapsuleToModule(PyObject *capsule) { 170 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_MODULE); 171 MlirModule module = {ptr}; 172 return module; 173 } 174 175 /** Creates a capsule object encapsulating the raw C-API MlirPassManager. 176 * The returned capsule does not extend or affect ownership of any Python 177 * objects that reference the module in any way. */ 178 static inline PyObject *mlirPythonPassManagerToCapsule(MlirPassManager pm) { 179 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(pm), 180 MLIR_PYTHON_CAPSULE_PASS_MANAGER, NULL); 181 } 182 183 /** Extracts an MlirPassManager from a capsule as produced from 184 * mlirPythonPassManagerToCapsule. If the capsule is not of the right type, then 185 * a null pass manager is returned (as checked via mlirPassManagerIsNull). */ 186 static inline MlirPassManager 187 mlirPythonCapsuleToPassManager(PyObject *capsule) { 188 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_PASS_MANAGER); 189 MlirPassManager pm = {ptr}; 190 return pm; 191 } 192 193 /** Creates a capsule object encapsulating the raw C-API MlirOperation. 194 * The returned capsule does not extend or affect ownership of any Python 195 * objects that reference the operation in any way. 196 */ 197 static inline PyObject *mlirPythonOperationToCapsule(MlirOperation operation) { 198 return PyCapsule_New(operation.ptr, MLIR_PYTHON_CAPSULE_OPERATION, NULL); 199 } 200 201 /** Extracts an MlirOperations from a capsule as produced from 202 * mlirPythonOperationToCapsule. If the capsule is not of the right type, then 203 * a null type is returned (as checked via mlirOperationIsNull). In such a 204 * case, the Python APIs will have already set an error. */ 205 static inline MlirOperation mlirPythonCapsuleToOperation(PyObject *capsule) { 206 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_OPERATION); 207 MlirOperation op = {ptr}; 208 return op; 209 } 210 211 /** Creates a capsule object encapsulating the raw C-API MlirType. 212 * The returned capsule does not extend or affect ownership of any Python 213 * objects that reference the type in any way. 214 */ 215 static inline PyObject *mlirPythonTypeToCapsule(MlirType type) { 216 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(type), 217 MLIR_PYTHON_CAPSULE_TYPE, NULL); 218 } 219 220 /** Extracts an MlirType from a capsule as produced from 221 * mlirPythonTypeToCapsule. If the capsule is not of the right type, then 222 * a null type is returned (as checked via mlirTypeIsNull). In such a 223 * case, the Python APIs will have already set an error. */ 224 static inline MlirType mlirPythonCapsuleToType(PyObject *capsule) { 225 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_TYPE); 226 MlirType type = {ptr}; 227 return type; 228 } 229 230 /** Creates a capsule object encapsulating the raw C-API MlirAffineMap. 231 * The returned capsule does not extend or affect ownership of any Python 232 * objects that reference the type in any way. 233 */ 234 static inline PyObject *mlirPythonAffineMapToCapsule(MlirAffineMap affineMap) { 235 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(affineMap), 236 MLIR_PYTHON_CAPSULE_AFFINE_MAP, NULL); 237 } 238 239 /** Extracts an MlirAffineMap from a capsule as produced from 240 * mlirPythonAffineMapToCapsule. If the capsule is not of the right type, then 241 * a null type is returned (as checked via mlirAffineMapIsNull). In such a 242 * case, the Python APIs will have already set an error. */ 243 static inline MlirAffineMap mlirPythonCapsuleToAffineMap(PyObject *capsule) { 244 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_AFFINE_MAP); 245 MlirAffineMap affineMap = {ptr}; 246 return affineMap; 247 } 248 249 /** Creates a capsule object encapsulating the raw C-API MlirIntegerSet. 250 * The returned capsule does not extend or affect ownership of any Python 251 * objects that reference the set in any way. */ 252 static inline PyObject * 253 mlirPythonIntegerSetToCapsule(MlirIntegerSet integerSet) { 254 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(integerSet), 255 MLIR_PYTHON_CAPSULE_INTEGER_SET, NULL); 256 } 257 258 /** Extracts an MlirIntegerSet from a capsule as produced from 259 * mlirPythonIntegerSetToCapsule. If the capsule is not of the right type, then 260 * a null set is returned (as checked via mlirIntegerSetIsNull). In such a 261 * case, the Python APIs will have already set an error. */ 262 static inline MlirIntegerSet mlirPythonCapsuleToIntegerSet(PyObject *capsule) { 263 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_INTEGER_SET); 264 MlirIntegerSet integerSet = {ptr}; 265 return integerSet; 266 } 267 268 /** Creates a capsule object encapsulating the raw C-API MlirExecutionEngine. 269 * The returned capsule does not extend or affect ownership of any Python 270 * objects that reference the set in any way. */ 271 static inline PyObject * 272 mlirPythonExecutionEngineToCapsule(MlirExecutionEngine jit) { 273 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(jit), 274 MLIR_PYTHON_CAPSULE_EXECUTION_ENGINE, NULL); 275 } 276 277 /** Extracts an MlirExecutionEngine from a capsule as produced from 278 * mlirPythonIntegerSetToCapsule. If the capsule is not of the right type, then 279 * a null set is returned (as checked via mlirExecutionEngineIsNull). In such a 280 * case, the Python APIs will have already set an error. */ 281 static inline MlirExecutionEngine 282 mlirPythonCapsuleToExecutionEngine(PyObject *capsule) { 283 void *ptr = 284 PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_EXECUTION_ENGINE); 285 MlirExecutionEngine jit = {ptr}; 286 return jit; 287 } 288 289 /** Creates a capsule object encapsulating the raw C-API MlirValue. 290 * The returned capsule does not extend or affect ownership of any Python 291 * objects that reference the operation in any way. 292 */ 293 static inline PyObject *mlirPythonValueToCapsule(MlirValue value) { 294 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(value), 295 MLIR_PYTHON_CAPSULE_VALUE, NULL); 296 } 297 298 /** Extracts an MlirValue from a capsule as produced from 299 * mlirPythonValueToCapsule. If the capsule is not of the right type, then a 300 * null type is returned (as checked via mlirValueIsNull). In such a case, the 301 * Python APIs will have already set an error. */ 302 static inline MlirValue mlirPythonCapsuleToValue(PyObject *capsule) { 303 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_VALUE); 304 MlirValue value = {ptr}; 305 return value; 306 } 307 308 #ifdef __cplusplus 309 } 310 #endif 311 312 #endif // MLIR_C_BINDINGS_PYTHON_INTEROP_H 313