Skip to content

Commit d2e405e

Browse files
Garra1980tkarna
andauthored
Add Python bindings (#1064)
Co-authored-by: Tuomas Karna <[email protected]>
1 parent a74c3a4 commit d2e405e

20 files changed

+449
-0
lines changed

CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,13 @@ else ()
272272
set(IMEX_ENABLE_PVC_TARGET 0)
273273
endif()
274274

275+
set(IMEX_ENABLE_BINDINGS_PYTHON 0 CACHE BOOL "Enable IMEX Python Binding")
276+
if (IMEX_ENABLE_BINDINGS_PYTHON)
277+
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -Wno-error=address -Wno-error=pragmas -Wno-error=pedantic -Wno-error=parentheses")
278+
set(IMEX_ENABLE_BINDINGS_PYTHON 1)
279+
else ()
280+
set(IMEX_ENABLE_BINDINGS_PYTHON 0)
281+
endif()
275282

276283
if (NOT (CMAKE_BUILD_TYPE MATCHES Debug))
277284
if (IMEX_ENABLE_DEBUG_BUILD)
@@ -326,6 +333,9 @@ option(IMEX_INCLUDE_DOCS "Generate build targets for the IMEX docs." ON)
326333
if (IMEX_INCLUDE_DOCS)
327334
add_subdirectory(docs)
328335
endif()
336+
if (IMEX_ENABLE_BINDINGS_PYTHON)
337+
add_subdirectory(python)
338+
endif()
329339

330340
# Custom target to install all imex headers
331341
add_custom_target(imex-headers)

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,17 @@ cd build
146146
cmake --build build --target doc_doxygen
147147
```
148148

149+
### Building Python bindings
150+
151+
IMEX can be built with Python bindings. The `imex_mlir` Python package functions similarly to the [MLIR Python bindings](https://mlir.llvm.org/docs/Bindings/Python/), providing access to the MLIR objects as well as IMEX dialects and passes. To enable the bindings:
152+
153+
- LLVM must be built with `-DMLIR_ENABLE_BINDINGS_PYTHON=1`.
154+
- IMEX must be built with `-DIMEX_ENABLE_BINDINGS_PYTHON=1`.
155+
- On systems with multiple Python implementations, you may need to specify the desired Python version, for example, `-DPython3_EXECUTABLE=$(which python3)`.
156+
- pybind11 and nanobind are additional build dependencies.
157+
158+
The `imex_mlir` package is located in the `<IMEX_ROOT>/python_packages/` directory, where `<IMEX_ROOT>` refers to the IMEX build or installation directory. To use the Python bindings, include `<IMEX_ROOT>/python_packages/` in your `PYTHONPATH` environment variable. Usage examples can be found in the [Python test suite](test/python/).
159+
149160
## Adding a new dialect
150161
```sh
151162
# enter root directory of mlir-extension

include/imex-c/Dialects.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===- Dialects.h - IMEX CAPI Registration ----------------------*- C++ -*-===//
2+
//
3+
// Copyright 2025 Intel Corporation
4+
// Part of the IMEX Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file defines the IMEX C API dialects.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef IMEX_C_DIALECTS_H
15+
#define IMEX_C_DIALECTS_H
16+
17+
#include "mlir-c/IR.h"
18+
19+
#ifdef __cplusplus
20+
extern "C" {
21+
#endif
22+
23+
MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(Region, region);
24+
25+
#ifdef __cplusplus
26+
}
27+
#endif
28+
#endif // IMEX_C_DIALECTS_H

include/imex-c/Passes.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===- Passes.h - IMEX CAPI Registration ------------------------*- C++ -*-===//
2+
//
3+
// Copyright 2025 Intel Corporation
4+
// Part of the IMEX Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file defines the IMEX C API passes.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef IMEX_MLIR_C_PASSES_H
15+
#define IMEX_MLIR_C_PASSES_H
16+
17+
#include "mlir-c/IR.h"
18+
19+
#ifdef __cplusplus
20+
extern "C" {
21+
#endif
22+
23+
MLIR_CAPI_EXPORTED void mlirRegisterAllIMEXPasses(void);
24+
25+
#ifdef __cplusplus
26+
}
27+
#endif
28+
#endif // IMEX_MLIR_C_PASSES_H

lib/CAPI/CMakeLists.txt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
set(IMEX_ALL_LIBS
2+
IMEXTransforms
3+
IMEXXeTileTransforms
4+
IMEXXeTileDialect
5+
IMEXNDArrayTransforms
6+
IMEXNDArrayDialect
7+
IMEXGPUXDialect
8+
IMEXDistRuntimeTransforms
9+
IMEXDistRuntimeDialect
10+
IMEXRegionTransforms
11+
IMEXRegionDialect
12+
IMEXArithToVC
13+
IMEXDropRegions
14+
IMEXGPUToGPUX
15+
IMEXGPUToSPIRV
16+
IMEXGPUXToLLVM
17+
IMEXMathToVC
18+
IMEXNDArrayToLinalg
19+
IMEXSCFToGPU
20+
IMEXXeGPUToVC
21+
IMEXXeTileToXeGPU
22+
MLIRXeGPUToXeVM
23+
MLIRXeVMToLLVM
24+
IMEXUtil
25+
imex_runner_utils
26+
)
27+
28+
if(IMEX_ENABLE_L0_RUNTIME)
29+
list(APPEND IMEX_ALL_LIBS level-zero-runtime)
30+
endif()
31+
32+
if(IMEX_ENABLE_SYCL_RUNTIME)
33+
list(APPEND IMEX_ALL_LIBS sycl-runtime)
34+
endif()
35+
36+
add_mlir_public_c_api_library(ImexCAPI
37+
Dialects.cpp
38+
Passes.cpp
39+
LINK_LIBS PUBLIC
40+
IMEXRegionDialect
41+
${IMEX_ALL_LIBS}
42+
)
43+
target_link_libraries(obj.ImexCAPI PUBLIC ImexInterface)
44+
set_property(GLOBAL APPEND PROPERTY IMEX_MLIR_LIBS ImexCAPI)

lib/CAPI/Dialects.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//===- Dialects.cpp - IMEX CAPI Registration --------------------*- C++ -*-===//
2+
//
3+
// Copyright 2025 Intel Corporation
4+
// Part of the IMEX Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "imex-c/Dialects.h"
11+
#include "imex/Dialect/Region/IR/RegionOps.h"
12+
#include "mlir/CAPI/Registration.h"
13+
14+
// name, namespace, classname
15+
MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(Region, region,
16+
imex::region::RegionDialect)

lib/CAPI/Passes.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===- Passes.cpp - IMEX CAPI Registration ----------------------*- C++ -*-===//
2+
//
3+
// Copyright 2025 Intel Corporation
4+
// Part of the IMEX Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "imex/InitIMEXPasses.h"
11+
#include "mlir-c/Pass.h"
12+
#include "mlir/CAPI/Pass.h"
13+
14+
using namespace imex;
15+
16+
#ifdef __cplusplus
17+
extern "C" {
18+
#endif
19+
20+
MLIR_CAPI_EXPORTED void mlirRegisterAllIMEXPasses() { registerAllPasses(); }
21+
#ifdef __cplusplus
22+
}
23+
#endif

lib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
add_subdirectory(Dialect)
2+
add_subdirectory(CAPI)
23
add_subdirectory(Conversion)
34
add_subdirectory(Transforms)
45
add_subdirectory(ExecutionEngine)

python/CMakeLists.txt

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
if(IMEX_ENABLE_BINDINGS_PYTHON)
2+
if(NOT MLIR_ENABLE_BINDINGS_PYTHON)
3+
message(STATUS "Failed to enable Python API due to the 'MLIR_ENABLE_BINDINGS_PYTHON' for LLVM is not ON.")
4+
set(IMEX_ENABLE_BINDINGS_PYTHON OFF CACHE BOOL "" FORCE)
5+
return()
6+
endif()
7+
message(STATUS "Enabling Python API")
8+
else()
9+
return()
10+
endif()
11+
12+
include(MLIRDetectPythonEnv)
13+
mlir_configure_python_dev_packages()
14+
include(AddMLIRPython)
15+
16+
# Specifies that all MLIR packages are co-located under the `imex_mlir`
17+
# top level package (the API has been embedded in a relocatable way).
18+
# TODO: Add an upstream cmake param for this vs having a global here.
19+
add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=imex_mlir.")
20+
21+
22+
################################################################################
23+
# Sources
24+
################################################################################
25+
26+
declare_mlir_python_sources(ImexPythonSources)
27+
28+
declare_mlir_python_sources(ImexPythonSources.Common
29+
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/imex_mlir"
30+
ADD_TO_PARENT ImexPythonSources
31+
SOURCES
32+
_mlir_libs/_site_initialize_0.py
33+
)
34+
35+
declare_mlir_dialect_python_bindings(
36+
ADD_TO_PARENT ImexPythonSources
37+
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/imex_mlir"
38+
TD_FILE dialects/RegionOps.td
39+
SOURCES
40+
dialects/region.py
41+
DIALECT_NAME region)
42+
43+
declare_mlir_python_extension(ImexPythonSources.Extension
44+
MODULE_NAME _imex_mlir
45+
ADD_TO_PARENT ImexPythonSources
46+
SOURCES
47+
ImexExtension.cpp
48+
EMBED_CAPI_LINK_LIBS
49+
ImexCAPI
50+
PYTHON_BINDINGS_LIBRARY nanobind
51+
)
52+
53+
54+
################################################################################
55+
# Common CAPI
56+
################################################################################
57+
58+
add_mlir_python_common_capi_library(ImexPythonCAPI
59+
INSTALL_COMPONENT ImexPythonModules
60+
INSTALL_DESTINATION python_packages/imex_mlir/_mlir_libs
61+
OUTPUT_DIRECTORY "${MLIR_BINARY_DIR}/python_packages/imex_mlir/_mlir_libs"
62+
RELATIVE_INSTALL_ROOT "../../../.."
63+
DECLARED_SOURCES
64+
ImexPythonSources
65+
MLIRPythonExtension.RegisterEverything
66+
MLIRPythonSources.Core
67+
MLIRPythonSources.ExecutionEngine
68+
)
69+
70+
################################################################################
71+
# Instantiation of all Python modules
72+
################################################################################
73+
74+
add_mlir_python_modules(ImexPythonModules
75+
ROOT_PREFIX "${MLIR_BINARY_DIR}/python_packages/imex_mlir"
76+
INSTALL_PREFIX "python_packages/imex_mlir"
77+
DECLARED_SOURCES
78+
ImexPythonSources
79+
MLIRPythonExtension.RegisterEverything
80+
MLIRPythonSources
81+
MLIRPythonSources.ExecutionEngine
82+
COMMON_CAPI_LINK_LIBS
83+
ImexPythonCAPI
84+
)

python/ImexExtension.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===- ImexExtension.cpp - Extension module -------------------------------===//
2+
//
3+
// Copyright 2025 Intel Corporation
4+
// Part of the IMEX Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "imex-c/Dialects.h"
11+
#include "imex-c/Passes.h"
12+
#include "mlir/Bindings/Python/Nanobind.h"
13+
#include "mlir/Bindings/Python/NanobindAdaptors.h"
14+
15+
namespace nb = nanobind;
16+
17+
NB_MODULE(_imex_mlir, m) {
18+
m.doc() = "Intel Extension for MLIR (IMEX) Python binding";
19+
20+
mlirRegisterAllIMEXPasses();
21+
22+
//===--------------------------------------------------------------------===//
23+
// region dialect
24+
//===--------------------------------------------------------------------===//
25+
auto regionM = m.def_submodule("region");
26+
27+
regionM.def(
28+
"register_dialect",
29+
[](MlirContext context, bool load) {
30+
MlirDialectHandle handle = mlirGetDialectHandle__region__();
31+
mlirDialectHandleRegisterDialect(handle, context);
32+
if (load) {
33+
mlirDialectHandleLoadDialect(handle, context);
34+
}
35+
},
36+
nb::arg("context").none() = nb::none(), nb::arg("load") = true);
37+
}

0 commit comments

Comments
 (0)