[Mlir-commits] [mlir] 86c8a78 - Add C bindings for mlir::ExecutionEngine

Mehdi Amini llvmlistbot at llvm.org
Wed Mar 3 10:19:52 PST 2021


Author: Mehdi Amini
Date: 2021-03-03T18:19:40Z
New Revision: 86c8a7857dc39ed28960d2e061bac118f7186fce

URL: https://github.com/llvm/llvm-project/commit/86c8a7857dc39ed28960d2e061bac118f7186fce
DIFF: https://github.com/llvm/llvm-project/commit/86c8a7857dc39ed28960d2e061bac118f7186fce.diff

LOG: Add C bindings for mlir::ExecutionEngine

This adds minimalistic bindings for the execution engine, allowing to
invoke the JIT from the C API. This is still quite early and
experimental and shouldn't be considered stable in any way.

Differential Revision: https://reviews.llvm.org/D96651

Added: 
    mlir/include/mlir-c/Conversion.h
    mlir/include/mlir-c/ExecutionEngine.h
    mlir/include/mlir/CAPI/ExecutionEngine.h
    mlir/lib/CAPI/Conversion/CMakeLists.txt
    mlir/lib/CAPI/Conversion/Passes.cpp
    mlir/lib/CAPI/ExecutionEngine/CMakeLists.txt
    mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
    mlir/test/CAPI/execution_engine.c

Modified: 
    mlir/include/mlir-c/Registration.h
    mlir/include/mlir/Conversion/CMakeLists.txt
    mlir/lib/CAPI/CMakeLists.txt
    mlir/lib/CAPI/Registration/Registration.cpp
    mlir/test/CAPI/CMakeLists.txt
    mlir/test/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir-c/Conversion.h b/mlir/include/mlir-c/Conversion.h
new file mode 100644
index 000000000000..b69c41710446
--- /dev/null
+++ b/mlir/include/mlir-c/Conversion.h
@@ -0,0 +1,22 @@
+//===-- mlir-c/Conversion.h - Conversion passes initialization ----*- C -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+// Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header declares the registration and creation method for conversion
+// passes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_C_CONVERSIONS_H
+#define MLIR_C_CONVERSIONS_H
+
+#include "mlir-c/Support.h"
+
+#include "mlir/Conversion/Passes.capi.h.inc"
+
+#endif // MLIR_C_CONVERSIONS_H

diff  --git a/mlir/include/mlir-c/ExecutionEngine.h b/mlir/include/mlir-c/ExecutionEngine.h
new file mode 100644
index 000000000000..02d41dcae684
--- /dev/null
+++ b/mlir/include/mlir-c/ExecutionEngine.h
@@ -0,0 +1,63 @@
+//===-- mlir-c/ExecutionEngine.h - Execution engine management ---*- C -*-====//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+// Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header provides basic access to the MLIR JIT. This is minimalist and
+// experimental at the moment.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_C_EXECUTIONENGINE_H
+#define MLIR_C_EXECUTIONENGINE_H
+
+#include "mlir-c/IR.h"
+#include "mlir-c/Support.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEFINE_C_API_STRUCT(name, storage)                                     \
+  struct name {                                                                \
+    storage *ptr;                                                              \
+  };                                                                           \
+  typedef struct name name
+
+DEFINE_C_API_STRUCT(MlirExecutionEngine, void);
+
+#undef DEFINE_C_API_STRUCT
+
+/// Creates an ExecutionEngine for the provided ModuleOp. The ModuleOp is
+/// expected to be "translatable" to LLVM IR (only contains operations in
+/// dialects that implement the `LLVMTranslationDialectInterface`). The module
+/// ownership stays with the client and can be destroyed as soon as the call
+/// returns.
+/// TODO: figure out options (optimization level, etc.).
+MLIR_CAPI_EXPORTED MlirExecutionEngine mlirExecutionEngineCreate(MlirModule op);
+
+/// Destroy an ExecutionEngine instance.
+MLIR_CAPI_EXPORTED void mlirExecutionEngineDestroy(MlirExecutionEngine jit);
+
+/// Checks whether an execution engine is null.
+static inline bool mlirExecutionEngineIsNull(MlirExecutionEngine jit) {
+  return !jit.ptr;
+}
+
+/// Invoke a native function in the execution engine by name with the arguments
+/// and result of the invoked function passed as an array of pointers. The
+/// function must have been tagged with the `llvm.emit_c_interface` attribute.
+/// Returns a failure if the execution fails for any reason (the function name
+/// can't be resolved for instance).
+MLIR_CAPI_EXPORTED MlirLogicalResult mlirExecutionEngineInvokePacked(
+    MlirExecutionEngine jit, MlirStringRef name, void **arguments);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // EXECUTIONENGINE_H

