brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.4 KiB · a33190c Raw
465 lines · c
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 LLVM4// Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9//10// This header declares constants and helpers necessary for C-level11// interop with the MLIR Python extension module. Since the Python bindings12// are a thin wrapper around the MLIR C-API, a further C-API is not provided13// specifically for the Python extension. Instead, simple facilities are14// provided for translating between Python types and corresponding MLIR C-API15// types.16//17// This header is standalone, requiring nothing beyond normal linking against18// the Python implementation.19//===----------------------------------------------------------------------===//20 21#ifndef MLIR_C_BINDINGS_PYTHON_INTEROP_H22#define MLIR_C_BINDINGS_PYTHON_INTEROP_H23 24// We *should*, in theory, include Python.h here in order to import the correct25// definitions for what we need below, however, importing Python.h directly on26// Windows results in the enforcement of either pythonX.lib or pythonX_d.lib27// depending on the build flavor. Instead, we rely on the fact that this file28// (Interop.h) is always included AFTER pybind11 and will therefore have access29// to the definitions from Python.h in addition to having a workaround applied30// through the pybind11 headers that allows us to control which python library31// is used.32#if !defined(_MSC_VER)33#include <Python.h>34#endif35 36#include "mlir-c/AffineExpr.h"37#include "mlir-c/AffineMap.h"38#include "mlir-c/ExecutionEngine.h"39#include "mlir-c/IR.h"40#include "mlir-c/IntegerSet.h"41#include "mlir-c/Pass.h"42#include "mlir-c/Rewrite.h"43 44// The 'mlir' Python package is relocatable and supports co-existing in multiple45// projects. Each project must define its outer package prefix with this define46// in order to provide proper isolation and local name resolution.47// The default is for the upstream "import mlir" package layout.48// Note that this prefix is internally stringified, allowing it to be passed49// unquoted on the compiler command line without shell quote escaping issues.50#ifndef MLIR_PYTHON_PACKAGE_PREFIX51#define MLIR_PYTHON_PACKAGE_PREFIX mlir.52#endif53 54// Makes a fully-qualified name relative to the MLIR python package.55#define MLIR_PYTHON_STRINGIZE(s) #s56#define MLIR_PYTHON_STRINGIZE_ARG(arg) MLIR_PYTHON_STRINGIZE(arg)57#define MAKE_MLIR_PYTHON_QUALNAME(local)                                       \58  MLIR_PYTHON_STRINGIZE_ARG(MLIR_PYTHON_PACKAGE_PREFIX) local59 60#define MLIR_PYTHON_CAPSULE_AFFINE_EXPR                                        \61  MAKE_MLIR_PYTHON_QUALNAME("ir.AffineExpr._CAPIPtr")62#define MLIR_PYTHON_CAPSULE_AFFINE_MAP                                         \63  MAKE_MLIR_PYTHON_QUALNAME("ir.AffineMap._CAPIPtr")64#define MLIR_PYTHON_CAPSULE_ATTRIBUTE                                          \65  MAKE_MLIR_PYTHON_QUALNAME("ir.Attribute._CAPIPtr")66#define MLIR_PYTHON_CAPSULE_BLOCK MAKE_MLIR_PYTHON_QUALNAME("ir.Block._CAPIPtr")67#define MLIR_PYTHON_CAPSULE_CONTEXT                                            \68  MAKE_MLIR_PYTHON_QUALNAME("ir.Context._CAPIPtr")69#define MLIR_PYTHON_CAPSULE_DIALECT_REGISTRY                                   \70  MAKE_MLIR_PYTHON_QUALNAME("ir.DialectRegistry._CAPIPtr")71#define MLIR_PYTHON_CAPSULE_EXECUTION_ENGINE                                   \72  MAKE_MLIR_PYTHON_QUALNAME("execution_engine.ExecutionEngine._CAPIPtr")73#define MLIR_PYTHON_CAPSULE_INTEGER_SET                                        \74  MAKE_MLIR_PYTHON_QUALNAME("ir.IntegerSet._CAPIPtr")75#define MLIR_PYTHON_CAPSULE_LOCATION                                           \76  MAKE_MLIR_PYTHON_QUALNAME("ir.Location._CAPIPtr")77#define MLIR_PYTHON_CAPSULE_MODULE                                             \78  MAKE_MLIR_PYTHON_QUALNAME("ir.Module._CAPIPtr")79#define MLIR_PYTHON_CAPSULE_OPERATION                                          \80  MAKE_MLIR_PYTHON_QUALNAME("ir.Operation._CAPIPtr")81#define MLIR_PYTHON_CAPSULE_TYPE MAKE_MLIR_PYTHON_QUALNAME("ir.Type._CAPIPtr")82#define MLIR_PYTHON_CAPSULE_PASS_MANAGER                                       \83  MAKE_MLIR_PYTHON_QUALNAME("passmanager.PassManager._CAPIPtr")84#define MLIR_PYTHON_CAPSULE_VALUE MAKE_MLIR_PYTHON_QUALNAME("ir.Value._CAPIPtr")85#define MLIR_PYTHON_CAPSULE_TYPEID                                             \86  MAKE_MLIR_PYTHON_QUALNAME("ir.TypeID._CAPIPtr")87 88/** Attribute on MLIR Python objects that expose their C-API pointer.89 * This will be a type-specific capsule created as per one of the helpers90 * below.91 *92 * Ownership is not transferred by acquiring a capsule in this way: the93 * validity of the pointer wrapped by the capsule will be bounded by the94 * lifetime of the Python object that produced it. Only the name and pointer95 * of the capsule are set. The caller is free to set a destructor and context96 * as needed to manage anything further. */97#define MLIR_PYTHON_CAPI_PTR_ATTR "_CAPIPtr"98 99/** Attribute on MLIR Python objects that exposes a factory function for100 * constructing the corresponding Python object from a type-specific101 * capsule wrapping the C-API pointer. The signature of the function is:102 *   def _CAPICreate(capsule) -> object103 * Calling such a function implies a transfer of ownership of the object the104 * capsule wraps: after such a call, the capsule should be considered invalid,105 * and its wrapped pointer must not be destroyed.106 *107 * Only a very small number of Python objects can be created in such a fashion108 * (i.e. top-level types such as Context where the lifetime can be cleanly109 * delineated). */110#define MLIR_PYTHON_CAPI_FACTORY_ATTR "_CAPICreate"111 112/** Attribute on MLIR Python objects that expose a function for downcasting the113 * corresponding Python object to a subclass if the object is in fact a subclass114 * (Concrete or mlir_type_subclass) of ir.Type. The signature of the function115 * is: def maybe_downcast(self) -> object where the resulting object will116 * (possibly) be an instance of the subclass.117 */118#define MLIR_PYTHON_MAYBE_DOWNCAST_ATTR "maybe_downcast"119 120/** Attribute on main C extension module (_mlir) that corresponds to the121 * type caster registration binding. The signature of the function is:122 *   def register_type_caster(MlirTypeID mlirTypeID, *, bool replace)123 * which then takes a typeCaster (register_type_caster is meant to be used as a124 * decorator from python), and where replace indicates the typeCaster should125 * replace any existing registered type casters (such as those for upstream126 * ConcreteTypes). The interface of the typeCaster is: def type_caster(ir.Type)127 * -> SubClassTypeT where SubClassTypeT indicates the result should be a128 * subclass (inherit from) ir.Type.129 */130#define MLIR_PYTHON_CAPI_TYPE_CASTER_REGISTER_ATTR "register_type_caster"131 132/** Attribute on main C extension module (_mlir) that corresponds to the133 * value caster registration binding. The signature of the function is:134 *   def register_value_caster(MlirTypeID mlirTypeID, *, bool replace)135 * which then takes a valueCaster (register_value_caster is meant to be used as136 * a decorator, from python), and where replace indicates the valueCaster should137 * replace any existing registered value casters. The interface of the138 * valueCaster is: def value_caster(ir.Value) -> SubClassValueT where139 * SubClassValueT indicates the result should be a subclass (inherit from)140 * ir.Value.141 */142#define MLIR_PYTHON_CAPI_VALUE_CASTER_REGISTER_ATTR "register_value_caster"143 144/// Gets a void* from a wrapped struct. Needed because const cast is different145/// between C/C++.146#ifdef __cplusplus147#define MLIR_PYTHON_GET_WRAPPED_POINTER(object)                                \148  (const_cast<void *>((object).ptr))149#else150#define MLIR_PYTHON_GET_WRAPPED_POINTER(object) (void *)(object.ptr)151#endif152 153#ifdef __cplusplus154extern "C" {155#endif156 157/** Creates a capsule object encapsulating the raw C-API MlirAffineExpr. The158 * returned capsule does not extend or affect ownership of any Python objects159 * that reference the expression in any way.160 */161static inline PyObject *mlirPythonAffineExprToCapsule(MlirAffineExpr expr) {162  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(expr),163                       MLIR_PYTHON_CAPSULE_AFFINE_EXPR, NULL);164}165 166/** Extracts an MlirAffineExpr from a capsule as produced from167 * mlirPythonAffineExprToCapsule. If the capsule is not of the right type, then168 * a null expression is returned (as checked via mlirAffineExprIsNull). In such169 * a case, the Python APIs will have already set an error. */170static inline MlirAffineExpr mlirPythonCapsuleToAffineExpr(PyObject *capsule) {171  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_AFFINE_EXPR);172  MlirAffineExpr expr = {ptr};173  return expr;174}175 176/** Creates a capsule object encapsulating the raw C-API MlirAttribute.177 * The returned capsule does not extend or affect ownership of any Python178 * objects that reference the attribute in any way.179 */180static inline PyObject *mlirPythonAttributeToCapsule(MlirAttribute attribute) {181  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(attribute),182                       MLIR_PYTHON_CAPSULE_ATTRIBUTE, NULL);183}184 185/** Extracts an MlirAttribute from a capsule as produced from186 * mlirPythonAttributeToCapsule. If the capsule is not of the right type, then187 * a null attribute is returned (as checked via mlirAttributeIsNull). In such a188 * case, the Python APIs will have already set an error. */189static inline MlirAttribute mlirPythonCapsuleToAttribute(PyObject *capsule) {190  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_ATTRIBUTE);191  MlirAttribute attr = {ptr};192  return attr;193}194 195/** Creates a capsule object encapsulating the raw C-API MlirBlock.196 * The returned capsule does not extend or affect ownership of any Python197 * objects that reference the module in any way. */198static inline PyObject *mlirPythonBlockToCapsule(MlirBlock block) {199  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(block),200                       MLIR_PYTHON_CAPSULE_BLOCK, NULL);201}202 203/** Extracts an MlirBlock from a capsule as produced from204 * mlirPythonBlockToCapsule. If the capsule is not of the right type, then205 * a null pass manager is returned (as checked via mlirBlockIsNull). */206static inline MlirBlock mlirPythonCapsuleToBlock(PyObject *capsule) {207  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_BLOCK);208  MlirBlock block = {ptr};209  return block;210}211 212/** Creates a capsule object encapsulating the raw C-API MlirContext.213 * The returned capsule does not extend or affect ownership of any Python214 * objects that reference the context in any way.215 */216static inline PyObject *mlirPythonContextToCapsule(MlirContext context) {217  return PyCapsule_New(context.ptr, MLIR_PYTHON_CAPSULE_CONTEXT, NULL);218}219 220/** Extracts a MlirContext from a capsule as produced from221 * mlirPythonContextToCapsule. If the capsule is not of the right type, then222 * a null context is returned (as checked via mlirContextIsNull). In such a223 * case, the Python APIs will have already set an error. */224static inline MlirContext mlirPythonCapsuleToContext(PyObject *capsule) {225  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_CONTEXT);226  MlirContext context = {ptr};227  return context;228}229 230/** Creates a capsule object encapsulating the raw C-API MlirDialectRegistry.231 * The returned capsule does not extend or affect ownership of any Python232 * objects that reference the context in any way.233 */234static inline PyObject *235mlirPythonDialectRegistryToCapsule(MlirDialectRegistry registry) {236  return PyCapsule_New(registry.ptr, MLIR_PYTHON_CAPSULE_DIALECT_REGISTRY,237                       NULL);238}239 240/** Extracts an MlirDialectRegistry from a capsule as produced from241 * mlirPythonDialectRegistryToCapsule. If the capsule is not of the right type,242 * then a null context is returned (as checked via mlirContextIsNull). In such a243 * case, the Python APIs will have already set an error. */244static inline MlirDialectRegistry245mlirPythonCapsuleToDialectRegistry(PyObject *capsule) {246  void *ptr =247      PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_DIALECT_REGISTRY);248  MlirDialectRegistry registry = {ptr};249  return registry;250}251 252/** Creates a capsule object encapsulating the raw C-API MlirLocation.253 * The returned capsule does not extend or affect ownership of any Python254 * objects that reference the location in any way. */255static inline PyObject *mlirPythonLocationToCapsule(MlirLocation loc) {256  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(loc),257                       MLIR_PYTHON_CAPSULE_LOCATION, NULL);258}259 260/** Extracts an MlirLocation from a capsule as produced from261 * mlirPythonLocationToCapsule. If the capsule is not of the right type, then262 * a null module is returned (as checked via mlirLocationIsNull). In such a263 * case, the Python APIs will have already set an error. */264static inline MlirLocation mlirPythonCapsuleToLocation(PyObject *capsule) {265  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_LOCATION);266  MlirLocation loc = {ptr};267  return loc;268}269 270/** Creates a capsule object encapsulating the raw C-API MlirModule.271 * The returned capsule does not extend or affect ownership of any Python272 * objects that reference the module in any way. */273static inline PyObject *mlirPythonModuleToCapsule(MlirModule module) {274  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(module),275                       MLIR_PYTHON_CAPSULE_MODULE, NULL);276}277 278/** Extracts an MlirModule from a capsule as produced from279 * mlirPythonModuleToCapsule. If the capsule is not of the right type, then280 * a null module is returned (as checked via mlirModuleIsNull). In such a281 * case, the Python APIs will have already set an error. */282static inline MlirModule mlirPythonCapsuleToModule(PyObject *capsule) {283  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_MODULE);284  MlirModule module = {ptr};285  return module;286}287 288/** Creates a capsule object encapsulating the raw C-API289 * MlirFrozenRewritePatternSet.290 * The returned capsule does not extend or affect ownership of any Python291 * objects that reference the module in any way. */292static inline PyObject *293mlirPythonFrozenRewritePatternSetToCapsule(MlirFrozenRewritePatternSet pm) {294  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(pm),295                       MLIR_PYTHON_CAPSULE_PASS_MANAGER, NULL);296}297 298/** Extracts an MlirFrozenRewritePatternSet from a capsule as produced from299 * mlirPythonFrozenRewritePatternSetToCapsule. If the capsule is not of the300 * right type, then a null module is returned. */301static inline MlirFrozenRewritePatternSet302mlirPythonCapsuleToFrozenRewritePatternSet(PyObject *capsule) {303  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_PASS_MANAGER);304  MlirFrozenRewritePatternSet pm = {ptr};305  return pm;306}307 308/** Creates a capsule object encapsulating the raw C-API MlirPassManager.309 * The returned capsule does not extend or affect ownership of any Python310 * objects that reference the module in any way. */311static inline PyObject *mlirPythonPassManagerToCapsule(MlirPassManager pm) {312  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(pm),313                       MLIR_PYTHON_CAPSULE_PASS_MANAGER, NULL);314}315 316/** Extracts an MlirPassManager from a capsule as produced from317 * mlirPythonPassManagerToCapsule. If the capsule is not of the right type, then318 * a null pass manager is returned (as checked via mlirPassManagerIsNull). */319static inline MlirPassManager320mlirPythonCapsuleToPassManager(PyObject *capsule) {321  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_PASS_MANAGER);322  MlirPassManager pm = {ptr};323  return pm;324}325 326/** Creates a capsule object encapsulating the raw C-API MlirOperation.327 * The returned capsule does not extend or affect ownership of any Python328 * objects that reference the operation in any way.329 */330static inline PyObject *mlirPythonOperationToCapsule(MlirOperation operation) {331  return PyCapsule_New(operation.ptr, MLIR_PYTHON_CAPSULE_OPERATION, NULL);332}333 334/** Extracts an MlirOperations from a capsule as produced from335 * mlirPythonOperationToCapsule. If the capsule is not of the right type, then336 * a null type is returned (as checked via mlirOperationIsNull). In such a337 * case, the Python APIs will have already set an error. */338static inline MlirOperation mlirPythonCapsuleToOperation(PyObject *capsule) {339  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_OPERATION);340  MlirOperation op = {ptr};341  return op;342}343 344/** Creates a capsule object encapsulating the raw C-API MlirTypeID.345 * The returned capsule does not extend or affect ownership of any Python346 * objects that reference the type in any way.347 */348static inline PyObject *mlirPythonTypeIDToCapsule(MlirTypeID typeID) {349  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(typeID),350                       MLIR_PYTHON_CAPSULE_TYPEID, NULL);351}352 353/** Extracts an MlirTypeID from a capsule as produced from354 * mlirPythonTypeIDToCapsule. If the capsule is not of the right type, then355 * a null type is returned (as checked via mlirTypeIDIsNull). In such a356 * case, the Python APIs will have already set an error. */357static inline MlirTypeID mlirPythonCapsuleToTypeID(PyObject *capsule) {358  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_TYPEID);359  MlirTypeID typeID = {ptr};360  return typeID;361}362 363/** Creates a capsule object encapsulating the raw C-API MlirType.364 * The returned capsule does not extend or affect ownership of any Python365 * objects that reference the type in any way.366 */367static inline PyObject *mlirPythonTypeToCapsule(MlirType type) {368  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(type),369                       MLIR_PYTHON_CAPSULE_TYPE, NULL);370}371 372/** Extracts an MlirType from a capsule as produced from373 * mlirPythonTypeToCapsule. If the capsule is not of the right type, then374 * a null type is returned (as checked via mlirTypeIsNull). In such a375 * case, the Python APIs will have already set an error. */376static inline MlirType mlirPythonCapsuleToType(PyObject *capsule) {377  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_TYPE);378  MlirType type = {ptr};379  return type;380}381 382/** Creates a capsule object encapsulating the raw C-API MlirAffineMap.383 * The returned capsule does not extend or affect ownership of any Python384 * objects that reference the type in any way.385 */386static inline PyObject *mlirPythonAffineMapToCapsule(MlirAffineMap affineMap) {387  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(affineMap),388                       MLIR_PYTHON_CAPSULE_AFFINE_MAP, NULL);389}390 391/** Extracts an MlirAffineMap from a capsule as produced from392 * mlirPythonAffineMapToCapsule. If the capsule is not of the right type, then393 * a null type is returned (as checked via mlirAffineMapIsNull). In such a394 * case, the Python APIs will have already set an error. */395static inline MlirAffineMap mlirPythonCapsuleToAffineMap(PyObject *capsule) {396  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_AFFINE_MAP);397  MlirAffineMap affineMap = {ptr};398  return affineMap;399}400 401/** Creates a capsule object encapsulating the raw C-API MlirIntegerSet.402 * The returned capsule does not extend or affect ownership of any Python403 * objects that reference the set in any way. */404static inline PyObject *405mlirPythonIntegerSetToCapsule(MlirIntegerSet integerSet) {406  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(integerSet),407                       MLIR_PYTHON_CAPSULE_INTEGER_SET, NULL);408}409 410/** Extracts an MlirIntegerSet from a capsule as produced from411 * mlirPythonIntegerSetToCapsule. If the capsule is not of the right type, then412 * a null set is returned (as checked via mlirIntegerSetIsNull). In such a413 * case, the Python APIs will have already set an error. */414static inline MlirIntegerSet mlirPythonCapsuleToIntegerSet(PyObject *capsule) {415  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_INTEGER_SET);416  MlirIntegerSet integerSet = {ptr};417  return integerSet;418}419 420/** Creates a capsule object encapsulating the raw C-API MlirExecutionEngine.421 * The returned capsule does not extend or affect ownership of any Python422 * objects that reference the set in any way. */423static inline PyObject *424mlirPythonExecutionEngineToCapsule(MlirExecutionEngine jit) {425  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(jit),426                       MLIR_PYTHON_CAPSULE_EXECUTION_ENGINE, NULL);427}428 429/** Extracts an MlirExecutionEngine from a capsule as produced from430 * mlirPythonIntegerSetToCapsule. If the capsule is not of the right type, then431 * a null set is returned (as checked via mlirExecutionEngineIsNull). In such a432 * case, the Python APIs will have already set an error. */433static inline MlirExecutionEngine434mlirPythonCapsuleToExecutionEngine(PyObject *capsule) {435  void *ptr =436      PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_EXECUTION_ENGINE);437  MlirExecutionEngine jit = {ptr};438  return jit;439}440 441/** Creates a capsule object encapsulating the raw C-API MlirValue.442 * The returned capsule does not extend or affect ownership of any Python443 * objects that reference the operation in any way.444 */445static inline PyObject *mlirPythonValueToCapsule(MlirValue value) {446  return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(value),447                       MLIR_PYTHON_CAPSULE_VALUE, NULL);448}449 450/** Extracts an MlirValue from a capsule as produced from451 * mlirPythonValueToCapsule. If the capsule is not of the right type, then a452 * null type is returned (as checked via mlirValueIsNull). In such a case, the453 * Python APIs will have already set an error. */454static inline MlirValue mlirPythonCapsuleToValue(PyObject *capsule) {455  void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_VALUE);456  MlirValue value = {ptr};457  return value;458}459 460#ifdef __cplusplus461}462#endif463 464#endif // MLIR_C_BINDINGS_PYTHON_INTEROP_H465