https://github.com/makslevental updated https://github.com/llvm/llvm-project/pull/173439
>From 5f4d2cdf5cf3c487ea7537b352166ff0252e9b89 Mon Sep 17 00:00:00 2001 From: makslevental <[email protected]> Date: Tue, 23 Dec 2025 12:20:34 -0800 Subject: [PATCH 1/3] try MLIR_PYTHON_API_EXPORTED --- mlir/cmake/modules/AddMLIRPython.cmake | 9 +- mlir/include/mlir-c/Support.h | 2 + mlir/include/mlir/Bindings/Python/Globals.h | 4 +- mlir/include/mlir/Bindings/Python/IRCore.h | 121 +++++++++++--------- mlir/include/mlir/Bindings/Python/IRTypes.h | 3 +- 5 files changed, 75 insertions(+), 64 deletions(-) diff --git a/mlir/cmake/modules/AddMLIRPython.cmake b/mlir/cmake/modules/AddMLIRPython.cmake index 0501e0b5e51fe..8ec9304421b54 100644 --- a/mlir/cmake/modules/AddMLIRPython.cmake +++ b/mlir/cmake/modules/AddMLIRPython.cmake @@ -854,11 +854,10 @@ function(add_mlir_python_extension libname extname nb_library_target_name) target_link_options(${libname} PRIVATE "-Wl,-z,undefs") endif() nanobind_link_options(${libname}) - target_compile_definitions(${libname} PRIVATE NB_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN}) - set_target_properties(${libname} PROPERTIES - VISIBILITY_INLINES_HIDDEN OFF - C_VISIBILITY_PRESET default - CXX_VISIBILITY_PRESET default + target_compile_definitions(${libname} + PRIVATE + NB_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN} + MLIR_CAPI_BUILDING_LIBRARY=1 ) if (MSVC) set_property(TARGET ${libname} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON) diff --git a/mlir/include/mlir-c/Support.h b/mlir/include/mlir-c/Support.h index 78fc94f93439e..6abd8894227c3 100644 --- a/mlir/include/mlir-c/Support.h +++ b/mlir/include/mlir-c/Support.h @@ -46,6 +46,8 @@ #define MLIR_CAPI_EXPORTED __attribute__((visibility("default"))) #endif +#define MLIR_PYTHON_API_EXPORTED MLIR_CAPI_EXPORTED + #ifdef __cplusplus extern "C" { #endif diff --git a/mlir/include/mlir/Bindings/Python/Globals.h b/mlir/include/mlir/Bindings/Python/Globals.h index 2184e7e2dc5ca..112c7b9b0547f 100644 --- a/mlir/include/mlir/Bindings/Python/Globals.h +++ b/mlir/include/mlir/Bindings/Python/Globals.h @@ -31,7 +31,7 @@ namespace python { /// Globals that are always accessible once the extension has been initialized. /// Methods of this class are thread-safe. -class PyGlobals { +class MLIR_PYTHON_API_EXPORTED PyGlobals { public: PyGlobals(); ~PyGlobals(); @@ -117,7 +117,7 @@ class PyGlobals { std::optional<nanobind::object> lookupOperationClass(llvm::StringRef operationName); - class TracebackLoc { + class MLIR_PYTHON_API_EXPORTED TracebackLoc { public: bool locTracebacksEnabled(); diff --git a/mlir/include/mlir/Bindings/Python/IRCore.h b/mlir/include/mlir/Bindings/Python/IRCore.h index 649dfce22ad35..ceedeb691eb58 100644 --- a/mlir/include/mlir/Bindings/Python/IRCore.h +++ b/mlir/include/mlir/Bindings/Python/IRCore.h @@ -52,7 +52,7 @@ class PyValue; /// Template for a reference to a concrete type which captures a python /// reference to its underlying python object. template <typename T> -class PyObjectRef { +class MLIR_PYTHON_API_EXPORTED PyObjectRef { public: PyObjectRef(T *referrent, nanobind::object object) : referrent(referrent), object(std::move(object)) { @@ -111,7 +111,7 @@ class PyObjectRef { /// Context. Pushing a Context will not modify the Location or InsertionPoint /// unless if they are from a different context, in which case, they are /// cleared. -class PyThreadContextEntry { +class MLIR_PYTHON_API_EXPORTED PyThreadContextEntry { public: enum class FrameKind { Context, @@ -167,7 +167,7 @@ class PyThreadContextEntry { /// Wrapper around MlirLlvmThreadPool /// Python object owns the C++ thread pool -class PyThreadPool { +class MLIR_PYTHON_API_EXPORTED PyThreadPool { public: PyThreadPool() { ownedThreadPool = std::make_unique<llvm::DefaultThreadPool>(); @@ -190,7 +190,7 @@ class PyThreadPool { /// Wrapper around MlirContext. using PyMlirContextRef = PyObjectRef<PyMlirContext>; -class PyMlirContext { +class MLIR_PYTHON_API_EXPORTED PyMlirContext { public: PyMlirContext() = delete; PyMlirContext(MlirContext context); @@ -271,7 +271,7 @@ class PyMlirContext { /// Used in function arguments when None should resolve to the current context /// manager set instance. -class DefaultingPyMlirContext +class MLIR_PYTHON_API_EXPORTED DefaultingPyMlirContext : public Defaulting<DefaultingPyMlirContext, PyMlirContext> { public: using Defaulting::Defaulting; @@ -283,7 +283,7 @@ class DefaultingPyMlirContext /// MlirContext. The lifetime of the context will extend at least to the /// lifetime of these instances. /// Immutable objects that depend on a context extend this directly. -class BaseContextObject { +class MLIR_PYTHON_API_EXPORTED BaseContextObject { public: BaseContextObject(PyMlirContextRef ref) : contextRef(std::move(ref)) { assert(this->contextRef && @@ -298,7 +298,7 @@ class BaseContextObject { }; /// Wrapper around an MlirLocation. -class PyLocation : public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyLocation : public BaseContextObject { public: PyLocation(PyMlirContextRef contextRef, MlirLocation loc) : BaseContextObject(std::move(contextRef)), loc(loc) {} @@ -329,7 +329,7 @@ class PyLocation : public BaseContextObject { /// are only valid for the duration of a diagnostic callback and attempting /// to access them outside of that will raise an exception. This applies to /// nested diagnostics (in the notes) as well. -class PyDiagnostic { +class MLIR_PYTHON_API_EXPORTED PyDiagnostic { public: PyDiagnostic(MlirDiagnostic diagnostic) : diagnostic(diagnostic) {} void invalidate(); @@ -379,7 +379,7 @@ class PyDiagnostic { /// The object may remain live from a Python perspective for an arbitrary time /// after detachment, but there is nothing the user can do with it (since there /// is no way to attach an existing handler object). -class PyDiagnosticHandler { +class MLIR_PYTHON_API_EXPORTED PyDiagnosticHandler { public: PyDiagnosticHandler(MlirContext context, nanobind::object callback); ~PyDiagnosticHandler(); @@ -407,7 +407,7 @@ class PyDiagnosticHandler { /// RAII object that captures any error diagnostics emitted to the provided /// context. -struct PyMlirContext::ErrorCapture { +struct MLIR_PYTHON_API_EXPORTED PyMlirContext::ErrorCapture { ErrorCapture(PyMlirContextRef ctx) : ctx(ctx), handlerID(mlirContextAttachDiagnosticHandler( ctx->get(), handler, /*userData=*/this, @@ -434,7 +434,7 @@ struct PyMlirContext::ErrorCapture { /// plugins which extend dialect functionality through extension python code. /// This should be seen as the "low-level" object and `Dialect` as the /// high-level, user facing object. -class PyDialectDescriptor : public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyDialectDescriptor : public BaseContextObject { public: PyDialectDescriptor(PyMlirContextRef contextRef, MlirDialect dialect) : BaseContextObject(std::move(contextRef)), dialect(dialect) {} @@ -447,7 +447,7 @@ class PyDialectDescriptor : public BaseContextObject { /// User-level object for accessing dialects with dotted syntax such as: /// ctx.dialect.std -class PyDialects : public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyDialects : public BaseContextObject { public: PyDialects(PyMlirContextRef contextRef) : BaseContextObject(std::move(contextRef)) {} @@ -458,7 +458,7 @@ class PyDialects : public BaseContextObject { /// User-level dialect object. For dialects that have a registered extension, /// this will be the base class of the extension dialect type. For un-extended, /// objects of this type will be returned directly. -class PyDialect { +class MLIR_PYTHON_API_EXPORTED PyDialect { public: PyDialect(nanobind::object descriptor) : descriptor(std::move(descriptor)) {} @@ -471,7 +471,7 @@ class PyDialect { /// Wrapper around an MlirDialectRegistry. /// Upon construction, the Python wrapper takes ownership of the /// underlying MlirDialectRegistry. -class PyDialectRegistry { +class MLIR_PYTHON_API_EXPORTED PyDialectRegistry { public: PyDialectRegistry() : registry(mlirDialectRegistryCreate()) {} PyDialectRegistry(MlirDialectRegistry registry) : registry(registry) {} @@ -497,7 +497,7 @@ class PyDialectRegistry { /// Used in function arguments when None should resolve to the current context /// manager set instance. -class DefaultingPyLocation +class MLIR_PYTHON_API_EXPORTED DefaultingPyLocation : public Defaulting<DefaultingPyLocation, PyLocation> { public: using Defaulting::Defaulting; @@ -511,7 +511,7 @@ class DefaultingPyLocation /// This is the top-level, user-owned object that contains regions/ops/blocks. class PyModule; using PyModuleRef = PyObjectRef<PyModule>; -class PyModule : public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyModule : public BaseContextObject { public: /// Returns a PyModule reference for the given MlirModule. This always returns /// a new object. @@ -551,7 +551,7 @@ class PyAsmState; /// Base class for PyOperation and PyOpView which exposes the primary, user /// visible methods for manipulating it. -class PyOperationBase { +class MLIR_PYTHON_API_EXPORTED PyOperationBase { public: virtual ~PyOperationBase() = default; /// Implements the bound 'print' method and helps with others. @@ -604,7 +604,8 @@ class PyOperationBase { class PyOperation; class PyOpView; using PyOperationRef = PyObjectRef<PyOperation>; -class PyOperation : public PyOperationBase, public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyOperation : public PyOperationBase, + public BaseContextObject { public: ~PyOperation() override; PyOperation &getOperation() override { return *this; } @@ -722,7 +723,7 @@ class PyOperation : public PyOperationBase, public BaseContextObject { /// custom ODS-style operation classes. Since this class is subclass on the /// python side, it must present an __init__ method that operates in pure /// python types. -class PyOpView : public PyOperationBase { +class MLIR_PYTHON_API_EXPORTED PyOpView : public PyOperationBase { public: PyOpView(const nanobind::object &operationObject); PyOperation &getOperation() override { return operation; } @@ -758,7 +759,7 @@ class PyOpView : public PyOperationBase { /// Wrapper around an MlirRegion. /// Regions are managed completely by their containing operation. Unlike the /// C++ API, the python API does not support detached regions. -class PyRegion { +class MLIR_PYTHON_API_EXPORTED PyRegion { public: PyRegion(PyOperationRef parentOperation, MlirRegion region) : parentOperation(std::move(parentOperation)), region(region) { @@ -777,7 +778,7 @@ class PyRegion { }; /// Wrapper around an MlirAsmState. -class PyAsmState { +class MLIR_PYTHON_API_EXPORTED PyAsmState { public: PyAsmState(MlirValue value, bool useLocalScope) { flags = mlirOpPrintingFlagsCreate(); @@ -812,7 +813,7 @@ class PyAsmState { /// Wrapper around an MlirBlock. /// Blocks are managed completely by their containing operation. Unlike the /// C++ API, the python API does not support detached blocks. -class PyBlock { +class MLIR_PYTHON_API_EXPORTED PyBlock { public: PyBlock(PyOperationRef parentOperation, MlirBlock block) : parentOperation(std::move(parentOperation)), block(block) { @@ -836,7 +837,7 @@ class PyBlock { /// Calls to insert() will insert a new operation before the /// reference operation. If the reference operation is null, then appends to /// the end of the block. -class PyInsertionPoint { +class MLIR_PYTHON_API_EXPORTED PyInsertionPoint { public: /// Creates an insertion point positioned after the last operation in the /// block, but still inside the block. @@ -877,7 +878,7 @@ class PyInsertionPoint { }; /// Wrapper around the generic MlirType. /// The lifetime of a type is bound by the PyContext that created it. -class PyType : public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyType : public BaseContextObject { public: PyType(PyMlirContextRef contextRef, MlirType type) : BaseContextObject(std::move(contextRef)), type(type) {} @@ -903,7 +904,7 @@ class PyType : public BaseContextObject { /// A TypeID provides an efficient and unique identifier for a specific C++ /// type. This allows for a C++ type to be compared, hashed, and stored in an /// opaque context. This class wraps around the generic MlirTypeID. -class PyTypeID { +class MLIR_PYTHON_API_EXPORTED PyTypeID { public: PyTypeID(MlirTypeID typeID) : typeID(typeID) {} // Note, this tests whether the underlying TypeIDs are the same, @@ -929,7 +930,7 @@ class PyTypeID { /// concrete type class extends PyType); however, intermediate python-visible /// base classes can be modeled by specifying a BaseTy. template <typename DerivedTy, typename BaseTy = PyType> -class PyConcreteType : public BaseTy { +class MLIR_PYTHON_API_EXPORTED PyConcreteType : public BaseTy { public: // Derived classes must define statics for: // IsAFunctionTy isaFunction @@ -1007,7 +1008,7 @@ class PyConcreteType : public BaseTy { /// Wrapper around the generic MlirAttribute. /// The lifetime of a type is bound by the PyContext that created it. -class PyAttribute : public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyAttribute : public BaseContextObject { public: PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr) : BaseContextObject(std::move(contextRef)), attr(attr) {} @@ -1033,7 +1034,7 @@ class PyAttribute : public BaseContextObject { /// Represents a Python MlirNamedAttr, carrying an optional owned name. /// TODO: Refactor this and the C-API to be based on an Identifier owned /// by the context so as to avoid ownership issues here. -class PyNamedAttribute { +class MLIR_PYTHON_API_EXPORTED PyNamedAttribute { public: /// Constructs a PyNamedAttr that retains an owned name. This should be /// used in any code that originates an MlirNamedAttribute from a python @@ -1059,7 +1060,7 @@ class PyNamedAttribute { /// concrete attribute class extends PyAttribute); however, intermediate /// python-visible base classes can be modeled by specifying a BaseTy. template <typename DerivedTy, typename BaseTy = PyAttribute> -class PyConcreteAttribute : public BaseTy { +class MLIR_PYTHON_API_EXPORTED PyConcreteAttribute : public BaseTy { public: // Derived classes must define statics for: // IsAFunctionTy isaFunction @@ -1149,7 +1150,8 @@ class PyConcreteAttribute : public BaseTy { static void bindDerived(ClassTy &m) {} }; -class PyStringAttribute : public PyConcreteAttribute<PyStringAttribute> { +class MLIR_PYTHON_API_EXPORTED PyStringAttribute + : public PyConcreteAttribute<PyStringAttribute> { public: static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAString; static constexpr const char *pyClassName = "StringAttr"; @@ -1166,7 +1168,7 @@ class PyStringAttribute : public PyConcreteAttribute<PyStringAttribute> { /// value. For block argument values, this is the operation that contains the /// block to which the value is an argument (blocks cannot be detached in Python /// bindings so such operation always exists). -class PyValue { +class MLIR_PYTHON_API_EXPORTED PyValue { public: // The virtual here is "load bearing" in that it enables RTTI // for PyConcreteValue CRTP classes that support maybeDownCast. @@ -1196,7 +1198,7 @@ class PyValue { }; /// Wrapper around MlirAffineExpr. Affine expressions are owned by the context. -class PyAffineExpr : public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyAffineExpr : public BaseContextObject { public: PyAffineExpr(PyMlirContextRef contextRef, MlirAffineExpr affineExpr) : BaseContextObject(std::move(contextRef)), affineExpr(affineExpr) {} @@ -1223,7 +1225,7 @@ class PyAffineExpr : public BaseContextObject { MlirAffineExpr affineExpr; }; -class PyAffineMap : public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyAffineMap : public BaseContextObject { public: PyAffineMap(PyMlirContextRef contextRef, MlirAffineMap affineMap) : BaseContextObject(std::move(contextRef)), affineMap(affineMap) {} @@ -1244,7 +1246,7 @@ class PyAffineMap : public BaseContextObject { MlirAffineMap affineMap; }; -class PyIntegerSet : public BaseContextObject { +class MLIR_PYTHON_API_EXPORTED PyIntegerSet : public BaseContextObject { public: PyIntegerSet(PyMlirContextRef contextRef, MlirIntegerSet integerSet) : BaseContextObject(std::move(contextRef)), integerSet(integerSet) {} @@ -1265,7 +1267,7 @@ class PyIntegerSet : public BaseContextObject { }; /// Bindings for MLIR symbol tables. -class PySymbolTable { +class MLIR_PYTHON_API_EXPORTED PySymbolTable { public: /// Constructs a symbol table for the given operation. explicit PySymbolTable(PyOperationBase &operation); @@ -1317,7 +1319,7 @@ class PySymbolTable { /// Custom exception that allows access to error diagnostic information. This is /// converted to the `ir.MLIRError` python exception when thrown. -struct MLIRError { +struct MLIR_PYTHON_API_EXPORTED MLIRError { MLIRError(llvm::Twine message, std::vector<PyDiagnostic::DiagnosticInfo> &&errorDiagnostics = {}) : message(message.str()), errorDiagnostics(std::move(errorDiagnostics)) {} @@ -1342,7 +1344,7 @@ inline void registerMLIRError() { }); } -void registerMLIRErrorInCore(); +MLIR_PYTHON_API_EXPORTED void registerMLIRErrorInCore(); //------------------------------------------------------------------------------ // Utilities. @@ -1455,7 +1457,7 @@ inline nanobind::object PyBlock::getCapsule() { // Collections. //------------------------------------------------------------------------------ -class PyRegionIterator { +class MLIR_PYTHON_API_EXPORTED PyRegionIterator { public: PyRegionIterator(PyOperationRef operation, int nextIndex) : operation(std::move(operation)), nextIndex(nextIndex) {} @@ -1486,7 +1488,8 @@ class PyRegionIterator { /// Regions of an op are fixed length and indexed numerically so are represented /// with a sequence-like container. -class PyRegionList : public Sliceable<PyRegionList, PyRegion> { +class MLIR_PYTHON_API_EXPORTED PyRegionList + : public Sliceable<PyRegionList, PyRegion> { public: static constexpr const char *pyClassName = "RegionSequence"; @@ -1529,7 +1532,7 @@ class PyRegionList : public Sliceable<PyRegionList, PyRegion> { PyOperationRef operation; }; -class PyBlockIterator { +class MLIR_PYTHON_API_EXPORTED PyBlockIterator { public: PyBlockIterator(PyOperationRef operation, MlirBlock next) : operation(std::move(operation)), next(next) {} @@ -1563,7 +1566,7 @@ class PyBlockIterator { /// Blocks are exposed by the C-API as a forward-only linked list. In Python, /// we present them as a more full-featured list-like container but optimize /// it for forward iteration. Blocks are always owned by a region. -class PyBlockList { +class MLIR_PYTHON_API_EXPORTED PyBlockList { public: PyBlockList(PyOperationRef operation, MlirRegion region) : operation(std::move(operation)), region(region) {} @@ -1636,7 +1639,7 @@ class PyBlockList { MlirRegion region; }; -class PyOperationIterator { +class MLIR_PYTHON_API_EXPORTED PyOperationIterator { public: PyOperationIterator(PyOperationRef parentOperation, MlirOperation next) : parentOperation(std::move(parentOperation)), next(next) {} @@ -1672,7 +1675,7 @@ class PyOperationIterator { /// Python, we present them as a more full-featured list-like container but /// optimize it for forward iteration. Iterable operations are always owned /// by a block. -class PyOperationList { +class MLIR_PYTHON_API_EXPORTED PyOperationList { public: PyOperationList(PyOperationRef parentOperation, MlirBlock block) : parentOperation(std::move(parentOperation)), block(block) {} @@ -1729,7 +1732,7 @@ class PyOperationList { MlirBlock block; }; -class PyOpOperand { +class MLIR_PYTHON_API_EXPORTED PyOpOperand { public: PyOpOperand(MlirOpOperand opOperand) : opOperand(opOperand) {} @@ -1754,7 +1757,7 @@ class PyOpOperand { MlirOpOperand opOperand; }; -class PyOpOperandIterator { +class MLIR_PYTHON_API_EXPORTED PyOpOperandIterator { public: PyOpOperandIterator(MlirOpOperand opOperand) : opOperand(opOperand) {} @@ -1785,7 +1788,7 @@ class PyOpOperandIterator { /// castable from it. The value hierarchy is one level deep and is not supposed /// to accommodate other levels unless core MLIR changes. template <typename DerivedTy> -class PyConcreteValue : public PyValue { +class MLIR_PYTHON_API_EXPORTED PyConcreteValue : public PyValue { public: // Derived classes must define statics for: // IsAFunctionTy isaFunction @@ -1843,7 +1846,7 @@ class PyConcreteValue : public PyValue { }; /// Python wrapper for MlirOpResult. -class PyOpResult : public PyConcreteValue<PyOpResult> { +class MLIR_PYTHON_API_EXPORTED PyOpResult : public PyConcreteValue<PyOpResult> { public: static constexpr IsAFunctionTy isaFunction = mlirValueIsAOpResult; static constexpr const char *pyClassName = "OpResult"; @@ -1887,7 +1890,8 @@ getValueTypes(Container &container, PyMlirContextRef &context) { /// elements, random access is cheap. The (returned) result list is associated /// with the operation whose results these are, and thus extends the lifetime of /// this operation. -class PyOpResultList : public Sliceable<PyOpResultList, PyOpResult> { +class MLIR_PYTHON_API_EXPORTED PyOpResultList + : public Sliceable<PyOpResultList, PyOpResult> { public: static constexpr const char *pyClassName = "OpResultList"; using SliceableT = Sliceable<PyOpResultList, PyOpResult>; @@ -1940,7 +1944,8 @@ class PyOpResultList : public Sliceable<PyOpResultList, PyOpResult> { }; /// Python wrapper for MlirBlockArgument. -class PyBlockArgument : public PyConcreteValue<PyBlockArgument> { +class MLIR_PYTHON_API_EXPORTED PyBlockArgument + : public PyConcreteValue<PyBlockArgument> { public: static constexpr IsAFunctionTy isaFunction = mlirValueIsABlockArgument; static constexpr const char *pyClassName = "BlockArgument"; @@ -1979,7 +1984,7 @@ class PyBlockArgument : public PyConcreteValue<PyBlockArgument> { /// elements, random access is cheap. The argument list is associated with the /// operation that contains the block (detached blocks are not allowed in /// Python bindings) and extends its lifetime. -class PyBlockArgumentList +class MLIR_PYTHON_API_EXPORTED PyBlockArgumentList : public Sliceable<PyBlockArgumentList, PyBlockArgument> { public: static constexpr const char *pyClassName = "BlockArgumentList"; @@ -2032,7 +2037,8 @@ class PyBlockArgumentList /// elements, random access is cheap. The (returned) operand list is associated /// with the operation whose operands these are, and thus extends the lifetime /// of this operation. -class PyOpOperandList : public Sliceable<PyOpOperandList, PyValue> { +class MLIR_PYTHON_API_EXPORTED PyOpOperandList + : public Sliceable<PyOpOperandList, PyValue> { public: static constexpr const char *pyClassName = "OpOperandList"; using SliceableT = Sliceable<PyOpOperandList, PyValue>; @@ -2090,7 +2096,8 @@ class PyOpOperandList : public Sliceable<PyOpOperandList, PyValue> { /// elements, random access is cheap. The (returned) successor list is /// associated with the operation whose successors these are, and thus extends /// the lifetime of this operation. -class PyOpSuccessors : public Sliceable<PyOpSuccessors, PyBlock> { +class MLIR_PYTHON_API_EXPORTED PyOpSuccessors + : public Sliceable<PyOpSuccessors, PyBlock> { public: static constexpr const char *pyClassName = "OpSuccessors"; @@ -2138,7 +2145,8 @@ class PyOpSuccessors : public Sliceable<PyOpSuccessors, PyBlock> { /// elements, random access is cheap. The (returned) successor list is /// associated with the operation and block whose successors these are, and thus /// extends the lifetime of this operation and block. -class PyBlockSuccessors : public Sliceable<PyBlockSuccessors, PyBlock> { +class MLIR_PYTHON_API_EXPORTED PyBlockSuccessors + : public Sliceable<PyBlockSuccessors, PyBlock> { public: static constexpr const char *pyClassName = "BlockSuccessors"; @@ -2180,7 +2188,8 @@ class PyBlockSuccessors : public Sliceable<PyBlockSuccessors, PyBlock> { /// WARNING: This Sliceable is more expensive than the others here because /// mlirBlockGetPredecessor actually iterates the use-def chain (of block /// operands) anew for each indexed access. -class PyBlockPredecessors : public Sliceable<PyBlockPredecessors, PyBlock> { +class MLIR_PYTHON_API_EXPORTED PyBlockPredecessors + : public Sliceable<PyBlockPredecessors, PyBlock> { public: static constexpr const char *pyClassName = "BlockPredecessors"; @@ -2218,7 +2227,7 @@ class PyBlockPredecessors : public Sliceable<PyBlockPredecessors, PyBlock> { /// A list of operation attributes. Can be indexed by name, producing /// attributes, or by index, producing named attributes. -class PyOpAttributeMap { +class MLIR_PYTHON_API_EXPORTED PyOpAttributeMap { public: PyOpAttributeMap(PyOperationRef operation) : operation(std::move(operation)) {} @@ -2354,7 +2363,7 @@ class PyOpAttributeMap { PyOperationRef operation; }; -MlirValue getUniqueResult(MlirOperation operation); +MLIR_PYTHON_API_EXPORTED MlirValue getUniqueResult(MlirOperation operation); } // namespace python } // namespace mlir diff --git a/mlir/include/mlir/Bindings/Python/IRTypes.h b/mlir/include/mlir/Bindings/Python/IRTypes.h index ba9642cf2c6a2..cd0cfbc7d61d8 100644 --- a/mlir/include/mlir/Bindings/Python/IRTypes.h +++ b/mlir/include/mlir/Bindings/Python/IRTypes.h @@ -14,7 +14,8 @@ namespace mlir { /// Shaped Type Interface - ShapedType -class PyShapedType : public python::PyConcreteType<PyShapedType> { +class MLIR_PYTHON_API_EXPORTED PyShapedType + : public python::PyConcreteType<PyShapedType> { public: static const IsAFunctionTy isaFunction; static constexpr const char *pyClassName = "ShapedType"; >From d9df23fc7a5a5d84cefa5735eb48893dccc4aff0 Mon Sep 17 00:00:00 2001 From: makslevental <[email protected]> Date: Tue, 23 Dec 2025 13:37:11 -0800 Subject: [PATCH 2/3] globals doesn't work --- mlir/cmake/modules/AddMLIRPython.cmake | 18 ++++++++++++------ mlir/examples/standalone/pyproject.toml | 3 +++ .../standalone/test/python/smoketest.py | 19 +++---------------- mlir/include/mlir/Bindings/Python/Globals.h | 2 -- mlir/lib/Bindings/Python/Globals.cpp | 18 ++++++++++++------ mlir/test/Examples/standalone/test.wheel.toy | 7 ++----- 6 files changed, 32 insertions(+), 35 deletions(-) diff --git a/mlir/cmake/modules/AddMLIRPython.cmake b/mlir/cmake/modules/AddMLIRPython.cmake index 8ec9304421b54..90b26aad03828 100644 --- a/mlir/cmake/modules/AddMLIRPython.cmake +++ b/mlir/cmake/modules/AddMLIRPython.cmake @@ -317,6 +317,10 @@ function(build_nanobind_lib) set(NB_LIBRARY_TARGET_NAME "nanobind${_ft}-${MLIR_BINDINGS_PYTHON_NB_DOMAIN}") set(NB_LIBRARY_TARGET_NAME "${NB_LIBRARY_TARGET_NAME}" PARENT_SCOPE) nanobind_build_library(${NB_LIBRARY_TARGET_NAME} AS_SYSINCLUDE) + target_compile_definitions(${NB_LIBRARY_TARGET_NAME} + PRIVATE + NB_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN} + ) # nanobind configures with LTO for shared build which doesn't work everywhere # (see https://github.com/llvm/llvm-project/issues/139602). if(NOT LLVM_ENABLE_LTO) @@ -365,6 +369,10 @@ function(add_mlir_python_modules name) "COMMON_CAPI_LINK_LIBS;DECLARED_SOURCES" ${ARGN}) + if(NOT MLIR_BINDINGS_PYTHON_NB_DOMAIN) + set(MLIR_BINDINGS_PYTHON_NB_DOMAIN "mlir" CACHE STRING "" FORCE) + endif() + # This call sets NB_LIBRARY_TARGET_NAME. build_nanobind_lib( INSTALL_COMPONENT ${name} @@ -420,6 +428,8 @@ function(add_mlir_python_modules name) get_target_property(_source_type ${sources_target} mlir_python_SOURCES_TYPE) if(_source_type STREQUAL "support") get_target_property(_module_name ${sources_target} mlir_python_EXTENSION_MODULE_NAME) + # Use a similar mechanism as nanobind to help the runtime loader pick the correct lib. + set(_module_name "${_module_name}-${MLIR_BINDINGS_PYTHON_NB_DOMAIN}") set(_extension_target "${name}.extension.${_module_name}.dso") add_mlir_python_extension(${_extension_target} "${_module_name}" ${NB_LIBRARY_TARGET_NAME} INSTALL_COMPONENT ${name} @@ -844,10 +854,6 @@ function(add_mlir_python_extension libname extname nb_library_target_name) set(eh_rtti_enable -frtti -fexceptions) endif () - if(NOT MLIR_BINDINGS_PYTHON_NB_DOMAIN) - set(MLIR_BINDINGS_PYTHON_NB_DOMAIN "mlir" CACHE STRING "" FORCE) - endif() - if(ARG_SUPPORT_LIB) add_library(${libname} SHARED ${ARG_SOURCES}) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") @@ -859,9 +865,9 @@ function(add_mlir_python_extension libname extname nb_library_target_name) NB_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN} MLIR_CAPI_BUILDING_LIBRARY=1 ) - if (MSVC) + if(MSVC) set_property(TARGET ${libname} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON) - endif () + endif() else() nanobind_add_module(${libname} NB_DOMAIN ${MLIR_BINDINGS_PYTHON_NB_DOMAIN} diff --git a/mlir/examples/standalone/pyproject.toml b/mlir/examples/standalone/pyproject.toml index c4194153743ef..a90fb417eb426 100644 --- a/mlir/examples/standalone/pyproject.toml +++ b/mlir/examples/standalone/pyproject.toml @@ -56,8 +56,11 @@ MLIR_DIR = { env = "MLIR_DIR", default = "" } # Non-optional CMAKE_BUILD_TYPE = { env = "CMAKE_BUILD_TYPE", default = "Release" } MLIR_ENABLE_BINDINGS_PYTHON = "ON" + # Effectively non-optional (any downstream project should specify this). +MLIR_BINDINGS_PYTHON_NB_DOMAIN = "mlir_standalone" MLIR_PYTHON_PACKAGE_PREFIX = "mlir_standalone" + # This specifies the directory in the install directory (i.e., /tmp/pip-wheel/platlib) where _mlir_libs, dialects, etc. # are installed. Thus, this will be the package location (and the name of the package) that pip assumes is # the root package. diff --git a/mlir/examples/standalone/test/python/smoketest.py b/mlir/examples/standalone/test/python/smoketest.py index 9c0ada92551af..ec75790fffeb4 100644 --- a/mlir/examples/standalone/test/python/smoketest.py +++ b/mlir/examples/standalone/test/python/smoketest.py @@ -1,20 +1,7 @@ # RUN: %python %s nanobind | FileCheck %s -from mlir_standalone.ir import * -from mlir_standalone.dialects import standalone_nanobind as standalone_d -with Context(): - standalone_d.register_dialects() - module = Module.parse( - """ - %0 = arith.constant 2 : i32 - %1 = standalone.foo %0 : i32 - """ - ) - # CHECK: %[[C:.*]] = arith.constant 2 : i32 - # CHECK: standalone.foo %[[C]] : i32 - print(str(module)) - custom_type = standalone_d.CustomType.get("foo") - # CHECK: !standalone.custom<"foo"> - print(custom_type) +import mlir_standalone.ir + +import mlir.ir diff --git a/mlir/include/mlir/Bindings/Python/Globals.h b/mlir/include/mlir/Bindings/Python/Globals.h index 112c7b9b0547f..d9334cb35cc27 100644 --- a/mlir/include/mlir/Bindings/Python/Globals.h +++ b/mlir/include/mlir/Bindings/Python/Globals.h @@ -174,8 +174,6 @@ class MLIR_PYTHON_API_EXPORTED PyGlobals { MlirTypeID allocateTypeID() { return typeIDAllocator.allocate(); } private: - static PyGlobals *instance; - nanobind::ft_mutex mutex; /// Module name prefixes to search under for dialect implementation modules. diff --git a/mlir/lib/Bindings/Python/Globals.cpp b/mlir/lib/Bindings/Python/Globals.cpp index ecac571a132f6..7e451c8009809 100644 --- a/mlir/lib/Bindings/Python/Globals.cpp +++ b/mlir/lib/Bindings/Python/Globals.cpp @@ -19,6 +19,8 @@ #include "mlir-c/Support.h" #include "mlir/Bindings/Python/Nanobind.h" +#include <iostream> + namespace nb = nanobind; using namespace mlir; @@ -26,22 +28,26 @@ using namespace mlir; // PyGlobals // ----------------------------------------------------------------------------- +namespace { +python::PyGlobals *pyGlobalsInstance = nullptr; +} + namespace mlir::python { -PyGlobals *PyGlobals::instance = nullptr; PyGlobals::PyGlobals() { - assert(!instance && "PyGlobals already constructed"); - instance = this; + std::cerr << MAKE_MLIR_PYTHON_QUALNAME("dialects") << "\n"; + assert(!pyGlobalsInstance && "PyGlobals already constructed"); + pyGlobalsInstance = this; // The default search path include {mlir.}dialects, where {mlir.} is the // package prefix configured at compile time. dialectSearchPrefixes.emplace_back(MAKE_MLIR_PYTHON_QUALNAME("dialects")); } -PyGlobals::~PyGlobals() { instance = nullptr; } +PyGlobals::~PyGlobals() { pyGlobalsInstance = nullptr; } PyGlobals &PyGlobals::get() { - assert(instance && "PyGlobals is null"); - return *instance; + assert(pyGlobalsInstance && "PyGlobals is null"); + return *pyGlobalsInstance; } bool PyGlobals::loadDialectModule(llvm::StringRef dialectNamespace) { diff --git a/mlir/test/Examples/standalone/test.wheel.toy b/mlir/test/Examples/standalone/test.wheel.toy index c8d188a3cacd0..55847f7430648 100644 --- a/mlir/test/Examples/standalone/test.wheel.toy +++ b/mlir/test/Examples/standalone/test.wheel.toy @@ -1,10 +1,6 @@ # There's no real issue with windows here, it's just that some CMake generated paths for targets end up being longer # than 255 chars when combined with the fact that pip wants to install into a tmp directory buried under # C/Users/ContainerAdministrator/AppData/Local/Temp. -# UNSUPPORTED: target={{.*(windows).*}} -# REQUIRES: expensive_checks -# REQUIRES: non-shared-libs-build -# REQUIRES: bindings-python # RUN: export CMAKE_BUILD_TYPE=%cmake_build_type # RUN: export CMAKE_CXX_COMPILER=%host_cxx @@ -15,7 +11,8 @@ # RUN: export LLVM_USE_LINKER=%llvm_use_linker # RUN: export MLIR_DIR="%mlir_cmake_dir" -# RUN: %python -m pip wheel "%mlir_src_root/examples/standalone" -w "%mlir_obj_root/wheelhouse" -v | tee %t +# RUN: %python -m pip install scikit-build-core +# RUN: %python -m pip wheel "%mlir_src_root/examples/standalone" -w "%mlir_obj_root/wheelhouse" -v --no-build-isolation | tee %t # RUN: rm -rf "%mlir_obj_root/standalone-python-bindings-install" # RUN: %python -m pip install standalone_python_bindings -f "%mlir_obj_root/wheelhouse" --target "%mlir_obj_root/standalone-python-bindings-install" -v | tee -a %t >From cf6a8251b852c5c03b47ef0b432c0f6b6a5a2a9a Mon Sep 17 00:00:00 2001 From: makslevental <[email protected]> Date: Tue, 23 Dec 2025 17:00:17 -0800 Subject: [PATCH 3/3] works --- .../examples/standalone/python/CMakeLists.txt | 1 + .../python/StandaloneExtensionNanobind.cpp | 6 +- .../standalone/test/python/smoketest.py | 21 ++- mlir/include/mlir/Bindings/Python/Globals.h | 5 +- mlir/include/mlir/Bindings/Python/IRCore.h | 43 ++++-- mlir/include/mlir/Bindings/Python/IRTypes.h | 8 +- mlir/lib/Bindings/Python/Globals.cpp | 26 ++-- mlir/lib/Bindings/Python/IRAffine.cpp | 34 +++-- mlir/lib/Bindings/Python/IRAttributes.cpp | 18 ++- mlir/lib/Bindings/Python/IRCore.cpp | 28 ++-- mlir/lib/Bindings/Python/IRInterfaces.cpp | 4 +- mlir/lib/Bindings/Python/IRTypes.cpp | 37 +++-- mlir/lib/Bindings/Python/MainModule.cpp | 133 ++++++++++-------- mlir/lib/Bindings/Python/Pass.cpp | 39 +++-- mlir/lib/Bindings/Python/Pass.h | 3 +- mlir/lib/Bindings/Python/Rewrite.cpp | 43 +++--- mlir/lib/Bindings/Python/Rewrite.h | 4 +- mlir/python/CMakeLists.txt | 1 + mlir/test/Examples/standalone/test.wheel.toy | 14 +- .../python/lib/PythonTestModuleNanobind.cpp | 13 +- 20 files changed, 303 insertions(+), 178 deletions(-) diff --git a/mlir/examples/standalone/python/CMakeLists.txt b/mlir/examples/standalone/python/CMakeLists.txt index edaedf18cc843..d3b3aeadb6396 100644 --- a/mlir/examples/standalone/python/CMakeLists.txt +++ b/mlir/examples/standalone/python/CMakeLists.txt @@ -3,6 +3,7 @@ include(AddMLIRPython) # Specifies that all MLIR packages are co-located under the `mlir_standalone` # top level package (the API has been embedded in a relocatable way). add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=${MLIR_PYTHON_PACKAGE_PREFIX}.") +add_compile_definitions("MLIR_BINDINGS_PYTHON_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN}") ################################################################################ diff --git a/mlir/examples/standalone/python/StandaloneExtensionNanobind.cpp b/mlir/examples/standalone/python/StandaloneExtensionNanobind.cpp index 37737cd89ee1e..c568369913595 100644 --- a/mlir/examples/standalone/python/StandaloneExtensionNanobind.cpp +++ b/mlir/examples/standalone/python/StandaloneExtensionNanobind.cpp @@ -17,7 +17,8 @@ namespace nb = nanobind; -struct PyCustomType : mlir::python::PyConcreteType<PyCustomType> { +struct PyCustomType + : mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::PyConcreteType<PyCustomType> { static constexpr IsAFunctionTy isaFunction = mlirStandaloneTypeIsACustomType; static constexpr GetTypeIDFunctionTy getTypeIdFunction = mlirStandaloneCustomTypeGetTypeID; @@ -28,7 +29,8 @@ struct PyCustomType : mlir::python::PyConcreteType<PyCustomType> { c.def_static( "get", [](const std::string &value, - mlir::python::DefaultingPyMlirContext context) { + mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext + context) { return PyCustomType( context->getRef(), mlirStandaloneCustomTypeGet( diff --git a/mlir/examples/standalone/test/python/smoketest.py b/mlir/examples/standalone/test/python/smoketest.py index ec75790fffeb4..9132bab75cfcc 100644 --- a/mlir/examples/standalone/test/python/smoketest.py +++ b/mlir/examples/standalone/test/python/smoketest.py @@ -1,7 +1,24 @@ # RUN: %python %s nanobind | FileCheck %s +import sys +from mlir_standalone.ir import * +from mlir_standalone.dialects import standalone_nanobind as standalone_d +with Context(): + standalone_d.register_dialects() + module = Module.parse( + """ + %0 = arith.constant 2 : i32 + %1 = standalone.foo %0 : i32 + """ + ) + # CHECK: %[[C:.*]] = arith.constant 2 : i32 + # CHECK: standalone.foo %[[C]] : i32 + print(str(module)) -import mlir_standalone.ir + custom_type = standalone_d.CustomType.get("foo") + # CHECK: !standalone.custom<"foo"> + print(custom_type) -import mlir.ir +if sys.argv[1] == "test-upstream": + from mlir.ir import * diff --git a/mlir/include/mlir/Bindings/Python/Globals.h b/mlir/include/mlir/Bindings/Python/Globals.h index d9334cb35cc27..5548a716cbe21 100644 --- a/mlir/include/mlir/Bindings/Python/Globals.h +++ b/mlir/include/mlir/Bindings/Python/Globals.h @@ -28,7 +28,7 @@ namespace mlir { namespace python { - +namespace MLIR_BINDINGS_PYTHON_DOMAIN { /// Globals that are always accessible once the extension has been initialized. /// Methods of this class are thread-safe. class MLIR_PYTHON_API_EXPORTED PyGlobals { @@ -174,6 +174,8 @@ class MLIR_PYTHON_API_EXPORTED PyGlobals { MlirTypeID allocateTypeID() { return typeIDAllocator.allocate(); } private: + static PyGlobals *instance; + nanobind::ft_mutex mutex; /// Module name prefixes to search under for dialect implementation modules. @@ -195,6 +197,7 @@ class MLIR_PYTHON_API_EXPORTED PyGlobals { TracebackLoc tracebackLoc; TypeIDAllocator typeIDAllocator; }; +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN } // namespace python } // namespace mlir diff --git a/mlir/include/mlir/Bindings/Python/IRCore.h b/mlir/include/mlir/Bindings/Python/IRCore.h index ceedeb691eb58..7ed0a9f63bfda 100644 --- a/mlir/include/mlir/Bindings/Python/IRCore.h +++ b/mlir/include/mlir/Bindings/Python/IRCore.h @@ -33,6 +33,7 @@ namespace mlir { namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { class PyBlock; class PyDiagnostic; @@ -325,6 +326,26 @@ class MLIR_PYTHON_API_EXPORTED PyLocation : public BaseContextObject { MlirLocation loc; }; +enum PyMlirDiagnosticSeverity : std::underlying_type< + MlirDiagnosticSeverity>::type { + MlirDiagnosticError = MlirDiagnosticError, + MlirDiagnosticWarning = MlirDiagnosticWarning, + MlirDiagnosticNote = MlirDiagnosticNote, + MlirDiagnosticRemark = MlirDiagnosticRemark +}; + +enum PyMlirWalkResult : std::underlying_type<MlirWalkResult>::type { + MlirWalkResultAdvance = MlirWalkResultAdvance, + MlirWalkResultInterrupt = MlirWalkResultInterrupt, + MlirWalkResultSkip = MlirWalkResultSkip +}; + +/// Traversal order for operation walk. +enum PyMlirWalkOrder : std::underlying_type<MlirWalkOrder>::type { + MlirWalkPreOrder = MlirWalkPreOrder, + MlirWalkPostOrder = MlirWalkPostOrder +}; + /// Python class mirroring the C MlirDiagnostic struct. Note that these structs /// are only valid for the duration of a diagnostic callback and attempting /// to access them outside of that will raise an exception. This applies to @@ -334,7 +355,7 @@ class MLIR_PYTHON_API_EXPORTED PyDiagnostic { PyDiagnostic(MlirDiagnostic diagnostic) : diagnostic(diagnostic) {} void invalidate(); bool isValid() { return valid; } - MlirDiagnosticSeverity getSeverity(); + PyMlirDiagnosticSeverity getSeverity(); PyLocation getLocation(); nanobind::str getMessage(); nanobind::tuple getNotes(); @@ -342,7 +363,7 @@ class MLIR_PYTHON_API_EXPORTED PyDiagnostic { /// Materialized diagnostic information. This is safe to access outside the /// diagnostic callback. struct DiagnosticInfo { - MlirDiagnosticSeverity severity; + PyMlirDiagnosticSeverity severity; PyLocation location; std::string message; std::vector<DiagnosticInfo> notes; @@ -573,8 +594,8 @@ class MLIR_PYTHON_API_EXPORTED PyOperationBase { std::optional<int64_t> bytecodeVersion); // Implement the walk method. - void walk(std::function<MlirWalkResult(MlirOperation)> callback, - MlirWalkOrder walkOrder); + void walk(std::function<PyMlirWalkResult(MlirOperation)> callback, + PyMlirWalkOrder walkOrder); /// Moves the operation before or after the other operation. void moveAfter(PyOperationBase &other); @@ -2364,6 +2385,7 @@ class MLIR_PYTHON_API_EXPORTED PyOpAttributeMap { }; MLIR_PYTHON_API_EXPORTED MlirValue getUniqueResult(MlirOperation operation); +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN } // namespace python } // namespace mlir @@ -2371,11 +2393,16 @@ namespace nanobind { namespace detail { template <> -struct type_caster<mlir::python::DefaultingPyMlirContext> - : MlirDefaultingCaster<mlir::python::DefaultingPyMlirContext> {}; +struct type_caster< + mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext> + : MlirDefaultingCaster< + mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext> { +}; template <> -struct type_caster<mlir::python::DefaultingPyLocation> - : MlirDefaultingCaster<mlir::python::DefaultingPyLocation> {}; +struct type_caster< + mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyLocation> + : MlirDefaultingCaster< + mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyLocation> {}; } // namespace detail } // namespace nanobind diff --git a/mlir/include/mlir/Bindings/Python/IRTypes.h b/mlir/include/mlir/Bindings/Python/IRTypes.h index cd0cfbc7d61d8..87e0e10764bd8 100644 --- a/mlir/include/mlir/Bindings/Python/IRTypes.h +++ b/mlir/include/mlir/Bindings/Python/IRTypes.h @@ -12,10 +12,11 @@ #include "mlir/Bindings/Python/NanobindAdaptors.h" namespace mlir { - +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { /// Shaped Type Interface - ShapedType class MLIR_PYTHON_API_EXPORTED PyShapedType - : public python::PyConcreteType<PyShapedType> { + : public PyConcreteType<PyShapedType> { public: static const IsAFunctionTy isaFunction; static constexpr const char *pyClassName = "ShapedType"; @@ -26,7 +27,8 @@ class MLIR_PYTHON_API_EXPORTED PyShapedType private: void requireHasRank(); }; - +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python } // namespace mlir #endif // MLIR_BINDINGS_PYTHON_IRTYPES_H diff --git a/mlir/lib/Bindings/Python/Globals.cpp b/mlir/lib/Bindings/Python/Globals.cpp index 7e451c8009809..e2e8693ba45f3 100644 --- a/mlir/lib/Bindings/Python/Globals.cpp +++ b/mlir/lib/Bindings/Python/Globals.cpp @@ -19,8 +19,6 @@ #include "mlir-c/Support.h" #include "mlir/Bindings/Python/Nanobind.h" -#include <iostream> - namespace nb = nanobind; using namespace mlir; @@ -28,26 +26,24 @@ using namespace mlir; // PyGlobals // ----------------------------------------------------------------------------- -namespace { -python::PyGlobals *pyGlobalsInstance = nullptr; -} - -namespace mlir::python { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { +PyGlobals *PyGlobals::instance = nullptr; PyGlobals::PyGlobals() { - std::cerr << MAKE_MLIR_PYTHON_QUALNAME("dialects") << "\n"; - assert(!pyGlobalsInstance && "PyGlobals already constructed"); - pyGlobalsInstance = this; + assert(!instance && "PyGlobals already constructed"); + instance = this; // The default search path include {mlir.}dialects, where {mlir.} is the // package prefix configured at compile time. dialectSearchPrefixes.emplace_back(MAKE_MLIR_PYTHON_QUALNAME("dialects")); } -PyGlobals::~PyGlobals() { pyGlobalsInstance = nullptr; } +PyGlobals::~PyGlobals() { instance = nullptr; } PyGlobals &PyGlobals::get() { - assert(pyGlobalsInstance && "PyGlobals is null"); - return *pyGlobalsInstance; + assert(instance && "PyGlobals is null"); + return *instance; } bool PyGlobals::loadDialectModule(llvm::StringRef dialectNamespace) { @@ -278,4 +274,6 @@ bool PyGlobals::TracebackLoc::isUserTracebackFilename( } return isUserTracebackFilenameCache[file]; } -} // namespace mlir::python +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir diff --git a/mlir/lib/Bindings/Python/IRAffine.cpp b/mlir/lib/Bindings/Python/IRAffine.cpp index 624d8f0fa57ce..ce235470bbdc7 100644 --- a/mlir/lib/Bindings/Python/IRAffine.cpp +++ b/mlir/lib/Bindings/Python/IRAffine.cpp @@ -30,7 +30,7 @@ namespace nb = nanobind; using namespace mlir; -using namespace mlir::python; +using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN; using llvm::SmallVector; using llvm::StringRef; @@ -80,7 +80,9 @@ static bool isPermutation(const std::vector<PermutationTy> &permutation) { return true; } -namespace { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { /// CRTP base class for Python MLIR affine expressions that subclass AffineExpr /// and should be castable from it. Intermediate hierarchy classes can be @@ -358,7 +360,9 @@ class PyAffineCeilDivExpr } }; -} // namespace +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir bool PyAffineExpr::operator==(const PyAffineExpr &other) const { return mlirAffineExprEqual(affineExpr, other.affineExpr); @@ -380,7 +384,9 @@ PyAffineExpr PyAffineExpr::createFromCapsule(const nb::object &capsule) { //------------------------------------------------------------------------------ // PyAffineMap and utilities. //------------------------------------------------------------------------------ -namespace { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { /// A list of expressions contained in an affine map. Internally these are /// stored as a consecutive array leading to inexpensive random access. Both @@ -416,7 +422,9 @@ class PyAffineMapExprList PyAffineMap affineMap; }; -} // namespace +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir bool PyAffineMap::operator==(const PyAffineMap &other) const { return mlirAffineMapEqual(affineMap, other.affineMap); @@ -438,7 +446,9 @@ PyAffineMap PyAffineMap::createFromCapsule(const nb::object &capsule) { //------------------------------------------------------------------------------ // PyIntegerSet and utilities. //------------------------------------------------------------------------------ -namespace { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { class PyIntegerSetConstraint { public: @@ -492,7 +502,9 @@ class PyIntegerSetConstraintList PyIntegerSet set; }; -} // namespace +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir bool PyIntegerSet::operator==(const PyIntegerSet &other) const { return mlirIntegerSetEqual(integerSet, other.integerSet); @@ -511,7 +523,9 @@ PyIntegerSet PyIntegerSet::createFromCapsule(const nb::object &capsule) { rawIntegerSet); } -namespace mlir::python { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { void populateIRAffine(nb::module_ &m) { //---------------------------------------------------------------------------- // Mapping of PyAffineExpr and derived classes. @@ -998,4 +1012,6 @@ void populateIRAffine(nb::module_ &m) { PyIntegerSetConstraint::bind(m); PyIntegerSetConstraintList::bind(m); } -} // namespace mlir::python +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir diff --git a/mlir/lib/Bindings/Python/IRAttributes.cpp b/mlir/lib/Bindings/Python/IRAttributes.cpp index e39eabdb136b8..a4d308bf049d8 100644 --- a/mlir/lib/Bindings/Python/IRAttributes.cpp +++ b/mlir/lib/Bindings/Python/IRAttributes.cpp @@ -24,7 +24,7 @@ namespace nb = nanobind; using namespace nanobind::literals; using namespace mlir; -using namespace mlir::python; +using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN; using llvm::SmallVector; @@ -121,7 +121,9 @@ subsequent processing. type or if the buffer does not meet expectations. )"; -namespace { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { struct nb_buffer_info { void *ptr = nullptr; @@ -1745,7 +1747,9 @@ nb::object symbolRefOrFlatSymbolRefAttributeCaster(PyAttribute &pyAttribute) { throw nb::type_error(msg.c_str()); } -} // namespace +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir void PyStringAttribute::bindDerived(ClassTy &c) { c.def_static( @@ -1791,7 +1795,9 @@ void PyStringAttribute::bindDerived(ClassTy &c) { "Returns the value of the string attribute as `bytes`"); } -namespace mlir::python { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { void populateIRAttributes(nb::module_ &m) { PyAffineMapAttribute::bind(m); PyDenseBoolArrayAttribute::bind(m); @@ -1846,4 +1852,6 @@ void populateIRAttributes(nb::module_ &m) { PyStridedLayoutAttribute::bind(m); registerMLIRError(); } -} // namespace mlir::python +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir diff --git a/mlir/lib/Bindings/Python/IRCore.cpp b/mlir/lib/Bindings/Python/IRCore.cpp index fc8743599508d..069e177708afc 100644 --- a/mlir/lib/Bindings/Python/IRCore.cpp +++ b/mlir/lib/Bindings/Python/IRCore.cpp @@ -31,13 +31,14 @@ namespace nb = nanobind; using namespace nb::literals; using namespace mlir; -using namespace mlir::python; using llvm::SmallVector; using llvm::StringRef; using llvm::Twine; -namespace mlir::python { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { //------------------------------------------------------------------------------ // PyMlirContext //------------------------------------------------------------------------------ @@ -169,7 +170,8 @@ MlirLogicalResult PyMlirContext::ErrorCapture::handler(MlirDiagnostic diag, if (self->ctx->emitErrorDiagnostics) return mlirLogicalResultFailure(); - if (mlirDiagnosticGetSeverity(diag) != MlirDiagnosticError) + if (mlirDiagnosticGetSeverity(diag) != + MlirDiagnosticSeverity::MlirDiagnosticError) return mlirLogicalResultFailure(); self->errors.emplace_back(PyDiagnostic(diag).getInfo()); @@ -356,9 +358,10 @@ void PyDiagnostic::checkValid() { } } -MlirDiagnosticSeverity PyDiagnostic::getSeverity() { +PyMlirDiagnosticSeverity PyDiagnostic::getSeverity() { checkValid(); - return mlirDiagnosticGetSeverity(diagnostic); + return static_cast<PyMlirDiagnosticSeverity>( + mlirDiagnosticGetSeverity(diagnostic)); } PyLocation PyDiagnostic::getLocation() { @@ -672,12 +675,12 @@ void PyOperationBase::writeBytecode(const nb::object &fileOrStringObject, } void PyOperationBase::walk( - std::function<MlirWalkResult(MlirOperation)> callback, - MlirWalkOrder walkOrder) { + std::function<PyMlirWalkResult(MlirOperation)> callback, + PyMlirWalkOrder walkOrder) { PyOperation &operation = getOperation(); operation.checkValid(); struct UserData { - std::function<MlirWalkResult(MlirOperation)> callback; + std::function<PyMlirWalkResult(MlirOperation)> callback; bool gotException; std::string exceptionWhat; nb::object exceptionType; @@ -687,7 +690,7 @@ void PyOperationBase::walk( void *userData) { UserData *calleeUserData = static_cast<UserData *>(userData); try { - return (calleeUserData->callback)(op); + return static_cast<MlirWalkResult>((calleeUserData->callback)(op)); } catch (nb::python_error &e) { calleeUserData->gotException = true; calleeUserData->exceptionWhat = std::string(e.what()); @@ -695,7 +698,8 @@ void PyOperationBase::walk( return MlirWalkResult::MlirWalkResultInterrupt; } }; - mlirOperationWalk(operation, walkCallback, &userData, walkOrder); + mlirOperationWalk(operation, walkCallback, &userData, + static_cast<MlirWalkOrder>(walkOrder)); if (userData.gotException) { std::string message("Exception raised in callback: "); message.append(userData.exceptionWhat); @@ -1685,4 +1689,6 @@ void registerMLIRErrorInCore() { } }); } -} // namespace mlir::python +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir diff --git a/mlir/lib/Bindings/Python/IRInterfaces.cpp b/mlir/lib/Bindings/Python/IRInterfaces.cpp index 78d1f977b2ebc..09112d4989ae4 100644 --- a/mlir/lib/Bindings/Python/IRInterfaces.cpp +++ b/mlir/lib/Bindings/Python/IRInterfaces.cpp @@ -25,7 +25,7 @@ namespace nb = nanobind; namespace mlir { namespace python { - +namespace MLIR_BINDINGS_PYTHON_DOMAIN { constexpr static const char *constructorDoc = R"(Creates an interface from a given operation/opview object or from a subclass of OpView. Raises ValueError if the operation does not implement the @@ -469,6 +469,6 @@ void populateIRInterfaces(nb::module_ &m) { PyShapedTypeComponents::bind(m); PyInferShapedTypeOpInterface::bind(m); } - +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN } // namespace python } // namespace mlir diff --git a/mlir/lib/Bindings/Python/IRTypes.cpp b/mlir/lib/Bindings/Python/IRTypes.cpp index 7d9a0f16c913a..62fb2ef207d58 100644 --- a/mlir/lib/Bindings/Python/IRTypes.cpp +++ b/mlir/lib/Bindings/Python/IRTypes.cpp @@ -20,12 +20,14 @@ namespace nb = nanobind; using namespace mlir; -using namespace mlir::python; +using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN; using llvm::SmallVector; using llvm::Twine; -namespace { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { /// Checks whether the given type is an integer or float type. static int mlirTypeIsAIntegerOrFloat(MlirType type) { @@ -508,10 +510,12 @@ class PyComplexType : public PyConcreteType<PyComplexType> { } }; -} // namespace +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir // Shaped Type Interface - ShapedType -void mlir::PyShapedType::bindDerived(ClassTy &c) { +void PyShapedType::bindDerived(ClassTy &c) { c.def_prop_ro( "element_type", [](PyShapedType &self) -> nb::typed<nb::object, PyType> { @@ -616,17 +620,18 @@ void mlir::PyShapedType::bindDerived(ClassTy &c) { "shaped types."); } -void mlir::PyShapedType::requireHasRank() { +void PyShapedType::requireHasRank() { if (!mlirShapedTypeHasRank(*this)) { throw nb::value_error( "calling this method requires that the type has a rank."); } } -const mlir::PyShapedType::IsAFunctionTy mlir::PyShapedType::isaFunction = - mlirTypeIsAShaped; +const PyShapedType::IsAFunctionTy PyShapedType::isaFunction = mlirTypeIsAShaped; -namespace { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { /// Vector Type subclass - VectorType. class PyVectorType : public PyConcreteType<PyVectorType, PyShapedType> { @@ -1098,10 +1103,6 @@ class PyFunctionType : public PyConcreteType<PyFunctionType> { } }; -static MlirStringRef toMlirStringRef(const std::string &s) { - return mlirStringRefCreate(s.data(), s.size()); -} - /// Opaque Type subclass - OpaqueType. class PyOpaqueType : public PyConcreteType<PyOpaqueType> { public: @@ -1141,9 +1142,13 @@ class PyOpaqueType : public PyConcreteType<PyOpaqueType> { } }; -} // namespace +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir -namespace mlir::python { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { void populateIRTypes(nb::module_ &m) { PyIntegerType::bind(m); PyFloatType::bind(m); @@ -1177,4 +1182,6 @@ void populateIRTypes(nb::module_ &m) { PyOpaqueType::bind(m); registerMLIRError(); } -} // namespace mlir::python +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir diff --git a/mlir/lib/Bindings/Python/MainModule.cpp b/mlir/lib/Bindings/Python/MainModule.cpp index f72775cc0b83a..392144ec5f0b7 100644 --- a/mlir/lib/Bindings/Python/MainModule.cpp +++ b/mlir/lib/Bindings/Python/MainModule.cpp @@ -16,7 +16,7 @@ namespace nb = nanobind; using namespace mlir; using namespace nb::literals; -using namespace mlir::python; +using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN; static const char kModuleParseDocstring[] = R"(Parses a module's assembly format from a string. @@ -35,6 +35,56 @@ in `exceptions`. `exceptions` can be either a single operation or a list of operations. )"; +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { +/// Wrapper for the global LLVM debugging flag. +struct PyGlobalDebugFlag { + static void set(nanobind::object &o, bool enable) { + nanobind::ft_lock_guard lock(mutex); + mlirEnableGlobalDebug(enable); + } + + static bool get(const nanobind::object &) { + nanobind::ft_lock_guard lock(mutex); + return mlirIsGlobalDebugEnabled(); + } + + static void bind(nanobind::module_ &m) { + // Debug flags. + nanobind::class_<PyGlobalDebugFlag>(m, "_GlobalDebug") + .def_prop_rw_static("flag", &PyGlobalDebugFlag::get, + &PyGlobalDebugFlag::set, "LLVM-wide debug flag.") + .def_static( + "set_types", + [](const std::string &type) { + nanobind::ft_lock_guard lock(mutex); + mlirSetGlobalDebugType(type.c_str()); + }, + nanobind::arg("types"), + "Sets specific debug types to be produced by LLVM.") + .def_static( + "set_types", + [](const std::vector<std::string> &types) { + std::vector<const char *> pointers; + pointers.reserve(types.size()); + for (const std::string &str : types) + pointers.push_back(str.c_str()); + nanobind::ft_lock_guard lock(mutex); + mlirSetGlobalDebugTypes(pointers.data(), pointers.size()); + }, + nanobind::arg("types"), + "Sets multiple specific debug types to be produced by LLVM."); + } + +private: + static nanobind::ft_mutex mutex; +}; +nanobind::ft_mutex PyGlobalDebugFlag::mutex; +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir + namespace { // see // https://raw.githubusercontent.com/python/pythoncapi_compat/master/pythoncapi_compat.h @@ -185,51 +235,6 @@ maybeGetTracebackLocation(const std::optional<PyLocation> &location) { PyMlirContextRef ref = PyMlirContext::forContext(ctx.get()); return {ref, mlirLoc}; } - -/// Wrapper for the global LLVM debugging flag. -struct PyGlobalDebugFlag { - static void set(nanobind::object &o, bool enable) { - nanobind::ft_lock_guard lock(mutex); - mlirEnableGlobalDebug(enable); - } - - static bool get(const nanobind::object &) { - nanobind::ft_lock_guard lock(mutex); - return mlirIsGlobalDebugEnabled(); - } - - static void bind(nanobind::module_ &m) { - // Debug flags. - nanobind::class_<PyGlobalDebugFlag>(m, "_GlobalDebug") - .def_prop_rw_static("flag", &PyGlobalDebugFlag::get, - &PyGlobalDebugFlag::set, "LLVM-wide debug flag.") - .def_static( - "set_types", - [](const std::string &type) { - nanobind::ft_lock_guard lock(mutex); - mlirSetGlobalDebugType(type.c_str()); - }, - nanobind::arg("types"), - "Sets specific debug types to be produced by LLVM.") - .def_static( - "set_types", - [](const std::vector<std::string> &types) { - std::vector<const char *> pointers; - pointers.reserve(types.size()); - for (const std::string &str : types) - pointers.push_back(str.c_str()); - nanobind::ft_lock_guard lock(mutex); - mlirSetGlobalDebugTypes(pointers.data(), pointers.size()); - }, - nanobind::arg("types"), - "Sets multiple specific debug types to be produced by LLVM."); - } - -private: - static nanobind::ft_mutex mutex; -}; - -nanobind::ft_mutex PyGlobalDebugFlag::mutex; } // namespace //------------------------------------------------------------------------------ @@ -242,20 +247,20 @@ static void populateIRCore(nb::module_ &m) { //---------------------------------------------------------------------------- // Enums. //---------------------------------------------------------------------------- - nb::enum_<MlirDiagnosticSeverity>(m, "DiagnosticSeverity") - .value("ERROR", MlirDiagnosticError) - .value("WARNING", MlirDiagnosticWarning) - .value("NOTE", MlirDiagnosticNote) - .value("REMARK", MlirDiagnosticRemark); + nb::enum_<PyMlirDiagnosticSeverity>(m, "DiagnosticSeverity") + .value("ERROR", PyMlirDiagnosticSeverity::MlirDiagnosticError) + .value("WARNING", PyMlirDiagnosticSeverity::MlirDiagnosticWarning) + .value("NOTE", PyMlirDiagnosticSeverity::MlirDiagnosticNote) + .value("REMARK", PyMlirDiagnosticSeverity::MlirDiagnosticRemark); - nb::enum_<MlirWalkOrder>(m, "WalkOrder") - .value("PRE_ORDER", MlirWalkPreOrder) - .value("POST_ORDER", MlirWalkPostOrder); + nb::enum_<PyMlirWalkOrder>(m, "WalkOrder") + .value("PRE_ORDER", PyMlirWalkOrder::MlirWalkPreOrder) + .value("POST_ORDER", PyMlirWalkOrder::MlirWalkPostOrder); - nb::enum_<MlirWalkResult>(m, "WalkResult") - .value("ADVANCE", MlirWalkResultAdvance) - .value("INTERRUPT", MlirWalkResultInterrupt) - .value("SKIP", MlirWalkResultSkip); + nb::enum_<PyMlirWalkResult>(m, "WalkResult") + .value("ADVANCE", PyMlirWalkResult::MlirWalkResultAdvance) + .value("INTERRUPT", PyMlirWalkResult::MlirWalkResultInterrupt) + .value("SKIP", PyMlirWalkResult::MlirWalkResultSkip); //---------------------------------------------------------------------------- // Mapping of Diagnostics. @@ -1186,7 +1191,7 @@ static void populateIRCore(nb::module_ &m) { Note: After erasing, any Python references to the operation become invalid.)") .def("walk", &PyOperationBase::walk, nb::arg("callback"), - nb::arg("walk_order") = MlirWalkPostOrder, + nb::arg("walk_order") = PyMlirWalkOrder::MlirWalkPostOrder, // clang-format off nb::sig("def walk(self, callback: Callable[[Operation], WalkResult], walk_order: WalkOrder) -> None"), // clang-format on @@ -2305,12 +2310,16 @@ static void populateIRCore(nb::module_ &m) { PyAttrBuilderMap::bind(m); } -namespace mlir::python { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { void populateIRAffine(nb::module_ &m); void populateIRAttributes(nb::module_ &m); void populateIRInterfaces(nb::module_ &m); void populateIRTypes(nb::module_ &m); -} // namespace mlir::python +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir // ----------------------------------------------------------------------------- // Module initialization. @@ -2453,5 +2462,5 @@ NB_MODULE(_mlir, m) { m.def_submodule("passmanager", "MLIR Pass Management Bindings"); populatePassManagerSubmodule(passManagerModule); registerMLIRError(); - registerMLIRErrorInCore(); + // registerMLIRErrorInCore(); } diff --git a/mlir/lib/Bindings/Python/Pass.cpp b/mlir/lib/Bindings/Python/Pass.cpp index 3cfdfe49b4e3e..e35923553e0a1 100644 --- a/mlir/lib/Bindings/Python/Pass.cpp +++ b/mlir/lib/Bindings/Python/Pass.cpp @@ -19,9 +19,11 @@ namespace nb = nanobind; using namespace nb::literals; using namespace mlir; -using namespace mlir::python; +using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN; -namespace { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { /// Owning Wrapper around a PassManager. class PyPassManager { @@ -53,23 +55,29 @@ class PyPassManager { MlirPassManager passManager; }; -} // namespace +enum PyMlirPassDisplayMode : std::underlying_type<MlirPassDisplayMode>::type { + MLIR_PASS_DISPLAY_MODE_LIST = MLIR_PASS_DISPLAY_MODE_LIST, + MLIR_PASS_DISPLAY_MODE_PIPELINE = MLIR_PASS_DISPLAY_MODE_PIPELINE +}; + +struct PyMlirExternalPass : MlirExternalPass {}; /// Create the `mlir.passmanager` here. -void mlir::python::populatePassManagerSubmodule(nb::module_ &m) { +void populatePassManagerSubmodule(nb::module_ &m) { //---------------------------------------------------------------------------- // Mapping of enumerated types //---------------------------------------------------------------------------- - nb::enum_<MlirPassDisplayMode>(m, "PassDisplayMode") + nb::enum_<PyMlirPassDisplayMode>(m, "PassDisplayMode") .value("LIST", MLIR_PASS_DISPLAY_MODE_LIST) .value("PIPELINE", MLIR_PASS_DISPLAY_MODE_PIPELINE); //---------------------------------------------------------------------------- // Mapping of MlirExternalPass //---------------------------------------------------------------------------- - nb::class_<MlirExternalPass>(m, "ExternalPass") - .def("signal_pass_failure", - [](MlirExternalPass pass) { mlirExternalPassSignalFailure(pass); }); + nb::class_<PyMlirExternalPass>(m, "ExternalPass") + .def("signal_pass_failure", [](PyMlirExternalPass pass) { + mlirExternalPassSignalFailure(pass); + }); //---------------------------------------------------------------------------- // Mapping of the top-level PassManager @@ -148,11 +156,12 @@ void mlir::python::populatePassManagerSubmodule(nb::module_ &m) { "Enable pass timing.") .def( "enable_statistics", - [](PyPassManager &passManager, MlirPassDisplayMode displayMode) { - mlirPassManagerEnableStatistics(passManager.get(), displayMode); + [](PyPassManager &passManager, PyMlirPassDisplayMode displayMode) { + mlirPassManagerEnableStatistics( + passManager.get(), + static_cast<MlirPassDisplayMode>(displayMode)); }, - "displayMode"_a = - MlirPassDisplayMode::MLIR_PASS_DISPLAY_MODE_PIPELINE, + "displayMode"_a = MLIR_PASS_DISPLAY_MODE_PIPELINE, "Enable pass statistics.") .def_static( "parse", @@ -211,7 +220,8 @@ void mlir::python::populatePassManagerSubmodule(nb::module_ &m) { }; callbacks.run = [](MlirOperation op, MlirExternalPass pass, void *userData) { - nb::handle(static_cast<PyObject *>(userData))(op, pass); + nb::handle(static_cast<PyObject *>(userData))( + op, PyMlirExternalPass{pass.ptr}); }; auto externalPass = mlirCreateExternalPass( passID, mlirStringRefCreate(name->data(), name->length()), @@ -256,3 +266,6 @@ void mlir::python::populatePassManagerSubmodule(nb::module_ &m) { "be passed to `parse` for round-tripping."); registerMLIRError(); } +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir diff --git a/mlir/lib/Bindings/Python/Pass.h b/mlir/lib/Bindings/Python/Pass.h index 0221bd10e723e..1a311666ebecd 100644 --- a/mlir/lib/Bindings/Python/Pass.h +++ b/mlir/lib/Bindings/Python/Pass.h @@ -13,8 +13,9 @@ namespace mlir { namespace python { - +namespace MLIR_BINDINGS_PYTHON_DOMAIN { void populatePassManagerSubmodule(nanobind::module_ &m); +} } // namespace python } // namespace mlir diff --git a/mlir/lib/Bindings/Python/Rewrite.cpp b/mlir/lib/Bindings/Python/Rewrite.cpp index 89092b768c6ca..cfe3dd9434e3b 100644 --- a/mlir/lib/Bindings/Python/Rewrite.cpp +++ b/mlir/lib/Bindings/Python/Rewrite.cpp @@ -22,9 +22,11 @@ namespace nb = nanobind; using namespace mlir; using namespace nb::literals; -using namespace mlir::python; +using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN; -namespace { +namespace mlir { +namespace python { +namespace MLIR_BINDINGS_PYTHON_DOMAIN { class PyPatternRewriter { public: @@ -60,6 +62,8 @@ class PyPatternRewriter { PyMlirContextRef ctx; }; +struct PyMlirPDLResultList : MlirPDLResultList {}; + #if MLIR_ENABLE_PDL_IN_PATTERNMATCH static nb::object objectFromPDLValue(MlirPDLValue value) { if (MlirValue v = mlirPDLValueAsValue(value); !mlirValueIsNull(v)) @@ -118,7 +122,7 @@ class PyPDLPatternModule { void *userData) -> MlirLogicalResult { nb::handle f = nb::handle(static_cast<PyObject *>(userData)); return logicalResultFromObject( - f(PyPatternRewriter(rewriter), results, + f(PyPatternRewriter(rewriter), PyMlirPDLResultList{results.ptr}, objectsFromPDLValues(nValues, values))); }, fn.ptr()); @@ -133,7 +137,7 @@ class PyPDLPatternModule { void *userData) -> MlirLogicalResult { nb::handle f = nb::handle(static_cast<PyObject *>(userData)); return logicalResultFromObject( - f(PyPatternRewriter(rewriter), results, + f(PyPatternRewriter(rewriter), PyMlirPDLResultList{results.ptr}, objectsFromPDLValues(nValues, values))); }, fn.ptr()); @@ -223,10 +227,8 @@ class PyRewritePatternSet { MlirContext ctx; }; -} // namespace - /// Create the `mlir.rewrite` here. -void mlir::python::populateRewriteSubmodule(nb::module_ &m) { +void populateRewriteSubmodule(nb::module_ &m) { //---------------------------------------------------------------------------- // Mapping of the PatternRewriter //---------------------------------------------------------------------------- @@ -293,10 +295,10 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) { // Mapping of the PDLResultList and PDLModule //---------------------------------------------------------------------------- #if MLIR_ENABLE_PDL_IN_PATTERNMATCH - nb::class_<MlirPDLResultList>(m, "PDLResultList") + nb::class_<PyMlirPDLResultList>(m, "PDLResultList") .def( "append", - [](MlirPDLResultList results, const PyValue &value) { + [](PyMlirPDLResultList results, const PyValue &value) { mlirPDLResultListPushBackValue(results, value); }, // clang-format off @@ -305,7 +307,7 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) { ) .def( "append", - [](MlirPDLResultList results, const PyOperation &op) { + [](PyMlirPDLResultList results, const PyOperation &op) { mlirPDLResultListPushBackOperation(results, op); }, // clang-format off @@ -314,7 +316,7 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) { ) .def( "append", - [](MlirPDLResultList results, const PyType &type) { + [](PyMlirPDLResultList results, const PyType &type) { mlirPDLResultListPushBackType(results, type); }, // clang-format off @@ -323,7 +325,7 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) { ) .def( "append", - [](MlirPDLResultList results, const PyAttribute &attr) { + [](PyMlirPDLResultList results, const PyAttribute &attr) { mlirPDLResultListPushBackAttribute(results, attr); }, // clang-format off @@ -333,9 +335,9 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) { nb::class_<PyPDLPatternModule>(m, "PDLModule") .def( "__init__", - [](PyPDLPatternModule &self, MlirModule module) { - new (&self) - PyPDLPatternModule(mlirPDLPatternModuleFromModule(module)); + [](PyPDLPatternModule &self, PyModule &module) { + new (&self) PyPDLPatternModule( + mlirPDLPatternModuleFromModule(module.get())); }, // clang-format off nb::sig("def __init__(self, module: " MAKE_MLIR_PYTHON_QUALNAME("ir.Module") ") -> None"), @@ -394,9 +396,9 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) { "results.") .def( "apply_patterns_and_fold_greedily", - [](PyModule &module, MlirFrozenRewritePatternSet set) { + [](PyModule &module, PyFrozenRewritePatternSet &set) { auto status = - mlirApplyPatternsAndFoldGreedily(module.get(), set, {}); + mlirApplyPatternsAndFoldGreedily(module.get(), set.get(), {}); if (mlirLogicalResultIsFailure(status)) throw std::runtime_error( "pattern application failed to converge"); @@ -425,9 +427,9 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) { "results.") .def( "apply_patterns_and_fold_greedily", - [](PyOperationBase &op, MlirFrozenRewritePatternSet set) { + [](PyOperationBase &op, PyFrozenRewritePatternSet &set) { auto status = mlirApplyPatternsAndFoldGreedilyWithOp( - op.getOperation(), set, {}); + op.getOperation(), set.get(), {}); if (mlirLogicalResultIsFailure(status)) throw std::runtime_error( "pattern application failed to converge"); @@ -439,3 +441,6 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) { "Applys the given patterns to the given op greedily while folding " "results."); } +} // namespace MLIR_BINDINGS_PYTHON_DOMAIN +} // namespace python +} // namespace mlir diff --git a/mlir/lib/Bindings/Python/Rewrite.h b/mlir/lib/Bindings/Python/Rewrite.h index f8ffdc7bdc458..d287f19187708 100644 --- a/mlir/lib/Bindings/Python/Rewrite.h +++ b/mlir/lib/Bindings/Python/Rewrite.h @@ -13,9 +13,9 @@ namespace mlir { namespace python { - +namespace MLIR_BINDINGS_PYTHON_DOMAIN { void populateRewriteSubmodule(nanobind::module_ &m); - +} } // namespace python } // namespace mlir diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt index b22d2ec75b3ba..2d2ae26bf3b28 100644 --- a/mlir/python/CMakeLists.txt +++ b/mlir/python/CMakeLists.txt @@ -3,6 +3,7 @@ include(AddMLIRPython) # Specifies that all MLIR packages are co-located under the `MLIR_PYTHON_PACKAGE_PREFIX.` # top level package (the API has been embedded in a relocatable way). add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=${MLIR_PYTHON_PACKAGE_PREFIX}.") +add_compile_definitions("MLIR_BINDINGS_PYTHON_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN}") set(MLIRPythonModules_ROOT_PREFIX "${MLIR_BINARY_DIR}/${MLIR_BINDINGS_PYTHON_INSTALL_PREFIX}") set(PYTHON_SOURCE_DIR "${MLIR_SOURCE_DIR}/lib/Bindings/Python") diff --git a/mlir/test/Examples/standalone/test.wheel.toy b/mlir/test/Examples/standalone/test.wheel.toy index 55847f7430648..91fed38e28612 100644 --- a/mlir/test/Examples/standalone/test.wheel.toy +++ b/mlir/test/Examples/standalone/test.wheel.toy @@ -1,6 +1,10 @@ # There's no real issue with windows here, it's just that some CMake generated paths for targets end up being longer # than 255 chars when combined with the fact that pip wants to install into a tmp directory buried under # C/Users/ContainerAdministrator/AppData/Local/Temp. +# UNSUPPORTED: target={{.*(windows).*}} +# REQUIRES: expensive_checks +# REQUIRES: non-shared-libs-build +# REQUIRES: bindings-python # RUN: export CMAKE_BUILD_TYPE=%cmake_build_type # RUN: export CMAKE_CXX_COMPILER=%host_cxx @@ -11,21 +15,21 @@ # RUN: export LLVM_USE_LINKER=%llvm_use_linker # RUN: export MLIR_DIR="%mlir_cmake_dir" -# RUN: %python -m pip install scikit-build-core -# RUN: %python -m pip wheel "%mlir_src_root/examples/standalone" -w "%mlir_obj_root/wheelhouse" -v --no-build-isolation | tee %t +# RUN: %python -m pip wheel "%mlir_src_root/examples/standalone" -w "%mlir_obj_root/wheelhouse" -v | tee %t # RUN: rm -rf "%mlir_obj_root/standalone-python-bindings-install" # RUN: %python -m pip install standalone_python_bindings -f "%mlir_obj_root/wheelhouse" --target "%mlir_obj_root/standalone-python-bindings-install" -v | tee -a %t -# RUN: export PYTHONPATH="%mlir_obj_root/standalone-python-bindings-install" -# RUN: %python "%mlir_src_root/examples/standalone/test/python/smoketest.py" nanobind | tee -a %t +# RUN: export PYTHONPATH="%mlir_obj_root/standalone-python-bindings-install:%mlir_obj_root/python_packages/mlir_core" +# RUN: %python "%mlir_src_root/examples/standalone/test/python/smoketest.py" test-upstream 2>&1 | tee -a %t # RUN: FileCheck --input-file=%t %s # CHECK: Successfully built standalone-python-bindings +# CHECK-NOT: RuntimeWarning: nanobind: type '{{.*}}' was already registered! + # CHECK: module { # CHECK: %[[C2:.*]] = arith.constant 2 : i32 # CHECK: %[[V0:.*]] = standalone.foo %[[C2]] : i32 # CHECK: } - diff --git a/mlir/test/python/lib/PythonTestModuleNanobind.cpp b/mlir/test/python/lib/PythonTestModuleNanobind.cpp index c8b95e2316778..43573cbc305fa 100644 --- a/mlir/test/python/lib/PythonTestModuleNanobind.cpp +++ b/mlir/test/python/lib/PythonTestModuleNanobind.cpp @@ -27,7 +27,8 @@ static bool mlirTypeIsARankedIntegerTensor(MlirType t) { mlirTypeIsAInteger(mlirShapedTypeGetElementType(t)); } -struct PyTestType : mlir::python::PyConcreteType<PyTestType> { +struct PyTestType + : mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::PyConcreteType<PyTestType> { static constexpr IsAFunctionTy isaFunction = mlirTypeIsAPythonTestTestType; static constexpr GetTypeIDFunctionTy getTypeIdFunction = mlirPythonTestTestTypeGetTypeID; @@ -37,7 +38,8 @@ struct PyTestType : mlir::python::PyConcreteType<PyTestType> { static void bindDerived(ClassTy &c) { c.def_static( "get", - [](mlir::python::DefaultingPyMlirContext context) { + [](mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext + context) { return PyTestType(context->getRef(), mlirPythonTestTestTypeGet(context.get()->get())); }, @@ -45,7 +47,9 @@ struct PyTestType : mlir::python::PyConcreteType<PyTestType> { } }; -class PyTestAttr : public mlir::python::PyConcreteAttribute<PyTestAttr> { +class PyTestAttr + : public mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::PyConcreteAttribute< + PyTestAttr> { public: static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAPythonTestTestAttribute; @@ -57,7 +61,8 @@ class PyTestAttr : public mlir::python::PyConcreteAttribute<PyTestAttr> { static void bindDerived(ClassTy &c) { c.def_static( "get", - [](mlir::python::DefaultingPyMlirContext context) { + [](mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext + context) { return PyTestAttr(context->getRef(), mlirPythonTestTestAttributeGet( context.get()->get())); }, _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
