[llvm] [OCaml][NPM] Add OCaml bindings to new pass manager (PR #66421)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 14 12:26:35 PDT 2023


https://github.com/alan-j-hu created https://github.com/llvm/llvm-project/pull/66421:

I'm still torn on how to translate the LLVM API's C error handling to OCaml. Should I use the result type or exceptions?

>From 4fc0fd21d9dfce643de0384d229b9eecf193bcb1 Mon Sep 17 00:00:00 2001
From: Alan Hu <alanh at ccs.neu.edu>
Date: Thu, 16 Mar 2023 18:28:28 -0400
Subject: [PATCH] [OCaml][NPM] Add OCaml bindings to new pass manager

---
 llvm/bindings/ocaml/llvm/META.llvm.in         |   8 ++
 llvm/bindings/ocaml/target/CMakeLists.txt     |   2 +-
 llvm/bindings/ocaml/target/target_ocaml.c     |  13 +-
 llvm/bindings/ocaml/target/target_ocaml.h     |  18 +++
 llvm/bindings/ocaml/transforms/CMakeLists.txt |   1 +
 .../transforms/passbuilder/CMakeLists.txt     |   6 +
 .../passbuilder/llvm_passbuilder.ml           |  71 +++++++++
 .../passbuilder/llvm_passbuilder.mli          |  85 +++++++++++
 .../passbuilder/passbuilder_ocaml.c           | 135 ++++++++++++++++++
 llvm/test/Bindings/OCaml/passbuilder.ml       |  50 +++++++
 llvm/test/CMakeLists.txt                      |   1 +
 11 files changed, 382 insertions(+), 8 deletions(-)
 create mode 100644 llvm/bindings/ocaml/target/target_ocaml.h
 create mode 100644 llvm/bindings/ocaml/transforms/passbuilder/CMakeLists.txt
 create mode 100644 llvm/bindings/ocaml/transforms/passbuilder/llvm_passbuilder.ml
 create mode 100644 llvm/bindings/ocaml/transforms/passbuilder/llvm_passbuilder.mli
 create mode 100644 llvm/bindings/ocaml/transforms/passbuilder/passbuilder_ocaml.c
 create mode 100644 llvm/test/Bindings/OCaml/passbuilder.ml

diff --git a/llvm/bindings/ocaml/llvm/META.llvm.in b/llvm/bindings/ocaml/llvm/META.llvm.in
index fce97083257e644..def5444b046e45a 100644
--- a/llvm/bindings/ocaml/llvm/META.llvm.in
+++ b/llvm/bindings/ocaml/llvm/META.llvm.in
@@ -61,6 +61,14 @@ package "transform_utils" (
     archive(native) = "llvm_transform_utils.cmxa"
 )
 
+package "passbuilder" (
+    requires = "llvm,llvm.target"
+    version = "@PACKAGE_VERSION@"
+    description = "Pass Manager Builder for LLVM"
+    archive(byte) = "llvm_passbuilder.cma"
+    archive(native) = "llvm_passbuilder.cmxa"
+)
+
 package "target" (
     requires = "llvm"
     version  = "@PACKAGE_VERSION@"
diff --git a/llvm/bindings/ocaml/target/CMakeLists.txt b/llvm/bindings/ocaml/target/CMakeLists.txt
index 03fd231f7bea3ef..7fe896c43616c07 100644
--- a/llvm/bindings/ocaml/target/CMakeLists.txt
+++ b/llvm/bindings/ocaml/target/CMakeLists.txt
@@ -2,5 +2,5 @@ add_ocaml_library(llvm_target
   OCAML    llvm_target
   OCAMLDEP llvm
   C        target_ocaml
-  CFLAGS   "-I${CMAKE_CURRENT_SOURCE_DIR}/../llvm"
+  CFLAGS   "-I${CMAKE_CURRENT_SOURCE_DIR}/ -I${CMAKE_CURRENT_SOURCE_DIR}/../llvm"
   LLVM     Target)
diff --git a/llvm/bindings/ocaml/target/target_ocaml.c b/llvm/bindings/ocaml/target/target_ocaml.c
index ba6bf4f62339531..e80072d5eb6354a 100644
--- a/llvm/bindings/ocaml/target/target_ocaml.c
+++ b/llvm/bindings/ocaml/target/target_ocaml.c
@@ -15,15 +15,16 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#include "llvm-c/Core.h"
-#include "llvm-c/Target.h"
-#include "llvm-c/TargetMachine.h"
+#include "target_ocaml.h"
 #include "caml/alloc.h"
+#include "caml/callback.h"
+#include "caml/custom.h"
 #include "caml/fail.h"
 #include "caml/memory.h"
-#include "caml/custom.h"
-#include "caml/callback.h"
 #include "llvm_ocaml.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/Target.h"
+#include "llvm-c/TargetMachine.h"
 
 void llvm_raise(value Prototype, char *Message);
 value llvm_string_of_message(char *Message);
@@ -210,8 +211,6 @@ value llvm_target_has_asm_backend(value Target) {
 
 /*===---- Target Machine --------------------------------------------------===*/
 
-#define TargetMachine_val(v) (*(LLVMTargetMachineRef *)(Data_custom_val(v)))
-
 static void llvm_finalize_target_machine(value Machine) {
   LLVMDisposeTargetMachine(TargetMachine_val(Machine));
 }
diff --git a/llvm/bindings/ocaml/target/target_ocaml.h b/llvm/bindings/ocaml/target/target_ocaml.h
new file mode 100644
index 000000000000000..692dc27eb01c7ff
--- /dev/null
+++ b/llvm/bindings/ocaml/target/target_ocaml.h
@@ -0,0 +1,18 @@
+/*===-- target_ocaml.h - LLVM OCaml Glue ------------------------*- 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 glues LLVM's OCaml interface to its C interface. These functions *|
+|* are by and large transparent wrappers to the corresponding C functions.    *|
+|*                                                                            *|
+|* Note that these functions intentionally take liberties with the CAMLparamX *|
+|* macros, since most of the parameters are not GC heap objects.              *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#define TargetMachine_val(v) (*(LLVMTargetMachineRef *)(Data_custom_val(v)))
diff --git a/llvm/bindings/ocaml/transforms/CMakeLists.txt b/llvm/bindings/ocaml/transforms/CMakeLists.txt
index 0628d6763874ed7..014c56285c59cf5 100644
--- a/llvm/bindings/ocaml/transforms/CMakeLists.txt
+++ b/llvm/bindings/ocaml/transforms/CMakeLists.txt
@@ -1,2 +1,3 @@
+add_subdirectory(passbuilder)
 add_subdirectory(utils)
 
diff --git a/llvm/bindings/ocaml/transforms/passbuilder/CMakeLists.txt b/llvm/bindings/ocaml/transforms/passbuilder/CMakeLists.txt
new file mode 100644
index 000000000000000..0004afd914a46ed
--- /dev/null
+++ b/llvm/bindings/ocaml/transforms/passbuilder/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_ocaml_library(llvm_passbuilder
+  OCAML    llvm_passbuilder
+  OCAMLDEP llvm llvm_target
+  C        passbuilder_ocaml
+  CFLAGS   "-I${CMAKE_CURRENT_SOURCE_DIR}/../../llvm -I${CMAKE_CURRENT_SOURCE_DIR}/../../target"
+  LLVM     Passes)
diff --git a/llvm/bindings/ocaml/transforms/passbuilder/llvm_passbuilder.ml b/llvm/bindings/ocaml/transforms/passbuilder/llvm_passbuilder.ml
new file mode 100644
index 000000000000000..077970c93f8113e
--- /dev/null
+++ b/llvm/bindings/ocaml/transforms/passbuilder/llvm_passbuilder.ml
@@ -0,0 +1,71 @@
+(*===-- llvm_passbuilder.ml - LLVM OCaml Interface -------------*- OCaml -*-===*
+ *
+ * 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
+ *
+ *===----------------------------------------------------------------------===*)
+
+type llpassbuilder_options
+
+external run_passes
+  : Llvm.llmodule
+  -> string
+  -> Llvm_target.TargetMachine.t
+  -> llpassbuilder_options
+  -> (unit, string) result
+  = "llvm_run_passes"
+
+external create_passbuilder_options : unit -> llpassbuilder_options =
+  "llvm_create_passbuilder_options"
+
+external passbuilder_options_set_verify_each
+  : llpassbuilder_options -> bool -> unit =
+  "llvm_passbuilder_options_set_verify_each"
+
+external passbuilder_options_set_debug_logging
+  : llpassbuilder_options -> bool -> unit =
+  "llvm_passbuilder_options_set_debug_logging"
+
+external passbuilder_options_set_loop_interleaving
+  : llpassbuilder_options -> bool -> unit =
+  "llvm_passbuilder_options_set_loop_interleaving"
+
+external passbuilder_options_set_loop_vectorization
+  : llpassbuilder_options -> bool -> unit =
+  "llvm_passbuilder_options_set_loop_vectorization"
+
+external passbuilder_options_set_slp_vectorization
+  : llpassbuilder_options -> bool -> unit =
+  "llvm_passbuilder_options_set_slp_vectorization"
+
+external passbuilder_options_set_loop_unrolling
+  : llpassbuilder_options -> bool -> unit =
+  "llvm_passbuilder_options_set_loop_unrolling"
+
+external passbuilder_options_set_forget_all_scev_in_loop_unroll
+  : llpassbuilder_options -> bool -> unit =
+  "llvm_passbuilder_options_set_forget_all_scev_in_loop_unroll"
+
+external passbuilder_options_set_licm_mssa_opt_cap
+  : llpassbuilder_options -> int -> unit =
+  "llvm_passbuilder_options_set_licm_mssa_opt_cap"
+
+external passbuilder_options_set_licm_mssa_no_acc_for_promotion_cap
+  : llpassbuilder_options -> int -> unit =
+  "llvm_passbuilder_options_set_licm_mssa_opt_cap"
+
+external passbuilder_options_set_call_graph_profile
+  : llpassbuilder_options -> bool -> unit =
+  "llvm_passbuilder_options_set_call_graph_profile"
+
+external passbuilder_options_set_merge_functions
+  : llpassbuilder_options -> bool -> unit =
+  "llvm_passbuilder_options_set_merge_functions"
+
+external passbuilder_options_set_inliner_threshold
+  : llpassbuilder_options -> int -> unit =
+  "llvm_passbuilder_options_set_inliner_threshold"
+
+external dispose_passbuilder_options : llpassbuilder_options -> unit =
+  "llvm_dispose_passbuilder_options"
diff --git a/llvm/bindings/ocaml/transforms/passbuilder/llvm_passbuilder.mli b/llvm/bindings/ocaml/transforms/passbuilder/llvm_passbuilder.mli
new file mode 100644
index 000000000000000..31b025f536aa924
--- /dev/null
+++ b/llvm/bindings/ocaml/transforms/passbuilder/llvm_passbuilder.mli
@@ -0,0 +1,85 @@
+(*===-- llvm_passbuilder.mli - LLVM OCaml Interface ------------*- OCaml -*-===*
+ *
+ * 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
+ *
+ *===----------------------------------------------------------------------===*)
+
+type llpassbuilder_options
+
+(** [run_passes m passes tm opts] runs a set of passes over a module. The
+    format of the string [passes] is the same as opt's -passes argument for
+    the new pass manager. Individual passes may be specified, separated by
+    commas. Full pipelines may also be invoked. *)
+val run_passes
+  : Llvm.llmodule
+  -> string
+  -> Llvm_target.TargetMachine.t
+  -> llpassbuilder_options
+  -> (unit, string) result
+
+(** Creates a new set of options for a PassBuilder. *)
+val create_passbuilder_options : unit -> llpassbuilder_options
+
+(** Toggles adding the VerifierPass for the PassBuilder. *)
+val passbuilder_options_set_verify_each
+  : llpassbuilder_options -> bool -> unit
+
+(** Toggles debug logging. *)
+val passbuilder_options_set_debug_logging
+  : llpassbuilder_options -> bool -> unit
+
+(** Tuning option to set loop interleaving on/off, set based on opt level.
+    See [llvm::PipelineTuningOptions::LoopInterleaving]. *)
+val passbuilder_options_set_loop_interleaving
+  : llpassbuilder_options -> bool -> unit
+
+(** Tuning option to enable/disable loop vectorization, set based on opt level.
+    See [llvm::PipelineTuningOptions::LoopVectorization]. *)
+val passbuilder_options_set_loop_vectorization
+  : llpassbuilder_options -> bool -> unit
+
+(** Tuning option to enable/disable slp loop vectorization, set based on opt
+    level. See [llvm::PipelineTuningOptions::SLPVectorization]. *)
+val passbuilder_options_set_slp_vectorization
+  : llpassbuilder_options -> bool -> unit
+
+(** Tuning option to enable/disable loop unrolling. Its default value is true.
+    See [llvm::PipelineTuningOptions::LoopUnrolling]. *)
+val passbuilder_options_set_loop_unrolling
+  : llpassbuilder_options -> bool -> unit
+
+(** Tuning option to forget all SCEV loops in LoopUnroll.
+    See [llvm::PipelineTuningOptions::ForgetAllSCEVInLoopUnroll]. *)
+val passbuilder_options_set_forget_all_scev_in_loop_unroll
+  : llpassbuilder_options -> bool -> unit
+
+(** Tuning option to cap the number of calls to retrive clobbering accesses in
+    MemorySSA, in LICM. See [llvm::PipelineTuningOptions::LicmMssaOptCap]. *)
+val passbuilder_options_set_licm_mssa_opt_cap
+  : llpassbuilder_options -> int -> unit
+
+(** Tuning option to disable promotion to scalars in LICM with MemorySSA, if
+    the number of access is too large. See
+    [llvm::PipelineTuningOptions::LicmMssaNoAccForPromotionCap]. *)
+val passbuilder_options_set_licm_mssa_no_acc_for_promotion_cap
+  : llpassbuilder_options -> int -> unit
+
+(** Tuning option to enable/disable call graph profile. See
+    [llvm::PipelineTuningOptions::CallGraphProfile]. *)
+val passbuilder_options_set_call_graph_profile
+  : llpassbuilder_options -> bool -> unit
+
+(** Tuning option to enable/disable function merging. See
+    [llvm::PipelineTuningOptions::MergeFunctions]. *)
+val passbuilder_options_set_merge_functions
+  : llpassbuilder_options -> bool -> unit
+
+(** Tuning option to override the default inliner threshold. See
+    [llvm::PipelineTuningOptions::InlinerThreshold]. *)
+val passbuilder_options_set_inliner_threshold
+  : llpassbuilder_options -> int -> unit
+
+(** Disposes of the options. *)
+val dispose_passbuilder_options : llpassbuilder_options -> unit
diff --git a/llvm/bindings/ocaml/transforms/passbuilder/passbuilder_ocaml.c b/llvm/bindings/ocaml/transforms/passbuilder/passbuilder_ocaml.c
new file mode 100644
index 000000000000000..6144c9a9efa5ef1
--- /dev/null
+++ b/llvm/bindings/ocaml/transforms/passbuilder/passbuilder_ocaml.c
@@ -0,0 +1,135 @@
+/*===-- passbuilder_ocaml.c - LLVM OCaml Glue -------------------*- 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 glues LLVM's OCaml interface to its C interface. These functions *|
+|* are by and large transparent wrappers to the corresponding C functions.    *|
+|*                                                                            *|
+|* Note that these functions intentionally take liberties with the CAMLparamX *|
+|* macros, since most of the parameters are not GC heap objects.              *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#include "llvm_ocaml.h"
+#include "target_ocaml.h"
+#include "llvm-c/Error.h"
+#include "llvm-c/Transforms/PassBuilder.h"
+#include <caml/memory.h>
+
+#define PassBuilderOptions_val(v) ((LLVMPassBuilderOptionsRef)from_val(v))
+
+value llvm_run_passes(value M, value Passes, value TM, value Options) {
+  LLVMErrorRef Err =
+      LLVMRunPasses(Module_val(M), String_val(Passes), TargetMachine_val(TM),
+                    PassBuilderOptions_val(Options));
+  if (Err == LLVMErrorSuccess) {
+    value result = caml_alloc(1, 0);
+    Store_field(result, 0, Val_unit);
+    return result;
+  } else {
+    char *str = LLVMGetErrorMessage(Err);
+    value v = caml_copy_string(str);
+    LLVMDisposeErrorMessage(str);
+    value result = caml_alloc(1, 1);
+    Store_field(result, 0, v);
+    return result;
+  }
+}
+
+value llvm_create_passbuilder_options(value Unit) {
+  LLVMPassBuilderOptionsRef PBO = LLVMCreatePassBuilderOptions();
+  return to_val(PBO);
+}
+
+value llvm_passbuilder_options_set_verify_each(value PBO, value VerifyEach) {
+  LLVMPassBuilderOptionsSetVerifyEach(PassBuilderOptions_val(PBO),
+                                      Bool_val(VerifyEach));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_debug_logging(value PBO,
+                                                 value DebugLogging) {
+  LLVMPassBuilderOptionsSetDebugLogging(PassBuilderOptions_val(PBO),
+                                        Bool_val(DebugLogging));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_loop_interleaving(value PBO,
+                                                     value LoopInterleaving) {
+  LLVMPassBuilderOptionsSetLoopInterleaving(PassBuilderOptions_val(PBO),
+                                            Bool_val(LoopInterleaving));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_loop_vectorization(value PBO,
+                                                      value LoopVectorization) {
+  LLVMPassBuilderOptionsSetLoopVectorization(PassBuilderOptions_val(PBO),
+                                             Bool_val(LoopVectorization));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_slp_vectorization(value PBO,
+                                                     value SLPVectorization) {
+  LLVMPassBuilderOptionsSetSLPVectorization(PassBuilderOptions_val(PBO),
+                                            Bool_val(SLPVectorization));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_loop_unrolling(value PBO,
+                                                  value LoopUnrolling) {
+  LLVMPassBuilderOptionsSetLoopUnrolling(PassBuilderOptions_val(PBO),
+                                         Bool_val(LoopUnrolling));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_forget_all_scev_in_loop_unroll(
+    value PBO, value ForgetAllSCEVInLoopUnroll) {
+  LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(
+      PassBuilderOptions_val(PBO), Bool_val(ForgetAllSCEVInLoopUnroll));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_licm_mssa_opt_cap(value PBO,
+                                                     value LicmMssaOptCap) {
+  LLVMPassBuilderOptionsSetLicmMssaOptCap(PassBuilderOptions_val(PBO),
+                                          Int_val(LicmMssaOptCap));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_licm_mssa_no_acc_for_promotion_cap(
+    value PBO, value LicmMssaNoAccForPromotionCap) {
+  LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(
+      PassBuilderOptions_val(PBO), Int_val(LicmMssaNoAccForPromotionCap));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_call_graph_profile(value PBO,
+                                                      value CallGraphProfile) {
+  LLVMPassBuilderOptionsSetCallGraphProfile(PassBuilderOptions_val(PBO),
+                                            Bool_val(CallGraphProfile));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_merge_functions(value PBO,
+                                                   value MergeFunctions) {
+  LLVMPassBuilderOptionsSetMergeFunctions(PassBuilderOptions_val(PBO),
+                                          Bool_val(MergeFunctions));
+  return Val_unit;
+}
+
+value llvm_passbuilder_options_set_inliner_threshold(value PBO,
+                                                     value InlinerThreshold) {
+  LLVMPassBuilderOptionsSetInlinerThreshold(PassBuilderOptions_val(PBO),
+                                            Int_val(InlinerThreshold));
+  return Val_unit;
+}
+
+value llvm_dispose_passbuilder_options(value PBO) {
+  LLVMDisposePassBuilderOptions(PassBuilderOptions_val(PBO));
+  return Val_unit;
+}
diff --git a/llvm/test/Bindings/OCaml/passbuilder.ml b/llvm/test/Bindings/OCaml/passbuilder.ml
new file mode 100644
index 000000000000000..f6219d7b182fa93
--- /dev/null
+++ b/llvm/test/Bindings/OCaml/passbuilder.ml
@@ -0,0 +1,50 @@
+(* RUN: rm -rf %t && mkdir -p %t && cp %s %t/passbuilder.ml
+ * RUN: %ocamlc -g -w +A -package llvm.passbuilder -package llvm.all_backends -linkpkg %t/passbuilder.ml -o %t/executable
+ * RUN: %t/executable
+ * RUN: %ocamlopt -g -w +A -package llvm.passbuilder -package llvm.all_backends -linkpkg %t/passbuilder.ml -o %t/executable
+ * RUN: %t/executable
+ * XFAIL: vg_leak
+ *)
+
+let () = Llvm_all_backends.initialize ()
+
+(*===-- Fixture -----------------------------------------------------------===*)
+
+let context = Llvm.global_context ()
+
+let m = Llvm.create_module context "mymodule"
+
+let target =
+  Llvm_target.Target.by_triple (Llvm_target.Target.default_triple ())
+
+let machine =
+  Llvm_target.TargetMachine.create
+    ~triple:(Llvm_target.Target.default_triple ()) target
+
+let options = Llvm_passbuilder.create_passbuilder_options ()
+
+(*===-- PassBuilder -------------------------------------------------------===*)
+let () =
+  Llvm_passbuilder.passbuilder_options_set_verify_each options true;
+  Llvm_passbuilder.passbuilder_options_set_debug_logging options true;
+  Llvm_passbuilder.passbuilder_options_set_loop_interleaving options true;
+  Llvm_passbuilder.passbuilder_options_set_loop_vectorization options true;
+  Llvm_passbuilder.passbuilder_options_set_slp_vectorization options true;
+  Llvm_passbuilder.passbuilder_options_set_loop_unrolling options true;
+  Llvm_passbuilder.passbuilder_options_set_forget_all_scev_in_loop_unroll
+    options true;
+  Llvm_passbuilder.passbuilder_options_set_licm_mssa_opt_cap options 2;
+  Llvm_passbuilder.passbuilder_options_set_licm_mssa_no_acc_for_promotion_cap
+    options 2;
+  Llvm_passbuilder.passbuilder_options_set_call_graph_profile options true;
+  Llvm_passbuilder.passbuilder_options_set_merge_functions options true;
+  Llvm_passbuilder.passbuilder_options_set_inliner_threshold options 2;
+  match Llvm_passbuilder.run_passes m "no-op-module" machine options with
+  | Error e ->
+    prerr_endline e;
+    assert false
+  | Ok () -> ()
+
+let () =
+  Llvm_passbuilder.dispose_passbuilder_options options;
+  Llvm.dispose_module m
diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt
index 0715e72d79f6b3f..ddfe7107ce68d85 100644
--- a/llvm/test/CMakeLists.txt
+++ b/llvm/test/CMakeLists.txt
@@ -209,6 +209,7 @@ if(TARGET ocaml_llvm)
           ocaml_llvm_executionengine
           ocaml_llvm_irreader
           ocaml_llvm_linker
+          ocaml_llvm_passbuilder
           ocaml_llvm_target
           ocaml_llvm_transform_utils
         )



More information about the llvm-commits mailing list