diff  --git a/mlir/include/mlir-c/Registration.h b/mlir/include/mlir-c/Registration.h
index 6c7a486373ee..4cfc967192c9 100644
--- a/mlir/include/mlir-c/Registration.h
+++ b/mlir/include/mlir-c/Registration.h
@@ -57,6 +57,9 @@ MLIR_CAPI_EXPORTED MlirDialect mlirDialectHandleLoadDialect(MlirDialectHandle,
 /// TODO: Remove this function once the real registration API is finished.
 MLIR_CAPI_EXPORTED void mlirRegisterAllDialects(MlirContext context);
 
+/// Register all translations to LLVM IR for dialects that can support it.
+MLIR_CAPI_EXPORTED void mlirRegisterAllLLVMTranslations(MlirContext context);
+
 #ifdef __cplusplus
 }
 #endif

diff  --git a/mlir/include/mlir/CAPI/ExecutionEngine.h b/mlir/include/mlir/CAPI/ExecutionEngine.h
new file mode 100644
index 000000000000..034c59f58477
--- /dev/null
+++ b/mlir/include/mlir/CAPI/ExecutionEngine.h
@@ -0,0 +1,24 @@
+//===- IR.h - C API Utils for Core MLIR classes -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains declarations of implementation details of the C API for
+// core MLIR classes. This file should not be included from C++ code other than
+// C API implementation nor from C code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_CAPI_EXECUTIONENGINE_H
+#define MLIR_CAPI_EXECUTIONENGINE_H
+
+#include "mlir-c/ExecutionEngine.h"
+#include "mlir/CAPI/Wrap.h"
+#include "mlir/ExecutionEngine/ExecutionEngine.h"
+
+DEFINE_C_API_PTR_METHODS(MlirExecutionEngine, mlir::ExecutionEngine)
+
+#endif // MLIR_CAPI_EXECUTIONENGINE_H

diff  --git a/mlir/include/mlir/Conversion/CMakeLists.txt b/mlir/include/mlir/Conversion/CMakeLists.txt
index ae0afc97dc63..4b5201a8aa1e 100644
--- a/mlir/include/mlir/Conversion/CMakeLists.txt
+++ b/mlir/include/mlir/Conversion/CMakeLists.txt
@@ -1,6 +1,8 @@
 
 set(LLVM_TARGET_DEFINITIONS Passes.td)
 mlir_tablegen(Passes.h.inc -gen-pass-decls -name Conversion)
+mlir_tablegen(Passes.capi.h.inc -gen-pass-capi-header --prefix Conversion)
+mlir_tablegen(Passes.capi.cpp.inc -gen-pass-capi-impl --prefix Conversion)
 add_public_tablegen_target(MLIRConversionPassIncGen)
 
 add_mlir_doc(Passes -gen-pass-doc ConversionPasses ./)

diff  --git a/mlir/lib/CAPI/CMakeLists.txt b/mlir/lib/CAPI/CMakeLists.txt
index 1ccf46204f9e..ba58d99a7c5a 100644
--- a/mlir/lib/CAPI/CMakeLists.txt
+++ b/mlir/lib/CAPI/CMakeLists.txt
@@ -1,6 +1,8 @@
+add_subdirectory(Dialect)
+add_subdirectory(Conversion)
+add_subdirectory(ExecutionEngine)
 add_subdirectory(IR)
 add_subdirectory(Registration)
-add_subdirectory(Dialect)
 add_subdirectory(Transforms)
 
 

diff  --git a/mlir/lib/CAPI/Conversion/CMakeLists.txt b/mlir/lib/CAPI/Conversion/CMakeLists.txt
new file mode 100644
index 000000000000..83435cd19057
--- /dev/null
+++ b/mlir/lib/CAPI/Conversion/CMakeLists.txt
@@ -0,0 +1,7 @@
+get_property(conversion_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS)
+add_mlir_public_c_api_library(MLIRCAPIConversion
+  Passes.cpp
+
+  LINK_LIBS PUBLIC
+  ${conversion_libs}
+)

