[llvm] 30f423a - [OCaml] Migrate from naked pointers to prepare for OCaml 5

Josh Berdine via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 28 15:53:53 PST 2023


Author: Alan Hu
Date: 2023-02-28T23:52:49Z
New Revision: 30f423a543641816e367cd17dad3d4808cba8a79

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

LOG: [OCaml] Migrate from naked pointers to prepare for OCaml 5

The OCaml bindings currently return pointers to LLVM objects as-is to
OCaml. These "naked pointers" end up appearing as values of local
variables in OCaml code, stored as part of other OCaml values,
etc. The safety of this design relies on the OCaml runtime system's
ability to distinguish these pointers from pointers to memory on the
OCaml garbage collected heap. In particular, when the OCaml GC
encounters a pointer to memory known to not be part of the OCaml heap,
it does not follow it.

In OCaml 4.02 an optimized "no naked pointers" mode was introduced
where the runtime system does not perform such checks and requires
that no such naked pointers be passed to OCaml code, instead one of
several encodings needs to be used. In OCaml 5, the no naked pointers
mode is now the only mode. This diff uses one of the potential
encodings to eliminate naked pointers, making the LLVM OCaml bindings
compatible with the "no naked pointers" mode of OCaml >= 4.02 and 5.

The encoding implemented in this diff relies on LLVM objects to be at
least 2-byte aligned, meaning that the lsb of pointers will
necessarily be clear. The encoding sets the lsb when passing LLVM
pointers to OCaml, and clears it on the return path. Setting the lsb
causes the OCaml runtime system to interpret the resulting value as a
tagged integer, which does not participate in garbage collection.

In some cases, particularly functions that receive an OCaml array of
LLVM pointers, this encoding requires allocation of a temporary array,
but otherwise this diff aims to preserve the existing performance
characteristics of the OCaml bindings.

Reviewed By: jberdine

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

Added: 
    

Modified: 
    llvm/bindings/ocaml/analysis/analysis_ocaml.c
    llvm/bindings/ocaml/bitreader/CMakeLists.txt
    llvm/bindings/ocaml/bitreader/bitreader_ocaml.c
    llvm/bindings/ocaml/bitwriter/CMakeLists.txt
    llvm/bindings/ocaml/bitwriter/bitwriter_ocaml.c
    llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c
    llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml
    llvm/bindings/ocaml/executionengine/CMakeLists.txt
    llvm/bindings/ocaml/executionengine/executionengine_ocaml.c
    llvm/bindings/ocaml/irreader/CMakeLists.txt
    llvm/bindings/ocaml/irreader/irreader_ocaml.c
    llvm/bindings/ocaml/linker/CMakeLists.txt
    llvm/bindings/ocaml/linker/linker_ocaml.c
    llvm/bindings/ocaml/llvm/llvm.ml
    llvm/bindings/ocaml/llvm/llvm_ocaml.c
    llvm/bindings/ocaml/llvm/llvm_ocaml.h
    llvm/bindings/ocaml/target/target_ocaml.c
    llvm/bindings/ocaml/transforms/utils/CMakeLists.txt
    llvm/bindings/ocaml/transforms/utils/transform_utils_ocaml.c
    llvm/test/Bindings/OCaml/core.ml
    llvm/test/Bindings/OCaml/debuginfo.ml

Removed: 
    


################################################################################
diff  --git a/llvm/bindings/ocaml/analysis/analysis_ocaml.c b/llvm/bindings/ocaml/analysis/analysis_ocaml.c
index 8fb81ee485258..c16a3ca9c9436 100644
--- a/llvm/bindings/ocaml/analysis/analysis_ocaml.c
+++ b/llvm/bindings/ocaml/analysis/analysis_ocaml.c
@@ -23,17 +23,18 @@
 #include "llvm_ocaml.h"
 
 /* Llvm.llmodule -> string option */
