[Mlir-commits] [mlir] f61d102 - Add a basic C API for the MLIR PassManager as well as a basic TableGen backend for creating passes

Mehdi Amini llvmlistbot at llvm.org
Tue Nov 3 22:37:09 PST 2020


Author: Mehdi Amini
Date: 2020-11-04T06:36:31Z
New Revision: f61d1028fa55846aadcd69be17ba06bf8a710952

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

LOG: Add a basic C API for the MLIR PassManager as well as a basic TableGen backend for creating passes

This is exposing the basic functionalities (create, nest, addPass, run) of
the PassManager through the C API in the new header: `include/mlir-c/Pass.h`.

In order to exercise it in the unit-test, a basic TableGen backend is
also provided to generate a simple C wrapper around the pass
constructor. It is used to expose the libTransforms passes to the C API.

Reviewed By: stellaraccident, ftynse

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

Added: 
    mlir/include/mlir-c/Pass.h
    mlir/include/mlir-c/Transforms.h
    mlir/include/mlir/CAPI/Pass.h
    mlir/lib/CAPI/IR/Pass.cpp
    mlir/lib/CAPI/Transforms/CMakeLists.txt
    mlir/lib/CAPI/Transforms/Passes.cpp
    mlir/test/CAPI/pass.c
    mlir/tools/mlir-tblgen/PassCAPIGen.cpp

Modified: 
    mlir/include/mlir/CAPI/IR.h
    mlir/include/mlir/Transforms/CMakeLists.txt
    mlir/lib/CAPI/CMakeLists.txt
    mlir/lib/CAPI/IR/CMakeLists.txt
    mlir/test/CAPI/CMakeLists.txt
    mlir/test/CMakeLists.txt
    mlir/test/lit.cfg.py
    mlir/tools/mlir-tblgen/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir-c/Pass.h b/mlir/include/mlir-c/Pass.h
new file mode 100644
index 000000000000..4e5a4abe87bc
--- /dev/null
+++ b/mlir/include/mlir-c/Pass.h
@@ -0,0 +1,90 @@
+/*===-- mlir-c/Pass.h - C API to Pass 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 declares the C interface to MLIR pass manager.                 *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef MLIR_C_PASS_H
+#define MLIR_C_PASS_H
+
+#include "mlir-c/IR.h"
+#include "mlir-c/Support.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*============================================================================*/
+/** Opaque type declarations.
+ *
+ * Types are exposed to C bindings as structs containing opaque pointers. They
+ * are not supposed to be inspected from C. This allows the underlying
+ * representation to change without affecting the API users. The use of structs
+ * instead of typedefs enables some type safety as structs are not implicitly
+ * convertible to each other.
+ *
+ * Instances of these types may or may not own the underlying object. The
+ * ownership semantics is defined by how an instance of the type was obtained.
+ */
+/*============================================================================*/
+
+#define DEFINE_C_API_STRUCT(name, storage)                                     \
+  struct name {                                                                \
+    storage *ptr;                                                              \
+  };                                                                           \
+  typedef struct name name
+
+DEFINE_C_API_STRUCT(MlirPass, void);
+DEFINE_C_API_STRUCT(MlirPassManager, void);
+DEFINE_C_API_STRUCT(MlirOpPassManager, void);
+
+#undef DEFINE_C_API_STRUCT
+
+/** Create a new top-level PassManager. */
+MlirPassManager mlirPassManagerCreate(MlirContext ctx);
+
+/** Destroy the provided PassManager. */
+void mlirPassManagerDestroy(MlirPassManager passManager);
+
+/** Run the provided `passManager` on the given `module`. */
+MlirLogicalResult mlirPassManagerRun(MlirPassManager passManager,
+                                     MlirModule module);
+
+/** Nest an OpPassManager under the top-level PassManager, the nested
+ * passmanager will only run on operations matching the provided name.
+ * The returned OpPassManager will be destroyed when the parent is destroyed.
+ * To further nest more OpPassManager under the newly returned one, see
+ * `mlirOpPassManagerNest` below. */
+MlirOpPassManager mlirPassManagerGetNestedUnder(MlirPassManager passManager,
+                                                MlirStringRef operationName);
+
+/** Nest an OpPassManager under the provided OpPassManager, the nested
+ * passmanager will only run on operations matching the provided name.
+ * The returned OpPassManager will be destroyed when the parent is destroyed. */
+MlirOpPassManager mlirOpPassManagerGetNestedUnder(MlirOpPassManager passManager,
+                                                  MlirStringRef operationName);
+
+/** Add a pass and transfer ownership to the provided top-level mlirPassManager.
+ * If the pass is not a generic operation pass or a ModulePass, a new
+ * OpPassManager is implicitly nested under the provided PassManager. */
+void mlirPassManagerAddOwnedPass(MlirPassManager passManager, MlirPass pass);
+
+/** Add a pass and transfer ownership to the provided mlirOpPassManager. If the
+ * pass is not a generic operation pass or matching the type of the provided
+ * PassManager, a new OpPassManager is implicitly nested under the provided
+ * PassManager. */
+void mlirOpPassManagerAddOwnedPass(MlirOpPassManager passManager,
+                                   MlirPass pass);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MLIR_C_PASS_H

