[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