-value llvm_verify_module(LLVMModuleRef M) {
+value llvm_verify_module(value M) {
   CAMLparam0();
   CAMLlocal2(String, Option);
 
   char *Message;
-  int Result = LLVMVerifyModule(M, LLVMReturnStatusAction, &Message);
+  int Result =
+      LLVMVerifyModule(Module_val(M), LLVMReturnStatusAction, &Message);
 
   if (0 == Result) {
     Option = Val_none;
   } else {
-    String = copy_string(Message);
+    String = caml_copy_string(Message);
     Option = caml_alloc_some(String);
   }
 
@@ -43,30 +44,31 @@ value llvm_verify_module(LLVMModuleRef M) {
 }
 
 /* Llvm.llvalue -> bool */
-value llvm_verify_function(LLVMValueRef Fn) {
-  return Val_bool(LLVMVerifyFunction(Fn, LLVMReturnStatusAction) == 0);
+value llvm_verify_function(value Fn) {
+  return Val_bool(LLVMVerifyFunction(Value_val(Fn), LLVMReturnStatusAction) ==
+                  0);
 }
 
 /* Llvm.llmodule -> unit */
-value llvm_assert_valid_module(LLVMModuleRef M) {
-  LLVMVerifyModule(M, LLVMAbortProcessAction, 0);
+value llvm_assert_valid_module(value M) {
+  LLVMVerifyModule(Module_val(M), LLVMAbortProcessAction, 0);
   return Val_unit;
 }
 
 /* Llvm.llvalue -> unit */
-value llvm_assert_valid_function(LLVMValueRef Fn) {
-  LLVMVerifyFunction(Fn, LLVMAbortProcessAction);
+value llvm_assert_valid_function(value Fn) {
+  LLVMVerifyFunction(Value_val(Fn), LLVMAbortProcessAction);
   return Val_unit;
 }
 
 /* Llvm.llvalue -> unit */
-value llvm_view_function_cfg(LLVMValueRef Fn) {
-  LLVMViewFunctionCFG(Fn);
+value llvm_view_function_cfg(value Fn) {
+  LLVMViewFunctionCFG(Value_val(Fn));
   return Val_unit;
 }
 
 /* Llvm.llvalue -> unit */
-value llvm_view_function_cfg_only(LLVMValueRef Fn) {
-  LLVMViewFunctionCFGOnly(Fn);
+value llvm_view_function_cfg_only(value Fn) {
+  LLVMViewFunctionCFGOnly(Value_val(Fn));
   return Val_unit;
 }

diff  --git a/llvm/bindings/ocaml/bitreader/CMakeLists.txt b/llvm/bindings/ocaml/bitreader/CMakeLists.txt
index d71f51c28b453..90e444b9657ef 100644
--- a/llvm/bindings/ocaml/bitreader/CMakeLists.txt
+++ b/llvm/bindings/ocaml/bitreader/CMakeLists.txt
@@ -2,4 +2,5 @@ add_ocaml_library(llvm_bitreader
   OCAML    llvm_bitreader
   OCAMLDEP llvm
   C        bitreader_ocaml
+  CFLAGS   "-I${CMAKE_CURRENT_SOURCE_DIR}/../llvm"
   LLVM     BitReader)

diff  --git a/llvm/bindings/ocaml/bitreader/bitreader_ocaml.c b/llvm/bindings/ocaml/bitreader/bitreader_ocaml.c
index 518103e6b606a..121474d5ae01e 100644
--- a/llvm/bindings/ocaml/bitreader/bitreader_ocaml.c
+++ b/llvm/bindings/ocaml/bitreader/bitreader_ocaml.c
@@ -12,33 +12,35 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#include "llvm-c/BitReader.h"
-#include "llvm-c/Core.h"
 #include "caml/alloc.h"
+#include "caml/callback.h"
 #include "caml/fail.h"
 #include "caml/memory.h"
-#include "caml/callback.h"
+#include "llvm_ocaml.h"
+#include "llvm-c/BitReader.h"
+#include "llvm-c/Core.h"
 
 void llvm_raise(value Prototype, char *Message);
 
 /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */
-LLVMModuleRef llvm_get_module(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) {
+value llvm_get_module(value C, value MemBuf) {
   LLVMModuleRef M;
 
-  if (LLVMGetBitcodeModuleInContext2(C, MemBuf, &M))
+  if (LLVMGetBitcodeModuleInContext2(Context_val(C), MemoryBuffer_val(MemBuf),
+                                     &M))
     llvm_raise(*caml_named_value("Llvm_bitreader.Error"),
                LLVMCreateMessage(""));
 
-  return M;
+  return to_val(M);
 }
 
 /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */
-LLVMModuleRef llvm_parse_bitcode(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) {
+value llvm_parse_bitcode(value C, value MemBuf) {
   LLVMModuleRef M;
 
-  if (LLVMParseBitcodeInContext2(C, MemBuf, &M))
+  if (LLVMParseBitcodeInContext2(Context_val(C), MemoryBuffer_val(MemBuf), &M))
     llvm_raise(*caml_named_value("Llvm_bitreader.Error"),
                LLVMCreateMessage(""));
 
-  return M;
+  return to_val(M);
 }

diff  --git a/llvm/bindings/ocaml/bitwriter/CMakeLists.txt b/llvm/bindings/ocaml/bitwriter/CMakeLists.txt
index 6462d65c8669a..ec7d0a5127b15 100644
--- a/llvm/bindings/ocaml/bitwriter/CMakeLists.txt
+++ b/llvm/bindings/ocaml/bitwriter/CMakeLists.txt
@@ -2,4 +2,6 @@ add_ocaml_library(llvm_bitwriter
   OCAML    llvm_bitwriter
   OCAMLDEP llvm
   C        bitwriter_ocaml
+  CFLAGS   "-I${CMAKE_CURRENT_SOURCE_DIR}/../llvm"
+  PKG      unix
   LLVM     BitWriter)

diff  --git a/llvm/bindings/ocaml/bitwriter/bitwriter_ocaml.c b/llvm/bindings/ocaml/bitwriter/bitwriter_ocaml.c
index 8ced8dd76eaf1..8812f52c18214 100644
--- a/llvm/bindings/ocaml/bitwriter/bitwriter_ocaml.c
+++ b/llvm/bindings/ocaml/bitwriter/bitwriter_ocaml.c
@@ -15,20 +15,21 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#include "llvm-c/BitWriter.h"
-#include "llvm-c/Core.h"
 #include "caml/alloc.h"
-#include "caml/mlvalues.h"
 #include "caml/memory.h"
+#include "caml/mlvalues.h"
+#include "llvm_ocaml.h"
+#include "llvm-c/BitWriter.h"
+#include "llvm-c/Core.h"
 
 /* Llvm.llmodule -> string -> bool */
-value llvm_write_bitcode_file(LLVMModuleRef M, value Path) {
-  int Result = LLVMWriteBitcodeToFile(M, String_val(Path));
+value llvm_write_bitcode_file(value M, value Path) {
+  int Result = LLVMWriteBitcodeToFile(Module_val(M), String_val(Path));
   return Val_bool(Result == 0);
 }
 
 /* ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool */
-value llvm_write_bitcode_to_fd(value U, LLVMModuleRef M, value FD) {
+value llvm_write_bitcode_to_fd(value U, value M, value FD) {
   int Unbuffered;
   int Result;
 
@@ -38,11 +39,11 @@ value llvm_write_bitcode_to_fd(value U, LLVMModuleRef M, value FD) {
     Unbuffered = Bool_val(Field(U, 0));
   }
 
-  Result = LLVMWriteBitcodeToFD(M, Int_val(FD), 0, Unbuffered);
+  Result = LLVMWriteBitcodeToFD(Module_val(M), Int_val(FD), 0, Unbuffered);
   return Val_bool(Result == 0);
 }
 
 /* Llvm.llmodule -> Llvm.llmemorybuffer */
-LLVMMemoryBufferRef llvm_write_bitcode_to_memory_buffer(LLVMModuleRef M) {
-  return LLVMWriteBitcodeToMemoryBuffer(M);
+value llvm_write_bitcode_to_memory_buffer(value M) {
+  return to_val(LLVMWriteBitcodeToMemoryBuffer(Module_val(M)));
 }

diff  --git a/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c b/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c
index afbdf87b66c34..510244b32c290 100644
--- a/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c
+++ b/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c
@@ -139,12 +139,14 @@ static LLVMDIFlags map_DIFlag(LLVMDIFlag_i DIF) {
   }
 }
 
+/* unit -> int */
 value llvm_debug_metadata_version(value Unit) {
   return Val_int(LLVMDebugMetadataVersion());
 }
 
-value llvm_get_module_debug_metadata_version(LLVMModuleRef Module) {
-  return Val_int(LLVMGetModuleDebugMetadataVersion(Module));
+/* llmodule -> int */
+value llvm_get_module_debug_metadata_version(value Module) {
+  return Val_int(LLVMGetModuleDebugMetadataVersion(Module_val(Module)));
 }
 
 #define DIFlags_val(v) (*(LLVMDIFlags *)(Data_custom_val(v)))
@@ -156,7 +158,7 @@ static struct custom_operations diflags_ops = {
     custom_compare_ext_default};
 
 static value alloc_diflags(LLVMDIFlags Flags) {
-  value V = alloc_custom(&diflags_ops, sizeof(LLVMDIFlags), 0, 1);
+  value V = caml_alloc_custom(&diflags_ops, sizeof(LLVMDIFlags), 0, 1);
   DIFlags_val(V) = Flags;
   return V;
 }
@@ -190,14 +192,14 @@ static struct custom_operations dibuilder_ops = {
     custom_compare_ext_default};
 
 static value alloc_dibuilder(LLVMDIBuilderRef B) {
-  value V = alloc_custom(&dibuilder_ops, sizeof(LLVMDIBuilderRef), 0, 1);
+  value V = caml_alloc_custom(&dibuilder_ops, sizeof(LLVMDIBuilderRef), 0, 1);
   DIBuilder_val(V) = B;
   return V;
 }
 
 /* llmodule -> lldibuilder */
-value llvm_dibuilder(LLVMModuleRef M) {
-  return alloc_dibuilder(LLVMCreateDIBuilder(M));
+value llvm_dibuilder(value M) {
+  return alloc_dibuilder(LLVMCreateDIBuilder(Module_val(M)));
 }
 
 value llvm_dibuild_finalize(value Builder) {
@@ -205,99 +207,97 @@ value llvm_dibuild_finalize(value Builder) {
   return Val_unit;
 }
 
-LLVMMetadataRef llvm_dibuild_create_compile_unit_native(
-    value Builder, value Lang, LLVMMetadataRef FileRef, value Producer,
-    value IsOptimized, value Flags, value RuntimeVer, value SplitName,
-    value Kind, value DWOId, value SplitDebugInline,
-    value DebugInfoForProfiling, value SysRoot, value SDK) {
-  return LLVMDIBuilderCreateCompileUnit(
-      DIBuilder_val(Builder), Int_val(Lang), FileRef, String_val(Producer),
-      caml_string_length(Producer), Bool_val(IsOptimized), String_val(Flags),
-      caml_string_length(Flags), Int_val(RuntimeVer), String_val(SplitName),
-      caml_string_length(SplitName), Int_val(Kind), Int_val(DWOId),
-      Bool_val(SplitDebugInline), Bool_val(DebugInfoForProfiling),
-      String_val(SysRoot), caml_string_length(SysRoot), String_val(SDK),
-      caml_string_length(SDK));
+value llvm_dibuild_create_compile_unit_native(
+    value Builder, value Lang, value FileRef, value Producer, value IsOptimized,
+    value Flags, value RuntimeVer, value SplitName, value Kind, value DWOId,
+    value SplitDebugInline, value DebugInfoForProfiling, value SysRoot,
+    value SDK) {
+  return to_val(LLVMDIBuilderCreateCompileUnit(
+      DIBuilder_val(Builder), Int_val(Lang), Metadata_val(FileRef),
+      String_val(Producer), caml_string_length(Producer), Bool_val(IsOptimized),
+      String_val(Flags), caml_string_length(Flags), Int_val(RuntimeVer),
+      String_val(SplitName), caml_string_length(SplitName), Int_val(Kind),
+      Int_val(DWOId), Bool_val(SplitDebugInline),
+      Bool_val(DebugInfoForProfiling), String_val(SysRoot),
+      caml_string_length(SysRoot), String_val(SDK), caml_string_length(SDK)));
 }
 
-LLVMMetadataRef llvm_dibuild_create_compile_unit_bytecode(value *argv,
-                                                          int argn) {
+value llvm_dibuild_create_compile_unit_bytecode(value *argv, int argn) {
   return llvm_dibuild_create_compile_unit_native(
-      argv[0],                  // Builder
-      argv[1],                  // Lang
-      (LLVMMetadataRef)argv[2], // FileRef
-      argv[3],                  // Producer
-      argv[4],                  // IsOptimized
-      argv[5],                  // Flags
-      argv[6],                  // RuntimeVer
-      argv[7],                  // SplitName
-      argv[8],                  // Kind
-      argv[9],                  // DWOId
-      argv[10],                 // SplitDebugInline
-      argv[11],                 // DebugInfoForProfiling
-      argv[12],                 // SysRoot
-      argv[13]                  // SDK
+      argv[0],  // Builder
+      argv[1],  // Lang
+      argv[2],  // FileRef
+      argv[3],  // Producer
+      argv[4],  // IsOptimized
+      argv[5],  // Flags
+      argv[6],  // RuntimeVer
+      argv[7],  // SplitName
+      argv[8],  // Kind
+      argv[9],  // DWOId
+      argv[10], // SplitDebugInline
+      argv[11], // DebugInfoForProfiling
+      argv[12], // SysRoot
+      argv[13]  // SDK
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_file(value Builder, value Filename,
-                                         value Directory) {
-  return LLVMDIBuilderCreateFile(DIBuilder_val(Builder), String_val(Filename),
-                                 caml_string_length(Filename),
-                                 String_val(Directory),
-                                 caml_string_length(Directory));
+value llvm_dibuild_create_file(value Builder, value Filename, value Directory) {
+  return to_val(LLVMDIBuilderCreateFile(
+      DIBuilder_val(Builder), String_val(Filename),
+      caml_string_length(Filename), String_val(Directory),
+      caml_string_length(Directory)));
 }
 
-LLVMMetadataRef
-llvm_dibuild_create_module_native(value Builder, LLVMMetadataRef ParentScope,
-                                  value Name, value ConfigMacros,
-                                  value IncludePath, value SysRoot) {
-  return LLVMDIBuilderCreateModule(
-      DIBuilder_val(Builder), ParentScope, String_val(Name),
+value llvm_dibuild_create_module_native(value Builder, value ParentScope,
+                                        value Name, value ConfigMacros,
+                                        value IncludePath, value SysRoot) {
+  return to_val(LLVMDIBuilderCreateModule(
+      DIBuilder_val(Builder), Metadata_val(ParentScope), String_val(Name),
       caml_string_length(Name), String_val(ConfigMacros),
       caml_string_length(ConfigMacros), String_val(IncludePath),
       caml_string_length(IncludePath), String_val(SysRoot),
-      caml_string_length(SysRoot));
+      caml_string_length(SysRoot)));
 }
 
-LLVMMetadataRef llvm_dibuild_create_module_bytecode(value *argv, int argn) {
-  return llvm_dibuild_create_module_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // ParentScope
-      argv[2],                  // Name
-      argv[3],                  // ConfigMacros
-      argv[4],                  // IncludePath
-      argv[5]                   // SysRoot
+value llvm_dibuild_create_module_bytecode(value *argv, int argn) {
+  return llvm_dibuild_create_module_native(argv[0], // Builder
+                                           argv[1], // ParentScope
+                                           argv[2], // Name
+                                           argv[3], // ConfigMacros
+                                           argv[4], // IncludePath
+                                           argv[5]  // SysRoot
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_namespace(value Builder,
-                                              LLVMMetadataRef ParentScope,
-                                              value Name, value ExportSymbols) {
-  return LLVMDIBuilderCreateNameSpace(
-      DIBuilder_val(Builder), ParentScope, String_val(Name),
-      caml_string_length(Name), Bool_val(ExportSymbols));
-}
-
-LLVMMetadataRef llvm_dibuild_create_function_native(
-    value Builder, LLVMMetadataRef Scope, value Name, value LinkageName,
-    LLVMMetadataRef File, value LineNo, LLVMMetadataRef Ty, value IsLocalToUnit,
-    value IsDefinition, value ScopeLine, value Flags, value IsOptimized) {
-  return LLVMDIBuilderCreateFunction(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      String_val(LinkageName), caml_string_length(LinkageName), File,
-      Int_val(LineNo), Ty, Bool_val(IsLocalToUnit), Bool_val(IsDefinition),
-      Int_val(ScopeLine), DIFlags_val(Flags), Bool_val(IsOptimized));
-}
-
-LLVMMetadataRef llvm_dibuild_create_function_bytecode(value *argv, int argn) {
-  return llvm_dibuild_create_function_native(argv[0], // Builder,
-                                             (LLVMMetadataRef)argv[1], // Scope
-                                             argv[2],                  // Name
-                                             argv[3], // LinkageName
-                                             (LLVMMetadataRef)argv[4], // File
-                                             argv[5],                  // LineNo
-                                             (LLVMMetadataRef)argv[6], // Ty
+value llvm_dibuild_create_namespace(value Builder, value ParentScope,
+                                    value Name, value ExportSymbols) {
+  return to_val(LLVMDIBuilderCreateNameSpace(
+      DIBuilder_val(Builder), Metadata_val(ParentScope), String_val(Name),
+      caml_string_length(Name), Bool_val(ExportSymbols)));
+}
+
+value llvm_dibuild_create_function_native(value Builder, value Scope,
+                                          value Name, value LinkageName,
+                                          value File, value LineNo, value Ty,
+                                          value IsLocalToUnit,
+                                          value IsDefinition, value ScopeLine,
+                                          value Flags, value IsOptimized) {
+  return to_val(LLVMDIBuilderCreateFunction(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), String_val(LinkageName),
+      caml_string_length(LinkageName), Metadata_val(File), Int_val(LineNo),
+      Metadata_val(Ty), Bool_val(IsLocalToUnit), Bool_val(IsDefinition),
+      Int_val(ScopeLine), DIFlags_val(Flags), Bool_val(IsOptimized)));
+}
+
+value llvm_dibuild_create_function_bytecode(value *argv, int argn) {
+  return llvm_dibuild_create_function_native(argv[0],  // Builder,
+                                             argv[1],  // Scope
+                                             argv[2],  // Name
+                                             argv[3],  // LinkageName
+                                             argv[4],  // File
+                                             argv[5],  // LineNo
+                                             argv[6],  // Ty
                                              argv[7],  // IsLocalUnit
                                              argv[8],  // IsDefinition
                                              argv[9],  // ScopeLine
@@ -306,703 +306,709 @@ LLVMMetadataRef llvm_dibuild_create_function_bytecode(value *argv, int argn) {
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_lexical_block(value Builder,
-                                                  LLVMMetadataRef Scope,
-                                                  LLVMMetadataRef File,
-                                                  value Line, value Column) {
-  return LLVMDIBuilderCreateLexicalBlock(DIBuilder_val(Builder), Scope, File,
-                                         Int_val(Line), Int_val(Column));
+value llvm_dibuild_create_lexical_block(value Builder, value Scope, value File,
+                                        value Line, value Column) {
+  return to_val(LLVMDIBuilderCreateLexicalBlock(
+      DIBuilder_val(Builder), Metadata_val(Scope), Metadata_val(File),
+      Int_val(Line), Int_val(Column)));
 }
 
-LLVMMetadataRef llvm_metadata_null() { return (LLVMMetadataRef)NULL; }
+value llvm_metadata_null(value Unit) { return to_val(NULL); }
 
-LLVMMetadataRef llvm_dibuild_create_debug_location(LLVMContextRef Ctx,
-                                                   value Line, value Column,
-                                                   LLVMMetadataRef Scope,
-                                                   LLVMMetadataRef InlinedAt) {
-  return LLVMDIBuilderCreateDebugLocation(Ctx, Int_val(Line), Int_val(Column),
-                                          Scope, InlinedAt);
+value llvm_dibuild_create_debug_location(value Ctx, value Line, value Column,
+                                         value Scope, value InlinedAt) {
+  return to_val(LLVMDIBuilderCreateDebugLocation(
+      Context_val(Ctx), Int_val(Line), Int_val(Column), Metadata_val(Scope),
+      Metadata_val(InlinedAt)));
 }
 
-value llvm_di_location_get_line(LLVMMetadataRef Location) {
-  return Val_int(LLVMDILocationGetLine(Location));
+value llvm_di_location_get_line(value Location) {
+  return Val_int(LLVMDILocationGetLine(Metadata_val(Location)));
 }
 
-value llvm_di_location_get_column(LLVMMetadataRef Location) {
-  return Val_int(LLVMDILocationGetColumn(Location));
+value llvm_di_location_get_column(value Location) {
+  return Val_int(LLVMDILocationGetColumn(Metadata_val(Location)));
 }
 
-LLVMMetadataRef llvm_di_location_get_scope(LLVMMetadataRef Location) {
-  return LLVMDILocationGetScope(Location);
+value llvm_di_location_get_scope(value Location) {
+  return to_val(LLVMDILocationGetScope(Metadata_val(Location)));
 }
 
-value llvm_di_location_get_inlined_at(LLVMMetadataRef Location) {
-  return (ptr_to_option(LLVMDILocationGetInlinedAt(Location)));
+value llvm_di_location_get_inlined_at(value Location) {
+  return ptr_to_option(LLVMDILocationGetInlinedAt(Metadata_val(Location)));
 }
 
-value llvm_di_scope_get_file(LLVMMetadataRef Scope) {
-  return (ptr_to_option(LLVMDIScopeGetFile(Scope)));
+value llvm_di_scope_get_file(value Scope) {
+  return ptr_to_option(LLVMDIScopeGetFile(Metadata_val(Scope)));
 }
 
-value llvm_di_file_get_directory(LLVMMetadataRef File) {
+value llvm_di_file_get_directory(value File) {
   unsigned Len;
-  const char *Directory = LLVMDIFileGetDirectory(File, &Len);
+  const char *Directory = LLVMDIFileGetDirectory(Metadata_val(File), &Len);
   return cstr_to_string(Directory, Len);
 }
 
-value llvm_di_file_get_filename(LLVMMetadataRef File) {
+value llvm_di_file_get_filename(value File) {
   unsigned Len;
-  const char *Filename = LLVMDIFileGetFilename(File, &Len);
+  const char *Filename = LLVMDIFileGetFilename(Metadata_val(File), &Len);
   return cstr_to_string(Filename, Len);
 }
 
-value llvm_di_file_get_source(LLVMMetadataRef File) {
+value llvm_di_file_get_source(value File) {
   unsigned Len;
-  const char *Source = LLVMDIFileGetSource(File, &Len);
+  const char *Source = LLVMDIFileGetSource(Metadata_val(File), &Len);
   return cstr_to_string(Source, Len);
 }
 
-LLVMMetadataRef llvm_dibuild_get_or_create_type_array(value Builder,
-                                                      value Data) {
-
-  return LLVMDIBuilderGetOrCreateTypeArray(DIBuilder_val(Builder),
-                                           (LLVMMetadataRef *)Op_val(Data),
-                                           Wosize_val(Data));
+value llvm_dibuild_get_or_create_type_array(value Builder, value Data) {
+  mlsize_t Count = Wosize_val(Data);
+  LLVMMetadataRef *Temp = from_val_array(Data);
+  LLVMMetadataRef Metadata =
+      LLVMDIBuilderGetOrCreateTypeArray(DIBuilder_val(Builder), Temp, Count);
+  free(Temp);
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_get_or_create_array(value Builder, value Data) {
-
-  return LLVMDIBuilderGetOrCreateArray(DIBuilder_val(Builder),
-                                       (LLVMMetadataRef *)Op_val(Data),
-                                       Wosize_val(Data));
+value llvm_dibuild_get_or_create_array(value Builder, value Data) {
+  mlsize_t Count = Wosize_val(Data);
+  LLVMMetadataRef *Temp = from_val_array(Data);
+  LLVMMetadataRef Metadata =
+      LLVMDIBuilderGetOrCreateArray(DIBuilder_val(Builder), Temp, Count);
+  free(Temp);
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_subroutine_type(value Builder,
-                                                    LLVMMetadataRef File,
-                                                    value ParameterTypes,
-                                                    value Flags) {
-
-  return LLVMDIBuilderCreateSubroutineType(
-      DIBuilder_val(Builder), File, (LLVMMetadataRef *)Op_val(ParameterTypes),
+value llvm_dibuild_create_subroutine_type(value Builder, value File,
+                                          value ParameterTypes, value Flags) {
+  mlsize_t Count = Wosize_val(ParameterTypes);
+  LLVMMetadataRef *Temp = from_val_array(ParameterTypes);
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateSubroutineType(
+      DIBuilder_val(Builder), Metadata_val(File), Temp,
       Wosize_val(ParameterTypes), DIFlags_val(Flags));
+  free(Temp);
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_enumerator(value Builder, value Name,
-                                               value Value, value IsUnsigned) {
-  return LLVMDIBuilderCreateEnumerator(
+value llvm_dibuild_create_enumerator(value Builder, value Name, value Value,
+                                     value IsUnsigned) {
+  return to_val(LLVMDIBuilderCreateEnumerator(
       DIBuilder_val(Builder), String_val(Name), caml_string_length(Name),
-      (int64_t)Int_val(Value), Bool_val(IsUnsigned));
-}
-
-LLVMMetadataRef llvm_dibuild_create_enumeration_type_native(
-    value Builder, LLVMMetadataRef Scope, value Name, LLVMMetadataRef File,
-    value LineNumber, value SizeInBits, value AlignInBits, value Elements,
-    LLVMMetadataRef ClassTy) {
-  return LLVMDIBuilderCreateEnumerationType(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      File, Int_val(LineNumber), (uint64_t)Int_val(SizeInBits),
-      Int_val(AlignInBits), (LLVMMetadataRef *)Op_val(Elements),
-      Wosize_val(Elements), ClassTy);
-}
-
-LLVMMetadataRef llvm_dibuild_create_enumeration_type_bytecode(value *argv,
-                                                              int argn) {
-  return llvm_dibuild_create_enumeration_type_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // Scope
-      argv[2],                  // Name
-      (LLVMMetadataRef)argv[3], // File
-      argv[4],                  // LineNumber
-      argv[5],                  // SizeInBits
-      argv[6],                  // AlignInBits
-      argv[7],                  // Elements
-      (LLVMMetadataRef)argv[8]  // ClassTy
+      (int64_t)Int_val(Value), Bool_val(IsUnsigned)));
+}
+
+value llvm_dibuild_create_enumeration_type_native(
+    value Builder, value Scope, value Name, value File, value LineNumber,
+    value SizeInBits, value AlignInBits, value Elements, value ClassTy) {
+  mlsize_t Count = Wosize_val(Elements);
+  LLVMMetadataRef *Temp = from_val_array(Elements);
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateEnumerationType(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), Metadata_val(File), Int_val(LineNumber),
+      (uint64_t)Int_val(SizeInBits), Int_val(AlignInBits), Temp, Count,
+      Metadata_val(ClassTy));
+  free(Temp);
+  return to_val(Metadata);
+}
+
+value llvm_dibuild_create_enumeration_type_bytecode(value *argv, int argn) {
+  return llvm_dibuild_create_enumeration_type_native(argv[0], // Builder
+                                                     argv[1], // Scope
+                                                     argv[2], // Name
+                                                     argv[3], // File
+                                                     argv[4], // LineNumber
+                                                     argv[5], // SizeInBits
+                                                     argv[6], // AlignInBits
+                                                     argv[7], // Elements
+                                                     argv[8]  // ClassTy
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_union_type_native(
-    value Builder, LLVMMetadataRef Scope, value Name, LLVMMetadataRef File,
-    value LineNumber, value SizeInBits, value AlignInBits, value Flags,
-    value Elements, value RunTimeLanguage, value UniqueId) {
-
-  return LLVMDIBuilderCreateUnionType(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      File, Int_val(LineNumber), (uint64_t)Int_val(SizeInBits),
-      Int_val(AlignInBits), DIFlags_val(Flags),
-      (LLVMMetadataRef *)Op_val(Elements), Wosize_val(Elements),
-      Int_val(RunTimeLanguage), String_val(UniqueId),
-      caml_string_length(UniqueId));
-}
-
-LLVMMetadataRef llvm_dibuild_create_union_type_bytecode(value *argv, int argn) {
-  return llvm_dibuild_create_union_type_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // Scope
-      argv[2],                  // Name
-      (LLVMMetadataRef)argv[3], // File
-      argv[4],                  // LineNumber
-      argv[5],                  // SizeInBits
-      argv[6],                  // AlignInBits
-      argv[7],                  // Flags
-      argv[8],                  // Elements
-      argv[9],                  // RunTimeLanguage
-      argv[10]                  // UniqueId
+value llvm_dibuild_create_union_type_native(
+    value Builder, value Scope, value Name, value File, value LineNumber,
+    value SizeInBits, value AlignInBits, value Flags, value Elements,
+    value RunTimeLanguage, value UniqueId) {
+  LLVMMetadataRef *Temp = from_val_array(Elements);
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateUnionType(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), Metadata_val(File), Int_val(LineNumber),
+      (uint64_t)Int_val(SizeInBits), Int_val(AlignInBits), DIFlags_val(Flags),
+      Temp, Wosize_val(Elements), Int_val(RunTimeLanguage),
+      String_val(UniqueId), caml_string_length(UniqueId));
+  free(Temp);
+  return to_val(Metadata);
+}
+
+value llvm_dibuild_create_union_type_bytecode(value *argv, int argn) {
+  return llvm_dibuild_create_union_type_native(argv[0], // Builder
+                                               argv[1], // Scope
+                                               argv[2], // Name
+                                               argv[3], // File
+                                               argv[4], // LineNumber
+                                               argv[5], // SizeInBits
+                                               argv[6], // AlignInBits
+                                               argv[7], // Flags
+                                               argv[8], // Elements
+                                               argv[9], // RunTimeLanguage
+                                               argv[10] // UniqueId
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_array_type(value Builder, value Size,
-                                               value AlignInBits,
-                                               LLVMMetadataRef Ty,
-                                               value Subscripts) {
-  return LLVMDIBuilderCreateArrayType(
-      DIBuilder_val(Builder), (uint64_t)Int_val(Size), Int_val(AlignInBits), Ty,
-      (LLVMMetadataRef *)Op_val(Subscripts), Wosize_val(Subscripts));
+value llvm_dibuild_create_array_type(value Builder, value Size,
+                                     value AlignInBits, value Ty,
+                                     value Subscripts) {
+  LLVMMetadataRef *Temp = from_val_array(Subscripts);
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateArrayType(
+      DIBuilder_val(Builder), (uint64_t)Int_val(Size), Int_val(AlignInBits),
+      Metadata_val(Ty), Temp, Wosize_val(Subscripts));
+  free(Temp);
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_vector_type(value Builder, value Size,
-                                                value AlignInBits,
-                                                LLVMMetadataRef Ty,
-                                                value Subscripts) {
-  return LLVMDIBuilderCreateVectorType(
-      DIBuilder_val(Builder), (uint64_t)Int_val(Size), Int_val(AlignInBits), Ty,
-      (LLVMMetadataRef *)Op_val(Subscripts), Wosize_val(Subscripts));
+value llvm_dibuild_create_vector_type(value Builder, value Size,
+                                      value AlignInBits, value Ty,
+                                      value Subscripts) {
+  LLVMMetadataRef *Temp = from_val_array(Subscripts);
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateVectorType(
+      DIBuilder_val(Builder), (uint64_t)Int_val(Size), Int_val(AlignInBits),
+      Metadata_val(Ty), Temp, Wosize_val(Subscripts));
+  free(Temp);
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_unspecified_type(value Builder,
-                                                     value Name) {
-  return LLVMDIBuilderCreateUnspecifiedType(
+value llvm_dibuild_create_unspecified_type(value Builder, value Name) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateUnspecifiedType(
       DIBuilder_val(Builder), String_val(Name), caml_string_length(Name));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_basic_type(value Builder, value Name,
-                                               value SizeInBits, value Encoding,
-                                               value Flags) {
-
-  return LLVMDIBuilderCreateBasicType(
+value llvm_dibuild_create_basic_type(value Builder, value Name,
+                                     value SizeInBits, value Encoding,
+                                     value Flags) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateBasicType(
       DIBuilder_val(Builder), String_val(Name), caml_string_length(Name),
       (uint64_t)Int_val(SizeInBits), Int_val(Encoding), DIFlags_val(Flags));
-}
-
-LLVMMetadataRef llvm_dibuild_create_pointer_type_native(
-    value Builder, LLVMMetadataRef PointeeTy, value SizeInBits,
-    value AlignInBits, value AddressSpace, value Name) {
-  return LLVMDIBuilderCreatePointerType(
-      DIBuilder_val(Builder), PointeeTy, (uint64_t)Int_val(SizeInBits),
-      Int_val(AlignInBits), Int_val(AddressSpace), String_val(Name),
-      caml_string_length(Name));
-}
-
-LLVMMetadataRef llvm_dibuild_create_pointer_type_bytecode(value *argv,
-                                                          int argn) {
-  return llvm_dibuild_create_pointer_type_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // PointeeTy
-      argv[2],                  // SizeInBits
-      argv[3],                  // AlignInBits
-      argv[4],                  // AddressSpace
-      argv[5]                   // Name
+  return to_val(Metadata);
+}
+
+value llvm_dibuild_create_pointer_type_native(value Builder, value PointeeTy,
+                                              value SizeInBits,
+                                              value AlignInBits,
+                                              value AddressSpace, value Name) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreatePointerType(
+      DIBuilder_val(Builder), Metadata_val(PointeeTy),
+      (uint64_t)Int_val(SizeInBits), Int_val(AlignInBits),
+      Int_val(AddressSpace), String_val(Name), caml_string_length(Name));
+  return to_val(Metadata);
+}
+
+value llvm_dibuild_create_pointer_type_bytecode(value *argv, int argn) {
+  return llvm_dibuild_create_pointer_type_native(argv[0], // Builder
+                                                 argv[1], // PointeeTy
+                                                 argv[2], // SizeInBits
+                                                 argv[3], // AlignInBits
+                                                 argv[4], // AddressSpace
+                                                 argv[5]  // Name
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_struct_type_native(
-    value Builder, LLVMMetadataRef Scope, value Name, LLVMMetadataRef File,
-    value LineNumber, value SizeInBits, value AlignInBits, value Flags,
-    LLVMMetadataRef DerivedFrom, value Elements, value RunTimeLanguage,
-    LLVMMetadataRef VTableHolder, value UniqueId) {
-
-  return LLVMDIBuilderCreateStructType(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      File, Int_val(LineNumber), (uint64_t)Int_val(SizeInBits),
-      Int_val(AlignInBits), DIFlags_val(Flags), DerivedFrom,
-      (LLVMMetadataRef *)Op_val(Elements), Wosize_val(Elements),
-      Int_val(RunTimeLanguage), VTableHolder, String_val(UniqueId),
-      caml_string_length(UniqueId));
-}
-
-LLVMMetadataRef llvm_dibuild_create_struct_type_bytecode(value *argv,
-                                                         int argn) {
-  return llvm_dibuild_create_struct_type_native(
-      argv[0],                   // Builder
-      (LLVMMetadataRef)argv[1],  // Scope
-      argv[2],                   // Name
-      (LLVMMetadataRef)argv[3],  // File
-      argv[4],                   // LineNumber
-      argv[5],                   // SizeInBits
-      argv[6],                   // AlignInBits
-      argv[7],                   // Flags
-      (LLVMMetadataRef)argv[8],  // DeriviedFrom
-      argv[9],                   // Elements
-      argv[10],                  // RunTimeLanguage
-      (LLVMMetadataRef)argv[11], // VTableHolder
-      argv[12]                   // UniqueId
+value llvm_dibuild_create_struct_type_native(
+    value Builder, value Scope, value Name, value File, value LineNumber,
+    value SizeInBits, value AlignInBits, value Flags, value DerivedFrom,
+    value Elements, value RunTimeLanguage, value VTableHolder, value UniqueId) {
+  LLVMMetadataRef *Temp = from_val_array(Elements);
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateStructType(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), Metadata_val(File), Int_val(LineNumber),
+      (uint64_t)Int_val(SizeInBits), Int_val(AlignInBits), DIFlags_val(Flags),
+      Metadata_val(DerivedFrom), Temp, Wosize_val(Elements),
+      Int_val(RunTimeLanguage), Metadata_val(VTableHolder),
+      String_val(UniqueId), caml_string_length(UniqueId));
+  free(Temp);
+  return to_val(Metadata);
+}
+
+value llvm_dibuild_create_struct_type_bytecode(value *argv, int argn) {
+  return llvm_dibuild_create_struct_type_native(argv[0],  // Builder
+                                                argv[1],  // Scope
+                                                argv[2],  // Name
+                                                argv[3],  // File
+                                                argv[4],  // LineNumber
+                                                argv[5],  // SizeInBits
+                                                argv[6],  // AlignInBits
+                                                argv[7],  // Flags
+                                                argv[8],  // DeriviedFrom
+                                                argv[9],  // Elements
+                                                argv[10], // RunTimeLanguage
+                                                argv[11], // VTableHolder
+                                                argv[12]  // UniqueId
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_member_type_native(
-    value Builder, LLVMMetadataRef Scope, value Name, LLVMMetadataRef File,
-    value LineNumber, value SizeInBits, value AlignInBits, value OffsetInBits,
-    value Flags, LLVMMetadataRef Ty) {
-
-  return LLVMDIBuilderCreateMemberType(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      File, Int_val(LineNumber), (uint64_t)Int_val(SizeInBits),
-      Int_val(AlignInBits), (uint64_t)Int_val(OffsetInBits), DIFlags_val(Flags),
-      Ty);
-}
-
-LLVMMetadataRef llvm_dibuild_create_member_type_bytecode(value *argv,
-                                                         int argn) {
-  return llvm_dibuild_create_member_type_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // Scope
-      argv[2],                  // Name
-      (LLVMMetadataRef)argv[3], // File
-      argv[4],                  // LineNumber
-      argv[5],                  // SizeInBits
-      argv[6],                  // AlignInBits
-      argv[7],                  // OffsetInBits
-      argv[8],                  // Flags
-      (LLVMMetadataRef)argv[9]  // Ty
+value llvm_dibuild_create_member_type_native(value Builder, value Scope,
+                                             value Name, value File,
+                                             value LineNumber, value SizeInBits,
+                                             value AlignInBits,
+                                             value OffsetInBits, value Flags,
+                                             value Ty) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateMemberType(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), Metadata_val(File), Int_val(LineNumber),
+      (uint64_t)Int_val(SizeInBits), Int_val(AlignInBits),
+      (uint64_t)Int_val(OffsetInBits), DIFlags_val(Flags), Metadata_val(Ty));
+  return to_val(Metadata);
+}
+
+value llvm_dibuild_create_member_type_bytecode(value *argv, int argn) {
+  return llvm_dibuild_create_member_type_native(argv[0], // Builder
+                                                argv[1], // Scope
+                                                argv[2], // Name
+                                                argv[3], // File
+                                                argv[4], // LineNumber
+                                                argv[5], // SizeInBits
+                                                argv[6], // AlignInBits
+                                                argv[7], // OffsetInBits
+                                                argv[8], // Flags
+                                                argv[9]  // Ty
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_static_member_type_native(
-    value Builder, LLVMMetadataRef Scope, value Name, LLVMMetadataRef File,
-    value LineNumber, LLVMMetadataRef Type, value Flags,
-    LLVMValueRef ConstantVal, value AlignInBits) {
-
-  return LLVMDIBuilderCreateStaticMemberType(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      File, Int_val(LineNumber), Type, DIFlags_val(Flags), ConstantVal,
+value llvm_dibuild_create_static_member_type_native(
+    value Builder, value Scope, value Name, value File, value LineNumber,
+    value Type, value Flags, value ConstantVal, value AlignInBits) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateStaticMemberType(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), Metadata_val(File), Int_val(LineNumber),
+      Metadata_val(Type), DIFlags_val(Flags), Value_val(ConstantVal),
       Int_val(AlignInBits));
-}
-
-LLVMMetadataRef llvm_dibuild_create_static_member_type_bytecode(value *argv,
-                                                                int argn) {
-  return llvm_dibuild_create_static_member_type_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // Scope
-      argv[2],                  // Name
-      (LLVMMetadataRef)argv[3], // File
-      argv[4],                  // LineNumber
-      (LLVMMetadataRef)argv[5], // Type
-      argv[6],                  // Flags,
-      (LLVMValueRef)argv[7],    // ConstantVal
-      argv[8]                   // AlignInBits
+  return to_val(Metadata);
+}
+
+value llvm_dibuild_create_static_member_type_bytecode(value *argv, int argn) {
+  return llvm_dibuild_create_static_member_type_native(argv[0], // Builder
+                                                       argv[1], // Scope
+                                                       argv[2], // Name
+                                                       argv[3], // File
+                                                       argv[4], // LineNumber
+                                                       argv[5], // Type
+                                                       argv[6], // Flags,
+                                                       argv[7], // ConstantVal
+                                                       argv[8]  // AlignInBits
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_member_pointer_type_native(
-    value Builder, LLVMMetadataRef PointeeType, LLVMMetadataRef ClassType,
-    uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags) {
-
-  return LLVMDIBuilderCreateMemberPointerType(
-      DIBuilder_val(Builder), PointeeType, ClassType,
-      (uint64_t)Int_val(SizeInBits), Int_val(AlignInBits), Flags);
+value llvm_dibuild_create_member_pointer_type_native(
+    value Builder, value PointeeType, value ClassType, value SizeInBits,
+    value AlignInBits, value Flags) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateMemberPointerType(
+      DIBuilder_val(Builder), Metadata_val(PointeeType),
+      Metadata_val(ClassType), (uint64_t)Int_val(SizeInBits),
+      Int_val(AlignInBits), llvm_diflags_get(Flags));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_member_pointer_type_bytecode(value *argv,
-                                                                 int argn) {
-  return llvm_dibuild_create_member_pointer_type_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // PointeeType
-      (LLVMMetadataRef)argv[2], // ClassType
-      argv[3],                  // SizeInBits
-      argv[4],                  // AlignInBits
-      argv[5]                   // Flags
+value llvm_dibuild_create_member_pointer_type_bytecode(value *argv, int argn) {
+  return llvm_dibuild_create_member_pointer_type_native(argv[0], // Builder
+                                                        argv[1], // PointeeType
+                                                        argv[2], // ClassType
+                                                        argv[3], // SizeInBits
+                                                        argv[4], // AlignInBits
+                                                        argv[5]  // Flags
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_object_pointer_type(value Builder,
-                                                        LLVMMetadataRef Type) {
-  return LLVMDIBuilderCreateObjectPointerType(DIBuilder_val(Builder), Type);
+value llvm_dibuild_create_object_pointer_type(value Builder, value Type) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateObjectPointerType(
+      DIBuilder_val(Builder), Metadata_val(Type));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_qualified_type(value Builder, value Tag,
-                                                   LLVMMetadataRef Type) {
-
-  return LLVMDIBuilderCreateQualifiedType(DIBuilder_val(Builder), Int_val(Tag),
-                                          Type);
+value llvm_dibuild_create_qualified_type(value Builder, value Tag, value Type) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateQualifiedType(
+      DIBuilder_val(Builder), Int_val(Tag), Metadata_val(Type));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_reference_type(value Builder, value Tag,
-                                                   LLVMMetadataRef Type) {
-
-  return LLVMDIBuilderCreateReferenceType(DIBuilder_val(Builder), Int_val(Tag),
-                                          Type);
+value llvm_dibuild_create_reference_type(value Builder, value Tag, value Type) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateReferenceType(
+      DIBuilder_val(Builder), Int_val(Tag), Metadata_val(Type));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_null_ptr_type(value Builder) {
-
-  return LLVMDIBuilderCreateNullPtrType(DIBuilder_val(Builder));
+value llvm_dibuild_create_null_ptr_type(value Builder) {
+  return to_val(LLVMDIBuilderCreateNullPtrType(DIBuilder_val(Builder)));
 }
 
-LLVMMetadataRef llvm_dibuild_create_typedef_native(
-    value Builder, LLVMMetadataRef Type, value Name, LLVMMetadataRef File,
-    value LineNo, LLVMMetadataRef Scope, value AlignInBits) {
-
-  return LLVMDIBuilderCreateTypedef(
-      DIBuilder_val(Builder), Type, String_val(Name), caml_string_length(Name),
-      File, Int_val(LineNo), Scope, Int_val(AlignInBits));
+value llvm_dibuild_create_typedef_native(value Builder, value Type, value Name,
+                                         value File, value LineNo, value Scope,
+                                         value AlignInBits) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateTypedef(
+      DIBuilder_val(Builder), Metadata_val(Type), String_val(Name),
+      caml_string_length(Name), Metadata_val(File), Int_val(LineNo),
+      Metadata_val(Scope), Int_val(AlignInBits));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_typedef_bytecode(value *argv, int argn) {
+value llvm_dibuild_create_typedef_bytecode(value *argv, int argn) {
 
-  return llvm_dibuild_create_typedef_native(argv[0],                  // Builder
-                                            (LLVMMetadataRef)argv[1], // Type
-                                            argv[2],                  // Name
-                                            (LLVMMetadataRef)argv[3], // File
-                                            argv[4],                  // LineNo
-                                            (LLVMMetadataRef)argv[5], // Scope
-                                            argv[6] // AlignInBits
+  return llvm_dibuild_create_typedef_native(argv[0], // Builder
+                                            argv[1], // Type
+                                            argv[2], // Name
+                                            argv[3], // File
+                                            argv[4], // LineNo
+                                            argv[5], // Scope
+                                            argv[6]  // AlignInBits
   );
 }
 
-LLVMMetadataRef
-llvm_dibuild_create_inheritance_native(value Builder, LLVMMetadataRef Ty,
-                                       LLVMMetadataRef BaseTy, value BaseOffset,
-                                       value VBPtrOffset, value Flags) {
-
-  return LLVMDIBuilderCreateInheritance(DIBuilder_val(Builder), Ty, BaseTy,
-                                        (uint64_t)Int_val(BaseOffset),
-                                        Int_val(VBPtrOffset), Flags);
+value llvm_dibuild_create_inheritance_native(value Builder, value Ty,
+                                             value BaseTy, value BaseOffset,
+                                             value VBPtrOffset, value Flags) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateInheritance(
+      DIBuilder_val(Builder), Metadata_val(Ty), Metadata_val(BaseTy),
+      (uint64_t)Int_val(BaseOffset), Int_val(VBPtrOffset), DIFlags_val(Flags));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_inheritance_bytecode(value *argv, int arg) {
-
-  return llvm_dibuild_create_inheritance_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // Ty
-      (LLVMMetadataRef)argv[2], // BaseTy
-      argv[3],                  // BaseOffset
-      argv[4],                  // VBPtrOffset
-      argv[5]                   // Flags
+value llvm_dibuild_create_inheritance_bytecode(value *argv, int arg) {
+  return llvm_dibuild_create_inheritance_native(argv[0], // Builder
+                                                argv[1], // Ty
+                                                argv[2], // BaseTy
+                                                argv[3], // BaseOffset
+                                                argv[4], // VBPtrOffset
+                                                argv[5]  // Flags
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_forward_decl_native(
-    value Builder, value Tag, value Name, LLVMMetadataRef Scope,
-    LLVMMetadataRef File, value Line, value RuntimeLang, value SizeInBits,
-    value AlignInBits, value UniqueIdentifier) {
-  return LLVMDIBuilderCreateForwardDecl(
+value llvm_dibuild_create_forward_decl_native(
+    value Builder, value Tag, value Name, value Scope, value File, value Line,
+    value RuntimeLang, value SizeInBits, value AlignInBits,
+    value UniqueIdentifier) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateForwardDecl(
       DIBuilder_val(Builder), Int_val(Tag), String_val(Name),
-      caml_string_length(Name), Scope, File, Int_val(Line),
-      Int_val(RuntimeLang), (uint64_t)Int_val(SizeInBits), Int_val(AlignInBits),
-      String_val(UniqueIdentifier), caml_string_length(UniqueIdentifier));
+      caml_string_length(Name), Metadata_val(Scope), Metadata_val(File),
+      Int_val(Line), Int_val(RuntimeLang), (uint64_t)Int_val(SizeInBits),
+      Int_val(AlignInBits), String_val(UniqueIdentifier),
+      caml_string_length(UniqueIdentifier));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_forward_decl_bytecode(value *argv,
-                                                          int arg) {
-
-  return llvm_dibuild_create_forward_decl_native(
-      argv[0],                  // Builder
-      argv[1],                  // Tag
-      argv[2],                  // Name
-      (LLVMMetadataRef)argv[3], // Scope
-      (LLVMMetadataRef)argv[4], // File
-      argv[5],                  // Line
-      argv[6],                  // RuntimeLang
-      argv[7],                  // SizeInBits
-      argv[8],                  // AlignInBits
-      argv[9]                   // UniqueIdentifier
+value llvm_dibuild_create_forward_decl_bytecode(value *argv, int arg) {
+
+  return llvm_dibuild_create_forward_decl_native(argv[0], // Builder
+                                                 argv[1], // Tag
+                                                 argv[2], // Name
+                                                 argv[3], // Scope
+                                                 argv[4], // File
+                                                 argv[5], // Line
+                                                 argv[6], // RuntimeLang
+                                                 argv[7], // SizeInBits
+                                                 argv[8], // AlignInBits
+                                                 argv[9]  // UniqueIdentifier
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_replaceable_composite_type_native(
-    value Builder, value Tag, value Name, LLVMMetadataRef Scope,
-    LLVMMetadataRef File, value Line, value RuntimeLang, value SizeInBits,
-    value AlignInBits, value Flags, value UniqueIdentifier) {
-
-  return LLVMDIBuilderCreateReplaceableCompositeType(
+value llvm_dibuild_create_replaceable_composite_type_native(
+    value Builder, value Tag, value Name, value Scope, value File, value Line,
+    value RuntimeLang, value SizeInBits, value AlignInBits, value Flags,
+    value UniqueIdentifier) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateReplaceableCompositeType(
       DIBuilder_val(Builder), Int_val(Tag), String_val(Name),
-      caml_string_length(Name), Scope, File, Int_val(Line),
-      Int_val(RuntimeLang), (uint64_t)Int_val(SizeInBits), Int_val(AlignInBits),
-      DIFlags_val(Flags), String_val(UniqueIdentifier),
+      caml_string_length(Name), Metadata_val(Scope), Metadata_val(File),
+      Int_val(Line), Int_val(RuntimeLang), (uint64_t)Int_val(SizeInBits),
+      Int_val(AlignInBits), DIFlags_val(Flags), String_val(UniqueIdentifier),
       caml_string_length(UniqueIdentifier));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef
-llvm_dibuild_create_replaceable_composite_type_bytecode(value *argv, int arg) {
+value llvm_dibuild_create_replaceable_composite_type_bytecode(value *argv,
+                                                              int arg) {
 
   return llvm_dibuild_create_replaceable_composite_type_native(
-      argv[0],                  // Builder
-      argv[1],                  // Tag
-      argv[2],                  // Name
-      (LLVMMetadataRef)argv[3], // Scope
-      (LLVMMetadataRef)argv[4], // File
-      argv[5],                  // Line
-      argv[6],                  // RuntimeLang
-      argv[7],                  // SizeInBits
-      argv[8],                  // AlignInBits
-      argv[9],                  // Flags
-      argv[10]                  // UniqueIdentifier
+      argv[0], // Builder
+      argv[1], // Tag
+      argv[2], // Name
+      argv[3], // Scope
+      argv[4], // File
+      argv[5], // Line
+      argv[6], // RuntimeLang
+      argv[7], // SizeInBits
+      argv[8], // AlignInBits
+      argv[9], // Flags
+      argv[10] // UniqueIdentifier
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_bit_field_member_type_native(
-    value Builder, LLVMMetadataRef Scope, value Name, LLVMMetadataRef File,
-    value LineNum, value SizeInBits, value OffsetInBits,
-    value StorageOffsetInBits, value Flags, LLVMMetadataRef Ty) {
-
-  return LLVMDIBuilderCreateBitFieldMemberType(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      File, Int_val(LineNum), (uint64_t)Int_val(SizeInBits),
-      (uint64_t)Int_val(OffsetInBits), (uint64_t)Int_val(StorageOffsetInBits),
-      DIFlags_val(Flags), Ty);
+value llvm_dibuild_create_bit_field_member_type_native(
+    value Builder, value Scope, value Name, value File, value LineNum,
+    value SizeInBits, value OffsetInBits, value StorageOffsetInBits,
+    value Flags, value Ty) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateBitFieldMemberType(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), Metadata_val(File), Int_val(LineNum),
+      (uint64_t)Int_val(SizeInBits), (uint64_t)Int_val(OffsetInBits),
+      (uint64_t)Int_val(StorageOffsetInBits), DIFlags_val(Flags),
+      Metadata_val(Ty));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_bit_field_member_type_bytecode(value *argv,
-                                                                   int arg) {
+value llvm_dibuild_create_bit_field_member_type_bytecode(value *argv, int arg) {
 
   return llvm_dibuild_create_bit_field_member_type_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // Scope
-      argv[2],                  // Name
-      (LLVMMetadataRef)argv[3], // File
-      argv[4],                  // LineNum
-      argv[5],                  // SizeInBits
-      argv[6],                  // OffsetInBits
-      argv[7],                  // StorageOffsetInBits
-      argv[8],                  // Flags
-      (LLVMMetadataRef)argv[9]  // Ty
+      argv[0], // Builder
+      argv[1], // Scope
+      argv[2], // Name
+      argv[3], // File
+      argv[4], // LineNum
+      argv[5], // SizeInBits
+      argv[6], // OffsetInBits
+      argv[7], // StorageOffsetInBits
+      argv[8], // Flags
+      argv[9]  // Ty
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_class_type_native(
-    value Builder, LLVMMetadataRef Scope, value Name, LLVMMetadataRef File,
-    value LineNumber, value SizeInBits, value AlignInBits, value OffsetInBits,
-    value Flags, LLVMMetadataRef DerivedFrom, value Elements,
-    LLVMMetadataRef VTableHolder, LLVMMetadataRef TemplateParamsNode,
-    value UniqueIdentifier) {
-
-  return LLVMDIBuilderCreateClassType(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      File, Int_val(LineNumber), (uint64_t)Int_val(SizeInBits),
-      Int_val(AlignInBits), (uint64_t)Int_val(OffsetInBits), DIFlags_val(Flags),
-      DerivedFrom, (LLVMMetadataRef *)Op_val(Elements), Wosize_val(Elements),
-      VTableHolder, TemplateParamsNode, String_val(UniqueIdentifier),
-      caml_string_length(UniqueIdentifier));
-}
-
-LLVMMetadataRef llvm_dibuild_create_class_type_bytecode(value *argv, int arg) {
-
-  return llvm_dibuild_create_class_type_native(
-      argv[0],                   // Builder
-      (LLVMMetadataRef)argv[1],  // Scope
-      argv[2],                   // Name
-      (LLVMMetadataRef)argv[3],  // File
-      argv[4],                   // LineNumber
-      argv[5],                   // SizeInBits
-      argv[6],                   // AlignInBits
-      argv[7],                   // OffsetInBits
-      argv[8],                   // Flags
-      (LLVMMetadataRef)argv[9],  // DerivedFrom
-      argv[10],                  // Elements
-      (LLVMMetadataRef)argv[11], // VTableHolder
-      (LLVMMetadataRef)argv[12], // TemplateParamsNode
-      argv[13]                   // UniqueIdentifier
+value llvm_dibuild_create_class_type_native(
+    value Builder, value Scope, value Name, value File, value LineNumber,
+    value SizeInBits, value AlignInBits, value OffsetInBits, value Flags,
+    value DerivedFrom, value Elements, value VTableHolder,
+    value TemplateParamsNode, value UniqueIdentifier) {
+  LLVMMetadataRef *Temp = from_val_array(Elements);
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateClassType(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), Metadata_val(File), Int_val(LineNumber),
+      (uint64_t)Int_val(SizeInBits), Int_val(AlignInBits),
+      (uint64_t)Int_val(OffsetInBits), DIFlags_val(Flags),
+      Metadata_val(DerivedFrom), Temp, Wosize_val(Elements),
+      Metadata_val(VTableHolder), Metadata_val(TemplateParamsNode),
+      String_val(UniqueIdentifier), caml_string_length(UniqueIdentifier));
+  free(Temp);
+  return to_val(Metadata);
+}
+
+value llvm_dibuild_create_class_type_bytecode(value *argv, int arg) {
+
+  return llvm_dibuild_create_class_type_native(argv[0],  // Builder
+                                               argv[1],  // Scope
+                                               argv[2],  // Name
+                                               argv[3],  // File
+                                               argv[4],  // LineNumber
+                                               argv[5],  // SizeInBits
+                                               argv[6],  // AlignInBits
+                                               argv[7],  // OffsetInBits
+                                               argv[8],  // Flags
+                                               argv[9],  // DerivedFrom
+                                               argv[10], // Elements
+                                               argv[11], // VTableHolder
+                                               argv[12], // TemplateParamsNode
+                                               argv[13]  // UniqueIdentifier
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_artificial_type(value Builder,
-                                                    LLVMMetadataRef Type) {
-  return LLVMDIBuilderCreateArtificialType(DIBuilder_val(Builder), Type);
+value llvm_dibuild_create_artificial_type(value Builder, value Type) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateArtificialType(
+      DIBuilder_val(Builder), Metadata_val(Type));
+  return to_val(Metadata);
 }
 
-value llvm_di_type_get_name(LLVMMetadataRef DType) {
+value llvm_di_type_get_name(value DType) {
   size_t Len;
-  const char *Name = LLVMDITypeGetName(DType, &Len);
+  const char *Name = LLVMDITypeGetName(Metadata_val(DType), &Len);
   return cstr_to_string(Name, Len);
 }
 
-value llvm_di_type_get_size_in_bits(LLVMMetadataRef DType) {
-  uint64_t Size = LLVMDITypeGetSizeInBits(DType);
+value llvm_di_type_get_size_in_bits(value DType) {
+  uint64_t Size = LLVMDITypeGetSizeInBits(Metadata_val(DType));
   return Val_int((int)Size);
 }
 
-value llvm_di_type_get_offset_in_bits(LLVMMetadataRef DType) {
-  uint64_t Size = LLVMDITypeGetOffsetInBits(DType);
+value llvm_di_type_get_offset_in_bits(value DType) {
+  uint64_t Size = LLVMDITypeGetOffsetInBits(Metadata_val(DType));
   return Val_int((int)Size);
 }
 
-value llvm_di_type_get_align_in_bits(LLVMMetadataRef DType) {
-  uint32_t Size = LLVMDITypeGetAlignInBits(DType);
+value llvm_di_type_get_align_in_bits(value DType) {
+  uint32_t Size = LLVMDITypeGetAlignInBits(Metadata_val(DType));
   return Val_int(Size);
 }
 
-value llvm_di_type_get_line(LLVMMetadataRef DType) {
-  unsigned Line = LLVMDITypeGetLine(DType);
+value llvm_di_type_get_line(value DType) {
+  unsigned Line = LLVMDITypeGetLine(Metadata_val(DType));
   return Val_int(Line);
 }
 
-value llvm_di_type_get_flags(LLVMMetadataRef DType) {
-  LLVMDIFlags Flags = LLVMDITypeGetLine(DType);
+value llvm_di_type_get_flags(value DType) {
+  LLVMDIFlags Flags = LLVMDITypeGetLine(Metadata_val(DType));
   return alloc_diflags(Flags);
 }
 
-value llvm_get_subprogram(LLVMValueRef Func) {
-  return (ptr_to_option(LLVMGetSubprogram(Func)));
+value llvm_get_subprogram(value Func) {
+  return ptr_to_option(LLVMGetSubprogram(Value_val(Func)));
 }
 
-value llvm_set_subprogram(LLVMValueRef Func, LLVMMetadataRef SP) {
-  LLVMSetSubprogram(Func, SP);
+value llvm_set_subprogram(value Func, value SP) {
+  LLVMSetSubprogram(Value_val(Func), Metadata_val(SP));
   return Val_unit;
 }
 
-value llvm_di_subprogram_get_line(LLVMMetadataRef Subprogram) {
-  return Val_int(LLVMDISubprogramGetLine(Subprogram));
+value llvm_di_subprogram_get_line(value Subprogram) {
+  return Val_int(LLVMDISubprogramGetLine(Metadata_val(Subprogram)));
 }
 
-value llvm_instr_get_debug_loc(LLVMValueRef Inst) {
-  return (ptr_to_option(LLVMInstructionGetDebugLoc(Inst)));
+value llvm_instr_get_debug_loc(value Inst) {
+  return ptr_to_option(LLVMInstructionGetDebugLoc(Value_val(Inst)));
 }
 
-value llvm_instr_set_debug_loc(LLVMValueRef Inst, LLVMMetadataRef Loc) {
-  LLVMInstructionSetDebugLoc(Inst, Loc);
+value llvm_instr_set_debug_loc(value Inst, value Loc) {
+  LLVMInstructionSetDebugLoc(Value_val(Inst), Metadata_val(Loc));
   return Val_unit;
 }
 
-LLVMMetadataRef llvm_dibuild_create_constant_value_expression(value Builder,
-                                                              value Value) {
-  return LLVMDIBuilderCreateConstantValueExpression(DIBuilder_val(Builder),
-                                                    (uint64_t)Int_val(Value));
+value llvm_dibuild_create_constant_value_expression(value Builder,
+                                                    value Value) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateConstantValueExpression(
+      DIBuilder_val(Builder), (uint64_t)Int_val(Value));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_global_variable_expression_native(
-    value Builder, LLVMMetadataRef Scope, value Name, value Linkage,
-    LLVMMetadataRef File, value Line, LLVMMetadataRef Ty, value LocalToUnit,
-    LLVMMetadataRef Expr, LLVMMetadataRef Decl, value AlignInBits) {
-  return LLVMDIBuilderCreateGlobalVariableExpression(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      String_val(Linkage), caml_string_length(Linkage), File, Int_val(Line), Ty,
-      Bool_val(LocalToUnit), Expr, Decl, Int_val(AlignInBits));
+value llvm_dibuild_create_global_variable_expression_native(
+    value Builder, value Scope, value Name, value Linkage, value File,
+    value Line, value Ty, value LocalToUnit, value Expr, value Decl,
+    value AlignInBits) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateGlobalVariableExpression(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), String_val(Linkage),
+      caml_string_length(Linkage), Metadata_val(File), Int_val(Line),
+      Metadata_val(Ty), Bool_val(LocalToUnit), Metadata_val(Expr),
+      Metadata_val(Decl), Int_val(AlignInBits));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef
-llvm_dibuild_create_global_variable_expression_bytecode(value *argv, int arg) {
+value llvm_dibuild_create_global_variable_expression_bytecode(value *argv,
+                                                              int arg) {
 
   return llvm_dibuild_create_global_variable_expression_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // Scope
-      argv[2],                  // Name
-      argv[3],                  // Linkage
-      (LLVMMetadataRef)argv[4], // File
-      argv[5],                  // Line
-      (LLVMMetadataRef)argv[6], // Ty
-      argv[7],                  // LocalToUnit
-      (LLVMMetadataRef)argv[8], // Expr
-      (LLVMMetadataRef)argv[9], // Decl
-      argv[10]                  // AlignInBits
+      argv[0], // Builder
+      argv[1], // Scope
+      argv[2], // Name
+      argv[3], // Linkage
+      argv[4], // File
+      argv[5], // Line
+      argv[6], // Ty
+      argv[7], // LocalToUnit
+      argv[8], // Expr
+      argv[9], // Decl
+      argv[10] // AlignInBits
   );
 }
 
-value llvm_di_global_variable_expression_get_variable(LLVMMetadataRef GVE) {
-  return (ptr_to_option(LLVMDIGlobalVariableExpressionGetVariable(GVE)));
+value llvm_di_global_variable_expression_get_variable(value GVE) {
+  return ptr_to_option(
+      LLVMDIGlobalVariableExpressionGetVariable(Metadata_val(GVE)));
 }
 
-value llvm_di_variable_get_line(LLVMMetadataRef Variable) {
-  return Val_int(LLVMDIVariableGetLine(Variable));
+value llvm_di_variable_get_line(value Variable) {
+  return Val_int(LLVMDIVariableGetLine(Metadata_val(Variable)));
 }
 
-value llvm_di_variable_get_file(LLVMMetadataRef Variable) {
-  return (ptr_to_option(LLVMDIVariableGetFile(Variable)));
+value llvm_di_variable_get_file(value Variable) {
+  return ptr_to_option(LLVMDIVariableGetFile(Metadata_val(Variable)));
 }
 
-value llvm_get_metadata_kind(LLVMMetadataRef Metadata) {
-  return Val_int(LLVMGetMetadataKind(Metadata));
+value llvm_get_metadata_kind(value Metadata) {
+  return Val_int(LLVMGetMetadataKind(Metadata_val(Metadata)));
 }
 
-LLVMMetadataRef llvm_dibuild_create_auto_variable_native(
-    value Builder, LLVMMetadataRef Scope, value Name, LLVMMetadataRef File,
-    value Line, LLVMMetadataRef Ty, value AlwaysPreserve, value Flags,
-    value AlignInBits) {
-  return LLVMDIBuilderCreateAutoVariable(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      File, Int_val(Line), Ty, Bool_val(AlwaysPreserve), DIFlags_val(Flags),
-      Int_val(AlignInBits));
+value llvm_dibuild_create_auto_variable_native(value Builder, value Scope,
+                                               value Name, value File,
+                                               value Line, value Ty,
+                                               value AlwaysPreserve,
+                                               value Flags, value AlignInBits) {
+  return to_val(LLVMDIBuilderCreateAutoVariable(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), Metadata_val(File), Int_val(Line),
+      Metadata_val(Ty), Bool_val(AlwaysPreserve), DIFlags_val(Flags),
+      Int_val(AlignInBits)));
 }
 
-LLVMMetadataRef llvm_dibuild_create_auto_variable_bytecode(value *argv,
-                                                           int arg) {
+value llvm_dibuild_create_auto_variable_bytecode(value *argv, int arg) {
 
-  return llvm_dibuild_create_auto_variable_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // Scope
-      argv[2],                  // Name
-      (LLVMMetadataRef)argv[3], // File
-      argv[4],                  // Line
-      (LLVMMetadataRef)argv[5], // Ty
-      argv[6],                  // AlwaysPreserve
-      argv[7],                  // Flags
-      argv[8]                   // AlignInBits
+  return llvm_dibuild_create_auto_variable_native(argv[0], // Builder
+                                                  argv[1], // Scope
+                                                  argv[2], // Name
+                                                  argv[3], // File
+                                                  argv[4], // Line
+                                                  argv[5], // Ty
+                                                  argv[6], // AlwaysPreserve
+                                                  argv[7], // Flags
+                                                  argv[8]  // AlignInBits
   );
 }
 
-LLVMMetadataRef llvm_dibuild_create_parameter_variable_native(
-    value Builder, LLVMMetadataRef Scope, value Name, unsigned ArgNo,
-    LLVMMetadataRef File, value Line, LLVMMetadataRef Ty, value AlwaysPreserve,
-    value Flags) {
-  return LLVMDIBuilderCreateParameterVariable(
-      DIBuilder_val(Builder), Scope, String_val(Name), caml_string_length(Name),
-      ArgNo, File, Int_val(Line), Ty, Bool_val(AlwaysPreserve),
+value llvm_dibuild_create_parameter_variable_native(
+    value Builder, value Scope, value Name, value ArgNo, value File, value Line,
+    value Ty, value AlwaysPreserve, value Flags) {
+  LLVMMetadataRef Metadata = LLVMDIBuilderCreateParameterVariable(
+      DIBuilder_val(Builder), Metadata_val(Scope), String_val(Name),
+      caml_string_length(Name), (unsigned)Int_val(ArgNo), Metadata_val(File),
+      Int_val(Line), Metadata_val(Ty), Bool_val(AlwaysPreserve),
       DIFlags_val(Flags));
+  return to_val(Metadata);
 }
 
-LLVMMetadataRef llvm_dibuild_create_parameter_variable_bytecode(value *argv,
-                                                                int arg) {
-
+value llvm_dibuild_create_parameter_variable_bytecode(value *argv, int arg) {
   return llvm_dibuild_create_parameter_variable_native(
-      argv[0],                  // Builder
-      (LLVMMetadataRef)argv[1], // Scope
-      argv[2],                  // Name
-      argv[3],                  // ArgNo
-      (LLVMMetadataRef)argv[4], // File
-      argv[5],                  // Line
-      (LLVMMetadataRef)argv[6], // Ty
-      argv[7],                  // AlwaysPreserve
-      argv[8]                   // Flags
+      argv[0], // Builder
+      argv[1], // Scope
+      argv[2], // Name
+      argv[3], // ArgNo
+      argv[4], // File
+      argv[5], // Line
+      argv[6], // Ty
+      argv[7], // AlwaysPreserve
+      argv[8]  // Flags
   );
 }
 
-LLVMValueRef llvm_dibuild_insert_declare_before_native(
-    value Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo,
-    LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr) {
-  return LLVMDIBuilderInsertDeclareBefore(DIBuilder_val(Builder), Storage,
-                                          VarInfo, Expr, DebugLoc, Instr);
+value llvm_dibuild_insert_declare_before_native(value Builder, value Storage,
+                                                value VarInfo, value Expr,
+                                                value DebugLoc, value Instr) {
+  LLVMValueRef Value = LLVMDIBuilderInsertDeclareBefore(
+      DIBuilder_val(Builder), Value_val(Storage), Metadata_val(VarInfo),
+      Metadata_val(Expr), Metadata_val(DebugLoc), Value_val(Instr));
+  return to_val(Value);
 }
 
-LLVMValueRef llvm_dibuild_insert_declare_before_bytecode(value *argv, int arg) {
+value llvm_dibuild_insert_declare_before_bytecode(value *argv, int arg) {
 
-  return llvm_dibuild_insert_declare_before_native(
-      argv[0],                  // Builder
-      (LLVMValueRef)argv[1],    // Storage
-      (LLVMMetadataRef)argv[2], // VarInfo
-      (LLVMMetadataRef)argv[3], // Expr
-      (LLVMMetadataRef)argv[4], // DebugLoc
-      (LLVMValueRef)argv[5]     // Instr
+  return llvm_dibuild_insert_declare_before_native(argv[0], // Builder
+                                                   argv[1], // Storage
+                                                   argv[2], // VarInfo
+                                                   argv[3], // Expr
+                                                   argv[4], // DebugLoc
+                                                   argv[5]  // Instr
   );
 }
 
-LLVMValueRef llvm_dibuild_insert_declare_at_end_native(
-    value Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo,
-    LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block) {
-  return LLVMDIBuilderInsertDeclareAtEnd(DIBuilder_val(Builder), Storage,
-                                         VarInfo, Expr, DebugLoc, Block);
+value llvm_dibuild_insert_declare_at_end_native(value Builder, value Storage,
+                                                value VarInfo, value Expr,
+                                                value DebugLoc, value Block) {
+  LLVMValueRef Value = LLVMDIBuilderInsertDeclareAtEnd(
+      DIBuilder_val(Builder), Value_val(Storage), Metadata_val(VarInfo),
+      Metadata_val(Expr), Metadata_val(DebugLoc), BasicBlock_val(Block));
+  return to_val(Value);
 }
 
-LLVMValueRef llvm_dibuild_insert_declare_at_end_bytecode(value *argv, int arg) {
-
-  return llvm_dibuild_insert_declare_at_end_native(
-      argv[0],                   // Builder
-      (LLVMValueRef)argv[1],     // Storage
-      (LLVMMetadataRef)argv[2],  // VarInfo
-      (LLVMMetadataRef)argv[3],  // Expr
-      (LLVMMetadataRef)argv[4],  // DebugLoc
-      (LLVMBasicBlockRef)argv[5] // Block
+value llvm_dibuild_insert_declare_at_end_bytecode(value *argv, int arg) {
+  return llvm_dibuild_insert_declare_at_end_native(argv[0], // Builder
+                                                   argv[1], // Storage
+                                                   argv[2], // VarInfo
+                                                   argv[3], // Expr
+                                                   argv[4], // DebugLoc
+                                                   argv[5]  // Block
   );
 }
 
-LLVMMetadataRef llvm_dibuild_expression(value Builder, value Addr) {
-  return LLVMDIBuilderCreateExpression(
-      DIBuilder_val(Builder), (uint64_t *)Op_val(Addr), Wosize_val(Addr));
+value llvm_dibuild_expression(value Builder, value Addr) {
+  return to_val(LLVMDIBuilderCreateExpression(
+      DIBuilder_val(Builder), (uint64_t *)Op_val(Addr), Wosize_val(Addr)));
 }

diff  --git a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml
index 59102fc883c54..a6d74ed0eb817 100644
--- a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml
+++ b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml
@@ -231,7 +231,7 @@ external llmetadata_null : unit -> Llvm.llmetadata = "llvm_metadata_null"
 
 let dibuild_create_debug_location ?(inlined_at = llmetadata_null ()) llctx ~line
     ~column ~scope =
-  dibuild_create_debug_location_helper llctx line column scope inlined_at
+  dibuild_create_debug_location_helper llctx ~line ~column ~scope ~inlined_at
 
 external di_location_get_line : location:Llvm.llmetadata -> int
   = "llvm_di_location_get_line"

diff  --git a/llvm/bindings/ocaml/executionengine/CMakeLists.txt b/llvm/bindings/ocaml/executionengine/CMakeLists.txt
index 0b1428aac1b80..c35d80ed6cd58 100644
--- a/llvm/bindings/ocaml/executionengine/CMakeLists.txt
+++ b/llvm/bindings/ocaml/executionengine/CMakeLists.txt
@@ -2,5 +2,6 @@ add_ocaml_library(llvm_executionengine
   OCAML    llvm_executionengine
   OCAMLDEP llvm llvm_target
   C        executionengine_ocaml
+  CFLAGS   "-I${CMAKE_CURRENT_SOURCE_DIR}/../llvm"
   LLVM     ExecutionEngine MCJIT native
   PKG      ctypes)

diff  --git a/llvm/bindings/ocaml/executionengine/executionengine_ocaml.c b/llvm/bindings/ocaml/executionengine/executionengine_ocaml.c
index 85990b0c9f555..9d77c086431df 100644
--- a/llvm/bindings/ocaml/executionengine/executionengine_ocaml.c
+++ b/llvm/bindings/ocaml/executionengine/executionengine_ocaml.c
@@ -15,16 +15,19 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#include <string.h>
-#include <assert.h>
-#include "llvm-c/Core.h"
-#include "llvm-c/ExecutionEngine.h"
-#include "llvm-c/Target.h"
 #include "caml/alloc.h"
+#include "caml/callback.h"
 #include "caml/custom.h"
 #include "caml/fail.h"
 #include "caml/memory.h"
-#include "caml/callback.h"
+#include "llvm_ocaml.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/ExecutionEngine.h"
+#include "llvm-c/Target.h"
+#include <assert.h>
+#include <string.h>
+
+#define ExecutionEngine_val(v) ((LLVMExecutionEngineRef)from_val(v))
 
 void llvm_raise(value Prototype, char *Message);
 
@@ -37,16 +40,15 @@ value llvm_ee_initialize(value Unit) {
                   !LLVMInitializeNativeAsmPrinter());
 }
 
-/* llmodule -> llcompileroption -> ExecutionEngine.t */
-LLVMExecutionEngineRef llvm_ee_create(value OptRecordOpt, LLVMModuleRef M) {
-  value OptRecord;
+/* llcompileroption -> llmodule -> ExecutionEngine.t */
+value llvm_ee_create(value OptRecordOpt, value M) {
   LLVMExecutionEngineRef MCJIT;
   char *Error;
   struct LLVMMCJITCompilerOptions Options;
 
   LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
   if (OptRecordOpt != Val_int(0)) {
-    OptRecord = Field(OptRecordOpt, 0);
+    value OptRecord = Field(OptRecordOpt, 0);
     Options.OptLevel = Int_val(Field(OptRecord, 0));
     Options.CodeModel = Int_val(Field(OptRecord, 1));
     Options.NoFramePointerElim = Int_val(Field(OptRecord, 2));
@@ -54,54 +56,55 @@ LLVMExecutionEngineRef llvm_ee_create(value OptRecordOpt, LLVMModuleRef M) {
     Options.MCJMM = NULL;
   }
 
-  if (LLVMCreateMCJITCompilerForModule(&MCJIT, M, &Options, sizeof(Options),
-                                       &Error))
+  if (LLVMCreateMCJITCompilerForModule(&MCJIT, Module_val(M), &Options,
+                                       sizeof(Options), &Error))
     llvm_raise(*caml_named_value("Llvm_executionengine.Error"), Error);
-  return MCJIT;
+  return to_val(MCJIT);
 }
 
 /* ExecutionEngine.t -> unit */
-value llvm_ee_dispose(LLVMExecutionEngineRef EE) {
-  LLVMDisposeExecutionEngine(EE);
+value llvm_ee_dispose(value EE) {
+  LLVMDisposeExecutionEngine(ExecutionEngine_val(EE));
   return Val_unit;
 }
 
 /* llmodule -> ExecutionEngine.t -> unit */
-value llvm_ee_add_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) {
-  LLVMAddModule(EE, M);
+value llvm_ee_add_module(value M, value EE) {
+  LLVMAddModule(ExecutionEngine_val(EE), Module_val(M));
   return Val_unit;
 }
 
 /* llmodule -> ExecutionEngine.t -> llmodule */
-value llvm_ee_remove_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) {
+value llvm_ee_remove_module(value M, value EE) {
   LLVMModuleRef RemovedModule;
   char *Error;
-  if (LLVMRemoveModule(EE, M, &RemovedModule, &Error))
+  if (LLVMRemoveModule(ExecutionEngine_val(EE), Module_val(M), &RemovedModule,
+                       &Error))
     llvm_raise(*caml_named_value("Llvm_executionengine.Error"), Error);
   return Val_unit;
 }
 
 /* ExecutionEngine.t -> unit */
-value llvm_ee_run_static_ctors(LLVMExecutionEngineRef EE) {
-  LLVMRunStaticConstructors(EE);
+value llvm_ee_run_static_ctors(value EE) {
+  LLVMRunStaticConstructors(ExecutionEngine_val(EE));
   return Val_unit;
 }
 
 /* ExecutionEngine.t -> unit */
-value llvm_ee_run_static_dtors(LLVMExecutionEngineRef EE) {
-  LLVMRunStaticDestructors(EE);
+value llvm_ee_run_static_dtors(value EE) {
+  LLVMRunStaticDestructors(ExecutionEngine_val(EE));
   return Val_unit;
 }
 
 extern value llvm_alloc_data_layout(LLVMTargetDataRef TargetData);
 
 /* ExecutionEngine.t -> Llvm_target.DataLayout.t */
-value llvm_ee_get_data_layout(LLVMExecutionEngineRef EE) {
+value llvm_ee_get_data_layout(value EE) {
   value DataLayout;
   LLVMTargetDataRef OrigDataLayout;
   char *TargetDataCStr;
 
-  OrigDataLayout = LLVMGetExecutionEngineTargetData(EE);
+  OrigDataLayout = LLVMGetExecutionEngineTargetData(ExecutionEngine_val(EE));
   TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout);
   DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr));
   LLVMDisposeMessage(TargetDataCStr);
@@ -110,17 +113,18 @@ value llvm_ee_get_data_layout(LLVMExecutionEngineRef EE) {
 }
 
 /* Llvm.llvalue -> int64 -> llexecutionengine -> unit */
-value llvm_ee_add_global_mapping(LLVMValueRef Global, value Ptr,
-                                 LLVMExecutionEngineRef EE) {
-  LLVMAddGlobalMapping(EE, Global, (void *)(Int64_val(Ptr)));
+value llvm_ee_add_global_mapping(value Global, value Ptr, value EE) {
+  LLVMAddGlobalMapping(ExecutionEngine_val(EE), Value_val(Global),
+                       (void *)(Int64_val(Ptr)));
   return Val_unit;
 }
 
-value llvm_ee_get_global_value_address(value Name, LLVMExecutionEngineRef EE) {
-  return caml_copy_int64(
-      (int64_t)LLVMGetGlobalValueAddress(EE, String_val(Name)));
+value llvm_ee_get_global_value_address(value Name, value EE) {
+  return caml_copy_int64((int64_t)LLVMGetGlobalValueAddress(
+      ExecutionEngine_val(EE), String_val(Name)));
 }
 
-value llvm_ee_get_function_address(value Name, LLVMExecutionEngineRef EE) {
-  return caml_copy_int64((int64_t)LLVMGetFunctionAddress(EE, String_val(Name)));
+value llvm_ee_get_function_address(value Name, value EE) {
+  return caml_copy_int64((int64_t)LLVMGetFunctionAddress(
+      ExecutionEngine_val(EE), String_val(Name)));
 }

diff  --git a/llvm/bindings/ocaml/irreader/CMakeLists.txt b/llvm/bindings/ocaml/irreader/CMakeLists.txt
index 5654b1803409c..d545723a1783c 100644
--- a/llvm/bindings/ocaml/irreader/CMakeLists.txt
+++ b/llvm/bindings/ocaml/irreader/CMakeLists.txt
@@ -2,4 +2,5 @@ add_ocaml_library(llvm_irreader
   OCAML    llvm_irreader
   OCAMLDEP llvm
   C        irreader_ocaml
+  CFLAGS   "-I${CMAKE_CURRENT_SOURCE_DIR}/../llvm"
   LLVM     IRReader)

diff  --git a/llvm/bindings/ocaml/irreader/irreader_ocaml.c b/llvm/bindings/ocaml/irreader/irreader_ocaml.c
index a0ccf629decc1..708d6fb5b0b79 100644
--- a/llvm/bindings/ocaml/irreader/irreader_ocaml.c
+++ b/llvm/bindings/ocaml/irreader/irreader_ocaml.c
@@ -12,23 +12,25 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#include "llvm-c/IRReader.h"
 #include "caml/alloc.h"
+#include "caml/callback.h"
 #include "caml/fail.h"
 #include "caml/memory.h"
-#include "caml/callback.h"
+#include "llvm_ocaml.h"
+#include "llvm-c/IRReader.h"
 
 void llvm_raise(value Prototype, char *Message);
 
 /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */
-value llvm_parse_ir(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) {
+value llvm_parse_ir(value C, value MemBuf) {
   CAMLparam0();
   CAMLlocal2(Variant, MessageVal);
   LLVMModuleRef M;
   char *Message;
 
-  if (LLVMParseIRInContext(C, MemBuf, &M, &Message))
+  if (LLVMParseIRInContext(Context_val(C), MemoryBuffer_val(MemBuf), &M,
+                           &Message))
     llvm_raise(*caml_named_value("Llvm_irreader.Error"), Message);
 
-  CAMLreturn((value)M);
+  CAMLreturn(to_val(M));
 }

diff  --git a/llvm/bindings/ocaml/linker/CMakeLists.txt b/llvm/bindings/ocaml/linker/CMakeLists.txt
index 3bb367225784e..add5a59297e0d 100644
--- a/llvm/bindings/ocaml/linker/CMakeLists.txt
+++ b/llvm/bindings/ocaml/linker/CMakeLists.txt
@@ -2,4 +2,5 @@ add_ocaml_library(llvm_linker
   OCAML    llvm_linker
   OCAMLDEP llvm
   C        linker_ocaml
+  CFLAGS   "-I${CMAKE_CURRENT_SOURCE_DIR}/../llvm"
   LLVM     Linker)

diff  --git a/llvm/bindings/ocaml/linker/linker_ocaml.c b/llvm/bindings/ocaml/linker/linker_ocaml.c
index 145de3b1bfbdd..2b2d61ce7f258 100644
--- a/llvm/bindings/ocaml/linker/linker_ocaml.c
+++ b/llvm/bindings/ocaml/linker/linker_ocaml.c
@@ -15,18 +15,19 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#include "llvm-c/Core.h"
-#include "llvm-c/Linker.h"
 #include "caml/alloc.h"
-#include "caml/memory.h"
-#include "caml/fail.h"
 #include "caml/callback.h"
+#include "caml/fail.h"
+#include "caml/memory.h"
+#include "llvm_ocaml.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/Linker.h"
 
 void llvm_raise(value Prototype, char *Message);
 
 /* llmodule -> llmodule -> unit */
-value llvm_link_modules(LLVMModuleRef Dst, LLVMModuleRef Src) {
-  if (LLVMLinkModules2(Dst, Src))
+value llvm_link_modules(value Dst, value Src) {
+  if (LLVMLinkModules2(Module_val(Dst), Module_val(Src)))
     llvm_raise(*caml_named_value("Llvm_linker.Error"),
                LLVMCreateMessage("Linking failed"));
 

diff  --git a/llvm/bindings/ocaml/llvm/llvm.ml b/llvm/bindings/ocaml/llvm/llvm.ml
index 4487866891e4d..6962dce737d24 100644
--- a/llvm/bindings/ocaml/llvm/llvm.ml
+++ b/llvm/bindings/ocaml/llvm/llvm.ml
@@ -441,7 +441,7 @@ external print_module : string -> llmodule -> unit = "llvm_print_module"
 external string_of_llmodule : llmodule -> string = "llvm_string_of_llmodule"
 external set_module_inline_asm : llmodule -> string -> unit
                                = "llvm_set_module_inline_asm"
-external module_context : llmodule -> llcontext = "LLVMGetModuleContext"
+external module_context : llmodule -> llcontext = "llvm_get_module_context"
 
 external get_module_identifier : llmodule -> string
                                = "llvm_get_module_identifier"
@@ -483,7 +483,7 @@ external function_type : lltype -> lltype array -> lltype = "llvm_function_type"
 external var_arg_function_type : lltype -> lltype array -> lltype
                                = "llvm_var_arg_function_type"
 external is_var_arg : lltype -> bool = "llvm_is_var_arg"
-external return_type : lltype -> lltype = "LLVMGetReturnType"
+external return_type : lltype -> lltype = "llvm_return_type"
 external param_types : lltype -> lltype array = "llvm_param_types"
 
 (*--... Operations on struct types .........................................--*)
@@ -510,7 +510,7 @@ external qualified_pointer_type : llcontext -> int -> lltype
                                 = "llvm_qualified_pointer_type"
 external vector_type : lltype -> int -> lltype = "llvm_vector_type"
 
-external element_type : lltype -> lltype = "LLVMGetElementType"
+external element_type : lltype -> lltype = "llvm_get_element_type"
 external array_length : lltype -> int = "llvm_array_length"
 external address_space : lltype -> int = "llvm_address_space"
 external vector_size : lltype -> int = "llvm_vector_size"
@@ -572,11 +572,11 @@ external indices : llvalue -> int array = "llvm_indices"
 
 (*--... Operations on constants of (mostly) any type .......................--*)
 external is_constant : llvalue -> bool = "llvm_is_constant"
-external const_null : lltype -> llvalue = "LLVMConstNull"
-external const_all_ones : (*int|vec*)lltype -> llvalue = "LLVMConstAllOnes"
-external const_pointer_null : lltype -> llvalue = "LLVMConstPointerNull"
-external undef : lltype -> llvalue = "LLVMGetUndef"
-external poison : lltype -> llvalue = "LLVMGetPoison"
+external const_null : lltype -> llvalue = "llvm_const_null"
+external const_all_ones : (*int|vec*)lltype -> llvalue = "llvm_const_all_ones"
+external const_pointer_null : lltype -> llvalue = "llvm_const_pointer_null"
+external undef : lltype -> llvalue = "llvm_get_undef"
+external poison : lltype -> llvalue = "llvm_get_poison"
 external is_null : llvalue -> bool = "llvm_is_null"
 external is_undef : llvalue -> bool = "llvm_is_undef"
 external is_poison : llvalue -> bool = "llvm_is_poison"
@@ -633,73 +633,74 @@ external aggregate_element : llvalue -> int -> llvalue option
                            = "llvm_aggregate_element"
 
 (*--... Constant expressions ...............................................--*)
-external align_of : lltype -> llvalue = "LLVMAlignOf"
-external size_of : lltype -> llvalue = "LLVMSizeOf"
-external const_neg : llvalue -> llvalue = "LLVMConstNeg"
-external const_nsw_neg : llvalue -> llvalue = "LLVMConstNSWNeg"
-external const_nuw_neg : llvalue -> llvalue = "LLVMConstNUWNeg"
-external const_not : llvalue -> llvalue = "LLVMConstNot"
-external const_add : llvalue -> llvalue -> llvalue = "LLVMConstAdd"
-external const_nsw_add : llvalue -> llvalue -> llvalue = "LLVMConstNSWAdd"
-external const_nuw_add : llvalue -> llvalue -> llvalue = "LLVMConstNUWAdd"
-external const_sub : llvalue -> llvalue -> llvalue = "LLVMConstSub"
-external const_nsw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNSWSub"
-external const_nuw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNUWSub"
-external const_mul : llvalue -> llvalue -> llvalue = "LLVMConstMul"
-external const_nsw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNSWMul"
-external const_nuw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNUWMul"
-external const_and : llvalue -> llvalue -> llvalue = "LLVMConstAnd"
-external const_or : llvalue -> llvalue -> llvalue = "LLVMConstOr"
-external const_xor : llvalue -> llvalue -> llvalue = "LLVMConstXor"
+external align_of : lltype -> llvalue = "llvm_align_of"
+external size_of : lltype -> llvalue = "llvm_size_of"
+external const_neg : llvalue -> llvalue = "llvm_const_neg"
+external const_nsw_neg : llvalue -> llvalue = "llvm_const_nsw_neg"
+external const_nuw_neg : llvalue -> llvalue = "llvm_const_nuw_neg"
+external const_not : llvalue -> llvalue = "llvm_const_not"
+external const_add : llvalue -> llvalue -> llvalue = "llvm_const_add"
+external const_nsw_add : llvalue -> llvalue -> llvalue = "llvm_const_nsw_add"
+external const_nuw_add : llvalue -> llvalue -> llvalue = "llvm_const_nuw_add"
+external const_sub : llvalue -> llvalue -> llvalue = "llvm_const_sub"
+external const_nsw_sub : llvalue -> llvalue -> llvalue = "llvm_const_nsw_sub"
+external const_nuw_sub : llvalue -> llvalue -> llvalue = "llvm_const_nuw_sub"
+external const_mul : llvalue -> llvalue -> llvalue = "llvm_const_mul"
+external const_nsw_mul : llvalue -> llvalue -> llvalue = "llvm_const_nsw_mul"
+external const_nuw_mul : llvalue -> llvalue -> llvalue = "llvm_const_nuw_mul"
+external const_and : llvalue -> llvalue -> llvalue = "llvm_const_and"
+external const_or : llvalue -> llvalue -> llvalue = "llvm_const_or"
+external const_xor : llvalue -> llvalue -> llvalue = "llvm_const_xor"
 external const_icmp : Icmp.t -> llvalue -> llvalue -> llvalue
                     = "llvm_const_icmp"
 external const_fcmp : Fcmp.t -> llvalue -> llvalue -> llvalue
                     = "llvm_const_fcmp"
-external const_shl : llvalue -> llvalue -> llvalue = "LLVMConstShl"
-external const_lshr : llvalue -> llvalue -> llvalue = "LLVMConstLShr"
-external const_ashr : llvalue -> llvalue -> llvalue = "LLVMConstAShr"
+external const_shl : llvalue -> llvalue -> llvalue = "llvm_const_shl"
+external const_lshr : llvalue -> llvalue -> llvalue = "llvm_const_lshr"
+external const_ashr : llvalue -> llvalue -> llvalue = "llvm_const_ashr"
 external const_gep : lltype -> llvalue -> llvalue array -> llvalue
-                    = "llvm_const_gep"
+                   = "llvm_const_gep"
 external const_in_bounds_gep : lltype -> llvalue -> llvalue array -> llvalue
                              = "llvm_const_in_bounds_gep"
-external const_trunc : llvalue -> lltype -> llvalue = "LLVMConstTrunc"
-external const_sext : llvalue -> lltype -> llvalue = "LLVMConstSExt"
-external const_zext : llvalue -> lltype -> llvalue = "LLVMConstZExt"
-external const_fptrunc : llvalue -> lltype -> llvalue = "LLVMConstFPTrunc"
-external const_fpext : llvalue -> lltype -> llvalue = "LLVMConstFPExt"
-external const_uitofp : llvalue -> lltype -> llvalue = "LLVMConstUIToFP"
-external const_sitofp : llvalue -> lltype -> llvalue = "LLVMConstSIToFP"
-external const_fptoui : llvalue -> lltype -> llvalue = "LLVMConstFPToUI"
-external const_fptosi : llvalue -> lltype -> llvalue = "LLVMConstFPToSI"
-external const_ptrtoint : llvalue -> lltype -> llvalue = "LLVMConstPtrToInt"
-external const_inttoptr : llvalue -> lltype -> llvalue = "LLVMConstIntToPtr"
-external const_bitcast : llvalue -> lltype -> llvalue = "LLVMConstBitCast"
+external const_trunc : llvalue -> lltype -> llvalue = "llvm_const_trunc"
+external const_sext : llvalue -> lltype -> llvalue = "llvm_const_sext"
+external const_zext : llvalue -> lltype -> llvalue = "llvm_const_zext"
+external const_fptrunc : llvalue -> lltype -> llvalue = "llvm_const_fptrunc"
+external const_fpext : llvalue -> lltype -> llvalue = "llvm_const_fpext"
+external const_uitofp : llvalue -> lltype -> llvalue = "llvm_const_uitofp"
+external const_sitofp : llvalue -> lltype -> llvalue = "llvm_const_sitofp"
+external const_fptoui : llvalue -> lltype -> llvalue = "llvm_const_fptoui"
+external const_fptosi : llvalue -> lltype -> llvalue = "llvm_const_fptosi"
+external const_ptrtoint : llvalue -> lltype -> llvalue = "llvm_const_ptrtoint"
+external const_inttoptr : llvalue -> lltype -> llvalue = "llvm_const_inttoptr"
+external const_bitcast : llvalue -> lltype -> llvalue = "llvm_const_bitcast"
 external const_zext_or_bitcast : llvalue -> lltype -> llvalue
-                             = "LLVMConstZExtOrBitCast"
+                               = "llvm_const_zext_or_bitcast"
 external const_sext_or_bitcast : llvalue -> lltype -> llvalue
-                             = "LLVMConstSExtOrBitCast"
+                               = "llvm_const_sext_or_bitcast"
 external const_trunc_or_bitcast : llvalue -> lltype -> llvalue
-                              = "LLVMConstTruncOrBitCast"
+                                = "llvm_const_trunc_or_bitcast"
 external const_pointercast : llvalue -> lltype -> llvalue
-                           = "LLVMConstPointerCast"
+                           = "llvm_const_pointercast"
 external const_intcast : llvalue -> lltype -> is_signed:bool -> llvalue
                        = "llvm_const_intcast"
-external const_fpcast : llvalue -> lltype -> llvalue = "LLVMConstFPCast"
+external const_fpcast : llvalue -> lltype -> llvalue = "llvm_const_fpcast"
 external const_select : llvalue -> llvalue -> llvalue -> llvalue
-                      = "LLVMConstSelect"
+                      = "llvm_const_select"
 external const_extractelement : llvalue -> llvalue -> llvalue
-                              = "LLVMConstExtractElement"
+                              = "llvm_const_extractelement"
 external const_insertelement : llvalue -> llvalue -> llvalue -> llvalue
-                             = "LLVMConstInsertElement"
+                             = "llvm_const_insertelement"
 external const_shufflevector : llvalue -> llvalue -> llvalue -> llvalue
-                             = "LLVMConstShuffleVector"
+                             = "llvm_const_shufflevector"
 external const_inline_asm : lltype -> string -> string -> bool -> bool ->
                             llvalue
                           = "llvm_const_inline_asm"
-external block_address : llvalue -> llbasicblock -> llvalue = "LLVMBlockAddress"
+external block_address : llvalue -> llbasicblock -> llvalue
+                       = "llvm_blockaddress"
 
 (*--... Operations on global variables, functions, and aliases (globals) ...--*)
-external global_parent : llvalue -> llmodule = "LLVMGetGlobalParent"
+external global_parent : llvalue -> llmodule = "llvm_global_parent"
 external is_declaration : llvalue -> bool = "llvm_is_declaration"
 external linkage : llvalue -> Linkage.t = "llvm_linkage"
 external set_linkage : Linkage.t -> llvalue -> unit = "llvm_set_linkage"
@@ -883,7 +884,7 @@ let remove_string_function_attr f k i =
 (*--... Operations on params ...............................................--*)
 external params : llvalue -> llvalue array = "llvm_params"
 external param : llvalue -> int -> llvalue = "llvm_param"
-external param_parent : llvalue -> llvalue = "LLVMGetParamParent"
+external param_parent : llvalue -> llvalue = "llvm_param_parent"
 external param_begin : llvalue -> (llvalue, llvalue) llpos = "llvm_param_begin"
 external param_succ : llvalue -> (llvalue, llvalue) llpos = "llvm_param_succ"
 external param_end : llvalue -> (llvalue, llvalue) llrev_pos = "llvm_param_end"
@@ -930,12 +931,12 @@ let fold_right_params f fn init =
   fold_right_param_range f init (param_end fn) (At_start fn)
 
 (*--... Operations on basic blocks .........................................--*)
-external value_of_block : llbasicblock -> llvalue = "LLVMBasicBlockAsValue"
+external value_of_block : llbasicblock -> llvalue = "llvm_value_of_block"
 external value_is_block : llvalue -> bool = "llvm_value_is_block"
-external block_of_value : llvalue -> llbasicblock = "LLVMValueAsBasicBlock"
-external block_parent : llbasicblock -> llvalue = "LLVMGetBasicBlockParent"
+external block_of_value : llvalue -> llbasicblock = "llvm_block_of_value"
+external block_parent : llbasicblock -> llvalue = "llvm_block_parent"
 external basic_blocks : llvalue -> llbasicblock array = "llvm_basic_blocks"
-external entry_block : llvalue -> llbasicblock = "LLVMGetEntryBasicBlock"
+external entry_block : llvalue -> llbasicblock = "llvm_entry_block"
 external delete_block : llbasicblock -> unit = "llvm_delete_block"
 external remove_block : llbasicblock -> unit = "llvm_remove_block"
 external move_block_before : llbasicblock -> llbasicblock -> unit
@@ -998,7 +999,7 @@ let fold_right_blocks f fn init =
   fold_right_block_range f init (block_end fn) (At_start fn)
 
 (*--... Operations on instructions .........................................--*)
-external instr_parent : llvalue -> llbasicblock = "LLVMGetInstructionParent"
+external instr_parent : llvalue -> llbasicblock = "llvm_instr_parent"
 external instr_begin : llbasicblock -> (llbasicblock, llvalue) llpos
                      = "llvm_instr_begin"
 external instr_succ : llvalue -> (llbasicblock, llvalue) llpos
@@ -1082,8 +1083,8 @@ let remove_string_call_site_attr f k i =
 external num_arg_operands : llvalue -> int = "llvm_num_arg_operands"
 external is_tail_call : llvalue -> bool = "llvm_is_tail_call"
 external set_tail_call : bool -> llvalue -> unit = "llvm_set_tail_call"
-external get_normal_dest : llvalue -> llbasicblock = "LLVMGetNormalDest"
-external get_unwind_dest : llvalue -> llbasicblock = "LLVMGetUnwindDest"
+external get_normal_dest : llvalue -> llbasicblock = "llvm_get_normal_dest"
+external get_unwind_dest : llvalue -> llbasicblock = "llvm_get_unwind_dest"
 
 (*--... Operations on load/store instructions (only) .......................--*)
 external is_volatile : llvalue -> bool = "llvm_is_volatile"
@@ -1202,7 +1203,7 @@ external build_free : llvalue -> llbuilder -> llvalue = "llvm_build_free"
 external add_case : llvalue -> llvalue -> llbasicblock -> unit
                   = "llvm_add_case"
 external switch_default_dest : llvalue -> llbasicblock =
-    "LLVMGetSwitchDefaultDest"
+    "llvm_switch_default_dest"
 external build_indirect_br : llvalue -> int -> llbuilder -> llvalue
                            = "llvm_build_indirect_br"
 external add_destination : llvalue -> llbasicblock -> unit

diff  --git a/llvm/bindings/ocaml/llvm/llvm_ocaml.c b/llvm/bindings/ocaml/llvm/llvm_ocaml.c
index dff14cf79c55e..a9d25751fd2ca 100644
--- a/llvm/bindings/ocaml/llvm/llvm_ocaml.c
+++ b/llvm/bindings/ocaml/llvm/llvm_ocaml.c
@@ -43,6 +43,19 @@ value caml_alloc_tuple_uninit(mlsize_t wosize) {
   }
 }
 
+value to_val(void *ptr) {
+  assert((((value)ptr) & 1) == 0 &&
+         "OCaml bindings assume LLVM objects are at least 2-byte aligned");
+  return ((value)ptr) | 1;
+}
+
+void *from_val(value v) {
+  assert(Is_long(v) && "OCaml values representing LLVM objects should have the "
+                       "low bit set so that the OCaml GC "
+                       "treats them as tagged integers");
+  return (void *)(v ^ 1);
+}
+
 value llvm_string_of_message(char *Message) {
   value String = caml_copy_string(Message);
   LLVMDisposeMessage(Message);
@@ -53,7 +66,7 @@ value llvm_string_of_message(char *Message) {
 value ptr_to_option(void *Ptr) {
   if (!Ptr)
     return Val_none;
-  return caml_alloc_some((value)Ptr);
+  return caml_alloc_some(to_val(Ptr));
 }
 
 value cstr_to_string(const char *Str, mlsize_t Len) {
@@ -79,7 +92,7 @@ void llvm_raise(value Prototype, char *Message) {
 static value llvm_fatal_error_handler;
 
 static void llvm_fatal_error_trampoline(const char *Reason) {
-  callback(llvm_fatal_error_handler, caml_copy_string(Reason));
+  caml_callback(llvm_fatal_error_handler, caml_copy_string(Reason));
 }
 
 value llvm_install_fatal_error_handler(value Handler) {
@@ -112,112 +125,126 @@ value llvm_parse_command_line_options(value Overview, value Args) {
   return Val_unit;
 }
 
-static value alloc_variant(int tag, void *Value) {
+void *from_val_array(value Elements) {
+  mlsize_t Length = Wosize_val(Elements);
+  void **Temp = malloc(sizeof(void *) * Length);
+  if (Temp == NULL)
+    caml_raise_out_of_memory();
+  for (unsigned I = 0; I < Length; ++I) {
+    Temp[I] = from_val(Field(Elements, I));
+  }
+  return Temp;
+}
+
+static value alloc_variant(int tag, value Value) {
   value Iter = caml_alloc_small(1, tag);
-  Field(Iter, 0) = Val_op(Value);
+  Field(Iter, 0) = Value;
   return Iter;
 }
 
 /* Macro to convert the C first/next/last/prev idiom to the Ocaml llpos/
    llrev_pos idiom. */
-#define DEFINE_ITERATORS(camlname, cname, pty, cty, pfun) \
-  /* llmodule -> ('a, 'b) llpos */                        \
-  value llvm_##camlname##_begin(pty Mom) {       \
-    cty First = LLVMGetFirst##cname(Mom);                 \
-    if (First)                                            \
-      return alloc_variant(1, First);                     \
-    return alloc_variant(0, Mom);                         \
-  }                                                       \
-                                                          \
-  /* llvalue -> ('a, 'b) llpos */                         \
-  value llvm_##camlname##_succ(cty Kid) {        \
-    cty Next = LLVMGetNext##cname(Kid);                   \
-    if (Next)                                             \
-      return alloc_variant(1, Next);                      \
-    return alloc_variant(0, pfun(Kid));                   \
-  }                                                       \
-                                                          \
-  /* llmodule -> ('a, 'b) llrev_pos */                    \
-  value llvm_##camlname##_end(pty Mom) {         \
-    cty Last = LLVMGetLast##cname(Mom);                   \
-    if (Last)                                             \
-      return alloc_variant(1, Last);                      \
-    return alloc_variant(0, Mom);                         \
-  }                                                       \
-                                                          \
-  /* llvalue -> ('a, 'b) llrev_pos */                     \
-  value llvm_##camlname##_pred(cty Kid) {        \
-    cty Prev = LLVMGetPrevious##cname(Kid);               \
-    if (Prev)                                             \
-      return alloc_variant(1, Prev);                      \
-    return alloc_variant(0, pfun(Kid));                   \
+#define DEFINE_ITERATORS(camlname, cname, pty_val, cty, cty_val, pfun)         \
+  /* llmodule -> ('a, 'b) llpos */                                             \
+  value llvm_##camlname##_begin(value Mom) {                                   \
+    cty First = LLVMGetFirst##cname(pty_val(Mom));                             \
+    if (First)                                                                 \
+      return alloc_variant(1, to_val(First));                                  \
+    return alloc_variant(0, Mom);                                              \
+  }                                                                            \
+                                                                               \
+  /* llvalue -> ('a, 'b) llpos */                                              \
+  value llvm_##camlname##_succ(value Kid) {                                    \
+    cty Next = LLVMGetNext##cname(cty_val(Kid));                               \
+    if (Next)                                                                  \
+      return alloc_variant(1, to_val(Next));                                   \
+    return alloc_variant(0, to_val(pfun(cty_val(Kid))));                       \
+  }                                                                            \
+                                                                               \
+  /* llmodule -> ('a, 'b) llrev_pos */                                         \
+  value llvm_##camlname##_end(value Mom) {                                     \
+    cty Last = LLVMGetLast##cname(pty_val(Mom));                               \
+    if (Last)                                                                  \
+      return alloc_variant(1, to_val(Last));                                   \
+    return alloc_variant(0, Mom);                                              \
+  }                                                                            \
+                                                                               \
+  /* llvalue -> ('a, 'b) llrev_pos */                                          \
+  value llvm_##camlname##_pred(value Kid) {                                    \
+    cty Prev = LLVMGetPrevious##cname(cty_val(Kid));                           \
+    if (Prev)                                                                  \
+      return alloc_variant(1, to_val(Prev));                                   \
+    return alloc_variant(0, to_val(pfun(cty_val(Kid))));                       \
   }
 
 /*===-- Context error handling --------------------------------------------===*/
 
 void llvm_diagnostic_handler_trampoline(LLVMDiagnosticInfoRef DI,
                                         void *DiagnosticContext) {
-  caml_callback(*((value *)DiagnosticContext), (value)DI);
+  caml_callback(*((value *)DiagnosticContext), to_val(DI));
 }
 
 /* Diagnostic.t -> string */
 value llvm_get_diagnostic_description(value Diagnostic) {
   return llvm_string_of_message(
-      LLVMGetDiagInfoDescription((LLVMDiagnosticInfoRef)Diagnostic));
+      LLVMGetDiagInfoDescription(DiagnosticInfo_val(Diagnostic)));
 }
 
 /* Diagnostic.t -> DiagnosticSeverity.t */
 value llvm_get_diagnostic_severity(value Diagnostic) {
-  return Val_int(LLVMGetDiagInfoSeverity((LLVMDiagnosticInfoRef)Diagnostic));
+  return Val_int(LLVMGetDiagInfoSeverity(DiagnosticInfo_val(Diagnostic)));
 }
 
-static void llvm_remove_diagnostic_handler(LLVMContextRef C) {
-  if (LLVMContextGetDiagnosticHandler(C) ==
+static void llvm_remove_diagnostic_handler(value C) {
+  CAMLparam1(C);
+  LLVMContextRef context = Context_val(C);
+  if (LLVMContextGetDiagnosticHandler(context) ==
       llvm_diagnostic_handler_trampoline) {
-    value *Handler = (value *)LLVMContextGetDiagnosticContext(C);
-    remove_global_root(Handler);
+    value *Handler = (value *)LLVMContextGetDiagnosticContext(context);
+    caml_remove_global_root(Handler);
     free(Handler);
   }
+  CAMLreturn0;
 }
 
 /* llcontext -> (Diagnostic.t -> unit) option -> unit */
-value llvm_set_diagnostic_handler(LLVMContextRef C, value Handler) {
+value llvm_set_diagnostic_handler(value C, value Handler) {
+  CAMLparam2(C, Handler);
+  LLVMContextRef context = Context_val(C);
   llvm_remove_diagnostic_handler(C);
   if (Handler == Val_none) {
-    LLVMContextSetDiagnosticHandler(C, NULL, NULL);
+    LLVMContextSetDiagnosticHandler(context, NULL, NULL);
   } else {
     value *DiagnosticContext = malloc(sizeof(value));
     if (DiagnosticContext == NULL)
       caml_raise_out_of_memory();
     caml_register_global_root(DiagnosticContext);
     *DiagnosticContext = Field(Handler, 0);
-    LLVMContextSetDiagnosticHandler(C, llvm_diagnostic_handler_trampoline,
+    LLVMContextSetDiagnosticHandler(context, llvm_diagnostic_handler_trampoline,
                                     DiagnosticContext);
   }
-  return Val_unit;
+  CAMLreturn(Val_unit);
 }
 
 /*===-- Contexts ----------------------------------------------------------===*/
 
 /* unit -> llcontext */
-LLVMContextRef llvm_create_context(value Unit) { return LLVMContextCreate(); }
+value llvm_create_context(value Unit) { return to_val(LLVMContextCreate()); }
 
 /* llcontext -> unit */
-value llvm_dispose_context(LLVMContextRef C) {
+value llvm_dispose_context(value C) {
   llvm_remove_diagnostic_handler(C);
-  LLVMContextDispose(C);
+  LLVMContextDispose(Context_val(C));
   return Val_unit;
 }
 
 /* unit -> llcontext */
-LLVMContextRef llvm_global_context(value Unit) {
-  return LLVMGetGlobalContext();
-}
+value llvm_global_context(value Unit) { return to_val(LLVMGetGlobalContext()); }
 
 /* llcontext -> string -> int */
-value llvm_mdkind_id(LLVMContextRef C, value Name) {
-  unsigned MDKindID =
-      LLVMGetMDKindIDInContext(C, String_val(Name), caml_string_length(Name));
+value llvm_mdkind_id(value C, value Name) {
+  unsigned MDKindID = LLVMGetMDKindIDInContext(Context_val(C), String_val(Name),
+                                               caml_string_length(Name));
   return Val_int(MDKindID);
 }
 
@@ -233,165 +260,173 @@ value llvm_enum_attr_kind(value Name) {
 }
 
 /* llcontext -> int -> int64 -> llattribute */
-LLVMAttributeRef llvm_create_enum_attr_by_kind(LLVMContextRef C, value Kind,
-                                               value Value) {
-  return LLVMCreateEnumAttribute(C, Int_val(Kind), Int64_val(Value));
+value llvm_create_enum_attr_by_kind(value C, value Kind, value Value) {
+  return to_val(
+      LLVMCreateEnumAttribute(Context_val(C), Int_val(Kind), Int64_val(Value)));
 }
 
 /* llattribute -> bool */
-value llvm_is_enum_attr(LLVMAttributeRef A) {
-  return Val_int(LLVMIsEnumAttribute(A));
+value llvm_is_enum_attr(value A) {
+  return Val_int(LLVMIsEnumAttribute(Attribute_val(A)));
 }
 
 /* llattribute -> llattrkind */
-value llvm_get_enum_attr_kind(LLVMAttributeRef A) {
-  return Val_int(LLVMGetEnumAttributeKind(A));
+value llvm_get_enum_attr_kind(value A) {
+  return Val_int(LLVMGetEnumAttributeKind(Attribute_val(A)));
 }
 
 /* llattribute -> int64 */
-value llvm_get_enum_attr_value(LLVMAttributeRef A) {
-  return caml_copy_int64(LLVMGetEnumAttributeValue(A));
+value llvm_get_enum_attr_value(value A) {
+  return caml_copy_int64(LLVMGetEnumAttributeValue(Attribute_val(A)));
 }
 
 /* llcontext -> kind:string -> name:string -> llattribute */
-LLVMAttributeRef llvm_create_string_attr(LLVMContextRef C, value Kind,
-                                         value Value) {
-  return LLVMCreateStringAttribute(C, String_val(Kind),
-                                   caml_string_length(Kind), String_val(Value),
-                                   caml_string_length(Value));
+value llvm_create_string_attr(value C, value Kind, value Value) {
+  return to_val(LLVMCreateStringAttribute(
+      Context_val(C), String_val(Kind), caml_string_length(Kind),
+      String_val(Value), caml_string_length(Value)));
 }
 
 /* llattribute -> bool */
-value llvm_is_string_attr(LLVMAttributeRef A) {
-  return Val_int(LLVMIsStringAttribute(A));
+value llvm_is_string_attr(value A) {
+  return Val_int(LLVMIsStringAttribute(Attribute_val(A)));
 }
 
 /* llattribute -> string */
-value llvm_get_string_attr_kind(LLVMAttributeRef A) {
+value llvm_get_string_attr_kind(value A) {
   unsigned Length;
-  const char *String = LLVMGetStringAttributeKind(A, &Length);
+  const char *String = LLVMGetStringAttributeKind(Attribute_val(A), &Length);
   return cstr_to_string(String, Length);
 }
 
 /* llattribute -> string */
-value llvm_get_string_attr_value(LLVMAttributeRef A) {
+value llvm_get_string_attr_value(value A) {
   unsigned Length;
-  const char *String = LLVMGetStringAttributeValue(A, &Length);
+  const char *String = LLVMGetStringAttributeValue(Attribute_val(A), &Length);
   return cstr_to_string(String, Length);
 }
 
 /*===-- Modules -----------------------------------------------------------===*/
 
 /* llcontext -> string -> llmodule */
-LLVMModuleRef llvm_create_module(LLVMContextRef C, value ModuleID) {
-  return LLVMModuleCreateWithNameInContext(String_val(ModuleID), C);
+value llvm_create_module(value C, value ModuleID) {
+  return to_val(
+      LLVMModuleCreateWithNameInContext(String_val(ModuleID), Context_val(C)));
 }
 
 /* llmodule -> unit */
-value llvm_dispose_module(LLVMModuleRef M) {
-  LLVMDisposeModule(M);
+value llvm_dispose_module(value M) {
+  LLVMDisposeModule(Module_val(M));
   return Val_unit;
 }
 
 /* llmodule -> string */
-value llvm_target_triple(LLVMModuleRef M) {
-  return caml_copy_string(LLVMGetTarget(M));
+value llvm_target_triple(value M) {
+  return caml_copy_string(LLVMGetTarget(Module_val(M)));
 }
 
 /* string -> llmodule -> unit */
-value llvm_set_target_triple(value Trip, LLVMModuleRef M) {
-  LLVMSetTarget(M, String_val(Trip));
+value llvm_set_target_triple(value Trip, value M) {
+  LLVMSetTarget(Module_val(M), String_val(Trip));
   return Val_unit;
 }
 
 /* llmodule -> string */
-value llvm_data_layout(LLVMModuleRef M) {
-  return caml_copy_string(LLVMGetDataLayout(M));
+value llvm_data_layout(value M) {
+  return caml_copy_string(LLVMGetDataLayout(Module_val(M)));
 }
 
 /* string -> llmodule -> unit */
-value llvm_set_data_layout(value Layout, LLVMModuleRef M) {
-  LLVMSetDataLayout(M, String_val(Layout));
+value llvm_set_data_layout(value Layout, value M) {
+  LLVMSetDataLayout(Module_val(M), String_val(Layout));
   return Val_unit;
 }
 
 /* llmodule -> unit */
-value llvm_dump_module(LLVMModuleRef M) {
-  LLVMDumpModule(M);
+value llvm_dump_module(value M) {
+  LLVMDumpModule(Module_val(M));
   return Val_unit;
 }
 
 /* string -> llmodule -> unit */
-value llvm_print_module(value Filename, LLVMModuleRef M) {
+value llvm_print_module(value Filename, value M) {
   char *Message;
 
-  if (LLVMPrintModuleToFile(M, String_val(Filename), &Message))
+  if (LLVMPrintModuleToFile(Module_val(M), String_val(Filename), &Message))
     llvm_raise(*caml_named_value("Llvm.IoError"), Message);
 
   return Val_unit;
 }
 
 /* llmodule -> string */
-value llvm_string_of_llmodule(LLVMModuleRef M) {
-  char *ModuleCStr = LLVMPrintModuleToString(M);
+value llvm_string_of_llmodule(value M) {
+  char *ModuleCStr = LLVMPrintModuleToString(Module_val(M));
   value ModuleStr = caml_copy_string(ModuleCStr);
   LLVMDisposeMessage(ModuleCStr);
 
   return ModuleStr;
 }
 
+/* llmodule -> llcontext */
+value llvm_get_module_context(value M) {
+  LLVMContextRef C = LLVMGetModuleContext(Module_val(M));
+  return to_val(C);
+}
+
 /* llmodule -> string */
-value llvm_get_module_identifier(LLVMModuleRef M) {
+value llvm_get_module_identifier(value M) {
   size_t Len;
-  const char *Name = LLVMGetModuleIdentifier(M, &Len);
+  const char *Name = LLVMGetModuleIdentifier(Module_val(M), &Len);
   return cstr_to_string(Name, (mlsize_t)Len);
 }
 
 /* llmodule -> string -> unit */
-value llvm_set_module_identifier(LLVMModuleRef M, value Id) {
-  LLVMSetModuleIdentifier(M, String_val(Id), caml_string_length(Id));
+value llvm_set_module_identifier(value M, value Id) {
+  LLVMSetModuleIdentifier(Module_val(M), String_val(Id),
+                          caml_string_length(Id));
   return Val_unit;
 }
 
 /* llmodule -> string -> unit */
-value llvm_set_module_inline_asm(LLVMModuleRef M, value Asm) {
-  LLVMSetModuleInlineAsm(M, String_val(Asm));
+value llvm_set_module_inline_asm(value M, value Asm) {
+  LLVMSetModuleInlineAsm(Module_val(M), String_val(Asm));
   return Val_unit;
 }
 
 /* llmodule -> string -> llmetadata option */
-value llvm_get_module_flag(LLVMModuleRef M, value Key) {
-  return ptr_to_option(
-      LLVMGetModuleFlag(M, String_val(Key), caml_string_length(Key)));
+value llvm_get_module_flag(value M, value Key) {
+  return ptr_to_option(LLVMGetModuleFlag(Module_val(M), String_val(Key),
+                                         caml_string_length(Key)));
 }
 
-value llvm_add_module_flag(LLVMModuleRef M, LLVMModuleFlagBehavior Behaviour,
-                           value Key, LLVMMetadataRef Val) {
-  LLVMAddModuleFlag(M, Int_val(Behaviour), String_val(Key),
-                    caml_string_length(Key), Val);
+/* llmodule -> ModuleFlagBehavior.t -> string -> llmetadata -> unit */
+value llvm_add_module_flag(value M, value Behaviour, value Key, value Val) {
+  LLVMAddModuleFlag(Module_val(M), Int_val(Behaviour), String_val(Key),
+                    caml_string_length(Key), Metadata_val(Val));
   return Val_unit;
 }
 
 /*===-- Types -------------------------------------------------------------===*/
 
 /* lltype -> TypeKind.t */
-value llvm_classify_type(LLVMTypeRef Ty) {
-  return Val_int(LLVMGetTypeKind(Ty));
+value llvm_classify_type(value Ty) {
+  return Val_int(LLVMGetTypeKind(Type_val(Ty)));
 }
 
-value llvm_type_is_sized(LLVMTypeRef Ty) {
-  return Val_bool(LLVMTypeIsSized(Ty));
+/* lltype -> bool */
+value llvm_type_is_sized(value Ty) {
+  return Val_bool(LLVMTypeIsSized(Type_val(Ty)));
 }
 
 /* lltype -> llcontext */
-LLVMContextRef llvm_type_context(LLVMTypeRef Ty) {
-  return LLVMGetTypeContext(Ty);
+value llvm_type_context(value Ty) {
+  return to_val(LLVMGetTypeContext(Type_val(Ty)));
 }
 
 /* lltype -> unit */
-value llvm_dump_type(LLVMTypeRef Val) {
+value llvm_dump_type(value Val) {
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-  LLVMDumpType(Val);
+  LLVMDumpType(Type_val(Val));
 #else
   caml_raise_with_arg(*caml_named_value("Llvm.FeatureDisabled"),
                       caml_copy_string("dump"));
@@ -400,8 +435,8 @@ value llvm_dump_type(LLVMTypeRef Val) {
 }
 
 /* lltype -> string */
-value llvm_string_of_lltype(LLVMTypeRef M) {
-  char *TypeCStr = LLVMPrintTypeToString(M);
+value llvm_string_of_lltype(value M) {
+  char *TypeCStr = LLVMPrintTypeToString(Type_val(M));
   value TypeStr = caml_copy_string(TypeCStr);
   LLVMDisposeMessage(TypeCStr);
 
@@ -411,121 +446,145 @@ value llvm_string_of_lltype(LLVMTypeRef M) {
 /*--... Operations on integer types ........................................--*/
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_i1_type(LLVMContextRef Context) {
-  return LLVMInt1TypeInContext(Context);
+value llvm_i1_type(value Context) {
+  return to_val(LLVMInt1TypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_i8_type(LLVMContextRef Context) {
-  return LLVMInt8TypeInContext(Context);
+value llvm_i8_type(value Context) {
+  return to_val(LLVMInt8TypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_i16_type(LLVMContextRef Context) {
-  return LLVMInt16TypeInContext(Context);
+value llvm_i16_type(value Context) {
+  return to_val(LLVMInt16TypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_i32_type(LLVMContextRef Context) {
-  return LLVMInt32TypeInContext(Context);
+value llvm_i32_type(value Context) {
+  return to_val(LLVMInt32TypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_i64_type(LLVMContextRef Context) {
-  return LLVMInt64TypeInContext(Context);
+value llvm_i64_type(value Context) {
+  return to_val(LLVMInt64TypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> int -> lltype */
-LLVMTypeRef llvm_integer_type(LLVMContextRef Context, value Width) {
-  return LLVMIntTypeInContext(Context, Int_val(Width));
+value llvm_integer_type(value Context, value Width) {
+  return to_val(LLVMIntTypeInContext(Context_val(Context), Int_val(Width)));
 }
 
 /* lltype -> int */
-value llvm_integer_bitwidth(LLVMTypeRef IntegerTy) {
-  return Val_int(LLVMGetIntTypeWidth(IntegerTy));
+value llvm_integer_bitwidth(value IntegerTy) {
+  return Val_int(LLVMGetIntTypeWidth(Type_val(IntegerTy)));
 }
 
 /*--... Operations on real types ...........................................--*/
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_float_type(LLVMContextRef Context) {
-  return LLVMFloatTypeInContext(Context);
+value llvm_float_type(value Context) {
+  return to_val(LLVMFloatTypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_double_type(LLVMContextRef Context) {
-  return LLVMDoubleTypeInContext(Context);
+value llvm_double_type(value Context) {
+  return to_val(LLVMDoubleTypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_x86fp80_type(LLVMContextRef Context) {
-  return LLVMX86FP80TypeInContext(Context);
+value llvm_x86fp80_type(value Context) {
+  return to_val(LLVMX86FP80TypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_fp128_type(LLVMContextRef Context) {
-  return LLVMFP128TypeInContext(Context);
+value llvm_fp128_type(value Context) {
+  return to_val(LLVMFP128TypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_ppc_fp128_type(LLVMContextRef Context) {
-  return LLVMPPCFP128TypeInContext(Context);
+value llvm_ppc_fp128_type(value Context) {
+  return to_val(LLVMPPCFP128TypeInContext(Context_val(Context)));
 }
 
 /*--... Operations on function types .......................................--*/
 
 /* lltype -> lltype array -> lltype */
-LLVMTypeRef llvm_function_type(LLVMTypeRef RetTy, value ParamTys) {
-  return LLVMFunctionType(RetTy, (LLVMTypeRef *)ParamTys, Wosize_val(ParamTys),
-                          0);
+value llvm_function_type(value RetTy, value ParamTys) {
+  mlsize_t len = Wosize_val(ParamTys);
+  LLVMTypeRef *Temp = from_val_array(ParamTys);
+  LLVMTypeRef Type = LLVMFunctionType(Type_val(RetTy), Temp, len, 0);
+  free(Temp);
+  return to_val(Type);
 }
 
 /* lltype -> lltype array -> lltype */
-LLVMTypeRef llvm_var_arg_function_type(LLVMTypeRef RetTy, value ParamTys) {
-  return LLVMFunctionType(RetTy, (LLVMTypeRef *)ParamTys, Wosize_val(ParamTys),
-                          1);
+value llvm_var_arg_function_type(value RetTy, value ParamTys) {
+  mlsize_t len = Wosize_val(ParamTys);
+  LLVMTypeRef *Temp = from_val_array(ParamTys);
+  LLVMTypeRef Type = LLVMFunctionType(Type_val(RetTy), Temp, len, 1);
+  free(Temp);
+  return to_val(Type);
 }
 
 /* lltype -> bool */
-value llvm_is_var_arg(LLVMTypeRef FunTy) {
-  return Val_bool(LLVMIsFunctionVarArg(FunTy));
+value llvm_is_var_arg(value FunTy) {
+  return Val_bool(LLVMIsFunctionVarArg(Type_val(FunTy)));
+}
+
+/* lltype -> lltype */
+value llvm_return_type(value FunTy) {
+  LLVMTypeRef Type = LLVMGetReturnType(Type_val(FunTy));
+  return to_val(Type);
 }
 
 /* lltype -> lltype array */
-value llvm_param_types(LLVMTypeRef FunTy) {
-  value Tys = caml_alloc_tuple_uninit(LLVMCountParamTypes(FunTy));
-  LLVMGetParamTypes(FunTy, (LLVMTypeRef *)Op_val(Tys));
+value llvm_param_types(value FunTy) {
+  unsigned Length = LLVMCountParamTypes(Type_val(FunTy));
+  value Tys = caml_alloc_tuple_uninit(Length);
+  LLVMGetParamTypes(Type_val(FunTy), (LLVMTypeRef *)Op_val(Tys));
+  for (unsigned I = 0; I < Length; ++I) {
+    Field(Tys, I) = to_val((LLVMTypeRef)Field(Tys, I));
+  }
   return Tys;
 }
 
 /*--... Operations on struct types .........................................--*/
 
 /* llcontext -> lltype array -> lltype */
-LLVMTypeRef llvm_struct_type(LLVMContextRef C, value ElementTypes) {
-  return LLVMStructTypeInContext(C, (LLVMTypeRef *)ElementTypes,
-                                 Wosize_val(ElementTypes), 0);
+value llvm_struct_type(value C, value ElementTypes) {
+  mlsize_t Length = Wosize_val(ElementTypes);
+  LLVMTypeRef *Temp = from_val_array(ElementTypes);
+  LLVMTypeRef Type = LLVMStructTypeInContext(Context_val(C), Temp, Length, 0);
+  free(Temp);
+  return to_val(Type);
 }
 
 /* llcontext -> lltype array -> lltype */
-LLVMTypeRef llvm_packed_struct_type(LLVMContextRef C, value ElementTypes) {
-  return LLVMStructTypeInContext(C, (LLVMTypeRef *)ElementTypes,
-                                 Wosize_val(ElementTypes), 1);
+value llvm_packed_struct_type(value C, value ElementTypes) {
+  mlsize_t Length = Wosize_val(ElementTypes);
+  LLVMTypeRef *Temp = from_val_array(ElementTypes);
+  LLVMTypeRef Type = LLVMStructTypeInContext(Context_val(C), Temp, Length, 1);
+  free(Temp);
+  return to_val(Type);
 }
 
 /* llcontext -> string -> lltype */
-LLVMTypeRef llvm_named_struct_type(LLVMContextRef C, value Name) {
-  return LLVMStructCreateNamed(C, String_val(Name));
+value llvm_named_struct_type(value C, value Name) {
+  return to_val(LLVMStructCreateNamed(Context_val(C), String_val(Name)));
 }
 
-value llvm_struct_set_body(LLVMTypeRef Ty, value ElementTypes, value Packed) {
-  LLVMStructSetBody(Ty, (LLVMTypeRef *)ElementTypes, Wosize_val(ElementTypes),
-                    Bool_val(Packed));
+/* lltype -> lltype array -> bool -> unit */
+value llvm_struct_set_body(value Ty, value ElementTypes, value Packed) {
+  mlsize_t Length = Wosize_val(ElementTypes);
+  LLVMTypeRef *Temp = from_val_array(ElementTypes);
+  LLVMStructSetBody(Type_val(Ty), Temp, Length, Bool_val(Packed));
   return Val_unit;
 }
 
 /* lltype -> string option */
-value llvm_struct_name(LLVMTypeRef Ty) {
-  const char *CStr = LLVMGetStructName(Ty);
+value llvm_struct_name(value Ty) {
+  const char *CStr = LLVMGetStructName(Type_val(Ty));
   size_t Len;
   if (!CStr)
     return Val_none;
@@ -534,97 +593,113 @@ value llvm_struct_name(LLVMTypeRef Ty) {
 }
 
 /* lltype -> lltype array */
-value llvm_struct_element_types(LLVMTypeRef StructTy) {
-  value Tys = caml_alloc_tuple_uninit(LLVMCountStructElementTypes(StructTy));
-  LLVMGetStructElementTypes(StructTy, (LLVMTypeRef *)Op_val(Tys));
+value llvm_struct_element_types(value StructTy) {
+  unsigned Length = LLVMCountStructElementTypes(Type_val(StructTy));
+  value Tys = caml_alloc_tuple_uninit(Length);
+  LLVMGetStructElementTypes(Type_val(StructTy), (LLVMTypeRef *)Op_val(Tys));
+  for (unsigned I = 0; I < Length; ++I) {
+    Field(Tys, I) = to_val((LLVMTypeRef)Field(Tys, I));
+  }
   return Tys;
 }
 
 /* lltype -> bool */
-value llvm_is_packed(LLVMTypeRef StructTy) {
-  return Val_bool(LLVMIsPackedStruct(StructTy));
+value llvm_is_packed(value StructTy) {
+  return Val_bool(LLVMIsPackedStruct(Type_val(StructTy)));
 }
 
 /* lltype -> bool */
-value llvm_is_opaque(LLVMTypeRef StructTy) {
-  return Val_bool(LLVMIsOpaqueStruct(StructTy));
+value llvm_is_opaque(value StructTy) {
+  return Val_bool(LLVMIsOpaqueStruct(Type_val(StructTy)));
 }
 
 /* lltype -> bool */
-value llvm_is_literal(LLVMTypeRef StructTy) {
-  return Val_bool(LLVMIsLiteralStruct(StructTy));
+value llvm_is_literal(value StructTy) {
+  return Val_bool(LLVMIsLiteralStruct(Type_val(StructTy)));
 }
 
 /*--... Operations on array, pointer, and vector types .....................--*/
 
 /* lltype -> lltype array */
-value llvm_subtypes(LLVMTypeRef Ty) {
-  unsigned Size = LLVMGetNumContainedTypes(Ty);
-  value Arr = caml_alloc_tuple_uninit(Size);
-  LLVMGetSubtypes(Ty, (LLVMTypeRef *)Op_val(Arr));
+value llvm_subtypes(value Ty) {
+  unsigned Length = LLVMGetNumContainedTypes(Type_val(Ty));
+  value Arr = caml_alloc_tuple_uninit(Length);
+  LLVMGetSubtypes(Type_val(Ty), (LLVMTypeRef *)Op_val(Arr));
+  for (unsigned I = 0; I < Length; ++I) {
+    Field(Arr, I) = to_val((LLVMTypeRef)Field(Arr, I));
+  }
   return Arr;
 }
 
 /* lltype -> int -> lltype */
-LLVMTypeRef llvm_array_type(LLVMTypeRef ElementTy, value Count) {
-  return LLVMArrayType(ElementTy, Int_val(Count));
+value llvm_array_type(value ElementTy, value Count) {
+  return to_val(LLVMArrayType(Type_val(ElementTy), Int_val(Count)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_pointer_type(LLVMContextRef C) {
-  return LLVMPointerTypeInContext(C, 0);
+value llvm_pointer_type(value C) {
+  LLVMTypeRef Type = LLVMPointerTypeInContext(Context_val(C), 0);
+  return to_val(Type);
 }
 
 /* llcontext -> int -> lltype */
-LLVMTypeRef llvm_qualified_pointer_type(LLVMContextRef C, value AddressSpace) {
-  return LLVMPointerTypeInContext(C, Int_val(AddressSpace));
+value llvm_qualified_pointer_type(value C, value AddressSpace) {
+  LLVMTypeRef Type =
+      LLVMPointerTypeInContext(Context_val(C), Int_val(AddressSpace));
+  return to_val(Type);
 }
 
 /* lltype -> int -> lltype */
-LLVMTypeRef llvm_vector_type(LLVMTypeRef ElementTy, value Count) {
-  return LLVMVectorType(ElementTy, Int_val(Count));
+value llvm_vector_type(value ElementTy, value Count) {
+  return to_val(LLVMVectorType(Type_val(ElementTy), Int_val(Count)));
+}
+
+/* lltype -> lltype */
+value llvm_get_element_type(value Ty) {
+  return to_val(LLVMGetElementType(Type_val(Ty)));
 }
 
 /* lltype -> int */
-value llvm_array_length(LLVMTypeRef ArrayTy) {
-  return Val_int(LLVMGetArrayLength2(ArrayTy));
+value llvm_array_length(value ArrayTy) {
+  return Val_int(LLVMGetArrayLength2(Type_val(ArrayTy)));
 }
 
 /* lltype -> int */
-value llvm_address_space(LLVMTypeRef PtrTy) {
-  return Val_int(LLVMGetPointerAddressSpace(PtrTy));
+value llvm_address_space(value PtrTy) {
+  return Val_int(LLVMGetPointerAddressSpace(Type_val(PtrTy)));
 }
 
 /* lltype -> int */
-value llvm_vector_size(LLVMTypeRef VectorTy) {
-  return Val_int(LLVMGetVectorSize(VectorTy));
+value llvm_vector_size(value VectorTy) {
+  return Val_int(LLVMGetVectorSize(Type_val(VectorTy)));
 }
 
 /*--... Operations on other types ..........................................--*/
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_void_type(LLVMContextRef Context) {
-  return LLVMVoidTypeInContext(Context);
+value llvm_void_type(value Context) {
+  return to_val(LLVMVoidTypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_label_type(LLVMContextRef Context) {
-  return LLVMLabelTypeInContext(Context);
+value llvm_label_type(value Context) {
+  return to_val(LLVMLabelTypeInContext(Context_val(Context)));
 }
 
 /* llcontext -> lltype */
-LLVMTypeRef llvm_x86_mmx_type(LLVMContextRef Context) {
-  return LLVMX86MMXTypeInContext(Context);
+value llvm_x86_mmx_type(value Context) {
+  return to_val(LLVMX86MMXTypeInContext(Context_val(Context)));
 }
 
-value llvm_type_by_name(LLVMModuleRef M, value Name) {
-  return ptr_to_option(LLVMGetTypeByName(M, String_val(Name)));
+/* llmodule -> string -> lltype option */
+value llvm_type_by_name(value M, value Name) {
+  return ptr_to_option(LLVMGetTypeByName(Module_val(M), String_val(Name)));
 }
 
 /*===-- VALUES ------------------------------------------------------------===*/
 
 /* llvalue -> lltype */
-LLVMTypeRef llvm_type_of(LLVMValueRef Val) { return LLVMTypeOf(Val); }
+value llvm_type_of(value Val) { return to_val(LLVMTypeOf(Value_val(Val))); }
 
 /* keep in sync with ValueKind.t */
 enum ValueKind {
@@ -655,10 +730,14 @@ enum ValueKind {
 };
 
 /* llvalue -> ValueKind.t */
-#define DEFINE_CASE(Val, Kind) \
-    do {if (LLVMIsA##Kind(Val)) return Val_int(Kind);} while(0)
-
-value llvm_classify_value(LLVMValueRef Val) {
+#define DEFINE_CASE(Val, Kind)                                                 \
+  do {                                                                         \
+    if (LLVMIsA##Kind(Val))                                                    \
+      return Val_int(Kind);                                                    \
+  } while (0)
+
+value llvm_classify_value(value V) {
+  LLVMValueRef Val = Value_val(V);
   if (!Val)
     return Val_int(NullValue);
   if (LLVMIsAConstant(Val)) {
@@ -692,29 +771,29 @@ value llvm_classify_value(LLVMValueRef Val) {
   DEFINE_CASE(Val, MDString);
   DEFINE_CASE(Val, UndefValue);
   DEFINE_CASE(Val, PoisonValue);
-  failwith("Unknown Value class");
+  caml_failwith("Unknown Value class");
 }
 
 /* llvalue -> string */
-value llvm_value_name(LLVMValueRef Val) {
-  return caml_copy_string(LLVMGetValueName(Val));
+value llvm_value_name(value Val) {
+  return caml_copy_string(LLVMGetValueName(Value_val(Val)));
 }
 
 /* string -> llvalue -> unit */
-value llvm_set_value_name(value Name, LLVMValueRef Val) {
-  LLVMSetValueName(Val, String_val(Name));
+value llvm_set_value_name(value Name, value Val) {
+  LLVMSetValueName(Value_val(Val), String_val(Name));
   return Val_unit;
 }
 
 /* llvalue -> unit */
-value llvm_dump_value(LLVMValueRef Val) {
-  LLVMDumpValue(Val);
+value llvm_dump_value(value Val) {
+  LLVMDumpValue(Value_val(Val));
   return Val_unit;
 }
 
 /* llvalue -> string */
-value llvm_string_of_llvalue(LLVMValueRef M) {
-  char *ValueCStr = LLVMPrintValueToString(M);
+value llvm_string_of_llvalue(value M) {
+  char *ValueCStr = LLVMPrintValueToString(Value_val(M));
   value ValueStr = caml_copy_string(ValueCStr);
   LLVMDisposeMessage(ValueCStr);
 
@@ -722,161 +801,208 @@ value llvm_string_of_llvalue(LLVMValueRef M) {
 }
 
 /* llvalue -> llvalue -> unit */
-value llvm_replace_all_uses_with(LLVMValueRef OldVal, LLVMValueRef NewVal) {
-  LLVMReplaceAllUsesWith(OldVal, NewVal);
+value llvm_replace_all_uses_with(value OldVal, value NewVal) {
+  LLVMReplaceAllUsesWith(Value_val(OldVal), Value_val(NewVal));
   return Val_unit;
 }
 
 /*--... Operations on users ................................................--*/
 
 /* llvalue -> int -> llvalue */
-LLVMValueRef llvm_operand(LLVMValueRef V, value I) {
-  return LLVMGetOperand(V, Int_val(I));
+value llvm_operand(value V, value I) {
+  return to_val(LLVMGetOperand(Value_val(V), Int_val(I)));
 }
 
 /* llvalue -> int -> lluse */
-LLVMUseRef llvm_operand_use(LLVMValueRef V, value I) {
-  return LLVMGetOperandUse(V, Int_val(I));
+value llvm_operand_use(value V, value I) {
+  return to_val(LLVMGetOperandUse(Value_val(V), Int_val(I)));
 }
 
 /* llvalue -> int -> llvalue -> unit */
-value llvm_set_operand(LLVMValueRef U, value I, LLVMValueRef V) {
-  LLVMSetOperand(U, Int_val(I), V);
+value llvm_set_operand(value U, value I, value V) {
+  LLVMSetOperand(Value_val(U), Int_val(I), Value_val(V));
   return Val_unit;
 }
 
 /* llvalue -> int */
-value llvm_num_operands(LLVMValueRef V) {
-  return Val_int(LLVMGetNumOperands(V));
+value llvm_num_operands(value V) {
+  return Val_int(LLVMGetNumOperands(Value_val(V)));
 }
 
 /* llvalue -> int array */
-value llvm_indices(LLVMValueRef Instr) {
-  unsigned n = LLVMGetNumIndices(Instr);
-  const unsigned *Indices = LLVMGetIndices(Instr);
-  value indices = caml_alloc_tuple_uninit(n);
-  for (unsigned i = 0; i < n; i++) {
-    Op_val(indices)[i] = Val_int(Indices[i]);
+value llvm_indices(value Instr) {
+  unsigned Length = LLVMGetNumIndices(Value_val(Instr));
+  const unsigned *Indices = LLVMGetIndices(Value_val(Instr));
+  value Array = caml_alloc_tuple_uninit(Length);
+  for (unsigned I = 0; I < Length; ++I) {
+    Field(Array, I) = Val_int(Indices[I]);
   }
-  return indices;
+  return Array;
 }
 
 /*--... Operations on constants of (mostly) any type .......................--*/
 
 /* llvalue -> bool */
-value llvm_is_constant(LLVMValueRef Val) {
-  return Val_bool(LLVMIsConstant(Val));
+value llvm_is_constant(value Val) {
+  return Val_bool(LLVMIsConstant(Value_val(Val)));
+}
+
+/* lltype -> llvalue */
+value llvm_const_null(value Ty) {
+  LLVMValueRef Value = LLVMConstNull(Type_val(Ty));
+  return to_val(Value);
+}
+
+/* lltype -> llvalue */
+value llvm_const_all_ones(value Ty) {
+  LLVMValueRef Value = LLVMConstAllOnes(Type_val(Ty));
+  return to_val(Value);
+}
+
+/* lltype -> llvalue */
+value llvm_const_pointer_null(value Ty) {
+  LLVMValueRef Value = LLVMConstPointerNull(Type_val(Ty));
+  return to_val(Value);
+}
+
+/* lltype -> llvalue */
+value llvm_get_undef(value Ty) {
+  LLVMValueRef Value = LLVMGetUndef(Type_val(Ty));
+  return to_val(Value);
+}
+
+/* lltype -> llvalue */
+value llvm_get_poison(value Ty) {
+  LLVMValueRef Value = LLVMGetPoison(Type_val(Ty));
+  return to_val(Value);
 }
 
 /* llvalue -> bool */
-value llvm_is_null(LLVMValueRef Val) { return Val_bool(LLVMIsNull(Val)); }
+value llvm_is_null(value Val) { return Val_bool(LLVMIsNull(Value_val(Val))); }
 
 /* llvalue -> bool */
-value llvm_is_undef(LLVMValueRef Val) { return Val_bool(LLVMIsUndef(Val)); }
+value llvm_is_undef(value Val) { return Val_bool(LLVMIsUndef(Value_val(Val))); }
 
 /* llvalue -> bool */
-value llvm_is_poison(LLVMValueRef Val) { return Val_bool(LLVMIsPoison(Val)); }
+value llvm_is_poison(value Val) {
+  return Val_bool(LLVMIsPoison(Value_val(Val)));
+}
 
 /* llvalue -> Opcode.t */
-value llvm_constexpr_get_opcode(LLVMValueRef Val) {
-  return LLVMIsAConstantExpr(Val) ? Val_int(LLVMGetConstOpcode(Val))
-                                  : Val_int(0);
+value llvm_constexpr_get_opcode(value Val) {
+  return LLVMIsAConstantExpr(Value_val(Val))
+             ? Val_int(LLVMGetConstOpcode(Value_val(Val)))
+             : Val_int(0);
 }
 
 /*--... Operations on instructions .........................................--*/
 
 /* llvalue -> bool */
-value llvm_has_metadata(LLVMValueRef Val) {
-  return Val_bool(LLVMHasMetadata(Val));
+value llvm_has_metadata(value Val) {
+  return Val_bool(LLVMHasMetadata(Value_val(Val)));
 }
 
 /* llvalue -> int -> llvalue option */
-value llvm_metadata(LLVMValueRef Val, value MDKindID) {
-  return ptr_to_option(LLVMGetMetadata(Val, Int_val(MDKindID)));
+value llvm_metadata(value Val, value MDKindID) {
+  return ptr_to_option(LLVMGetMetadata(Value_val(Val), Int_val(MDKindID)));
 }
 
 /* llvalue -> int -> llvalue -> unit */
-value llvm_set_metadata(LLVMValueRef Val, value MDKindID, LLVMValueRef MD) {
-  LLVMSetMetadata(Val, Int_val(MDKindID), MD);
+value llvm_set_metadata(value Val, value MDKindID, value MD) {
+  LLVMSetMetadata(Value_val(Val), Int_val(MDKindID), Value_val(MD));
   return Val_unit;
 }
 
 /* llvalue -> int -> unit */
-value llvm_clear_metadata(LLVMValueRef Val, value MDKindID) {
-  LLVMSetMetadata(Val, Int_val(MDKindID), NULL);
+value llvm_clear_metadata(value Val, value MDKindID) {
+  LLVMSetMetadata(Value_val(Val), Int_val(MDKindID), NULL);
   return Val_unit;
 }
 
 /*--... Operations on metadata .............................................--*/
 
 /* llcontext -> string -> llvalue */
-LLVMValueRef llvm_mdstring(LLVMContextRef C, value S) {
-  return LLVMMDStringInContext(C, String_val(S), caml_string_length(S));
+value llvm_mdstring(value C, value S) {
+  return to_val(LLVMMDStringInContext(Context_val(C), String_val(S),
+                                      caml_string_length(S)));
 }
 
 /* llcontext -> llvalue array -> llvalue */
-LLVMValueRef llvm_mdnode(LLVMContextRef C, value ElementVals) {
-  return LLVMMDNodeInContext(C, (LLVMValueRef *)Op_val(ElementVals),
-                             Wosize_val(ElementVals));
+value llvm_mdnode(value C, value ElementVals) {
+  mlsize_t Length = Wosize_val(ElementVals);
+  LLVMValueRef *Temp = from_val_array(ElementVals);
+  LLVMValueRef Value = LLVMMDNodeInContext(Context_val(C), Temp, Length);
+  free(Temp);
+  return to_val(Value);
 }
 
 /* llcontext -> llvalue */
-LLVMValueRef llvm_mdnull(LLVMContextRef C) { return NULL; }
+value llvm_mdnull(value C) { return to_val(NULL); }
 
 /* llvalue -> string option */
-value llvm_get_mdstring(LLVMValueRef V) {
+value llvm_get_mdstring(value V) {
   unsigned Len;
-  const char *CStr = LLVMGetMDString(V, &Len);
+  const char *CStr = LLVMGetMDString(Value_val(V), &Len);
   return cstr_to_string_option(CStr, Len);
 }
 
-value llvm_get_mdnode_operands(LLVMValueRef V) {
-  unsigned int n = LLVMGetMDNodeNumOperands(V);
-  value Operands = caml_alloc_tuple_uninit(n);
+/* llvalue -> llvalue array */
+value llvm_get_mdnode_operands(value Value) {
+  LLVMValueRef V = Value_val(Value);
+  unsigned Length = LLVMGetMDNodeNumOperands(V);
+  value Operands = caml_alloc_tuple_uninit(Length);
   LLVMGetMDNodeOperands(V, (LLVMValueRef *)Op_val(Operands));
+  for (unsigned I = 0; I < Length; ++I) {
+    Field(Operands, I) = to_val((LLVMValueRef)Field(Operands, I));
+  }
   return Operands;
 }
 
 /* llmodule -> string -> llvalue array */
-value llvm_get_namedmd(LLVMModuleRef M, value Name) {
+value llvm_get_namedmd(value M, value Name) {
   CAMLparam1(Name);
-  value Nodes = caml_alloc_tuple_uninit(
-      LLVMGetNamedMetadataNumOperands(M, String_val(Name)));
-  LLVMGetNamedMetadataOperands(M, String_val(Name),
+  unsigned Length =
+      LLVMGetNamedMetadataNumOperands(Module_val(M), String_val(Name));
+  value Nodes = caml_alloc_tuple_uninit(Length);
+  LLVMGetNamedMetadataOperands(Module_val(M), String_val(Name),
                                (LLVMValueRef *)Op_val(Nodes));
+  for (unsigned I = 0; I < Length; ++I) {
+    Field(Nodes, I) = to_val((LLVMValueRef)Field(Nodes, I));
+  }
   CAMLreturn(Nodes);
 }
 
 /* llmodule -> string -> llvalue -> unit */
-value llvm_append_namedmd(LLVMModuleRef M, value Name, LLVMValueRef Val) {
-  LLVMAddNamedMetadataOperand(M, String_val(Name), Val);
+value llvm_append_namedmd(value M, value Name, value Val) {
+  LLVMAddNamedMetadataOperand(Module_val(M), String_val(Name), Value_val(Val));
   return Val_unit;
 }
 
 /* llvalue -> llmetadata */
-LLVMMetadataRef llvm_value_as_metadata(LLVMValueRef Val) {
-  return LLVMValueAsMetadata(Val);
+value llvm_value_as_metadata(value Val) {
+  return to_val(LLVMValueAsMetadata(Value_val(Val)));
 }
 
 /* llcontext -> llmetadata -> llvalue */
-LLVMValueRef llvm_metadata_as_value(LLVMContextRef C, LLVMMetadataRef MD) {
-  return LLVMMetadataAsValue(C, MD);
+value llvm_metadata_as_value(value C, value MD) {
+  return to_val(LLVMMetadataAsValue(Context_val(C), Metadata_val(MD)));
 }
 
 /*--... Operations on scalar constants .....................................--*/
 
 /* lltype -> int -> llvalue */
-LLVMValueRef llvm_const_int(LLVMTypeRef IntTy, value N) {
-  return LLVMConstInt(IntTy, (long long)Long_val(N), 1);
+value llvm_const_int(value IntTy, value N) {
+  return to_val(LLVMConstInt(Type_val(IntTy), (long long)Long_val(N), 1));
 }
 
 /* lltype -> Int64.t -> bool -> llvalue */
-LLVMValueRef llvm_const_of_int64(LLVMTypeRef IntTy, value N, value SExt) {
-  return LLVMConstInt(IntTy, Int64_val(N), Bool_val(SExt));
+value llvm_const_of_int64(value IntTy, value N, value SExt) {
+  return to_val(LLVMConstInt(Type_val(IntTy), Int64_val(N), Bool_val(SExt)));
 }
 
-/* llvalue -> Int64.t */
-value llvm_int64_of_const(LLVMValueRef Const) {
+/* llvalue -> Int64.t option */
+value llvm_int64_of_const(value C) {
+  LLVMValueRef Const = Value_val(C);
   if (!(LLVMIsAConstantInt(Const)) ||
       !(LLVMGetIntTypeWidth(LLVMTypeOf(Const)) <= 64))
     return Val_none;
@@ -884,18 +1010,19 @@ value llvm_int64_of_const(LLVMValueRef Const) {
 }
 
 /* lltype -> string -> int -> llvalue */
-LLVMValueRef llvm_const_int_of_string(LLVMTypeRef IntTy, value S, value Radix) {
-  return LLVMConstIntOfStringAndSize(IntTy, String_val(S),
-                                     caml_string_length(S), Int_val(Radix));
+value llvm_const_int_of_string(value IntTy, value S, value Radix) {
+  return to_val(LLVMConstIntOfStringAndSize(
+      Type_val(IntTy), String_val(S), caml_string_length(S), Int_val(Radix)));
 }
 
 /* lltype -> float -> llvalue */
-LLVMValueRef llvm_const_float(LLVMTypeRef RealTy, value N) {
-  return LLVMConstReal(RealTy, Double_val(N));
+value llvm_const_float(value RealTy, value N) {
+  return to_val(LLVMConstReal(Type_val(RealTy), Double_val(N)));
 }
 
-/* llvalue -> float */
-value llvm_float_of_const(LLVMValueRef Const) {
+/* llvalue -> float option */
+value llvm_float_of_const(value C) {
+  LLVMValueRef Const = Value_val(C);
   LLVMBool LosesInfo;
   double Result;
   if (!LLVMIsAConstantFP(Const))
@@ -907,61 +1034,78 @@ value llvm_float_of_const(LLVMValueRef Const) {
 }
 
 /* lltype -> string -> llvalue */
-LLVMValueRef llvm_const_float_of_string(LLVMTypeRef RealTy, value S) {
-  return LLVMConstRealOfStringAndSize(RealTy, String_val(S),
-                                      caml_string_length(S));
+value llvm_const_float_of_string(value RealTy, value S) {
+  return to_val(LLVMConstRealOfStringAndSize(Type_val(RealTy), String_val(S),
+                                             caml_string_length(S)));
 }
 
 /*--... Operations on composite constants ..................................--*/
 
 /* llcontext -> string -> llvalue */
-LLVMValueRef llvm_const_string(LLVMContextRef Context, value Str,
-                               value NullTerminate) {
-  return LLVMConstStringInContext(Context, String_val(Str), string_length(Str),
-                                  1);
+value llvm_const_string(value Context, value Str) {
+  return to_val(LLVMConstStringInContext(Context_val(Context), String_val(Str),
+                                         caml_string_length(Str), 1));
 }
 
 /* llcontext -> string -> llvalue */
-LLVMValueRef llvm_const_stringz(LLVMContextRef Context, value Str,
-                                value NullTerminate) {
-  return LLVMConstStringInContext(Context, String_val(Str), string_length(Str),
-                                  0);
+value llvm_const_stringz(value Context, value Str) {
+  return to_val(LLVMConstStringInContext(Context_val(Context), String_val(Str),
+                                         caml_string_length(Str), 0));
 }
 
 /* lltype -> llvalue array -> llvalue */
-LLVMValueRef llvm_const_array(LLVMTypeRef ElementTy, value ElementVals) {
-  return LLVMConstArray(ElementTy, (LLVMValueRef *)Op_val(ElementVals),
-                        Wosize_val(ElementVals));
+value llvm_const_array(value ElementTy, value ElementVals) {
+  mlsize_t Length = Wosize_val(ElementVals);
+  LLVMValueRef *Temp = from_val_array(ElementVals);
+  LLVMValueRef Value = LLVMConstArray(Type_val(ElementTy), Temp, Length);
+  free(Temp);
+  return to_val(Value);
 }
 
 /* llcontext -> llvalue array -> llvalue */
-LLVMValueRef llvm_const_struct(LLVMContextRef C, value ElementVals) {
-  return LLVMConstStructInContext(C, (LLVMValueRef *)Op_val(ElementVals),
-                                  Wosize_val(ElementVals), 0);
+value llvm_const_struct(value C, value ElementVals) {
+  mlsize_t Length = Wosize_val(ElementVals);
+  LLVMValueRef *Temp = from_val_array(ElementVals);
+  LLVMValueRef Value =
+      LLVMConstStructInContext(Context_val(C), Temp, Length, 0);
+  free(Temp);
+  return to_val(Value);
 }
 
 /* lltype -> llvalue array -> llvalue */
-LLVMValueRef llvm_const_named_struct(LLVMTypeRef Ty, value ElementVals) {
-  return LLVMConstNamedStruct(Ty, (LLVMValueRef *)Op_val(ElementVals),
-                              Wosize_val(ElementVals));
+value llvm_const_named_struct(value Ty, value ElementVals) {
+  mlsize_t Length = Wosize_val(ElementVals);
+  LLVMValueRef *Temp = from_val_array(ElementVals);
+  LLVMValueRef Value =
+      LLVMConstNamedStruct(Type_val(Ty), (LLVMValueRef *)Temp, Length);
+  free(Temp);
+  return to_val(Value);
 }
 
 /* llcontext -> llvalue array -> llvalue */
-LLVMValueRef llvm_const_packed_struct(LLVMContextRef C, value ElementVals) {
-  return LLVMConstStructInContext(C, (LLVMValueRef *)Op_val(ElementVals),
-                                  Wosize_val(ElementVals), 1);
+value llvm_const_packed_struct(value C, value ElementVals) {
+  mlsize_t Length = Wosize_val(ElementVals);
+  LLVMValueRef *Temp = from_val_array(ElementVals);
+  LLVMValueRef Value =
+      LLVMConstStructInContext(Context_val(C), Temp, Length, 1);
+  free(Temp);
+  return to_val(Value);
 }
 
 /* llvalue array -> llvalue */
-LLVMValueRef llvm_const_vector(value ElementVals) {
-  return LLVMConstVector((LLVMValueRef *)Op_val(ElementVals),
-                         Wosize_val(ElementVals));
+value llvm_const_vector(value ElementVals) {
+  mlsize_t Length = Wosize_val(ElementVals);
+  LLVMValueRef *Temp = from_val_array(ElementVals);
+  LLVMValueRef Value = LLVMConstVector(Temp, Length);
+  free(Temp);
+  return to_val(Value);
 }
 
 /* llvalue -> string option */
-value llvm_string_of_const(LLVMValueRef Const) {
+value llvm_string_of_const(value C) {
   size_t Len;
   const char *CStr;
+  LLVMValueRef Const = Value_val(C);
   if (!LLVMIsAConstantDataSequential(Const) || !LLVMIsConstantString(Const))
     return Val_none;
   CStr = LLVMGetAsString(Const, &Len);
@@ -969,136 +1113,410 @@ value llvm_string_of_const(LLVMValueRef Const) {
 }
 
 /* llvalue -> int -> llvalue option */
-value llvm_aggregate_element(LLVMValueRef Const, value N) {
-  return ptr_to_option(LLVMGetAggregateElement(Const, Int_val(N)));
+value llvm_aggregate_element(value Const, value N) {
+  return ptr_to_option(LLVMGetAggregateElement(Value_val(Const), Int_val(N)));
 }
 
 /*--... Constant expressions ...............................................--*/
 
+/* lltype -> llvalue */
+value llvm_align_of(value Type) {
+  LLVMValueRef Value = LLVMAlignOf(Type_val(Type));
+  return to_val(Value);
+}
+
+/* lltype -> llvalue */
+value llvm_size_of(value Type) {
+  LLVMValueRef Value = LLVMSizeOf(Type_val(Type));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue */
+value llvm_const_neg(value Value) {
+  LLVMValueRef NegValue = LLVMConstNeg(Value_val(Value));
+  return to_val(NegValue);
+}
+
+/* llvalue -> llvalue */
+value llvm_const_nsw_neg(value Value) {
+  LLVMValueRef NegValue = LLVMConstNSWNeg(Value_val(Value));
+  return to_val(NegValue);
+}
+
+/* llvalue -> llvalue */
+value llvm_const_nuw_neg(value Value) {
+  LLVMValueRef NegValue = LLVMConstNUWNeg(Value_val(Value));
+  return to_val(NegValue);
+}
+
+/* llvalue -> llvalue */
+value llvm_const_not(value Value) {
+  LLVMValueRef NotValue = LLVMConstNot(Value_val(Value));
+  return to_val(NotValue);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_add(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstAdd(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_nsw_add(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstNSWAdd(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_nuw_add(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstNUWAdd(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_sub(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstSub(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_nsw_sub(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstNSWSub(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_nuw_sub(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstNUWSub(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_mul(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstMul(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_nsw_mul(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstNSWMul(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_nuw_mul(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstNUWMul(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_and(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstAnd(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_or(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstOr(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_xor(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstXor(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
 /* Icmp.t -> llvalue -> llvalue -> llvalue */
-LLVMValueRef llvm_const_icmp(value Pred, LLVMValueRef LHSConstant,
-                             LLVMValueRef RHSConstant) {
-  return LLVMConstICmp(Int_val(Pred) + LLVMIntEQ, LHSConstant, RHSConstant);
+value llvm_const_icmp(value Pred, value LHSConstant, value RHSConstant) {
+  return to_val(LLVMConstICmp(Int_val(Pred) + LLVMIntEQ, Value_val(LHSConstant),
+                              Value_val(RHSConstant)));
 }
 
 /* Fcmp.t -> llvalue -> llvalue -> llvalue */
-LLVMValueRef llvm_const_fcmp(value Pred, LLVMValueRef LHSConstant,
-                             LLVMValueRef RHSConstant) {
-  return LLVMConstFCmp(Int_val(Pred), LHSConstant, RHSConstant);
+value llvm_const_fcmp(value Pred, value LHSConstant, value RHSConstant) {
+  return to_val(LLVMConstFCmp(Int_val(Pred), Value_val(LHSConstant),
+                              Value_val(RHSConstant)));
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_shl(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstShl(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_lshr(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstLShr(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_ashr(value LHS, value RHS) {
+  LLVMValueRef Value = LLVMConstAShr(Value_val(LHS), Value_val(RHS));
+  return to_val(Value);
+}
+
+/* lltype -> llvalue -> llvalue array -> llvalue */
+value llvm_const_gep(value Ty, value ConstantVal, value Indices) {
+  mlsize_t Length = Wosize_val(Indices);
+  LLVMValueRef *Temp = from_val_array(Indices);
+  LLVMValueRef Value =
+      LLVMConstGEP2(Type_val(Ty), Value_val(ConstantVal), Temp, Length);
+  free(Temp);
+  return to_val(Value);
 }
 
 /* lltype -> llvalue -> llvalue array -> llvalue */
-LLVMValueRef llvm_const_gep(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
-                            value Indices) {
-  return LLVMConstGEP2(Ty, ConstantVal, (LLVMValueRef *)Op_val(Indices),
-                       Wosize_val(Indices));
+value llvm_const_in_bounds_gep(value Ty, value ConstantVal, value Indices) {
+  mlsize_t Length = Wosize_val(Indices);
+  LLVMValueRef *Temp = from_val_array(Indices);
+  LLVMValueRef Value =
+      LLVMConstInBoundsGEP2(Type_val(Ty), Value_val(ConstantVal), Temp, Length);
+  free(Temp);
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_trunc(value CV, value T) {
+  LLVMValueRef Value = LLVMConstTrunc(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_sext(value CV, value T) {
+  LLVMValueRef Value = LLVMConstSExt(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_zext(value CV, value T) {
+  LLVMValueRef Value = LLVMConstZExt(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_fptrunc(value CV, value T) {
+  LLVMValueRef Value = LLVMConstFPTrunc(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_fpext(value CV, value T) {
+  LLVMValueRef Value = LLVMConstFPExt(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_uitofp(value CV, value T) {
+  LLVMValueRef Value = LLVMConstUIToFP(Value_val(CV), Type_val(T));
+  return to_val(Value);
 }
 
-/* llvalue -> llvalue array -> llvalue */
-LLVMValueRef llvm_const_in_bounds_gep(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
-                                      value Indices) {
-  return LLVMConstInBoundsGEP2(Ty, ConstantVal, (LLVMValueRef *)Op_val(Indices),
-                               Wosize_val(Indices));
+/* llvalue -> lltype -> llvalue */
+value llvm_const_sitofp(value CV, value T) {
+  LLVMValueRef Value = LLVMConstSIToFP(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_fptoui(value CV, value T) {
+  LLVMValueRef Value = LLVMConstFPToUI(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_fptosi(value CV, value T) {
+  LLVMValueRef Value = LLVMConstFPToSI(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_ptrtoint(value CV, value T) {
+  LLVMValueRef Value = LLVMConstPtrToInt(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_inttoptr(value CV, value T) {
+  LLVMValueRef Value = LLVMConstIntToPtr(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_bitcast(value CV, value T) {
+  LLVMValueRef Value = LLVMConstBitCast(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_zext_or_bitcast(value CV, value T) {
+  LLVMValueRef Value = LLVMConstZExtOrBitCast(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_sext_or_bitcast(value CV, value T) {
+  LLVMValueRef Value = LLVMConstSExtOrBitCast(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_trunc_or_bitcast(value CV, value T) {
+  LLVMValueRef Value = LLVMConstTruncOrBitCast(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_pointercast(value CV, value T) {
+  LLVMValueRef Value = LLVMConstPointerCast(Value_val(CV), Type_val(T));
+  return to_val(Value);
 }
 
 /* llvalue -> lltype -> is_signed:bool -> llvalue */
-LLVMValueRef llvm_const_intcast(LLVMValueRef CV, LLVMTypeRef T,
-                                value IsSigned) {
-  return LLVMConstIntCast(CV, T, Bool_val(IsSigned));
+value llvm_const_intcast(value CV, value T, value IsSigned) {
+  return to_val(
+      LLVMConstIntCast(Value_val(CV), Type_val(T), Bool_val(IsSigned)));
+}
+
+/* llvalue -> lltype -> llvalue */
+value llvm_const_fpcast(value CV, value T) {
+  LLVMValueRef Value = LLVMConstFPCast(Value_val(CV), Type_val(T));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue -> llvalue */
+value llvm_const_select(value Cond, value IfTrue, value IfFalse) {
+  LLVMValueRef Value =
+      LLVMConstSelect(Value_val(Cond), Value_val(IfTrue), Value_val(IfFalse));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue */
+value llvm_const_extractelement(value V, value I) {
+  LLVMValueRef Value = LLVMConstExtractElement(Value_val(V), Value_val(I));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue -> llvalue */
+value llvm_const_insertelement(value V, value E, value I) {
+  LLVMValueRef Value =
+      LLVMConstInsertElement(Value_val(V), Value_val(E), Value_val(I));
+  return to_val(Value);
+}
+
+/* llvalue -> llvalue -> llvalue -> llvalue */
+value llvm_const_shufflevector(value VA, value VB, value Mask) {
+  LLVMValueRef Value =
+      LLVMConstShuffleVector(Value_val(VA), Value_val(VB), Value_val(Mask));
+  return to_val(Value);
 }
 
 /* lltype -> string -> string -> bool -> bool -> llvalue */
-LLVMValueRef llvm_const_inline_asm(LLVMTypeRef Ty, value Asm, value Constraints,
-                                   value HasSideEffects, value IsAlignStack) {
-  return LLVMConstInlineAsm(Ty, String_val(Asm), String_val(Constraints),
-                            Bool_val(HasSideEffects), Bool_val(IsAlignStack));
+value llvm_const_inline_asm(value Ty, value Asm, value Constraints,
+                            value HasSideEffects, value IsAlignStack) {
+  return to_val(
+      LLVMConstInlineAsm(Type_val(Ty), String_val(Asm), String_val(Constraints),
+                         Bool_val(HasSideEffects), Bool_val(IsAlignStack)));
+}
+
+/* llvalue -> llbasicblock -> llvalue */
+value llvm_blockaddress(value V, value B) {
+  LLVMValueRef Value = LLVMBlockAddress(Value_val(V), BasicBlock_val(B));
+  return to_val(Value);
 }
 
 /*--... Operations on global variables, functions, and aliases (globals) ...--*/
 
+/* llvalue -> llmodule */
+value llvm_global_parent(value Value) {
+  LLVMModuleRef Module = LLVMGetGlobalParent(Value_val(Value));
+  return to_val(Module);
+}
+
 /* llvalue -> bool */
-value llvm_is_declaration(LLVMValueRef Global) {
-  return Val_bool(LLVMIsDeclaration(Global));
+value llvm_is_declaration(value Global) {
+  return Val_bool(LLVMIsDeclaration(Value_val(Global)));
 }
 
 /* llvalue -> Linkage.t */
-value llvm_linkage(LLVMValueRef Global) {
-  return Val_int(LLVMGetLinkage(Global));
+value llvm_linkage(value Global) {
+  return Val_int(LLVMGetLinkage(Value_val(Global)));
 }
 
 /* Linkage.t -> llvalue -> unit */
-value llvm_set_linkage(value Linkage, LLVMValueRef Global) {
-  LLVMSetLinkage(Global, Int_val(Linkage));
+value llvm_set_linkage(value Linkage, value Global) {
+  LLVMSetLinkage(Value_val(Global), Int_val(Linkage));
   return Val_unit;
 }
 
 /* llvalue -> bool */
-value llvm_unnamed_addr(LLVMValueRef Global) {
-  return Val_bool(LLVMHasUnnamedAddr(Global));
+value llvm_unnamed_addr(value Global) {
+  return Val_bool(LLVMHasUnnamedAddr(Value_val(Global)));
 }
 
 /* bool -> llvalue -> unit */
-value llvm_set_unnamed_addr(value UseUnnamedAddr, LLVMValueRef Global) {
-  LLVMSetUnnamedAddr(Global, Bool_val(UseUnnamedAddr));
+value llvm_set_unnamed_addr(value UseUnnamedAddr, value Global) {
+  LLVMSetUnnamedAddr(Value_val(Global), Bool_val(UseUnnamedAddr));
   return Val_unit;
 }
 
 /* llvalue -> string */
-value llvm_section(LLVMValueRef Global) {
-  return caml_copy_string(LLVMGetSection(Global));
+value llvm_section(value Global) {
+  return caml_copy_string(LLVMGetSection(Value_val(Global)));
 }
 
 /* string -> llvalue -> unit */
-value llvm_set_section(value Section, LLVMValueRef Global) {
-  LLVMSetSection(Global, String_val(Section));
+value llvm_set_section(value Section, value Global) {
+  LLVMSetSection(Value_val(Global), String_val(Section));
   return Val_unit;
 }
 
 /* llvalue -> Visibility.t */
-value llvm_visibility(LLVMValueRef Global) {
-  return Val_int(LLVMGetVisibility(Global));
+value llvm_visibility(value Global) {
+  return Val_int(LLVMGetVisibility(Value_val(Global)));
 }
 
 /* Visibility.t -> llvalue -> unit */
-value llvm_set_visibility(value Viz, LLVMValueRef Global) {
-  LLVMSetVisibility(Global, Int_val(Viz));
+value llvm_set_visibility(value Viz, value Global) {
+  LLVMSetVisibility(Value_val(Global), Int_val(Viz));
   return Val_unit;
 }
 
 /* llvalue -> DLLStorageClass.t */
-value llvm_dll_storage_class(LLVMValueRef Global) {
-  return Val_int(LLVMGetDLLStorageClass(Global));
+value llvm_dll_storage_class(value Global) {
+  return Val_int(LLVMGetDLLStorageClass(Value_val(Global)));
 }
 
 /* DLLStorageClass.t -> llvalue -> unit */
-value llvm_set_dll_storage_class(value Viz, LLVMValueRef Global) {
-  LLVMSetDLLStorageClass(Global, Int_val(Viz));
+value llvm_set_dll_storage_class(value Viz, value Global) {
+  LLVMSetDLLStorageClass(Value_val(Global), Int_val(Viz));
   return Val_unit;
 }
 
 /* llvalue -> int */
-value llvm_alignment(LLVMValueRef Global) {
-  return Val_int(LLVMGetAlignment(Global));
+value llvm_alignment(value Global) {
+  return Val_int(LLVMGetAlignment(Value_val(Global)));
 }
 
 /* int -> llvalue -> unit */
-value llvm_set_alignment(value Bytes, LLVMValueRef Global) {
-  LLVMSetAlignment(Global, Int_val(Bytes));
+value llvm_set_alignment(value Bytes, value Global) {
+  LLVMSetAlignment(Value_val(Global), Int_val(Bytes));
   return Val_unit;
 }
 
 /* llvalue -> (llmdkind * llmetadata) array */
-value llvm_global_copy_all_metadata(LLVMValueRef Global) {
+value llvm_global_copy_all_metadata(value Global) {
   CAMLparam0();
   CAMLlocal1(Array);
   size_t NumEntries;
   LLVMValueMetadataEntry *Entries =
-      LLVMGlobalCopyAllMetadata(Global, &NumEntries);
+      LLVMGlobalCopyAllMetadata(Value_val(Global), &NumEntries);
   Array = caml_alloc_tuple(NumEntries);
-  for (int i = 0; i < NumEntries; i++) {
+  for (int i = 0; i < NumEntries; ++i) {
     value Pair = caml_alloc_small(2, 0);
     Field(Pair, 0) = Val_int(LLVMValueMetadataEntriesGetKind(Entries, i));
-    Field(Pair, 1) = (value)LLVMValueMetadataEntriesGetMetadata(Entries, i);
+    Field(Pair, 1) = to_val(LLVMValueMetadataEntriesGetMetadata(Entries, i));
     Store_field(Array, i, Pair);
   }
   LLVMDisposeValueMetadataEntries(Entries);
@@ -1108,484 +1526,549 @@ value llvm_global_copy_all_metadata(LLVMValueRef Global) {
 /*--... Operations on uses .................................................--*/
 
 /* llvalue -> lluse option */
-value llvm_use_begin(LLVMValueRef Val) {
-  return ptr_to_option(LLVMGetFirstUse(Val));
+value llvm_use_begin(value Val) {
+  return ptr_to_option(LLVMGetFirstUse(Value_val(Val)));
 }
 
 /* lluse -> lluse option */
-value llvm_use_succ(LLVMUseRef U) { return ptr_to_option(LLVMGetNextUse(U)); }
+value llvm_use_succ(value U) {
+  return ptr_to_option(LLVMGetNextUse(Use_val(U)));
+}
 
 /* lluse -> llvalue */
-LLVMValueRef llvm_user(LLVMUseRef UR) { return LLVMGetUser(UR); }
+value llvm_user(value UR) { return to_val(LLVMGetUser(Use_val(UR))); }
 
 /* lluse -> llvalue */
-LLVMValueRef llvm_used_value(LLVMUseRef UR) { return LLVMGetUsedValue(UR); }
+value llvm_used_value(value UR) {
+  return to_val(LLVMGetUsedValue(Use_val(UR)));
+}
 
 /*--... Operations on global variables .....................................--*/
 
-DEFINE_ITERATORS(global, Global, LLVMModuleRef, LLVMValueRef,
+DEFINE_ITERATORS(global, Global, Module_val, LLVMValueRef, Value_val,
                  LLVMGetGlobalParent)
 
 /* lltype -> string -> llmodule -> llvalue */
-LLVMValueRef llvm_declare_global(LLVMTypeRef Ty, value Name, LLVMModuleRef M) {
+value llvm_declare_global(value Ty, value Name, value M) {
   LLVMValueRef GlobalVar;
-  if ((GlobalVar = LLVMGetNamedGlobal(M, String_val(Name)))) {
-    if (LLVMGlobalGetValueType(GlobalVar) != Ty)
-      return LLVMConstBitCast(GlobalVar, LLVMPointerType(Ty, 0));
-    return GlobalVar;
+  if ((GlobalVar = LLVMGetNamedGlobal(Module_val(M), String_val(Name)))) {
+    if (LLVMGlobalGetValueType(GlobalVar) != Type_val(Ty))
+      return to_val(
+          LLVMConstBitCast(GlobalVar, LLVMPointerType(Type_val(Ty), 0)));
+    return to_val(GlobalVar);
   }
-  return LLVMAddGlobal(M, Ty, String_val(Name));
+  return to_val(LLVMAddGlobal(Module_val(M), Type_val(Ty), String_val(Name)));
 }
 
 /* lltype -> string -> int -> llmodule -> llvalue */
-LLVMValueRef llvm_declare_qualified_global(LLVMTypeRef Ty, value Name,
-                                           value AddressSpace,
-                                           LLVMModuleRef M) {
+value llvm_declare_qualified_global(value Ty, value Name, value AddressSpace,
+                                    value M) {
   LLVMValueRef GlobalVar;
-  if ((GlobalVar = LLVMGetNamedGlobal(M, String_val(Name)))) {
-    if (LLVMGlobalGetValueType(GlobalVar) != Ty)
-      return LLVMConstBitCast(GlobalVar,
-                              LLVMPointerType(Ty, Int_val(AddressSpace)));
-    return GlobalVar;
+  if ((GlobalVar = LLVMGetNamedGlobal(Module_val(M), String_val(Name)))) {
+    if (LLVMGlobalGetValueType(GlobalVar) != Type_val(Ty))
+      return to_val(LLVMConstBitCast(
+          GlobalVar, LLVMPointerType(Type_val(Ty), Int_val(AddressSpace))));
+    return to_val(GlobalVar);
   }
-  return LLVMAddGlobalInAddressSpace(M, Ty, String_val(Name),
-                                     Int_val(AddressSpace));
+  return to_val(LLVMAddGlobalInAddressSpace(
+      Module_val(M), Type_val(Ty), String_val(Name), Int_val(AddressSpace)));
 }
 
 /* string -> llmodule -> llvalue option */
-value llvm_lookup_global(value Name, LLVMModuleRef M) {
-  return ptr_to_option(LLVMGetNamedGlobal(M, String_val(Name)));
+value llvm_lookup_global(value Name, value M) {
+  return ptr_to_option(LLVMGetNamedGlobal(Module_val(M), String_val(Name)));
 }
 
 /* string -> llvalue -> llmodule -> llvalue */
-LLVMValueRef llvm_define_global(value Name, LLVMValueRef Initializer,
-                                LLVMModuleRef M) {
-  LLVMValueRef GlobalVar =
-      LLVMAddGlobal(M, LLVMTypeOf(Initializer), String_val(Name));
-  LLVMSetInitializer(GlobalVar, Initializer);
-  return GlobalVar;
+value llvm_define_global(value Name, value Initializer, value M) {
+  LLVMValueRef GlobalVar = LLVMAddGlobal(
+      Module_val(M), LLVMTypeOf(Value_val(Initializer)), String_val(Name));
+  LLVMSetInitializer(GlobalVar, Value_val(Initializer));
+  return to_val(GlobalVar);
 }
 
 /* string -> llvalue -> int -> llmodule -> llvalue */
-LLVMValueRef llvm_define_qualified_global(value Name, LLVMValueRef Initializer,
-                                          value AddressSpace, LLVMModuleRef M) {
+value llvm_define_qualified_global(value Name, value Initializer,
+                                   value AddressSpace, value M) {
   LLVMValueRef GlobalVar = LLVMAddGlobalInAddressSpace(
-      M, LLVMTypeOf(Initializer), String_val(Name), Int_val(AddressSpace));
-  LLVMSetInitializer(GlobalVar, Initializer);
-  return GlobalVar;
+      Module_val(M), LLVMTypeOf(Value_val(Initializer)), String_val(Name),
+      Int_val(AddressSpace));
+  LLVMSetInitializer(GlobalVar, Value_val(Initializer));
+  return to_val(GlobalVar);
 }
 
 /* llvalue -> unit */
-value llvm_delete_global(LLVMValueRef GlobalVar) {
-  LLVMDeleteGlobal(GlobalVar);
+value llvm_delete_global(value GlobalVar) {
+  LLVMDeleteGlobal(Value_val(GlobalVar));
   return Val_unit;
 }
 
 /* llvalue -> llvalue option */
-value llvm_global_initializer(LLVMValueRef GlobalVar) {
-  return ptr_to_option(LLVMGetInitializer(GlobalVar));
+value llvm_global_initializer(value GlobalVar) {
+  return ptr_to_option(LLVMGetInitializer(Value_val(GlobalVar)));
 }
 
 /* llvalue -> llvalue -> unit */
-value llvm_set_initializer(LLVMValueRef ConstantVal, LLVMValueRef GlobalVar) {
-  LLVMSetInitializer(GlobalVar, ConstantVal);
+value llvm_set_initializer(value ConstantVal, value GlobalVar) {
+  LLVMSetInitializer(Value_val(GlobalVar), Value_val(ConstantVal));
   return Val_unit;
 }
 
 /* llvalue -> unit */
-value llvm_remove_initializer(LLVMValueRef GlobalVar) {
-  LLVMSetInitializer(GlobalVar, NULL);
+value llvm_remove_initializer(value GlobalVar) {
+  LLVMSetInitializer(Value_val(GlobalVar), NULL);
   return Val_unit;
 }
 
 /* llvalue -> bool */
-value llvm_is_thread_local(LLVMValueRef GlobalVar) {
-  return Val_bool(LLVMIsThreadLocal(GlobalVar));
+value llvm_is_thread_local(value GlobalVar) {
+  return Val_bool(LLVMIsThreadLocal(Value_val(GlobalVar)));
 }
 
 /* bool -> llvalue -> unit */
-value llvm_set_thread_local(value IsThreadLocal, LLVMValueRef GlobalVar) {
-  LLVMSetThreadLocal(GlobalVar, Bool_val(IsThreadLocal));
+value llvm_set_thread_local(value IsThreadLocal, value GlobalVar) {
+  LLVMSetThreadLocal(Value_val(GlobalVar), Bool_val(IsThreadLocal));
   return Val_unit;
 }
 
 /* llvalue -> ThreadLocalMode.t */
-value llvm_thread_local_mode(LLVMValueRef GlobalVar) {
-  return Val_int(LLVMGetThreadLocalMode(GlobalVar));
+value llvm_thread_local_mode(value GlobalVar) {
+  return Val_int(LLVMGetThreadLocalMode(Value_val(GlobalVar)));
 }
 
 /* ThreadLocalMode.t -> llvalue -> unit */
-value llvm_set_thread_local_mode(value ThreadLocalMode,
-                                 LLVMValueRef GlobalVar) {
-  LLVMSetThreadLocalMode(GlobalVar, Int_val(ThreadLocalMode));
+value llvm_set_thread_local_mode(value ThreadLocalMode, value GlobalVar) {
+  LLVMSetThreadLocalMode(Value_val(GlobalVar), Int_val(ThreadLocalMode));
   return Val_unit;
 }
 
 /* llvalue -> bool */
-value llvm_is_externally_initialized(LLVMValueRef GlobalVar) {
-  return Val_bool(LLVMIsExternallyInitialized(GlobalVar));
+value llvm_is_externally_initialized(value GlobalVar) {
+  return Val_bool(LLVMIsExternallyInitialized(Value_val(GlobalVar)));
 }
 
 /* bool -> llvalue -> unit */
 value llvm_set_externally_initialized(value IsExternallyInitialized,
-                                      LLVMValueRef GlobalVar) {
-  LLVMSetExternallyInitialized(GlobalVar, Bool_val(IsExternallyInitialized));
+                                      value GlobalVar) {
+  LLVMSetExternallyInitialized(Value_val(GlobalVar),
+                               Bool_val(IsExternallyInitialized));
   return Val_unit;
 }
 
 /* llvalue -> bool */
-value llvm_is_global_constant(LLVMValueRef GlobalVar) {
-  return Val_bool(LLVMIsGlobalConstant(GlobalVar));
+value llvm_is_global_constant(value GlobalVar) {
+  return Val_bool(LLVMIsGlobalConstant(Value_val(GlobalVar)));
 }
 
 /* bool -> llvalue -> unit */
-value llvm_set_global_constant(value Flag, LLVMValueRef GlobalVar) {
-  LLVMSetGlobalConstant(GlobalVar, Bool_val(Flag));
+value llvm_set_global_constant(value Flag, value GlobalVar) {
+  LLVMSetGlobalConstant(Value_val(GlobalVar), Bool_val(Flag));
   return Val_unit;
 }
 
 /*--... Operations on aliases ..............................................--*/
 
-LLVMValueRef llvm_add_alias(LLVMModuleRef M, LLVMTypeRef ValueTy,
-                            value AddrSpace, LLVMValueRef Aliasee, value Name) {
-  return LLVMAddAlias2(M, ValueTy, Int_val(AddrSpace), Aliasee,
-                       String_val(Name));
+/* llmodule -> lltype -> int -> llvalue -> string -> llvalue */
+value llvm_add_alias(value M, value ValueTy, value AddrSpace, value Aliasee,
+                     value Name) {
+  return to_val(LLVMAddAlias2(Module_val(M), Type_val(ValueTy),
+                              Int_val(AddrSpace), Value_val(Aliasee),
+                              String_val(Name)));
 }
 
 /*--... Operations on functions ............................................--*/
 
-DEFINE_ITERATORS(function, Function, LLVMModuleRef, LLVMValueRef,
+DEFINE_ITERATORS(function, Function, Module_val, LLVMValueRef, Value_val,
                  LLVMGetGlobalParent)
 
 /* string -> lltype -> llmodule -> llvalue */
-LLVMValueRef llvm_declare_function(value Name, LLVMTypeRef Ty,
-                                   LLVMModuleRef M) {
+value llvm_declare_function(value Name, value Ty, value M) {
   LLVMValueRef Fn;
-  if ((Fn = LLVMGetNamedFunction(M, String_val(Name)))) {
-    if (LLVMGlobalGetValueType(Fn) != Ty)
-      return LLVMConstBitCast(Fn, LLVMPointerType(Ty, 0));
-    return Fn;
+  if ((Fn = LLVMGetNamedFunction(Module_val(M), String_val(Name)))) {
+    if (LLVMGlobalGetValueType(Fn) != Type_val(Ty))
+      return to_val(LLVMConstBitCast(Fn, LLVMPointerType(Type_val(Ty), 0)));
+    return to_val(Fn);
   }
-  return LLVMAddFunction(M, String_val(Name), Ty);
+  return to_val(LLVMAddFunction(Module_val(M), String_val(Name), Type_val(Ty)));
 }
 
 /* string -> llmodule -> llvalue option */
-value llvm_lookup_function(value Name, LLVMModuleRef M) {
-  return ptr_to_option(LLVMGetNamedFunction(M, String_val(Name)));
+value llvm_lookup_function(value Name, value M) {
+  return ptr_to_option(LLVMGetNamedFunction(Module_val(M), String_val(Name)));
 }
 
 /* string -> lltype -> llmodule -> llvalue */
-LLVMValueRef llvm_define_function(value Name, LLVMTypeRef Ty, LLVMModuleRef M) {
-  LLVMValueRef Fn = LLVMAddFunction(M, String_val(Name), Ty);
-  LLVMAppendBasicBlockInContext(LLVMGetTypeContext(Ty), Fn, "entry");
-  return Fn;
+value llvm_define_function(value Name, value Ty, value M) {
+  LLVMValueRef Fn =
+      LLVMAddFunction(Module_val(M), String_val(Name), Type_val(Ty));
+  LLVMAppendBasicBlockInContext(LLVMGetTypeContext(Type_val(Ty)), Fn, "entry");
+  return to_val(Fn);
 }
 
 /* llvalue -> unit */
-value llvm_delete_function(LLVMValueRef Fn) {
-  LLVMDeleteFunction(Fn);
+value llvm_delete_function(value Fn) {
+  LLVMDeleteFunction(Value_val(Fn));
   return Val_unit;
 }
 
 /* llvalue -> bool */
-value llvm_is_intrinsic(LLVMValueRef Fn) {
-  return Val_bool(LLVMGetIntrinsicID(Fn));
+value llvm_is_intrinsic(value Fn) {
+  return Val_bool(LLVMGetIntrinsicID(Value_val(Fn)));
 }
 
 /* llvalue -> int */
-value llvm_function_call_conv(LLVMValueRef Fn) {
-  return Val_int(LLVMGetFunctionCallConv(Fn));
+value llvm_function_call_conv(value Fn) {
+  return Val_int(LLVMGetFunctionCallConv(Value_val(Fn)));
 }
 
 /* int -> llvalue -> unit */
-value llvm_set_function_call_conv(value Id, LLVMValueRef Fn) {
-  LLVMSetFunctionCallConv(Fn, Int_val(Id));
+value llvm_set_function_call_conv(value Id, value Fn) {
+  LLVMSetFunctionCallConv(Value_val(Fn), Int_val(Id));
   return Val_unit;
 }
 
 /* llvalue -> string option */
-value llvm_gc(LLVMValueRef Fn) {
-  const char *GC = LLVMGetGC(Fn);
+value llvm_gc(value Fn) {
+  const char *GC = LLVMGetGC(Value_val(Fn));
   if (!GC)
     return Val_none;
   return caml_alloc_some(caml_copy_string(GC));
 }
 
 /* string option -> llvalue -> unit */
-value llvm_set_gc(value GC, LLVMValueRef Fn) {
-  LLVMSetGC(Fn, GC == Val_none ? 0 : String_val(Field(GC, 0)));
+value llvm_set_gc(value GC, value Fn) {
+  LLVMSetGC(Value_val(Fn), GC == Val_none ? 0 : String_val(Field(GC, 0)));
   return Val_unit;
 }
 
 /* llvalue -> llattribute -> int -> unit */
-value llvm_add_function_attr(LLVMValueRef F, LLVMAttributeRef A, value Index) {
-  LLVMAddAttributeAtIndex(F, Int_val(Index), A);
+value llvm_add_function_attr(value F, value A, value Index) {
+  LLVMAddAttributeAtIndex(Value_val(F), Int_val(Index), Attribute_val(A));
   return Val_unit;
 }
 
 /* llvalue -> int -> llattribute array */
-value llvm_function_attrs(LLVMValueRef F, value Index) {
-  unsigned Length = LLVMGetAttributeCountAtIndex(F, Int_val(Index));
+value llvm_function_attrs(value F, value Index) {
+  unsigned Length = LLVMGetAttributeCountAtIndex(Value_val(F), Int_val(Index));
   value Array = caml_alloc_tuple_uninit(Length);
-  LLVMGetAttributesAtIndex(F, Int_val(Index),
+  LLVMGetAttributesAtIndex(Value_val(F), Int_val(Index),
                            (LLVMAttributeRef *)Op_val(Array));
+  for (unsigned I = 0; I < Length; ++I) {
+    Field(Array, I) = to_val((LLVMAttributeRef)Field(Array, I));
+  }
   return Array;
 }
 
 /* llvalue -> llattrkind -> int -> unit */
-value llvm_remove_enum_function_attr(LLVMValueRef F, value Kind, value Index) {
-  LLVMRemoveEnumAttributeAtIndex(F, Int_val(Index), Int_val(Kind));
+value llvm_remove_enum_function_attr(value F, value Kind, value Index) {
+  LLVMRemoveEnumAttributeAtIndex(Value_val(F), Int_val(Index), Int_val(Kind));
   return Val_unit;
 }
 
 /* llvalue -> string -> int -> unit */
-value llvm_remove_string_function_attr(LLVMValueRef F, value Kind,
-                                       value Index) {
-  LLVMRemoveStringAttributeAtIndex(F, Int_val(Index), String_val(Kind),
-                                   caml_string_length(Kind));
+value llvm_remove_string_function_attr(value F, value Kind, value Index) {
+  LLVMRemoveStringAttributeAtIndex(Value_val(F), Int_val(Index),
+                                   String_val(Kind), caml_string_length(Kind));
   return Val_unit;
 }
 
 /*--... Operations on parameters ...........................................--*/
 
-DEFINE_ITERATORS(param, Param, LLVMValueRef, LLVMValueRef, LLVMGetParamParent)
+DEFINE_ITERATORS(param, Param, Value_val, LLVMValueRef, Value_val,
+                 LLVMGetParamParent)
 
 /* llvalue -> int -> llvalue */
-LLVMValueRef llvm_param(LLVMValueRef Fn, value Index) {
-  return LLVMGetParam(Fn, Int_val(Index));
+value llvm_param(value Fn, value Index) {
+  return to_val(LLVMGetParam(Value_val(Fn), Int_val(Index)));
 }
 
-/* llvalue -> llvalue */
-value llvm_params(LLVMValueRef Fn) {
-  value Params = caml_alloc_tuple_uninit(LLVMCountParams(Fn));
-  LLVMGetParams(Fn, (LLVMValueRef *)Op_val(Params));
+/* llvalue -> llvalue array */
+value llvm_params(value Fn) {
+  unsigned Length = LLVMCountParams(Value_val(Fn));
+  value Params = caml_alloc_tuple_uninit(Length);
+  LLVMGetParams(Value_val(Fn), (LLVMValueRef *)Op_val(Params));
+  for (unsigned I = 0; I < Length; ++I) {
+    Field(Params, I) = to_val((LLVMValueRef)Field(Params, I));
+  }
   return Params;
 }
 
+/* llvalue -> llvalue */
+value llvm_param_parent(value Value) {
+  LLVMValueRef Parent = LLVMGetParamParent(Value_val(Value));
+  return to_val(Parent);
+}
+
 /*--... Operations on basic blocks .........................................--*/
 
-DEFINE_ITERATORS(block, BasicBlock, LLVMValueRef, LLVMBasicBlockRef,
-                 LLVMGetBasicBlockParent)
+DEFINE_ITERATORS(block, BasicBlock, Value_val, LLVMBasicBlockRef,
+                 BasicBlock_val, LLVMGetBasicBlockParent)
 
 /* llbasicblock -> llvalue option */
-value llvm_block_terminator(LLVMBasicBlockRef Block) {
-  return ptr_to_option(LLVMGetBasicBlockTerminator(Block));
+value llvm_block_terminator(value Block) {
+  return ptr_to_option(LLVMGetBasicBlockTerminator(BasicBlock_val(Block)));
 }
 
 /* llvalue -> llbasicblock array */
-value llvm_basic_blocks(LLVMValueRef Fn) {
-  value MLArray = caml_alloc_tuple_uninit(LLVMCountBasicBlocks(Fn));
-  LLVMGetBasicBlocks(Fn, (LLVMBasicBlockRef *)Op_val(MLArray));
+value llvm_basic_blocks(value Fn) {
+  unsigned Length = LLVMCountBasicBlocks(Value_val(Fn));
+  value MLArray = caml_alloc_tuple_uninit(Length);
+  LLVMGetBasicBlocks(Value_val(Fn), (LLVMBasicBlockRef *)Op_val(MLArray));
+  for (unsigned I = 0; I < Length; ++I) {
+    Field(MLArray, I) = to_val((LLVMBasicBlockRef)Field(MLArray, I));
+  }
   return MLArray;
 }
 
 /* llbasicblock -> unit */
-value llvm_delete_block(LLVMBasicBlockRef BB) {
-  LLVMDeleteBasicBlock(BB);
+value llvm_delete_block(value BB) {
+  LLVMDeleteBasicBlock(BasicBlock_val(BB));
   return Val_unit;
 }
 
 /* llbasicblock -> unit */
-value llvm_remove_block(LLVMBasicBlockRef BB) {
-  LLVMRemoveBasicBlockFromParent(BB);
+value llvm_remove_block(value BB) {
+  LLVMRemoveBasicBlockFromParent(BasicBlock_val(BB));
   return Val_unit;
 }
 
 /* llbasicblock -> llbasicblock -> unit */
-value llvm_move_block_before(LLVMBasicBlockRef Pos, LLVMBasicBlockRef BB) {
-  LLVMMoveBasicBlockBefore(BB, Pos);
+value llvm_move_block_before(value Pos, value BB) {
+  LLVMMoveBasicBlockBefore(BasicBlock_val(BB), BasicBlock_val(Pos));
   return Val_unit;
 }
 
 /* llbasicblock -> llbasicblock -> unit */
-value llvm_move_block_after(LLVMBasicBlockRef Pos, LLVMBasicBlockRef BB) {
-  LLVMMoveBasicBlockAfter(BB, Pos);
+value llvm_move_block_after(value Pos, value BB) {
+  LLVMMoveBasicBlockAfter(BasicBlock_val(BB), BasicBlock_val(Pos));
   return Val_unit;
 }
 
 /* string -> llvalue -> llbasicblock */
-LLVMBasicBlockRef llvm_append_block(LLVMContextRef Context, value Name,
-                                    LLVMValueRef Fn) {
-  return LLVMAppendBasicBlockInContext(Context, Fn, String_val(Name));
+value llvm_append_block(value Context, value Name, value Fn) {
+  return to_val(LLVMAppendBasicBlockInContext(Context_val(Context),
+                                              Value_val(Fn), String_val(Name)));
+}
+
+/* llcontext -> string -> llbasicblock -> llbasicblock */
+value llvm_insert_block(value Context, value Name, value BB) {
+  return to_val(LLVMInsertBasicBlockInContext(
+      Context_val(Context), BasicBlock_val(BB), String_val(Name)));
 }
 
-/* string -> llbasicblock -> llbasicblock */
-LLVMBasicBlockRef llvm_insert_block(LLVMContextRef Context, value Name,
-                                    LLVMBasicBlockRef BB) {
-  return LLVMInsertBasicBlockInContext(Context, BB, String_val(Name));
+/* llbasicblock -> llvalue */
+value llvm_value_of_block(value BB) {
+  return to_val(LLVMBasicBlockAsValue(BasicBlock_val(BB)));
 }
 
 /* llvalue -> bool */
-value llvm_value_is_block(LLVMValueRef Val) {
-  return Val_bool(LLVMValueIsBasicBlock(Val));
+value llvm_value_is_block(value Val) {
+  return Val_bool(LLVMValueIsBasicBlock(Value_val(Val)));
+}
+
+/* llbasicblock -> llvalue */
+value llvm_block_of_value(value Val) {
+  return to_val(LLVMValueAsBasicBlock(Value_val(Val)));
+}
+
+/* llbasicblock -> llvalue */
+value llvm_block_parent(value BB) {
+  return to_val(LLVMGetBasicBlockParent(BasicBlock_val(BB)));
+}
+
+/* llvalue -> llbasicblock */
+value llvm_entry_block(value Val) {
+  LLVMBasicBlockRef BB = LLVMGetEntryBasicBlock(Value_val(Val));
+  return to_val(BB);
 }
 
 /*--... Operations on instructions .........................................--*/
 
-DEFINE_ITERATORS(instr, Instruction, LLVMBasicBlockRef, LLVMValueRef,
+/* llvalue -> llbasicblock */
+value llvm_instr_parent(value Inst) {
+  LLVMBasicBlockRef BB = LLVMGetInstructionParent(Value_val(Inst));
+  return to_val(BB);
+}
+
+DEFINE_ITERATORS(instr, Instruction, BasicBlock_val, LLVMValueRef, Value_val,
                  LLVMGetInstructionParent)
 
 /* llvalue -> Opcode.t */
-value llvm_instr_get_opcode(LLVMValueRef Inst) {
+value llvm_instr_get_opcode(value Inst) {
   LLVMOpcode o;
-  if (!LLVMIsAInstruction(Inst))
-    failwith("Not an instruction");
-  o = LLVMGetInstructionOpcode(Inst);
+  if (!LLVMIsAInstruction(Value_val(Inst)))
+    caml_failwith("Not an instruction");
+  o = LLVMGetInstructionOpcode(Value_val(Inst));
   assert(o <= LLVMFreeze);
   return Val_int(o);
 }
 
 /* llvalue -> ICmp.t option */
-value llvm_instr_icmp_predicate(LLVMValueRef Val) {
-  int x = LLVMGetICmpPredicate(Val);
+value llvm_instr_icmp_predicate(value Val) {
+  int x = LLVMGetICmpPredicate(Value_val(Val));
   if (!x)
     return Val_none;
   return caml_alloc_some(Val_int(x - LLVMIntEQ));
 }
 
 /* llvalue -> FCmp.t option */
-value llvm_instr_fcmp_predicate(LLVMValueRef Val) {
-  int x = LLVMGetFCmpPredicate(Val);
+value llvm_instr_fcmp_predicate(value Val) {
+  int x = LLVMGetFCmpPredicate(Value_val(Val));
   if (!x)
     return Val_none;
   return caml_alloc_some(Val_int(x - LLVMRealPredicateFalse));
 }
 
 /* llvalue -> llvalue */
-LLVMValueRef llvm_instr_clone(LLVMValueRef Inst) {
-  if (!LLVMIsAInstruction(Inst))
-    failwith("Not an instruction");
-  return LLVMInstructionClone(Inst);
+value llvm_instr_clone(value Inst) {
+  if (!LLVMIsAInstruction(Value_val(Inst)))
+    caml_failwith("Not an instruction");
+  return to_val(LLVMInstructionClone(Value_val(Inst)));
 }
 
 /*--... Operations on call sites ...........................................--*/
 
 /* llvalue -> int */
-value llvm_instruction_call_conv(LLVMValueRef Inst) {
-  return Val_int(LLVMGetInstructionCallConv(Inst));
+value llvm_instruction_call_conv(value Inst) {
+  return Val_int(LLVMGetInstructionCallConv(Value_val(Inst)));
 }
 
 /* int -> llvalue -> unit */
-value llvm_set_instruction_call_conv(value CC, LLVMValueRef Inst) {
-  LLVMSetInstructionCallConv(Inst, Int_val(CC));
+value llvm_set_instruction_call_conv(value CC, value Inst) {
+  LLVMSetInstructionCallConv(Value_val(Inst), Int_val(CC));
   return Val_unit;
 }
 
 /* llvalue -> llattribute -> int -> unit */
-value llvm_add_call_site_attr(LLVMValueRef F, LLVMAttributeRef A, value Index) {
-  LLVMAddCallSiteAttribute(F, Int_val(Index), A);
+value llvm_add_call_site_attr(value F, value A, value Index) {
+  LLVMAddCallSiteAttribute(Value_val(F), Int_val(Index), Attribute_val(A));
   return Val_unit;
 }
 
 /* llvalue -> int -> llattribute array */
-value llvm_call_site_attrs(LLVMValueRef F, value Index) {
-  unsigned Count = LLVMGetCallSiteAttributeCount(F, Int_val(Index));
+value llvm_call_site_attrs(value F, value Index) {
+  unsigned Count = LLVMGetCallSiteAttributeCount(Value_val(F), Int_val(Index));
   value Array = caml_alloc_tuple_uninit(Count);
-  LLVMGetCallSiteAttributes(F, Int_val(Index),
+  LLVMGetCallSiteAttributes(Value_val(F), Int_val(Index),
                             (LLVMAttributeRef *)Op_val(Array));
+  for (unsigned I = 0; I < Count; ++I) {
+    Field(Array, I) = to_val((LLVMAttributeRef)Field(Array, I));
+  }
   return Array;
 }
 
 /* llvalue -> llattrkind -> int -> unit */
-value llvm_remove_enum_call_site_attr(LLVMValueRef F, value Kind, value Index) {
-  LLVMRemoveCallSiteEnumAttribute(F, Int_val(Index), Int_val(Kind));
+value llvm_remove_enum_call_site_attr(value F, value Kind, value Index) {
+  LLVMRemoveCallSiteEnumAttribute(Value_val(F), Int_val(Index), Int_val(Kind));
   return Val_unit;
 }
 
 /* llvalue -> string -> int -> unit */
-value llvm_remove_string_call_site_attr(LLVMValueRef F, value Kind,
-                                        value Index) {
-  LLVMRemoveCallSiteStringAttribute(F, Int_val(Index), String_val(Kind),
-                                    caml_string_length(Kind));
+value llvm_remove_string_call_site_attr(value F, value Kind, value Index) {
+  LLVMRemoveCallSiteStringAttribute(Value_val(F), Int_val(Index),
+                                    String_val(Kind), caml_string_length(Kind));
   return Val_unit;
 }
 
 /*--... Operations on call instructions (only) .............................--*/
 
 /* llvalue -> int */
-value llvm_num_arg_operands(LLVMValueRef V) {
-  return Val_int(LLVMGetNumArgOperands(V));
+value llvm_num_arg_operands(value V) {
+  return Val_int(LLVMGetNumArgOperands(Value_val(V)));
 }
 
 /* llvalue -> bool */
-value llvm_is_tail_call(LLVMValueRef CallInst) {
-  return Val_bool(LLVMIsTailCall(CallInst));
+value llvm_is_tail_call(value CallInst) {
+  return Val_bool(LLVMIsTailCall(Value_val(CallInst)));
 }
 
 /* bool -> llvalue -> unit */
-value llvm_set_tail_call(value IsTailCall, LLVMValueRef CallInst) {
-  LLVMSetTailCall(CallInst, Bool_val(IsTailCall));
+value llvm_set_tail_call(value IsTailCall, value CallInst) {
+  LLVMSetTailCall(Value_val(CallInst), Bool_val(IsTailCall));
   return Val_unit;
 }
 
+/* llvalue -> llbasicblock */
+value llvm_get_normal_dest(value Val) {
+  LLVMBasicBlockRef BB = LLVMGetNormalDest(Value_val(Val));
+  return to_val(BB);
+}
+
+/* llvalue -> llbasicblock */
+value llvm_get_unwind_dest(value Val) {
+  LLVMBasicBlockRef BB = LLVMGetUnwindDest(Value_val(Val));
+  return to_val(BB);
+}
+
 /*--... Operations on load/store instructions (only)........................--*/
 
 /* llvalue -> bool */
-value llvm_is_volatile(LLVMValueRef MemoryInst) {
-  return Val_bool(LLVMGetVolatile(MemoryInst));
+value llvm_is_volatile(value MemoryInst) {
+  return Val_bool(LLVMGetVolatile(Value_val(MemoryInst)));
 }
 
 /* bool -> llvalue -> unit */
-value llvm_set_volatile(value IsVolatile, LLVMValueRef MemoryInst) {
-  LLVMSetVolatile(MemoryInst, Bool_val(IsVolatile));
+value llvm_set_volatile(value IsVolatile, value MemoryInst) {
+  LLVMSetVolatile(Value_val(MemoryInst), Bool_val(IsVolatile));
   return Val_unit;
 }
 
 /*--.. Operations on terminators ...........................................--*/
 
 /* llvalue -> int -> llbasicblock */
-LLVMBasicBlockRef llvm_successor(LLVMValueRef V, value I) {
-  return LLVMGetSuccessor(V, Int_val(I));
+value llvm_successor(value V, value I) {
+  return to_val(LLVMGetSuccessor(Value_val(V), Int_val(I)));
 }
 
 /* llvalue -> int -> llvalue -> unit */
-value llvm_set_successor(LLVMValueRef U, value I, LLVMBasicBlockRef B) {
-  LLVMSetSuccessor(U, Int_val(I), B);
+value llvm_set_successor(value U, value I, value B) {
+  LLVMSetSuccessor(Value_val(U), Int_val(I), BasicBlock_val(B));
   return Val_unit;
 }
 
 /* llvalue -> int */
-value llvm_num_successors(LLVMValueRef V) {
-  return Val_int(LLVMGetNumSuccessors(V));
+value llvm_num_successors(value V) {
+  return Val_int(LLVMGetNumSuccessors(Value_val(V)));
 }
 
 /*--.. Operations on branch ................................................--*/
 
 /* llvalue -> llvalue */
-LLVMValueRef llvm_condition(LLVMValueRef V) { return LLVMGetCondition(V); }
+value llvm_condition(value V) { return to_val(LLVMGetCondition(Value_val(V))); }
 
 /* llvalue -> llvalue -> unit */
-value llvm_set_condition(LLVMValueRef B, LLVMValueRef C) {
-  LLVMSetCondition(B, C);
+value llvm_set_condition(value B, value C) {
+  LLVMSetCondition(Value_val(B), Value_val(C));
   return Val_unit;
 }
 
 /* llvalue -> bool */
-value llvm_is_conditional(LLVMValueRef V) {
-  return Val_bool(LLVMIsConditional(V));
+value llvm_is_conditional(value V) {
+  return Val_bool(LLVMIsConditional(Value_val(V)));
 }
 
 /*--... Operations on phi nodes ............................................--*/
 
 /* (llvalue * llbasicblock) -> llvalue -> unit */
-value llvm_add_incoming(value Incoming, LLVMValueRef PhiNode) {
-  LLVMAddIncoming(PhiNode, (LLVMValueRef *)&Field(Incoming, 0),
-                  (LLVMBasicBlockRef *)&Field(Incoming, 1), 1);
+value llvm_add_incoming(value Incoming, value PhiNode) {
+  LLVMValueRef V = Value_val(Field(Incoming, 0));
+  LLVMBasicBlockRef BB = BasicBlock_val(Field(Incoming, 1));
+  LLVMAddIncoming(Value_val(PhiNode), &V, &BB, 1);
   return Val_unit;
 }
 
 /* llvalue -> (llvalue * llbasicblock) list */
-value llvm_incoming(LLVMValueRef PhiNode) {
-  unsigned I;
+value llvm_incoming(value Phi) {
   CAMLparam0();
   CAMLlocal2(Hd, Tl);
+  LLVMValueRef PhiNode = Value_val(Phi);
 
   /* Build a tuple list of them. */
   Tl = Val_int(0);
-  for (I = LLVMCountIncoming(PhiNode); I != 0;) {
+  for (unsigned I = LLVMCountIncoming(PhiNode); I != 0;) {
     Hd = caml_alloc_small(2, 0);
-    Field(Hd, 0) = (value)LLVMGetIncomingValue(PhiNode, --I);
-    Field(Hd, 1) = (value)LLVMGetIncomingBlock(PhiNode, I);
+    Field(Hd, 0) = to_val(LLVMGetIncomingValue(PhiNode, --I));
+    Field(Hd, 1) = to_val(LLVMGetIncomingBlock(PhiNode, I));
 
     value Tmp = caml_alloc_small(2, 0);
     Field(Tmp, 0) = Hd;
@@ -1597,8 +2080,8 @@ value llvm_incoming(LLVMValueRef PhiNode) {
 }
 
 /* llvalue -> unit */
-value llvm_delete_instruction(LLVMValueRef Instruction) {
-  LLVMInstructionEraseFromParent(Instruction);
+value llvm_delete_instruction(value Instruction) {
+  LLVMInstructionEraseFromParent(Value_val(Instruction));
   return Val_unit;
 }
 
@@ -1617,47 +2100,47 @@ static struct custom_operations builder_ops = {
     custom_compare_ext_default};
 
 static value alloc_builder(LLVMBuilderRef B) {
-  value V = alloc_custom(&builder_ops, sizeof(LLVMBuilderRef), 0, 1);
+  value V = caml_alloc_custom(&builder_ops, sizeof(LLVMBuilderRef), 0, 1);
   Builder_val(V) = B;
   return V;
 }
 
 /* llcontext -> llbuilder */
-value llvm_builder(LLVMContextRef C) {
-  return alloc_builder(LLVMCreateBuilderInContext(C));
+value llvm_builder(value C) {
+  return alloc_builder(LLVMCreateBuilderInContext(Context_val(C)));
 }
 
 /* (llbasicblock, llvalue) llpos -> llbuilder -> unit */
 value llvm_position_builder(value Pos, value B) {
   if (Tag_val(Pos) == 0) {
-    LLVMBasicBlockRef BB = (LLVMBasicBlockRef)Op_val(Field(Pos, 0));
+    LLVMBasicBlockRef BB = BasicBlock_val(Field(Pos, 0));
     LLVMPositionBuilderAtEnd(Builder_val(B), BB);
   } else {
-    LLVMValueRef I = (LLVMValueRef)Op_val(Field(Pos, 0));
+    LLVMValueRef I = Value_val(Field(Pos, 0));
     LLVMPositionBuilderBefore(Builder_val(B), I);
   }
   return Val_unit;
 }
 
 /* llbuilder -> llbasicblock */
-LLVMBasicBlockRef llvm_insertion_block(value B) {
+value llvm_insertion_block(value B) {
   LLVMBasicBlockRef InsertBlock = LLVMGetInsertBlock(Builder_val(B));
   if (!InsertBlock)
     caml_raise_not_found();
-  return InsertBlock;
+  return to_val(InsertBlock);
 }
 
 /* llvalue -> string -> llbuilder -> unit */
-value llvm_insert_into_builder(LLVMValueRef I, value Name, value B) {
-  LLVMInsertIntoBuilderWithName(Builder_val(B), I, String_val(Name));
+value llvm_insert_into_builder(value I, value Name, value B) {
+  LLVMInsertIntoBuilderWithName(Builder_val(B), Value_val(I), String_val(Name));
   return Val_unit;
 }
 
 /*--... Metadata ...........................................................--*/
 
 /* llbuilder -> llvalue -> unit */
-value llvm_set_current_debug_location(value B, LLVMValueRef V) {
-  LLVMSetCurrentDebugLocation(Builder_val(B), V);
+value llvm_set_current_debug_location(value B, value V) {
+  LLVMSetCurrentDebugLocation(Builder_val(B), Value_val(V));
   return Val_unit;
 }
 
@@ -1673,646 +2156,676 @@ value llvm_current_debug_location(value B) {
 }
 
 /* llbuilder -> llvalue -> unit */
-value llvm_set_inst_debug_location(value B, LLVMValueRef V) {
-  LLVMSetInstDebugLocation(Builder_val(B), V);
+value llvm_set_inst_debug_location(value B, value V) {
+  LLVMSetInstDebugLocation(Builder_val(B), Value_val(V));
   return Val_unit;
 }
 
 /*--... Terminators ........................................................--*/
 
 /* llbuilder -> llvalue */
-LLVMValueRef llvm_build_ret_void(value B) {
-  return LLVMBuildRetVoid(Builder_val(B));
+value llvm_build_ret_void(value B) {
+  return to_val(LLVMBuildRetVoid(Builder_val(B)));
 }
 
 /* llvalue -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_ret(LLVMValueRef Val, value B) {
-  return LLVMBuildRet(Builder_val(B), Val);
+value llvm_build_ret(value Val, value B) {
+  return to_val(LLVMBuildRet(Builder_val(B), Value_val(Val)));
 }
 
 /* llvalue array -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_aggregate_ret(value RetVals, value B) {
-  return LLVMBuildAggregateRet(Builder_val(B), (LLVMValueRef *)Op_val(RetVals),
-                               Wosize_val(RetVals));
+value llvm_build_aggregate_ret(value RetVals, value B) {
+  mlsize_t Length = Wosize_val(RetVals);
+  LLVMValueRef *Temp = from_val_array(RetVals);
+  LLVMValueRef Value = LLVMBuildAggregateRet(Builder_val(B), Temp, Length);
+  free(Temp);
+  return to_val(Value);
 }
 
 /* llbasicblock -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_br(LLVMBasicBlockRef BB, value B) {
-  return LLVMBuildBr(Builder_val(B), BB);
+value llvm_build_br(value BB, value B) {
+  return to_val(LLVMBuildBr(Builder_val(B), BasicBlock_val(BB)));
 }
 
 /* llvalue -> llbasicblock -> llbasicblock -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_cond_br(LLVMValueRef If, LLVMBasicBlockRef Then,
-                                LLVMBasicBlockRef Else, value B) {
-  return LLVMBuildCondBr(Builder_val(B), If, Then, Else);
+value llvm_build_cond_br(value If, value Then, value Else, value B) {
+  return to_val(LLVMBuildCondBr(Builder_val(B), Value_val(If),
+                                BasicBlock_val(Then), BasicBlock_val(Else)));
 }
 
 /* llvalue -> llbasicblock -> int -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_switch(LLVMValueRef Of, LLVMBasicBlockRef Else,
-                               value EstimatedCount, value B) {
-  return LLVMBuildSwitch(Builder_val(B), Of, Else, Int_val(EstimatedCount));
+value llvm_build_switch(value Of, value Else, value EstimatedCount, value B) {
+  return to_val(LLVMBuildSwitch(Builder_val(B), Value_val(Of),
+                                BasicBlock_val(Else), Int_val(EstimatedCount)));
 }
 
 /* lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_malloc(LLVMTypeRef Ty, value Name, value B) {
-  return LLVMBuildMalloc(Builder_val(B), Ty, String_val(Name));
+value llvm_build_malloc(value Ty, value Name, value B) {
+  return to_val(
+      LLVMBuildMalloc(Builder_val(B), Type_val(Ty), String_val(Name)));
 }
 
 /* lltype -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_array_malloc(LLVMTypeRef Ty, LLVMValueRef Val,
-                                     value Name, value B) {
-  return LLVMBuildArrayMalloc(Builder_val(B), Ty, Val, String_val(Name));
+value llvm_build_array_malloc(value Ty, value Val, value Name, value B) {
+  return to_val(LLVMBuildArrayMalloc(Builder_val(B), Type_val(Ty),
+                                     Value_val(Val), String_val(Name)));
 }
 
 /* llvalue -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_free(LLVMValueRef P, value B) {
-  return LLVMBuildFree(Builder_val(B), P);
+value llvm_build_free(value P, value B) {
+  return to_val(LLVMBuildFree(Builder_val(B), Value_val(P)));
 }
 
 /* llvalue -> llvalue -> llbasicblock -> unit */
-value llvm_add_case(LLVMValueRef Switch, LLVMValueRef OnVal,
-                    LLVMBasicBlockRef Dest) {
-  LLVMAddCase(Switch, OnVal, Dest);
+value llvm_add_case(value Switch, value OnVal, value Dest) {
+  LLVMAddCase(Value_val(Switch), Value_val(OnVal), BasicBlock_val(Dest));
   return Val_unit;
 }
 
-/* llvalue -> llbasicblock -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_indirect_br(LLVMValueRef Addr, value EstimatedDests,
-                                    value B) {
-  return LLVMBuildIndirectBr(Builder_val(B), Addr, EstimatedDests);
+/* llvalue -> llbasicblock */
+value llvm_switch_default_dest(value Val) {
+  LLVMBasicBlockRef BB = LLVMGetSwitchDefaultDest(Value_val(Val));
+  return to_val(BB);
 }
 
-/* llvalue -> llvalue -> llbasicblock -> unit */
-value llvm_add_destination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest) {
-  LLVMAddDestination(IndirectBr, Dest);
+/* llvalue -> int -> llbuilder -> llvalue */
+value llvm_build_indirect_br(value Addr, value EstimatedDests, value B) {
+  return to_val(LLVMBuildIndirectBr(Builder_val(B), Value_val(Addr),
+                                    Int_val(EstimatedDests)));
+}
+
+/* llvalue -> llbasicblock -> unit */
+value llvm_add_destination(value IndirectBr, value Dest) {
+  LLVMAddDestination(Value_val(IndirectBr), BasicBlock_val(Dest));
   return Val_unit;
 }
 
 /* lltype -> llvalue -> llvalue array -> llbasicblock -> llbasicblock ->
    string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_invoke_nat(LLVMTypeRef FnTy, LLVMValueRef Fn,
-                                   value Args, LLVMBasicBlockRef Then,
-                                   LLVMBasicBlockRef Catch, value Name,
-                                   value B) {
-  return LLVMBuildInvoke2(Builder_val(B), FnTy, Fn,
-                          (LLVMValueRef *)Op_val(Args), Wosize_val(Args),
-                          Then, Catch, String_val(Name));
+value llvm_build_invoke_nat(value FnTy, value Fn, value Args, value Then,
+                            value Catch, value Name, value B) {
+  mlsize_t Length = Wosize_val(Args);
+  LLVMValueRef *Temp = from_val_array(Args);
+  LLVMValueRef Value = LLVMBuildInvoke2(
+      Builder_val(B), Type_val(FnTy), Value_val(Fn), Temp, Length,
+      BasicBlock_val(Then), BasicBlock_val(Catch), String_val(Name));
+  free(Temp);
+  return to_val(Value);
 }
 
 /* lltype -> llvalue -> llvalue array -> llbasicblock -> llbasicblock ->
    string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_invoke_bc(value Args[], int NumArgs) {
-  return llvm_build_invoke_nat((LLVMTypeRef)Args[0], (LLVMValueRef)Args[1],
-                               Args[2], (LLVMBasicBlockRef)Args[3],
-                               (LLVMBasicBlockRef)Args[4], Args[5], Args[6]);
+value llvm_build_invoke_bc(value Args[], int NumArgs) {
+  return llvm_build_invoke_nat(Args[0], Args[1], Args[2], Args[3], Args[4],
+                               Args[5], Args[6]);
 }
 
 /* lltype -> llvalue -> int -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_landingpad(LLVMTypeRef Ty, LLVMValueRef PersFn,
-                                   value NumClauses, value Name, value B) {
-  return LLVMBuildLandingPad(Builder_val(B), Ty, PersFn, Int_val(NumClauses),
-                             String_val(Name));
+value llvm_build_landingpad(value Ty, value PersFn, value NumClauses,
+                            value Name, value B) {
+  return to_val(LLVMBuildLandingPad(Builder_val(B), Type_val(Ty),
+                                    Value_val(PersFn), Int_val(NumClauses),
+                                    String_val(Name)));
 }
 
 /* llvalue -> llvalue -> unit */
-value llvm_add_clause(LLVMValueRef LandingPadInst, LLVMValueRef ClauseVal) {
-  LLVMAddClause(LandingPadInst, ClauseVal);
+value llvm_add_clause(value LandingPadInst, value ClauseVal) {
+  LLVMAddClause(Value_val(LandingPadInst), Value_val(ClauseVal));
   return Val_unit;
 }
 
 /* llvalue -> bool */
-value llvm_is_cleanup(LLVMValueRef LandingPadInst) {
-  return Val_bool(LLVMIsCleanup(LandingPadInst));
+value llvm_is_cleanup(value LandingPadInst) {
+  return Val_bool(LLVMIsCleanup(Value_val(LandingPadInst)));
 }
 
 /* llvalue -> bool -> unit */
-value llvm_set_cleanup(LLVMValueRef LandingPadInst, value flag) {
-  LLVMSetCleanup(LandingPadInst, Bool_val(flag));
+value llvm_set_cleanup(value LandingPadInst, value flag) {
+  LLVMSetCleanup(Value_val(LandingPadInst), Bool_val(flag));
   return Val_unit;
 }
 
 /* llvalue -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_resume(LLVMValueRef Exn, value B) {
-  return LLVMBuildResume(Builder_val(B), Exn);
+value llvm_build_resume(value Exn, value B) {
+  return to_val(LLVMBuildResume(Builder_val(B), Value_val(Exn)));
 }
 
 /* llbuilder -> llvalue */
-LLVMValueRef llvm_build_unreachable(value B) {
-  return LLVMBuildUnreachable(Builder_val(B));
+value llvm_build_unreachable(value B) {
+  return to_val(LLVMBuildUnreachable(Builder_val(B)));
 }
 
 /*--... Arithmetic .........................................................--*/
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_add(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                            value B) {
-  return LLVMBuildAdd(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_add(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildAdd(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                             String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_nsw_add(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                                value B) {
-  return LLVMBuildNSWAdd(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_nsw_add(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildNSWAdd(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                                String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_nuw_add(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                                value B) {
-  return LLVMBuildNUWAdd(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_nuw_add(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildNUWAdd(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                                String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fadd(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildFAdd(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_fadd(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildFAdd(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_sub(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                            value B) {
-  return LLVMBuildSub(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_sub(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildSub(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                             String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_nsw_sub(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                                value B) {
-  return LLVMBuildNSWSub(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_nsw_sub(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildNSWSub(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                                String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_nuw_sub(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                                value B) {
-  return LLVMBuildNUWSub(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_nuw_sub(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildNUWSub(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                                String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fsub(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildFSub(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_fsub(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildFSub(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_mul(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                            value B) {
-  return LLVMBuildMul(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_mul(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildMul(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                             String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_nsw_mul(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                                value B) {
-  return LLVMBuildNSWMul(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_nsw_mul(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildNSWMul(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                                String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_nuw_mul(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                                value B) {
-  return LLVMBuildNUWMul(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_nuw_mul(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildNUWMul(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                                String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fmul(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildFMul(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_fmul(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildFMul(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_udiv(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildUDiv(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_udiv(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildUDiv(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_sdiv(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildSDiv(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_sdiv(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildSDiv(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_exact_sdiv(LLVMValueRef LHS, LLVMValueRef RHS,
-                                   value Name, value B) {
-  return LLVMBuildExactSDiv(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_exact_sdiv(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildExactSDiv(Builder_val(B), Value_val(LHS),
+                                   Value_val(RHS), String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fdiv(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildFDiv(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_fdiv(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildFDiv(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_urem(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildURem(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_urem(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildURem(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_srem(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildSRem(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_srem(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildSRem(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_frem(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildFRem(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_frem(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildFRem(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_shl(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                            value B) {
-  return LLVMBuildShl(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_shl(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildShl(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                             String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_lshr(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildLShr(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_lshr(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildLShr(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_ashr(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                             value B) {
-  return LLVMBuildAShr(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_ashr(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildAShr(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_and(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                            value B) {
-  return LLVMBuildAnd(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_and(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildAnd(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                             String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_or(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                           value B) {
-  return LLVMBuildOr(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_or(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildOr(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                            String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_xor(LLVMValueRef LHS, LLVMValueRef RHS, value Name,
-                            value B) {
-  return LLVMBuildXor(Builder_val(B), LHS, RHS, String_val(Name));
+value llvm_build_xor(value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildXor(Builder_val(B), Value_val(LHS), Value_val(RHS),
+                             String_val(Name)));
 }
 
 /* llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_neg(LLVMValueRef X, value Name, value B) {
-  return LLVMBuildNeg(Builder_val(B), X, String_val(Name));
+value llvm_build_neg(value X, value Name, value B) {
+  return to_val(LLVMBuildNeg(Builder_val(B), Value_val(X), String_val(Name)));
 }
 
 /* llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_nsw_neg(LLVMValueRef X, value Name, value B) {
-  return LLVMBuildNSWNeg(Builder_val(B), X, String_val(Name));
+value llvm_build_nsw_neg(value X, value Name, value B) {
+  return to_val(
+      LLVMBuildNSWNeg(Builder_val(B), Value_val(X), String_val(Name)));
 }
 
 /* llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_nuw_neg(LLVMValueRef X, value Name, value B) {
-  return LLVMBuildNUWNeg(Builder_val(B), X, String_val(Name));
+value llvm_build_nuw_neg(value X, value Name, value B) {
+  return to_val(
+      LLVMBuildNUWNeg(Builder_val(B), Value_val(X), String_val(Name)));
 }
 
 /* llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fneg(LLVMValueRef X, value Name, value B) {
-  return LLVMBuildFNeg(Builder_val(B), X, String_val(Name));
+value llvm_build_fneg(value X, value Name, value B) {
+  return to_val(LLVMBuildFNeg(Builder_val(B), Value_val(X), String_val(Name)));
 }
 
 /* llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_not(LLVMValueRef X, value Name, value B) {
-  return LLVMBuildNot(Builder_val(B), X, String_val(Name));
+value llvm_build_not(value X, value Name, value B) {
+  return to_val(LLVMBuildNot(Builder_val(B), Value_val(X), String_val(Name)));
 }
 
 /*--... Memory .............................................................--*/
 
 /* lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_alloca(LLVMTypeRef Ty, value Name, value B) {
-  return LLVMBuildAlloca(Builder_val(B), Ty, String_val(Name));
+value llvm_build_alloca(value Ty, value Name, value B) {
+  return to_val(
+      LLVMBuildAlloca(Builder_val(B), Type_val(Ty), String_val(Name)));
 }
 
 /* lltype -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_array_alloca(LLVMTypeRef Ty, LLVMValueRef Size,
-                                     value Name, value B) {
-  return LLVMBuildArrayAlloca(Builder_val(B), Ty, Size, String_val(Name));
+value llvm_build_array_alloca(value Ty, value Size, value Name, value B) {
+  return to_val(LLVMBuildArrayAlloca(Builder_val(B), Type_val(Ty),
+                                     Value_val(Size), String_val(Name)));
 }
 
 /* lltype -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_load(LLVMTypeRef Ty, LLVMValueRef Pointer, value Name,
-                             value B) {
-  return LLVMBuildLoad2(Builder_val(B), Ty, Pointer, String_val(Name));
+value llvm_build_load(value Ty, value Pointer, value Name, value B) {
+  return to_val(LLVMBuildLoad2(Builder_val(B), Type_val(Ty), Value_val(Pointer),
+                               String_val(Name)));
 }
 
 /* llvalue -> llvalue -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_store(LLVMValueRef Value, LLVMValueRef Pointer,
-                              value B) {
-  return LLVMBuildStore(Builder_val(B), Value, Pointer);
+value llvm_build_store(value Value, value Pointer, value B) {
+  return to_val(
+      LLVMBuildStore(Builder_val(B), Value_val(Value), Value_val(Pointer)));
 }
 
 /* AtomicRMWBinOp.t -> llvalue -> llvalue -> AtomicOrdering.t ->
-   bool -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_atomicrmw_native(value BinOp, LLVMValueRef Ptr,
-                                         LLVMValueRef Val, value Ord, value ST,
-                                         value Name, value B) {
+   bool -> string -> llbuilder -> llvalue */
+value llvm_build_atomicrmw_native(value BinOp, value Ptr, value Val, value Ord,
+                                  value ST, value Name, value B) {
   LLVMValueRef Instr;
-  Instr = LLVMBuildAtomicRMW(Builder_val(B), Int_val(BinOp), Ptr, Val,
-                             Int_val(Ord), Bool_val(ST));
+  Instr = LLVMBuildAtomicRMW(Builder_val(B), Int_val(BinOp), Value_val(Ptr),
+                             Value_val(Val), Int_val(Ord), Bool_val(ST));
   LLVMSetValueName(Instr, String_val(Name));
-  return Instr;
+  return to_val(Instr);
 }
 
-LLVMValueRef llvm_build_atomicrmw_bytecode(value *argv, int argn) {
-  return llvm_build_atomicrmw_native(argv[0], (LLVMValueRef)argv[1],
-                                     (LLVMValueRef)argv[2], argv[3], argv[4],
-                                     argv[5], argv[6]);
+value llvm_build_atomicrmw_bytecode(value *argv, int argn) {
+  return llvm_build_atomicrmw_native(argv[0], argv[1], argv[2], argv[3],
+                                     argv[4], argv[5], argv[6]);
 }
 
 /* lltype -> llvalue -> llvalue array -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_gep(LLVMTypeRef Ty, LLVMValueRef Pointer, value Indices,
-                            value Name, value B) {
-  return LLVMBuildGEP2(Builder_val(B), Ty, Pointer,
-                       (LLVMValueRef *)Op_val(Indices), Wosize_val(Indices),
-                       String_val(Name));
+value llvm_build_gep(value Ty, value Pointer, value Indices, value Name,
+                     value B) {
+  mlsize_t Length = Wosize_val(Indices);
+  LLVMValueRef *Temp = from_val_array(Indices);
+  LLVMValueRef Value =
+      LLVMBuildGEP2(Builder_val(B), Type_val(Ty), Value_val(Pointer), Temp,
+                    Length, String_val(Name));
+  free(Temp);
+  return to_val(Value);
 }
 
 /* lltype -> llvalue -> llvalue array -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_in_bounds_gep(LLVMTypeRef Ty, LLVMValueRef Pointer,
-                                      value Indices, value Name, value B) {
-  return LLVMBuildInBoundsGEP2(Builder_val(B), Ty, Pointer,
-                               (LLVMValueRef *)Op_val(Indices),
-                               Wosize_val(Indices), String_val(Name));
+value llvm_build_in_bounds_gep(value Ty, value Pointer, value Indices,
+                               value Name, value B) {
+  mlsize_t Length = Wosize_val(Indices);
+  LLVMValueRef *Temp = from_val_array(Indices);
+  LLVMValueRef Value =
+      LLVMBuildInBoundsGEP2(Builder_val(B), Type_val(Ty), Value_val(Pointer),
+                            Temp, Length, String_val(Name));
+  free(Temp);
+  return to_val(Value);
 }
 
 /* lltype -> llvalue -> int -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_struct_gep(LLVMTypeRef Ty, LLVMValueRef Pointer,
-                                   value Index, value Name, value B) {
-  return LLVMBuildStructGEP2(Builder_val(B), Ty, Pointer, Int_val(Index),
-                             String_val(Name));
+value llvm_build_struct_gep(value Ty, value Pointer, value Index, value Name,
+                            value B) {
+  return to_val(LLVMBuildStructGEP2(Builder_val(B), Type_val(Ty),
+                                    Value_val(Pointer), Int_val(Index),
+                                    String_val(Name)));
 }
 
 /* string -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_global_string(value Str, value Name, value B) {
-  return LLVMBuildGlobalString(Builder_val(B), String_val(Str),
-                               String_val(Name));
+value llvm_build_global_string(value Str, value Name, value B) {
+  return to_val(
+      LLVMBuildGlobalString(Builder_val(B), String_val(Str), String_val(Name)));
 }
 
 /* string -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_global_stringptr(value Str, value Name, value B) {
-  return LLVMBuildGlobalStringPtr(Builder_val(B), String_val(Str),
-                                  String_val(Name));
+value llvm_build_global_stringptr(value Str, value Name, value B) {
+  return to_val(LLVMBuildGlobalStringPtr(Builder_val(B), String_val(Str),
+                                         String_val(Name)));
 }
 
 /*--... Casts ..............................................................--*/
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_trunc(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                              value B) {
-  return LLVMBuildTrunc(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_trunc(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildTrunc(Builder_val(B), Value_val(X), Type_val(Ty),
+                               String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_zext(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                             value B) {
-  return LLVMBuildZExt(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_zext(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildZExt(Builder_val(B), Value_val(X), Type_val(Ty),
+                              String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_sext(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                             value B) {
-  return LLVMBuildSExt(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_sext(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildSExt(Builder_val(B), Value_val(X), Type_val(Ty),
+                              String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fptoui(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                               value B) {
-  return LLVMBuildFPToUI(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_fptoui(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildFPToUI(Builder_val(B), Value_val(X), Type_val(Ty),
+                                String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fptosi(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                               value B) {
-  return LLVMBuildFPToSI(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_fptosi(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildFPToSI(Builder_val(B), Value_val(X), Type_val(Ty),
+                                String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_uitofp(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                               value B) {
-  return LLVMBuildUIToFP(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_uitofp(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildUIToFP(Builder_val(B), Value_val(X), Type_val(Ty),
+                                String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_sitofp(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                               value B) {
-  return LLVMBuildSIToFP(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_sitofp(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildSIToFP(Builder_val(B), Value_val(X), Type_val(Ty),
+                                String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fptrunc(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                                value B) {
-  return LLVMBuildFPTrunc(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_fptrunc(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildFPTrunc(Builder_val(B), Value_val(X), Type_val(Ty),
+                                 String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fpext(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                              value B) {
-  return LLVMBuildFPExt(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_fpext(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildFPExt(Builder_val(B), Value_val(X), Type_val(Ty),
+                               String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_prttoint(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                                 value B) {
-  return LLVMBuildPtrToInt(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_prttoint(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildPtrToInt(Builder_val(B), Value_val(X), Type_val(Ty),
+                                  String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_inttoptr(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                                 value B) {
-  return LLVMBuildIntToPtr(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_inttoptr(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildIntToPtr(Builder_val(B), Value_val(X), Type_val(Ty),
+                                  String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_bitcast(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                                value B) {
-  return LLVMBuildBitCast(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_bitcast(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildBitCast(Builder_val(B), Value_val(X), Type_val(Ty),
+                                 String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_zext_or_bitcast(LLVMValueRef X, LLVMTypeRef Ty,
-                                        value Name, value B) {
-  return LLVMBuildZExtOrBitCast(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_zext_or_bitcast(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildZExtOrBitCast(Builder_val(B), Value_val(X),
+                                       Type_val(Ty), String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_sext_or_bitcast(LLVMValueRef X, LLVMTypeRef Ty,
-                                        value Name, value B) {
-  return LLVMBuildSExtOrBitCast(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_sext_or_bitcast(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildSExtOrBitCast(Builder_val(B), Value_val(X),
+                                       Type_val(Ty), String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_trunc_or_bitcast(LLVMValueRef X, LLVMTypeRef Ty,
-                                         value Name, value B) {
-  return LLVMBuildTruncOrBitCast(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_trunc_or_bitcast(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildTruncOrBitCast(Builder_val(B), Value_val(X),
+                                        Type_val(Ty), String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_pointercast(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                                    value B) {
-  return LLVMBuildPointerCast(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_pointercast(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildPointerCast(Builder_val(B), Value_val(X), Type_val(Ty),
+                                     String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_intcast(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                                value B) {
-  return LLVMBuildIntCast(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_intcast(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildIntCast(Builder_val(B), Value_val(X), Type_val(Ty),
+                                 String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fpcast(LLVMValueRef X, LLVMTypeRef Ty, value Name,
-                               value B) {
-  return LLVMBuildFPCast(Builder_val(B), X, Ty, String_val(Name));
+value llvm_build_fpcast(value X, value Ty, value Name, value B) {
+  return to_val(LLVMBuildFPCast(Builder_val(B), Value_val(X), Type_val(Ty),
+                                String_val(Name)));
 }
 
 /*--... Comparisons ........................................................--*/
 
 /* Icmp.t -> llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_icmp(value Pred, LLVMValueRef LHS, LLVMValueRef RHS,
-                             value Name, value B) {
-  return LLVMBuildICmp(Builder_val(B), Int_val(Pred) + LLVMIntEQ, LHS, RHS,
-                       String_val(Name));
+value llvm_build_icmp(value Pred, value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildICmp(Builder_val(B), Int_val(Pred) + LLVMIntEQ,
+                              Value_val(LHS), Value_val(RHS),
+                              String_val(Name)));
 }
 
 /* Fcmp.t -> llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_fcmp(value Pred, LLVMValueRef LHS, LLVMValueRef RHS,
-                             value Name, value B) {
-  return LLVMBuildFCmp(Builder_val(B), Int_val(Pred), LHS, RHS,
-                       String_val(Name));
+value llvm_build_fcmp(value Pred, value LHS, value RHS, value Name, value B) {
+  return to_val(LLVMBuildFCmp(Builder_val(B), Int_val(Pred), Value_val(LHS),
+                              Value_val(RHS), String_val(Name)));
 }
 
 /*--... Miscellaneous instructions .........................................--*/
 
 /* (llvalue * llbasicblock) list -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_phi(value Incoming, value Name, value B) {
+value llvm_build_phi(value Incoming, value Name, value B) {
   value Hd, Tl;
   LLVMValueRef FirstValue, PhiNode;
 
   assert(Incoming != Val_int(0) && "Empty list passed to Llvm.build_phi!");
 
   Hd = Field(Incoming, 0);
-  FirstValue = (LLVMValueRef)Field(Hd, 0);
+  FirstValue = Value_val(Field(Hd, 0));
   PhiNode =
       LLVMBuildPhi(Builder_val(B), LLVMTypeOf(FirstValue), String_val(Name));
 
   for (Tl = Incoming; Tl != Val_int(0); Tl = Field(Tl, 1)) {
-    value Hd = Field(Tl, 0);
-    LLVMAddIncoming(PhiNode, (LLVMValueRef *)&Field(Hd, 0),
-                    (LLVMBasicBlockRef *)&Field(Hd, 1), 1);
+    Hd = Field(Tl, 0);
+    LLVMValueRef V = Value_val(Field(Hd, 0));
+    LLVMBasicBlockRef BB = BasicBlock_val(Field(Hd, 1));
+    LLVMAddIncoming(PhiNode, &V, &BB, 1);
   }
 
-  return PhiNode;
+  return to_val(PhiNode);
 }
 
 /* lltype -> string -> llbuilder -> value */
-LLVMValueRef llvm_build_empty_phi(LLVMTypeRef Type, value Name, value B) {
-  return LLVMBuildPhi(Builder_val(B), Type, String_val(Name));
+value llvm_build_empty_phi(value Type, value Name, value B) {
+  return to_val(LLVMBuildPhi(Builder_val(B), Type_val(Type), String_val(Name)));
 }
 
 /* lltype -> llvalue -> llvalue array -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_call(LLVMTypeRef FnTy, LLVMValueRef Fn, value Params,
-                             value Name, value B) {
-  return LLVMBuildCall2(Builder_val(B), FnTy, Fn,
-                        (LLVMValueRef *)Op_val(Params), Wosize_val(Params),
-                        String_val(Name));
+value llvm_build_call(value FnTy, value Fn, value Params, value Name, value B) {
+  mlsize_t Length = Wosize_val(Params);
+  LLVMValueRef *Temp = from_val_array(Params);
+  LLVMValueRef Value =
+      LLVMBuildCall2(Builder_val(B), Type_val(FnTy), Value_val(Fn), Temp,
+                     Length, String_val(Name));
+  free(Temp);
+  return to_val(Value);
 }
 
 /* llvalue -> llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_select(LLVMValueRef If, LLVMValueRef Then,
-                               LLVMValueRef Else, value Name, value B) {
-  return LLVMBuildSelect(Builder_val(B), If, Then, Else, String_val(Name));
+value llvm_build_select(value If, value Then, value Else, value Name, value B) {
+  return to_val(LLVMBuildSelect(Builder_val(B), Value_val(If), Value_val(Then),
+                                Value_val(Else), String_val(Name)));
 }
 
 /* llvalue -> lltype -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_va_arg(LLVMValueRef List, LLVMTypeRef Ty, value Name,
-                               value B) {
-  return LLVMBuildVAArg(Builder_val(B), List, Ty, String_val(Name));
+value llvm_build_va_arg(value List, value Ty, value Name, value B) {
+  return to_val(LLVMBuildVAArg(Builder_val(B), Value_val(List), Type_val(Ty),
+                               String_val(Name)));
 }
 
 /* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_extractelement(LLVMValueRef Vec, LLVMValueRef Idx,
-                                       value Name, value B) {
-  return LLVMBuildExtractElement(Builder_val(B), Vec, Idx, String_val(Name));
+value llvm_build_extractelement(value Vec, value Idx, value Name, value B) {
+  return to_val(LLVMBuildExtractElement(Builder_val(B), Value_val(Vec),
+                                        Value_val(Idx), String_val(Name)));
 }
 
 /* llvalue -> llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_insertelement(LLVMValueRef Vec, LLVMValueRef Element,
-                                      LLVMValueRef Idx, value Name, value B) {
-  return LLVMBuildInsertElement(Builder_val(B), Vec, Element, Idx,
-                                String_val(Name));
+value llvm_build_insertelement(value Vec, value Element, value Idx, value Name,
+                               value B) {
+  return to_val(LLVMBuildInsertElement(Builder_val(B), Value_val(Vec),
+                                       Value_val(Element), Value_val(Idx),
+                                       String_val(Name)));
 }
 
 /* llvalue -> llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_shufflevector(LLVMValueRef V1, LLVMValueRef V2,
-                                      LLVMValueRef Mask, value Name, value B) {
-  return LLVMBuildShuffleVector(Builder_val(B), V1, V2, Mask, String_val(Name));
+value llvm_build_shufflevector(value V1, value V2, value Mask, value Name,
+                               value B) {
+  return to_val(LLVMBuildShuffleVector(Builder_val(B), Value_val(V1),
+                                       Value_val(V2), Value_val(Mask),
+                                       String_val(Name)));
 }
 
 /* llvalue -> int -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_extractvalue(LLVMValueRef Aggregate, value Idx,
-                                     value Name, value B) {
-  return LLVMBuildExtractValue(Builder_val(B), Aggregate, Int_val(Idx),
-                               String_val(Name));
+value llvm_build_extractvalue(value Aggregate, value Idx, value Name, value B) {
+  return to_val(LLVMBuildExtractValue(Builder_val(B), Value_val(Aggregate),
+                                      Int_val(Idx), String_val(Name)));
 }
 
 /* llvalue -> llvalue -> int -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_insertvalue(LLVMValueRef Aggregate, LLVMValueRef Val,
-                                    value Idx, value Name, value B) {
-  return LLVMBuildInsertValue(Builder_val(B), Aggregate, Val, Int_val(Idx),
-                              String_val(Name));
+value llvm_build_insertvalue(value Aggregate, value Val, value Idx, value Name,
+                             value B) {
+  return to_val(LLVMBuildInsertValue(Builder_val(B), Value_val(Aggregate),
+                                     Value_val(Val), Int_val(Idx),
+                                     String_val(Name)));
 }
 
 /* llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_is_null(LLVMValueRef Val, value Name, value B) {
-  return LLVMBuildIsNull(Builder_val(B), Val, String_val(Name));
+value llvm_build_is_null(value Val, value Name, value B) {
+  return to_val(
+      LLVMBuildIsNull(Builder_val(B), Value_val(Val), String_val(Name)));
 }
 
 /* llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_is_not_null(LLVMValueRef Val, value Name, value B) {
-  return LLVMBuildIsNotNull(Builder_val(B), Val, String_val(Name));
+value llvm_build_is_not_null(value Val, value Name, value B) {
+  return to_val(
+      LLVMBuildIsNotNull(Builder_val(B), Value_val(Val), String_val(Name)));
 }
 
-/* llvalue -> llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_ptr
diff (LLVMTypeRef ElemTy, LLVMValueRef LHS,
-                                LLVMValueRef RHS, value Name, value B) {
-  return LLVMBuildPtrDiff2(Builder_val(B), ElemTy, LHS, RHS, String_val(Name));
+/* lltype -> llvalue -> llvalue -> string -> llbuilder -> llvalue */
+value llvm_build_ptr
diff (value ElemTy, value LHS, value RHS, value Name,
+                         value B) {
+  return to_val(LLVMBuildPtrDiff2(Builder_val(B), Type_val(ElemTy),
+                                  Value_val(LHS), Value_val(RHS),
+                                  String_val(Name)));
 }
 
 /* llvalue -> string -> llbuilder -> llvalue */
-LLVMValueRef llvm_build_freeze(LLVMValueRef X, value Name, value B) {
-  return LLVMBuildFreeze(Builder_val(B), X, String_val(Name));
+value llvm_build_freeze(value X, value Name, value B) {
+  return to_val(
+      LLVMBuildFreeze(Builder_val(B), Value_val(X), String_val(Name)));
 }
 
 /*===-- Memory buffers ----------------------------------------------------===*/
 
 /* string -> llmemorybuffer
    raises IoError msg on error */
-LLVMMemoryBufferRef llvm_memorybuffer_of_file(value Path) {
+value llvm_memorybuffer_of_file(value Path) {
   char *Message;
   LLVMMemoryBufferRef MemBuf;
 
   if (LLVMCreateMemoryBufferWithContentsOfFile(String_val(Path), &MemBuf,
                                                &Message))
     llvm_raise(*caml_named_value("Llvm.IoError"), Message);
-
-  return MemBuf;
+  return to_val(MemBuf);
 }
 
 /* unit -> llmemorybuffer
    raises IoError msg on error */
-LLVMMemoryBufferRef llvm_memorybuffer_of_stdin(value Unit) {
+value llvm_memorybuffer_of_stdin(value Unit) {
   char *Message;
   LLVMMemoryBufferRef MemBuf;
 
   if (LLVMCreateMemoryBufferWithSTDIN(&MemBuf, &Message))
     llvm_raise(*caml_named_value("Llvm.IoError"), Message);
-
-  return MemBuf;
+  return to_val(MemBuf);
 }
 
 /* ?name:string -> string -> llmemorybuffer */
-LLVMMemoryBufferRef llvm_memorybuffer_of_string(value Name, value String) {
+value llvm_memorybuffer_of_string(value Name, value String) {
   LLVMMemoryBufferRef MemBuf;
   const char *NameCStr;
 
@@ -2323,19 +2836,19 @@ LLVMMemoryBufferRef llvm_memorybuffer_of_string(value Name, value String) {
 
   MemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy(
       String_val(String), caml_string_length(String), NameCStr);
-
-  return MemBuf;
+  return to_val(MemBuf);
 }
 
 /* llmemorybuffer -> string */
-value llvm_memorybuffer_as_string(LLVMMemoryBufferRef MemBuf) {
+value llvm_memorybuffer_as_string(value MB) {
+  LLVMMemoryBufferRef MemBuf = MemoryBuffer_val(MB);
   size_t BufferSize = LLVMGetBufferSize(MemBuf);
   const char *BufferStart = LLVMGetBufferStart(MemBuf);
   return cstr_to_string(BufferStart, BufferSize);
 }
 
 /* llmemorybuffer -> unit */
-value llvm_memorybuffer_dispose(LLVMMemoryBufferRef MemBuf) {
-  LLVMDisposeMemoryBuffer(MemBuf);
+value llvm_memorybuffer_dispose(value MemBuf) {
+  LLVMDisposeMemoryBuffer(MemoryBuffer_val(MemBuf));
   return Val_unit;
 }

diff  --git a/llvm/bindings/ocaml/llvm/llvm_ocaml.h b/llvm/bindings/ocaml/llvm/llvm_ocaml.h
index 09e3c6cfb30d7..3790a3638d01d 100644
--- a/llvm/bindings/ocaml/llvm/llvm_ocaml.h
+++ b/llvm/bindings/ocaml/llvm/llvm_ocaml.h
@@ -32,6 +32,32 @@
 value caml_alloc_some(value);
 #endif
 
+/* to_val and from_val convert between an OCaml value and a pointer from LLVM,
+   which points outside the OCaml heap. They assume that all pointers from LLVM
+   are 2-byte aligned: to_val sets the low bit so that OCaml treats the value
+   as an integer, and from_val clears the low bit. */
+value to_val(void *ptr);
+
+void *from_val(value v);
+
+/* from_val_array takes an OCaml array value of LLVM references encoded with
+   the representation described above and returns a malloc'd array
+   of decoded LLVM references. The returned array must be deallocated using
+   free. */
+void *from_val_array(value Elements);
+
+#define DiagnosticInfo_val(v) ((LLVMDiagnosticInfoRef)from_val(v))
+#define Context_val(v) ((LLVMContextRef)from_val(v))
+#define Attribute_val(v) ((LLVMAttributeRef)from_val(v))
+#define Module_val(v) ((LLVMModuleRef)from_val(v))
+#define Metadata_val(v) ((LLVMMetadataRef)from_val(v))
+#define Type_val(v) ((LLVMTypeRef)from_val(v))
+#define Value_val(v) ((LLVMValueRef)from_val(v))
+#define Use_val(v) ((LLVMUseRef)from_val(v))
+#define BasicBlock_val(v) ((LLVMBasicBlockRef)from_val(v))
+#define MemoryBuffer_val(v) ((LLVMMemoryBufferRef)from_val(v))
+#define PassManager_val(v) ((LLVMPassManagerRef)from_val(v))
+
 /* Convert a C pointer to an OCaml option */
 value ptr_to_option(void *Ptr);
 

diff  --git a/llvm/bindings/ocaml/target/target_ocaml.c b/llvm/bindings/ocaml/target/target_ocaml.c
index d0bc6f162f0d2..ba6bf4f623395 100644
--- a/llvm/bindings/ocaml/target/target_ocaml.c
+++ b/llvm/bindings/ocaml/target/target_ocaml.c
@@ -47,7 +47,7 @@ static struct custom_operations llvm_data_layout_ops = {
 
 value llvm_alloc_data_layout(LLVMTargetDataRef DataLayout) {
   value V =
-      alloc_custom(&llvm_data_layout_ops, sizeof(LLVMTargetDataRef), 0, 1);
+      caml_alloc_custom(&llvm_data_layout_ops, sizeof(LLVMTargetDataRef), 0, 1);
   DataLayout_val(V) = DataLayout;
   return V;
 }
@@ -60,7 +60,7 @@ value llvm_datalayout_of_string(value StringRep) {
 /* DataLayout.t -> string */
 value llvm_datalayout_as_string(value TD) {
   char *StringRep = LLVMCopyStringRepOfTargetData(DataLayout_val(TD));
-  value Copy = copy_string(StringRep);
+  value Copy = caml_copy_string(StringRep);
   LLVMDisposeMessage(StringRep);
   return Copy;
 }
@@ -76,8 +76,10 @@ value llvm_datalayout_pointer_size(value DL) {
 }
 
 /* Llvm.llcontext -> DataLayout.t -> Llvm.lltype */
-LLVMTypeRef llvm_datalayout_intptr_type(LLVMContextRef C, value DL) {
-  return LLVMIntPtrTypeInContext(C, DataLayout_val(DL));
+value llvm_datalayout_intptr_type(value C, value DL) {
+  LLVMTypeRef Type =
+      LLVMIntPtrTypeInContext(Context_val(C), DataLayout_val(DL));
+  return to_val(Type);
 }
 
 /* int -> DataLayout.t -> int */
@@ -86,68 +88,72 @@ value llvm_datalayout_qualified_pointer_size(value AS, value DL) {
 }
 
 /* Llvm.llcontext -> int -> DataLayout.t -> Llvm.lltype */
-LLVMTypeRef llvm_datalayout_qualified_intptr_type(LLVMContextRef C, value AS,
-                                                  value DL) {
-  return LLVMIntPtrTypeForASInContext(C, DataLayout_val(DL), Int_val(AS));
+value llvm_datalayout_qualified_intptr_type(value C, value AS, value DL) {
+  LLVMTypeRef Type = LLVMIntPtrTypeForASInContext(
+      Context_val(C), DataLayout_val(DL), Int_val(AS));
+  return to_val(Type);
 }
 
 /* Llvm.lltype -> DataLayout.t -> Int64.t */
-value llvm_datalayout_size_in_bits(LLVMTypeRef Ty, value DL) {
-  return caml_copy_int64(LLVMSizeOfTypeInBits(DataLayout_val(DL), Ty));
+value llvm_datalayout_size_in_bits(value Ty, value DL) {
+  return caml_copy_int64(
+      LLVMSizeOfTypeInBits(DataLayout_val(DL), Type_val(Ty)));
 }
 
 /* Llvm.lltype -> DataLayout.t -> Int64.t */
-value llvm_datalayout_store_size(LLVMTypeRef Ty, value DL) {
-  return caml_copy_int64(LLVMStoreSizeOfType(DataLayout_val(DL), Ty));
+value llvm_datalayout_store_size(value Ty, value DL) {
+  return caml_copy_int64(LLVMStoreSizeOfType(DataLayout_val(DL), Type_val(Ty)));
 }
 
 /* Llvm.lltype -> DataLayout.t -> Int64.t */
-value llvm_datalayout_abi_size(LLVMTypeRef Ty, value DL) {
-  return caml_copy_int64(LLVMABISizeOfType(DataLayout_val(DL), Ty));
+value llvm_datalayout_abi_size(value Ty, value DL) {
+  return caml_copy_int64(LLVMABISizeOfType(DataLayout_val(DL), Type_val(Ty)));
 }
 
 /* Llvm.lltype -> DataLayout.t -> int */
-value llvm_datalayout_abi_align(LLVMTypeRef Ty, value DL) {
-  return Val_int(LLVMABIAlignmentOfType(DataLayout_val(DL), Ty));
+value llvm_datalayout_abi_align(value Ty, value DL) {
+  return Val_int(LLVMABIAlignmentOfType(DataLayout_val(DL), Type_val(Ty)));
 }
 
 /* Llvm.lltype -> DataLayout.t -> int */
-value llvm_datalayout_stack_align(LLVMTypeRef Ty, value DL) {
-  return Val_int(LLVMCallFrameAlignmentOfType(DataLayout_val(DL), Ty));
+value llvm_datalayout_stack_align(value Ty, value DL) {
+  return Val_int(
+      LLVMCallFrameAlignmentOfType(DataLayout_val(DL), Type_val(Ty)));
 }
 
 /* Llvm.lltype -> DataLayout.t -> int */
-value llvm_datalayout_preferred_align(LLVMTypeRef Ty, value DL) {
-  return Val_int(LLVMPreferredAlignmentOfType(DataLayout_val(DL), Ty));
+value llvm_datalayout_preferred_align(value Ty, value DL) {
+  return Val_int(
+      LLVMPreferredAlignmentOfType(DataLayout_val(DL), Type_val(Ty)));
 }
 
 /* Llvm.llvalue -> DataLayout.t -> int */
-value llvm_datalayout_preferred_align_of_global(LLVMValueRef GlobalVar,
-                                                value DL) {
-  return Val_int(LLVMPreferredAlignmentOfGlobal(DataLayout_val(DL), GlobalVar));
+value llvm_datalayout_preferred_align_of_global(value GlobalVar, value DL) {
+  return Val_int(
+      LLVMPreferredAlignmentOfGlobal(DataLayout_val(DL), Value_val(GlobalVar)));
 }
 
 /* Llvm.lltype -> Int64.t -> DataLayout.t -> int */
-value llvm_datalayout_element_at_offset(LLVMTypeRef Ty, value Offset,
-                                        value DL) {
+value llvm_datalayout_element_at_offset(value Ty, value Offset, value DL) {
   return Val_int(
-      LLVMElementAtOffset(DataLayout_val(DL), Ty, Int64_val(Offset)));
+      LLVMElementAtOffset(DataLayout_val(DL), Type_val(Ty), Int64_val(Offset)));
 }
 
 /* Llvm.lltype -> int -> DataLayout.t -> Int64.t */
-value llvm_datalayout_offset_of_element(LLVMTypeRef Ty, value Index, value DL) {
+value llvm_datalayout_offset_of_element(value Ty, value Index, value DL) {
   return caml_copy_int64(
-      LLVMOffsetOfElement(DataLayout_val(DL), Ty, Int_val(Index)));
+      LLVMOffsetOfElement(DataLayout_val(DL), Type_val(Ty), Int_val(Index)));
 }
 
 /*===---- Target ----------------------------------------------------------===*/
 
+#define Target_val(v) ((LLVMTargetRef)from_val(v))
+
 /* unit -> string */
 value llvm_target_default_triple(value Unit) {
   char *TripleCStr = LLVMGetDefaultTargetTriple();
   value TripleStr = caml_copy_string(TripleCStr);
   LLVMDisposeMessage(TripleCStr);
-
   return TripleStr;
 }
 
@@ -157,8 +163,8 @@ value llvm_target_first(value Unit) {
 }
 
 /* Target.t -> Target.t option */
-value llvm_target_succ(LLVMTargetRef Target) {
-  return ptr_to_option(LLVMGetNextTarget(Target));
+value llvm_target_succ(value Target) {
+  return ptr_to_option(LLVMGetNextTarget(Target_val(Target)));
 }
 
 /* string -> Target.t option */
@@ -167,39 +173,39 @@ value llvm_target_by_name(value Name) {
 }
 
 /* string -> Target.t */
-LLVMTargetRef llvm_target_by_triple(value Triple) {
+value llvm_target_by_triple(value Triple) {
   LLVMTargetRef T;
   char *Error;
 
   if (LLVMGetTargetFromTriple(String_val(Triple), &T, &Error))
     llvm_raise(*caml_named_value("Llvm_target.Error"), Error);
 
-  return T;
+  return to_val(T);
 }
 
 /* Target.t -> string */
-value llvm_target_name(LLVMTargetRef Target) {
-  return caml_copy_string(LLVMGetTargetName(Target));
+value llvm_target_name(value Target) {
+  return caml_copy_string(LLVMGetTargetName(Target_val(Target)));
 }
 
 /* Target.t -> string */
-value llvm_target_description(LLVMTargetRef Target) {
-  return caml_copy_string(LLVMGetTargetDescription(Target));
+value llvm_target_description(value Target) {
+  return caml_copy_string(LLVMGetTargetDescription(Target_val(Target)));
 }
 
 /* Target.t -> bool */
-value llvm_target_has_jit(LLVMTargetRef Target) {
-  return Val_bool(LLVMTargetHasJIT(Target));
+value llvm_target_has_jit(value Target) {
+  return Val_bool(LLVMTargetHasJIT(Target_val(Target)));
 }
 
 /* Target.t -> bool */
-value llvm_target_has_target_machine(LLVMTargetRef Target) {
-  return Val_bool(LLVMTargetHasTargetMachine(Target));
+value llvm_target_has_target_machine(value Target) {
+  return Val_bool(LLVMTargetHasTargetMachine(Target_val(Target)));
 }
 
 /* Target.t -> bool */
-value llvm_target_has_asm_backend(LLVMTargetRef Target) {
-  return Val_bool(LLVMTargetHasAsmBackend(Target));
+value llvm_target_has_asm_backend(value Target) {
+  return Val_bool(LLVMTargetHasAsmBackend(Target_val(Target)));
 }
 
 /*===---- Target Machine --------------------------------------------------===*/
@@ -220,8 +226,8 @@ static struct custom_operations llvm_target_machine_ops = {
     custom_compare_ext_default};
 
 static value llvm_alloc_targetmachine(LLVMTargetMachineRef Machine) {
-  value V = alloc_custom(&llvm_target_machine_ops, sizeof(LLVMTargetMachineRef),
-                         0, 1);
+  value V = caml_alloc_custom(&llvm_target_machine_ops,
+                              sizeof(LLVMTargetMachineRef), 0, 1);
   TargetMachine_val(V) = Machine;
   return V;
 }
@@ -231,7 +237,7 @@ static value llvm_alloc_targetmachine(LLVMTargetMachineRef Machine) {
    ?code_model:CodeModel.t -> Target.t -> TargetMachine.t */
 value llvm_create_targetmachine_native(value Triple, value CPU, value Features,
                                        value OptLevel, value RelocMode,
-                                       value CodeModel, LLVMTargetRef Target) {
+                                       value CodeModel, value Target) {
   LLVMTargetMachineRef Machine;
   const char *CPUStr = "", *FeaturesStr = "";
   LLVMCodeGenOptLevel OptLevelEnum = LLVMCodeGenLevelDefault;
@@ -249,22 +255,21 @@ value llvm_create_targetmachine_native(value Triple, value CPU, value Features,
   if (CodeModel != Val_int(0))
     CodeModelEnum = Int_val(Field(CodeModel, 0));
 
-  Machine =
-      LLVMCreateTargetMachine(Target, String_val(Triple), CPUStr, FeaturesStr,
-                              OptLevelEnum, RelocModeEnum, CodeModelEnum);
+  Machine = LLVMCreateTargetMachine(Target_val(Target), String_val(Triple),
+                                    CPUStr, FeaturesStr, OptLevelEnum,
+                                    RelocModeEnum, CodeModelEnum);
 
   return llvm_alloc_targetmachine(Machine);
 }
 
 value llvm_create_targetmachine_bytecode(value *argv, int argn) {
   return llvm_create_targetmachine_native(argv[0], argv[1], argv[2], argv[3],
-                                          argv[4], argv[5],
-                                          (LLVMTargetRef)argv[6]);
+                                          argv[4], argv[5], argv[6]);
 }
 
 /* TargetMachine.t -> Target.t */
-LLVMTargetRef llvm_targetmachine_target(value Machine) {
-  return LLVMGetTargetMachineTarget(TargetMachine_val(Machine));
+value llvm_targetmachine_target(value Machine) {
+  return to_val(LLVMGetTargetMachineTarget(TargetMachine_val(Machine)));
 }
 
 /* TargetMachine.t -> string */
@@ -298,13 +303,13 @@ value llvm_targetmachine_set_verbose_asm(value Verb, value Machine) {
 }
 
 /* Llvm.llmodule -> CodeGenFileType.t -> string -> TargetMachine.t -> unit */
-value llvm_targetmachine_emit_to_file(LLVMModuleRef Module, value FileType,
+value llvm_targetmachine_emit_to_file(value Module, value FileType,
                                       value FileName, value Machine) {
   char *ErrorMessage;
 
-  if (LLVMTargetMachineEmitToFile(TargetMachine_val(Machine), Module,
-                                  (char *)String_val(FileName),
-                                  Int_val(FileType), &ErrorMessage)) {
+  if (LLVMTargetMachineEmitToFile(
+          TargetMachine_val(Machine), Module_val(Module),
+          (char *)String_val(FileName), Int_val(FileType), &ErrorMessage)) {
     llvm_raise(*caml_named_value("Llvm_target.Error"), ErrorMessage);
   }
 
@@ -313,17 +318,16 @@ value llvm_targetmachine_emit_to_file(LLVMModuleRef Module, value FileType,
 
 /* Llvm.llmodule -> CodeGenFileType.t -> TargetMachine.t ->
    Llvm.llmemorybuffer */
-LLVMMemoryBufferRef
-llvm_targetmachine_emit_to_memory_buffer(LLVMModuleRef Module, value FileType,
-                                         value Machine) {
+value llvm_targetmachine_emit_to_memory_buffer(value Module, value FileType,
+                                               value Machine) {
   char *ErrorMessage;
   LLVMMemoryBufferRef Buffer;
 
-  if (LLVMTargetMachineEmitToMemoryBuffer(TargetMachine_val(Machine), Module,
-                                          Int_val(FileType), &ErrorMessage,
-                                          &Buffer)) {
+  if (LLVMTargetMachineEmitToMemoryBuffer(TargetMachine_val(Machine),
+                                          Module_val(Module), Int_val(FileType),
+                                          &ErrorMessage, &Buffer)) {
     llvm_raise(*caml_named_value("Llvm_target.Error"), ErrorMessage);
   }
 
-  return Buffer;
+  return to_val(Buffer);
 }

diff  --git a/llvm/bindings/ocaml/transforms/utils/CMakeLists.txt b/llvm/bindings/ocaml/transforms/utils/CMakeLists.txt
index 920ed793bcedc..eecc1f80aa7a7 100644
--- a/llvm/bindings/ocaml/transforms/utils/CMakeLists.txt
+++ b/llvm/bindings/ocaml/transforms/utils/CMakeLists.txt
@@ -2,4 +2,5 @@ add_ocaml_library(llvm_transform_utils
   OCAML    llvm_transform_utils
   OCAMLDEP llvm
   C        transform_utils_ocaml
+  CFLAGS   "-I${CMAKE_CURRENT_SOURCE_DIR}/../../llvm"
   LLVM     TransformUtils)

diff  --git a/llvm/bindings/ocaml/transforms/utils/transform_utils_ocaml.c b/llvm/bindings/ocaml/transforms/utils/transform_utils_ocaml.c
index 3e0f52e940caf..6d0566b54725a 100644
--- a/llvm/bindings/ocaml/transforms/utils/transform_utils_ocaml.c
+++ b/llvm/bindings/ocaml/transforms/utils/transform_utils_ocaml.c
@@ -15,9 +15,11 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#include "llvm-c/Core.h"
-#include "caml/mlvalues.h"
+#include "caml/memory.h"
 #include "caml/misc.h"
+#include "caml/mlvalues.h"
+#include "llvm_ocaml.h"
+#include "llvm-c/Core.h"
 
 /*
  * Do not move directly into external. This function is here to pull in
@@ -26,4 +28,6 @@
  */
 
 /* llmodule -> llmodule */
-LLVMModuleRef llvm_clone_module(LLVMModuleRef M) { return LLVMCloneModule(M); }
+value llvm_clone_module(value M) {
+  return to_val(LLVMCloneModule(Module_val(M)));
+}

diff  --git a/llvm/test/Bindings/OCaml/core.ml b/llvm/test/Bindings/OCaml/core.ml
index 86a5a115172ce..33841deb42cfa 100644
--- a/llvm/test/Bindings/OCaml/core.ml
+++ b/llvm/test/Bindings/OCaml/core.ml
@@ -34,18 +34,24 @@ let fp128_type = Llvm.fp128_type context
 let filename = Sys.argv.(1)
 let m = create_module context filename
 
+(*===-- Modules  ----------------------------------------------------------===*)
+
+let test_modules () =
+  insist (module_context m = context)
+
 (*===-- Contained types  --------------------------------------------------===*)
 
 let test_contained_types () =
   let ar = struct_type context [| i32_type; i8_type |] in
   insist (i32_type = (Array.get (subtypes ar)) 0);
-  insist (i8_type = (Array.get (subtypes ar)) 1)
+  insist (i8_type = (Array.get (subtypes ar)) 1);
+  insist ([| i32_type; i8_type |] = struct_element_types ar)
 
 (*===-- Pointer types  ----------------------------------------------------===*)
 let test_pointer_types () =
-  insist (address_space (pointer_type context) = 0);
-  insist (address_space (qualified_pointer_type context 0) = 0);
-  insist (address_space (qualified_pointer_type context 1) = 1)
+  insist (0 = address_space (pointer_type context));
+  insist (0 = address_space (qualified_pointer_type context 0));
+  insist (1 = address_space (qualified_pointer_type context 1))
 
 (*===-- Conversion --------------------------------------------------------===*)
 
@@ -185,6 +191,7 @@ let test_constants () =
   let c = const_array i32_type [| three; four |] in
   ignore (define_global "const_array" c m);
   insist ((array_type i32_type 2) = (type_of c));
+  insist (element_type (type_of c) = i32_type);
   insist (Some three = (aggregate_element c 0));
   insist (Some four = (aggregate_element c 1));
   insist (None = (aggregate_element c 2));
@@ -196,6 +203,7 @@ let test_constants () =
                           one; two; one; two |] in
   ignore (define_global "const_vector" c m);
   insist ((vector_type i16_type 8) = (type_of c));
+  insist (element_type (type_of c) = i16_type);
 
   (* CHECK: const_structure{{.*.}}i16 1, i16 2, i32 3, i32 4
    *)
@@ -1484,6 +1492,7 @@ let test_writer () =
 (*===-- Driver ------------------------------------------------------------===*)
 
 let _ =
+  suite "modules"          test_modules;
   suite "contained types"  test_contained_types;
   suite "pointer types"    test_pointer_types;
   suite "conversion"       test_conversion;

diff  --git a/llvm/test/Bindings/OCaml/debuginfo.ml b/llvm/test/Bindings/OCaml/debuginfo.ml
index d9439c0e69f3e..d35b2b72f2296 100644
--- a/llvm/test/Bindings/OCaml/debuginfo.ml
+++ b/llvm/test/Bindings/OCaml/debuginfo.ml
@@ -290,7 +290,7 @@ let test_variables f dibuilder file_di fun_di =
   *)
   let arg0 = (Llvm.params f).(0) in
   let arg_var = Llvm_debuginfo.dibuild_create_parameter_variable dibuilder ~scope:fun_di
-    ~name:"my_arg" ~argno:0 ~file:file_di ~line:10 ~ty
+    ~name:"my_arg" ~argno:1 ~file:file_di ~line:10 ~ty
     ~always_preserve:false flags_zero
   in
   let argdi = Llvm_debuginfo.dibuild_insert_declare_before dibuilder ~storage:arg0


        


More information about the llvm-commits mailing list