diff  --git a/mlir/include/mlir-c/Transforms.h b/mlir/include/mlir-c/Transforms.h
new file mode 100644
index 000000000000..2374910cc7dc
--- /dev/null
+++ b/mlir/include/mlir-c/Transforms.h
@@ -0,0 +1,20 @@
+/*===-- mlir-c/Transforms.h - Helpers for C API to Core MLIR ------*- 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              *|
+|* transformation passes.                                                     *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef MLIR_C_TRANSFORMS_H
+#define MLIR_C_TRANSFORMS_H
+
+#include "mlir/Transforms/Transforms.capi.h.inc"
+
+#endif // MLIR_C_TRANSFORMS_H

diff  --git a/mlir/include/mlir/CAPI/IR.h b/mlir/include/mlir/CAPI/IR.h
index 60ba84d1f4db..5baeea3b7edf 100644
--- a/mlir/include/mlir/CAPI/IR.h
+++ b/mlir/include/mlir/CAPI/IR.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MLIR_INCLUDE_MLIR_CAPI_IR_H
-#define MLIR_INCLUDE_MLIR_CAPI_IR_H
+#ifndef MLIR_CAPI_IR_H
+#define MLIR_CAPI_IR_H
 
 #include "mlir/CAPI/Wrap.h"
 #include "mlir/IR/Identifier.h"
@@ -35,4 +35,4 @@ DEFINE_C_API_METHODS(MlirModule, mlir::ModuleOp)
 DEFINE_C_API_METHODS(MlirType, mlir::Type)
 DEFINE_C_API_METHODS(MlirValue, mlir::Value)
 
-#endif // MLIR_INCLUDE_MLIR_CAPI_IR_H
+#endif // MLIR_CAPI_IR_H

diff  --git a/mlir/include/mlir/CAPI/Pass.h b/mlir/include/mlir/CAPI/Pass.h
new file mode 100644
index 000000000000..f895da0c8257
--- /dev/null
+++ b/mlir/include/mlir/CAPI/Pass.h
@@ -0,0 +1,28 @@
+//===- 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_PASS_H
+#define MLIR_CAPI_PASS_H
+
+#include "mlir-c/Pass.h"
+
+#include "mlir/CAPI/Wrap.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Pass/PassManager.h"
+
+DEFINE_C_API_PTR_METHODS(MlirPass, mlir::Pass)
+DEFINE_C_API_PTR_METHODS(MlirPassManager, mlir::PassManager)
+DEFINE_C_API_PTR_METHODS(MlirOpPassManager, mlir::OpPassManager)
+
+#endif // MLIR_CAPI_PASS_H

diff  --git a/mlir/include/mlir/Transforms/CMakeLists.txt b/mlir/include/mlir/Transforms/CMakeLists.txt
index f1006e06757b..a27add5968ea 100644
--- a/mlir/include/mlir/Transforms/CMakeLists.txt
+++ b/mlir/include/mlir/Transforms/CMakeLists.txt
@@ -1,6 +1,8 @@
 
 set(LLVM_TARGET_DEFINITIONS Passes.td)
 mlir_tablegen(Passes.h.inc -gen-pass-decls -name Transforms)
+mlir_tablegen(Transforms.capi.h.inc -gen-pass-capi-header --prefix Transforms)
+mlir_tablegen(Transforms.capi.cpp.inc -gen-pass-capi-impl --prefix Transforms)
 add_public_tablegen_target(MLIRTransformsPassIncGen)
 
 add_mlir_doc(Passes -gen-pass-doc GeneralPasses ./)

diff  --git a/mlir/lib/CAPI/CMakeLists.txt b/mlir/lib/CAPI/CMakeLists.txt
index b9d2c4601b98..276d7b721bca 100644
--- a/mlir/lib/CAPI/CMakeLists.txt
+++ b/mlir/lib/CAPI/CMakeLists.txt
@@ -1,3 +1,4 @@
 add_subdirectory(IR)
 add_subdirectory(Registration)
 add_subdirectory(Standard)
+add_subdirectory(Transforms)

diff  --git a/mlir/lib/CAPI/IR/CMakeLists.txt b/mlir/lib/CAPI/IR/CMakeLists.txt
index 362728fc2d6e..711bd3294bc8 100644
--- a/mlir/lib/CAPI/IR/CMakeLists.txt
+++ b/mlir/lib/CAPI/IR/CMakeLists.txt
@@ -4,6 +4,7 @@ add_mlir_library(MLIRCAPIIR
   AffineMap.cpp
   Diagnostics.cpp
   IR.cpp
+  Pass.cpp
   StandardAttributes.cpp
   StandardTypes.cpp
   Support.cpp

diff  --git a/mlir/lib/CAPI/IR/Pass.cpp b/mlir/lib/CAPI/IR/Pass.cpp
new file mode 100644
index 000000000000..7d35875d28a6
--- /dev/null
+++ b/mlir/lib/CAPI/IR/Pass.cpp
@@ -0,0 +1,53 @@
+//===- Pass.cpp - C Interface for General Pass Management APIs ------------===//
+//
+// 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/Pass.h"
+
+#include "mlir/CAPI/IR.h"
+#include "mlir/CAPI/Pass.h"
+#include "mlir/CAPI/Support.h"
+#include "mlir/CAPI/Utils.h"
+#include "mlir/Pass/PassManager.h"
+
+using namespace mlir;
+
+/* ========================================================================== */
+/* PassManager/OpPassManager APIs. */
+/* ========================================================================== */
+
+MlirPassManager mlirPassManagerCreate(MlirContext ctx) {
+  return wrap(new PassManager(unwrap(ctx)));
+}
+
+void mlirPassManagerDestroy(MlirPassManager passManager) {
+  delete unwrap(passManager);
+}
+
+MlirLogicalResult mlirPassManagerRun(MlirPassManager passManager,
+                                     MlirModule module) {
+  return wrap(unwrap(passManager)->run(unwrap(module)));
+}
+
+MlirOpPassManager mlirPassManagerGetNestedUnder(MlirPassManager passManager,
+                                                MlirStringRef operationName) {
+  return wrap(&unwrap(passManager)->nest(unwrap(operationName)));
+}
+
+MlirOpPassManager mlirOpPassManagerGetNestedUnder(MlirOpPassManager passManager,
+                                                  MlirStringRef operationName) {
+  return wrap(&unwrap(passManager)->nest(unwrap(operationName)));
+}
+
+void mlirPassManagerAddOwnedPass(MlirPassManager passManager, MlirPass pass) {
+  unwrap(passManager)->addPass(std::unique_ptr<Pass>(unwrap(pass)));
+}
+
+void mlirOpPassManagerAddOwnedPass(MlirOpPassManager passManager,
+                                   MlirPass pass) {
+  unwrap(passManager)->addPass(std::unique_ptr<Pass>(unwrap(pass)));
+}

