[Mlir-commits] [mlir] [MLIR][Python] expose translate_module_to_llvmir (PR #163881)

Maksim Levental llvmlistbot at llvm.org
Thu Oct 16 20:35:17 PDT 2025


https://github.com/makslevental updated https://github.com/llvm/llvm-project/pull/163881

>From 5193c35e295a7eb370229a5841b45b3d68faeca8 Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Thu, 16 Oct 2025 15:31:56 -0700
Subject: [PATCH] [MLIR][Python] expose translate_module_to_llvmir

---
 mlir/include/mlir-c/Target/LLVMIR.h      |  3 +++
 mlir/lib/Bindings/Python/DialectLLVM.cpp | 13 ++++++++++++-
 mlir/lib/CAPI/Target/LLVMIR.cpp          |  9 +++++++++
 mlir/python/CMakeLists.txt               |  2 ++
 mlir/test/python/dialects/llvm.py        | 19 +++++++++++++++++++
 5 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/mlir/include/mlir-c/Target/LLVMIR.h b/mlir/include/mlir-c/Target/LLVMIR.h
index b5f948961e898..ec5ae88d485dc 100644
--- a/mlir/include/mlir-c/Target/LLVMIR.h
+++ b/mlir/include/mlir-c/Target/LLVMIR.h
@@ -33,6 +33,9 @@ extern "C" {
 MLIR_CAPI_EXPORTED LLVMModuleRef
 mlirTranslateModuleToLLVMIR(MlirOperation module, LLVMContextRef context);
 
+MLIR_CAPI_EXPORTED char *
+mlirTranslateModuleToLLVMIRToString(MlirOperation module);
+
 struct MlirTypeFromLLVMIRTranslator {
   void *ptr;
 };
diff --git a/mlir/lib/Bindings/Python/DialectLLVM.cpp b/mlir/lib/Bindings/Python/DialectLLVM.cpp
index 38de4a0e329a0..870a713b8edcb 100644
--- a/mlir/lib/Bindings/Python/DialectLLVM.cpp
+++ b/mlir/lib/Bindings/Python/DialectLLVM.cpp
@@ -11,6 +11,7 @@
 #include "mlir-c/Dialect/LLVM.h"
 #include "mlir-c/IR.h"
 #include "mlir-c/Support.h"
+#include "mlir-c/Target/LLVMIR.h"
 #include "mlir/Bindings/Python/Diagnostics.h"
 #include "mlir/Bindings/Python/Nanobind.h"
 #include "mlir/Bindings/Python/NanobindAdaptors.h"
@@ -24,7 +25,7 @@ using namespace mlir;
 using namespace mlir::python;
 using namespace mlir::python::nanobind_adaptors;
 
-static void populateDialectLLVMSubmodule(const nanobind::module_ &m) {
+static void populateDialectLLVMSubmodule(nanobind::module_ &m) {
 
   //===--------------------------------------------------------------------===//
   // StructType
@@ -154,6 +155,16 @@ static void populateDialectLLVMSubmodule(const nanobind::module_ &m) {
       .def_property_readonly("address_space", [](MlirType type) {
         return mlirLLVMPointerTypeGetAddressSpace(type);
       });
+
+  m.def(
+      "translate_module_to_llvmir",
+      [](MlirOperation module) {
+        return mlirTranslateModuleToLLVMIRToString(module);
+      },
+      // clang-format off
+      nb::sig("def translate_module_to_llvmir(module: " MAKE_MLIR_PYTHON_QUALNAME("ir.Operation") ") -> str"),
+      // clang-format on
+      "module"_a, nb::rv_policy::take_ownership);
 }
 
 NB_MODULE(_mlirDialectsLLVM, m) {
diff --git a/mlir/lib/CAPI/Target/LLVMIR.cpp b/mlir/lib/CAPI/Target/LLVMIR.cpp
index 1c1912aec0f2f..00229dffafb61 100644
--- a/mlir/lib/CAPI/Target/LLVMIR.cpp
+++ b/mlir/lib/CAPI/Target/LLVMIR.cpp
@@ -34,6 +34,15 @@ LLVMModuleRef mlirTranslateModuleToLLVMIR(MlirOperation module,
   return moduleRef;
 }
 
+char *mlirTranslateModuleToLLVMIRToString(MlirOperation module) {
+  LLVMContextRef llvmCtx = LLVMContextCreate();
+  LLVMModuleRef llvmModule = mlirTranslateModuleToLLVMIR(module, llvmCtx);
+  char *llvmir = LLVMPrintModuleToString(llvmModule);
+  LLVMDisposeModule(llvmModule);
+  LLVMContextDispose(llvmCtx);
+  return llvmir;
+}
+
 DEFINE_C_API_PTR_METHODS(MlirTypeFromLLVMIRTranslator,
                          mlir::LLVM::TypeFromLLVMIRTranslator)
 
diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt
index 9f5246de6bda0..a64d2e49c974f 100644
--- a/mlir/python/CMakeLists.txt
+++ b/mlir/python/CMakeLists.txt
@@ -591,6 +591,8 @@ declare_mlir_python_extension(MLIRPythonExtension.Dialects.LLVM.Pybind
   EMBED_CAPI_LINK_LIBS
     MLIRCAPIIR
     MLIRCAPILLVM
+    # Misnomer - this is only the LLVMIR translation target.
+    MLIRCAPITarget
 )
 
 declare_mlir_python_extension(MLIRPythonExtension.Dialects.Quant.Pybind
diff --git a/mlir/test/python/dialects/llvm.py b/mlir/test/python/dialects/llvm.py
index d9ffdeb65bfd4..8ea0fddee3f7c 100644
--- a/mlir/test/python/dialects/llvm.py
+++ b/mlir/test/python/dialects/llvm.py
@@ -150,3 +150,22 @@ def testIntrinsics():
     result = llvm.intr_memset(alloca, c_0, c_128, False)
     # CHECK: "llvm.intr.memset"(%[[ALLOCA]], %[[CST0]], %[[CST128]]) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> ()
     print(result)
+
+
+# CHECK-LABEL: testTranslateToLLVMIR
+ at constructAndPrintInModule
+def testTranslateToLLVMIR():
+    with Context(), Location.unknown():
+        module = Module.parse(
+            """\
+            llvm.func @add(%arg0: i64, %arg1: i64) -> i64 { 
+               %0 = llvm.add %arg0, %arg1  : i64 
+               llvm.return %0 : i64 
+            }
+        """
+        )
+        # CHECK: define i64 @add(i64 %0, i64 %1) {
+        # CHECK:   %3 = add i64 %0, %1
+        # CHECK:   ret i64 %3
+        # CHECK: }
+        print(llvm.translate_module_to_llvmir(module.operation))



More information about the Mlir-commits mailing list