diff  --git a/mlir/lib/CAPI/Conversion/Passes.cpp b/mlir/lib/CAPI/Conversion/Passes.cpp
new file mode 100644
index 000000000000..8e95f2245ec8
--- /dev/null
+++ b/mlir/lib/CAPI/Conversion/Passes.cpp
@@ -0,0 +1,26 @@
+//===- Conversion.cpp - C API for Conversion Passes -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Conversion/Passes.h"
+#include "mlir/CAPI/Pass.h"
+#include "mlir/Pass/Pass.h"
+
+// Must include the declarations as they carry important visibility attributes.
+#include "mlir/Conversion/Passes.capi.h.inc"
+
+using namespace mlir;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mlir/Conversion/Passes.capi.cpp.inc"
+
+#ifdef __cplusplus
+}
+#endif

diff  --git a/mlir/lib/CAPI/ExecutionEngine/CMakeLists.txt b/mlir/lib/CAPI/ExecutionEngine/CMakeLists.txt
new file mode 100644
index 000000000000..ab1c8e9ddaa9
--- /dev/null
+++ b/mlir/lib/CAPI/ExecutionEngine/CMakeLists.txt
@@ -0,0 +1,7 @@
+# Main API shared library.
+add_mlir_public_c_api_library(MLIRCEXECUTIONENGINE
+  ExecutionEngine.cpp
+
+  LINK_LIBS PUBLIC
+  MLIRExecutionEngine
+)

diff  --git a/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp b/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
new file mode 100644
index 000000000000..1cffddcd8525
--- /dev/null
+++ b/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
@@ -0,0 +1,46 @@
+//===- ExecutionEngine.cpp - C API for MLIR JIT ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir-c/ExecutionEngine.h"
+#include "mlir/CAPI/ExecutionEngine.h"
+#include "mlir/CAPI/IR.h"
+#include "mlir/CAPI/Support.h"
+#include "llvm/Support/TargetSelect.h"
+
+using namespace mlir;
+
+extern "C" MlirExecutionEngine mlirExecutionEngineCreate(MlirModule op) {
+  static bool init_once = [] {
+    llvm::InitializeNativeTarget();
+    llvm::InitializeNativeTargetAsmPrinter();
+    return true;
+  }();
+  (void)init_once;
+
+  auto jitOrError = ExecutionEngine::create(unwrap(op));
+  if (!jitOrError) {
+    consumeError(jitOrError.takeError());
+    return MlirExecutionEngine{nullptr};
+  }
+  return wrap(jitOrError->release());
+}
+
+extern "C" void mlirExecutionEngineDestroy(MlirExecutionEngine jit) {
+  delete (unwrap(jit));
+}
+
+extern "C" MlirLogicalResult
+mlirExecutionEngineInvokePacked(MlirExecutionEngine jit, MlirStringRef name,
+                                void **arguments) {
+  const std::string ifaceName = ("_mlir_ciface_" + unwrap(name)).str();
+  llvm::Error error = unwrap(jit)->invokePacked(
+      ifaceName, MutableArrayRef<void *>{arguments, (size_t)0});
+  if (error)
+    return wrap(failure());
+  return wrap(success());
+}

diff  --git a/mlir/lib/CAPI/Registration/Registration.cpp b/mlir/lib/CAPI/Registration/Registration.cpp
index 223188ac6ccd..f8e1bd3f3cb1 100644
--- a/mlir/lib/CAPI/Registration/Registration.cpp
+++ b/mlir/lib/CAPI/Registration/Registration.cpp
@@ -10,9 +10,14 @@
 
 #include "mlir/CAPI/IR.h"
 #include "mlir/InitAllDialects.h"
+#include "mlir/Target/LLVMIR.h"
 
 void mlirRegisterAllDialects(MlirContext context) {
   mlir::registerAllDialects(*unwrap(context));
   // TODO: we may not want to eagerly load here.
   unwrap(context)->loadAllAvailableDialects();
 }
+
+void mlirRegisterAllLLVMTranslations(MlirContext context) {
+  mlir::registerLLVMDialectTranslation(*unwrap(context));
+}

diff  --git a/mlir/test/CAPI/CMakeLists.txt b/mlir/test/CAPI/CMakeLists.txt
index 099cf4034a1b..d01cb0220b2c 100644
--- a/mlir/test/CAPI/CMakeLists.txt
+++ b/mlir/test/CAPI/CMakeLists.txt
@@ -1,4 +1,5 @@
 set(LLVM_OPTIONAL_SOURCES
+  execution_engine.c
   ir.c
   pass.c
 )