diff  --git a/mlir/lib/CAPI/Transforms/CMakeLists.txt b/mlir/lib/CAPI/Transforms/CMakeLists.txt
new file mode 100644
index 000000000000..5d73be0d5dd0
--- /dev/null
+++ b/mlir/lib/CAPI/Transforms/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_mlir_library(MLIRCAPITransforms
+
+  Passes.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir-c
+
+  LINK_LIBS PUBLIC
+  MLIRTransforms
+  )

diff  --git a/mlir/lib/CAPI/Transforms/Passes.cpp b/mlir/lib/CAPI/Transforms/Passes.cpp
new file mode 100644
index 000000000000..9fd00efa4767
--- /dev/null
+++ b/mlir/lib/CAPI/Transforms/Passes.cpp
@@ -0,0 +1,23 @@
+//===- CAPIPAsses.cpp - C API for Tranformations 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/Transforms/Passes.h"
+#include "mlir/CAPI/Pass.h"
+#include "mlir/Pass/Pass.h"
+
+using namespace mlir;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "mlir/Transforms/Transforms.capi.cpp.inc"
+
+#ifdef __cplusplus
+}
+#endif

diff  --git a/mlir/test/CAPI/CMakeLists.txt b/mlir/test/CAPI/CMakeLists.txt
index 876d701d7211..cf7731405817 100644
--- a/mlir/test/CAPI/CMakeLists.txt
+++ b/mlir/test/CAPI/CMakeLists.txt
@@ -1,3 +1,8 @@
+set(LLVM_OPTIONAL_SOURCES
+  ir.c
+  pass.c
+)
+
 set(LLVM_LINK_COMPONENTS
   Core
   Support
@@ -15,3 +20,18 @@ target_link_libraries(mlir-capi-ir-test
   MLIRCAPIRegistration
   MLIRCAPIStandard
   ${dialect_libs})
+
+
+add_llvm_executable(mlir-capi-pass-test
+  pass.c
+  )
+llvm_update_compile_flags(mlir-capi-pass-test)
+
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+target_link_libraries(mlir-capi-pass-test
+  PRIVATE
+  MLIRCAPIIR
+  MLIRCAPIRegistration
+  MLIRCAPIStandard
+  MLIRCAPITransforms
+  ${dialect_libs})

diff  --git a/mlir/test/CAPI/pass.c b/mlir/test/CAPI/pass.c
new file mode 100644
index 000000000000..ff67eda68cc9
--- /dev/null
+++ b/mlir/test/CAPI/pass.c
@@ -0,0 +1,124 @@
+/*===- pass.c - Simple test of C APIs -------------------------------------===*\
+|*                                                                            *|
+|* 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-pass-test 2>&1 | FileCheck %s
+ */
+
+#include "mlir-c/Pass.h"
+#include "mlir-c/IR.h"
+#include "mlir-c/Registration.h"
+#include "mlir-c/Transforms.h"
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void testRunPassOnModule() {
+  MlirContext ctx = mlirContextCreate();
+  mlirRegisterAllDialects(ctx);
+
+  MlirModule module =
+      mlirModuleCreateParse(ctx,
+                            // clang-format off
+"func @foo(%arg0 : i32) -> i32 {                                            \n"
+"  %res = addi %arg0, %arg0 : i32                                           \n"
+"  return %res : i32                                                        \n"
+"}");
+  // clang-format on
+  if (mlirModuleIsNull(module))
+    exit(EXIT_FAILURE);
+
+  // Run the print-op-stats pass on the top-level module:
+  // CHECK-LABEL: Operations encountered:
+  // CHECK: func              , 1
+  // CHECK: module_terminator , 1
+  // CHECK: std.addi          , 1
+  // CHECK: std.return        , 1
+  {
+    MlirPassManager pm = mlirPassManagerCreate(ctx);
+    MlirPass printOpStatPass = mlirCreateTransformsPrintOpStats();
+    mlirPassManagerAddOwnedPass(pm, printOpStatPass);
+    MlirLogicalResult success = mlirPassManagerRun(pm, module);
+    if (mlirLogicalResultIsFailure(success))
+      exit(EXIT_FAILURE);
+    mlirPassManagerDestroy(pm);
+  }
+  mlirModuleDestroy(module);
+  mlirContextDestroy(ctx);
+}
+
+void testRunPassOnNestedModule() {
+  MlirContext ctx = mlirContextCreate();
+  mlirRegisterAllDialects(ctx);
+
+  MlirModule module =
+      mlirModuleCreateParse(ctx,
+                            // clang-format off
+"func @foo(%arg0 : i32) -> i32 {                                            \n"
+"  %res = addi %arg0, %arg0 : i32                                           \n"
+"  return %res : i32                                                        \n"
+"}                                                                          \n"
+"module {                                                                   \n"
+"  func @bar(%arg0 : f32) -> f32 {                                          \n"
+"    %res = addf %arg0, %arg0 : f32                                         \n"
+"    return %res : f32                                                      \n"
+"  }                                                                        \n"
+"}");
+  // clang-format on
+  if (mlirModuleIsNull(module))
+    exit(1);
+
+  // Run the print-op-stats pass on functions under the top-level module:
+  // CHECK-LABEL: Operations encountered:
+  // CHECK-NOT: module_terminator
+  // CHECK: func              , 1
+  // CHECK: std.addi          , 1
+  // CHECK: std.return        , 1
+  {
+    MlirPassManager pm = mlirPassManagerCreate(ctx);
+    MlirOpPassManager nestedFuncPm = mlirPassManagerGetNestedUnder(
+        pm, mlirStringRefCreateFromCString("func"));
+    MlirPass printOpStatPass = mlirCreateTransformsPrintOpStats();
+    mlirOpPassManagerAddOwnedPass(nestedFuncPm, printOpStatPass);
+    MlirLogicalResult success = mlirPassManagerRun(pm, module);
+    if (mlirLogicalResultIsFailure(success))
+      exit(2);
+    mlirPassManagerDestroy(pm);
+  }
+  // Run the print-op-stats pass on functions under the nested module:
+  // CHECK-LABEL: Operations encountered:
+  // CHECK-NOT: module_terminator
+  // CHECK: func              , 1
+  // CHECK: std.addf          , 1
+  // CHECK: std.return        , 1
+  {
+    MlirPassManager pm = mlirPassManagerCreate(ctx);
+    MlirOpPassManager nestedModulePm = mlirPassManagerGetNestedUnder(
+        pm, mlirStringRefCreateFromCString("module"));
+    MlirOpPassManager nestedFuncPm = mlirOpPassManagerGetNestedUnder(
+        nestedModulePm, mlirStringRefCreateFromCString("func"));
+    MlirPass printOpStatPass = mlirCreateTransformsPrintOpStats();
+    mlirOpPassManagerAddOwnedPass(nestedFuncPm, printOpStatPass);
+    MlirLogicalResult success = mlirPassManagerRun(pm, module);
+    if (mlirLogicalResultIsFailure(success))
+      exit(2);
+    mlirPassManagerDestroy(pm);
+  }
+
+  mlirModuleDestroy(module);
+  mlirContextDestroy(ctx);
+}
+
+int main() {
+  testRunPassOnModule();
+  testRunPassOnNestedModule();
+  return 0;
+}

diff  --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt
index b9bc6bfb960a..8b5d3d409e43 100644
--- a/mlir/test/CMakeLists.txt
+++ b/mlir/test/CMakeLists.txt
@@ -43,6 +43,7 @@ set(MLIR_TEST_DEPENDS
   FileCheck count not
   MLIRUnitTests
   mlir-capi-ir-test
+  mlir-capi-pass-test
   mlir-cpu-runner
   mlir-edsc-builder-api-test
   mlir-linalg-ods-gen

diff  --git a/mlir/test/lit.cfg.py b/mlir/test/lit.cfg.py
index e50d4b0b8049..482513b8bb74 100644
--- a/mlir/test/lit.cfg.py
+++ b/mlir/test/lit.cfg.py
@@ -59,6 +59,7 @@
     'mlir-tblgen',
     'mlir-translate',
     'mlir-capi-ir-test',
+    'mlir-capi-pass-test',
     'mlir-edsc-builder-api-test',
 ]
 

diff  --git a/mlir/tools/mlir-tblgen/CMakeLists.txt b/mlir/tools/mlir-tblgen/CMakeLists.txt
index 280fcc4762e7..5686e63fbdde 100644
--- a/mlir/tools/mlir-tblgen/CMakeLists.txt
+++ b/mlir/tools/mlir-tblgen/CMakeLists.txt
@@ -15,8 +15,9 @@ add_tablegen(mlir-tblgen MLIR
   OpFormatGen.cpp
   OpInterfacesGen.cpp
   OpenMPCommonGen.cpp
-  PassGen.cpp
+  PassCAPIGen.cpp
   PassDocGen.cpp
+  PassGen.cpp
   RewriterGen.cpp
   SPIRVUtilsGen.cpp
   StructsGen.cpp

diff  --git a/mlir/tools/mlir-tblgen/PassCAPIGen.cpp b/mlir/tools/mlir-tblgen/PassCAPIGen.cpp
new file mode 100644
index 000000000000..42507c5da7e3
--- /dev/null
+++ b/mlir/tools/mlir-tblgen/PassCAPIGen.cpp
@@ -0,0 +1,93 @@
+//===- Pass.cpp - MLIR pass registration generator ------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// PassCAPIGen uses the description of passes to generate C API for the passes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/TableGen/GenInfo.h"
+#include "mlir/TableGen/Pass.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+
+using namespace mlir;
+using namespace mlir::tblgen;
+
+static llvm::cl::OptionCategory
+    passGenCat("Options for -gen-pass-capi-header and -gen-pass-capi-impl");
+static llvm::cl::opt<std::string>
+    groupName("prefix",
+              llvm::cl::desc("The prefix to use for this group of passes. The "
+                             "form will be mlirCreate<prefix><passname>, the "
+                             "prefix can avoid conflicts across libraries."),
+              llvm::cl::cat(passGenCat));
+
+const char *const passDecl = R"(
+/* Create {0} Pass. */
+MlirPass mlirCreate{0}{1}();
+
+)";
+
+const char *const fileHeader = R"(
+/* Autogenerated by mlir-tblgen; don't manually edit. */
+
+#include "mlir-c/Pass.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+)";
+
+const char *const fileFooter = R"(
+
+#ifdef __cplusplus
+}
+#endif
+)";
+
+/// Emit TODO
+static bool emitCAPIHeader(const llvm::RecordKeeper &records, raw_ostream &os) {
+  os << fileHeader;
+  for (const auto *def : records.getAllDerivedDefinitions("PassBase")) {
+    Pass pass(def);
+    StringRef defName = pass.getDef()->getName();
+    os << llvm::formatv(passDecl, groupName, defName);
+  }
+  os << fileFooter;
+  return false;
+}
+
+const char *const passCreateDef = R"(
+MlirPass mlirCreate{0}{1}() {
+  return wrap({2}.release());
+}
+
+)";
+
+static bool emitCAPIImpl(const llvm::RecordKeeper &records, raw_ostream &os) {
+  os << "/* Autogenerated by mlir-tblgen; don't manually edit. */";
+  for (const auto *def : records.getAllDerivedDefinitions("PassBase")) {
+    Pass pass(def);
+    StringRef defName = pass.getDef()->getName();
+    os << llvm::formatv(passCreateDef, groupName, defName,
+                        pass.getConstructor());
+  }
+  return false;
+}
+
+static mlir::GenRegistration genCAPIHeader("gen-pass-capi-header",
+                                           "Generate pass C API header",
+                                           &emitCAPIHeader);
+
+static mlir::GenRegistration genCAPIImpl("gen-pass-capi-impl",
+                                         "Generate pass C API implementation",
+                                         &emitCAPIImpl);


        


More information about the Mlir-commits mailing list