@@ -28,3 +29,16 @@ target_link_libraries(mlir-capi-pass-test
   PRIVATE
   MLIRPublicAPI
   )
+
+add_llvm_executable(mlir-capi-execution-engine-test
+  execution_engine.c
+DEPENDS
+  MLIRConversionPassIncGen
+  )
+llvm_update_compile_flags(mlir-capi-execution-engine-test)
+
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+target_link_libraries(mlir-capi-execution-engine-test
+  PRIVATE
+  MLIRPublicAPI
+  )

diff  --git a/mlir/test/CAPI/execution_engine.c b/mlir/test/CAPI/execution_engine.c
new file mode 100644
index 000000000000..160bdbebe9e5
--- /dev/null
+++ b/mlir/test/CAPI/execution_engine.c
@@ -0,0 +1,81 @@
+//===- execution_engine.c - Test for the C bindings for the MLIR JIT-------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+// Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+/* RUN: mlir-capi-execution-engine-test 2>&1 | FileCheck %s
+ */
+
+#include "mlir-c/Conversion.h"
+#include "mlir-c/ExecutionEngine.h"
+#include "mlir-c/IR.h"
+#include "mlir-c/Registration.h"
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void lowerModuleToLLVM(MlirContext ctx, MlirModule module) {
+  MlirPassManager pm = mlirPassManagerCreate(ctx);
+  mlirPassManagerAddOwnedPass(pm, mlirCreateConversionConvertStandardToLLVM());
+  MlirLogicalResult status = mlirPassManagerRun(pm, module);
+  if (mlirLogicalResultIsFailure(status)) {
+    fprintf(stderr, "Unexpected failure running pass pipeline\n");
+    exit(2);
+  }
+  mlirPassManagerDestroy(pm);
+}
+
+// CHECK-LABEL: Running test 'testSimpleExecution'
+void testSimpleExecution() {
+  MlirContext ctx = mlirContextCreate();
+  mlirRegisterAllDialects(ctx);
+  MlirModule module = mlirModuleCreateParse(
+      ctx, mlirStringRefCreateFromCString(
+               // clang-format off
+"module {                                                                   \n"
+"  func @add(%arg0 : i32) -> i32 attributes { llvm.emit_c_interface } {     \n"
+"    %res = std.addi %arg0, %arg0 : i32                                     \n"
+"    return %res : i32                                                      \n"
+"  }                                                                        \n"
+"}"));
+  // clang-format on
+  lowerModuleToLLVM(ctx, module);
+  mlirRegisterAllLLVMTranslations(ctx);
+  MlirExecutionEngine jit = mlirExecutionEngineCreate(module);
+  if (mlirExecutionEngineIsNull(jit)) {
+    fprintf(stderr, "Execution engine creation failed");
+    exit(2);
+  }
+  int input = 42;
+  int result = -1;
+  void *args[2] = {&input, &result};
+  if (mlirLogicalResultIsFailure(mlirExecutionEngineInvokePacked(
+          jit, mlirStringRefCreateFromCString("add"), args))) {
+    fprintf(stderr, "Execution engine creation failed");
+    abort();
+  }
+  // CHECK: Input: 42 Result: 84
+  printf("Input: %d Result: %d\n", input, result);
+  mlirExecutionEngineDestroy(jit);
+  mlirModuleDestroy(module);
+  mlirContextDestroy(ctx);
+}
+
+int main() {
+
+#define _STRINGIFY(x) #x
+#define STRINGIFY(x) _STRINGIFY(x)
+#define TEST(test)                                                             \
+  printf("Running test '" STRINGIFY(test) "'\n");                              \
+  test();
+
+  TEST(testSimpleExecution);
+  return 0;
+}

diff  --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt
index 6f4c2384a798..d50946eddbd8 100644
--- a/mlir/test/CMakeLists.txt
+++ b/mlir/test/CMakeLists.txt
@@ -54,6 +54,7 @@ configure_lit_site_cfg(
 
 set(MLIR_TEST_DEPENDS
   FileCheck count not
+  mlir-capi-execution-engine-test
   mlir-capi-ir-test
   mlir-capi-pass-test
   mlir-cpu-runner


        


More information about the Mlir-commits mailing list