Adding bindings for memory buffers and module providers. Switching
authorGordon Henriksen <gordonhenriksen@mac.com>
Wed, 19 Dec 2007 22:30:40 +0000 (22:30 +0000)
committerGordon Henriksen <gordonhenriksen@mac.com>
Wed, 19 Dec 2007 22:30:40 +0000 (22:30 +0000)
to exceptions rather than variants for error handling in Ocaml.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45226 91177308-0d34-0410-b5e6-96231b3b80d8

16 files changed:
Xcode/LLVM.xcodeproj/project.pbxproj
bindings/ocaml/analysis/analysis_ocaml.c
bindings/ocaml/bitreader/bitreader_ocaml.c
bindings/ocaml/bitreader/llvm_bitreader.ml
bindings/ocaml/bitreader/llvm_bitreader.mli
bindings/ocaml/llvm/llvm.ml
bindings/ocaml/llvm/llvm.mli
bindings/ocaml/llvm/llvm_ocaml.c
include/llvm-c/Analysis.h
include/llvm-c/BitReader.h
include/llvm-c/Core.h
lib/Analysis/Analysis.cpp
lib/Bitcode/Reader/BitReader.cpp
lib/VMCore/Core.cpp
test/Bindings/Ocaml/bitreader.ml
test/Bindings/Ocaml/vmcore.ml

index 3920a8c..8c7762e 100644 (file)
@@ -98,6 +98,7 @@
                9F68EB130C77AD2C004AA152 /* BitcodeWriterPass.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BitcodeWriterPass.cpp; sourceTree = "<group>"; };
                9F68EB250C77AD2C004AA152 /* ValueEnumerator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ValueEnumerator.cpp; sourceTree = "<group>"; };
                9F68EB260C77AD2C004AA152 /* ValueEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ValueEnumerator.h; sourceTree = "<group>"; };
+               9F6B2CC00D0F6E56000F00FD /* bitreader.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bitreader.ml; sourceTree = "<group>"; };
                9F7793460C73BC2000551F9C /* CodeGenPrepare.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenPrepare.cpp; sourceTree = "<group>"; };
                9F7793470C73BC2000551F9C /* GVN.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GVN.cpp; sourceTree = "<group>"; };
                9F7793480C73BC2000551F9C /* GVNPRE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GVNPRE.cpp; sourceTree = "<group>"; };
                        isa = PBXGroup;
                        children = (
                                9F7C2C4F0CB9496C00498408 /* analysis.ml */,
+                               9F6B2CC00D0F6E56000F00FD /* bitreader.ml */,
                                9F7C2C520CB9496C00498408 /* bitwriter.ml */,
                                9F7C2C5D0CB9496C00498408 /* vmcore.ml */,
                        );
index c77fa73..9286b4c 100644 (file)
@@ -37,7 +37,7 @@ CAMLprim value llvm_verify_module(LLVMModuleRef M) {
     Store_field(Option, 0, String);
   }
   
-  LLVMDisposeVerifierMessage(Message);
+  LLVMDisposeMessage(Message);
   
   CAMLreturn(Option);
 }
index 7088fa5..87477f6 100644 (file)
 #include "caml/alloc.h"
 #include "caml/mlvalues.h"
 #include "caml/memory.h"
+#include <stdio.h>
+
+
+/* Can't use the recommended caml_named_value mechanism for backwards
+   compatibility reasons. This is largely equivalent. */
+static value llvm_bitreader_error_exn;
+
+CAMLprim value llvm_register_bitreader_exns(value Error) {
+  llvm_bitreader_error_exn = Field(Error, 0);
+  register_global_root(&llvm_bitreader_error_exn);
+  return Val_unit;
+}
+
+void llvm_raise(value Prototype, char *Message);
+
 
 /*===-- Modules -----------------------------------------------------------===*/
 
-/* string -> bitreader_result
+/* Llvm.llmemorybuffer -> Llvm.module */
+CAMLprim value llvm_get_module_provider(LLVMMemoryBufferRef MemBuf) {
+  CAMLparam0();
+  CAMLlocal2(Variant, MessageVal);
+  char *Message;
+  
+  LLVMModuleProviderRef MP;
+  if (LLVMGetBitcodeModuleProvider(MemBuf, &MP, &Message))
+    llvm_raise(llvm_bitreader_error_exn, Message);
+  
+  CAMLreturn((value) MemBuf);
+}
 
-   type bitreader_result =
-   | Bitreader_success of Llvm.llmodule
-   | Bitreader_failure of string
- */
-CAMLprim value llvm_read_bitcode_file(value Path) {
+/* Llvm.llmemorybuffer -> Llvm.llmodule */
+CAMLprim value llvm_parse_bitcode(LLVMMemoryBufferRef MemBuf) {
+  CAMLparam0();
+  CAMLlocal2(Variant, MessageVal);
   LLVMModuleRef M;
   char *Message;
-  CAMLparam1(Path);
-  CAMLlocal2(Variant, MessageVal);
   
-  if (LLVMReadBitcodeFromFile(String_val(Path), &M, &Message)) {
-    MessageVal = copy_string(Message);
-    LLVMDisposeBitcodeReaderMessage(Message);
-    
-    Variant = alloc(1, 1);
-    Field(Variant, 0) = MessageVal;
-  } else {
-    Variant = alloc(1, 0);
-    Field(Variant, 0) = Val_op(M);
-  }
+  if (LLVMParseBitcode(MemBuf, &M, &Message))
+    llvm_raise(llvm_bitreader_error_exn, Message);
   
-  CAMLreturn(Variant);
+  CAMLreturn((value) M);
 }
index 39d0434..266ff15 100644 (file)
@@ -8,10 +8,12 @@
  *===----------------------------------------------------------------------===*)
 
 
-type bitreader_result =
-| Bitreader_success of Llvm.llmodule
-| Bitreader_failure of string
+exception Error of string
 
+external register_exns : exn -> unit = "llvm_register_bitreader_exns"
+let _ = register_exns (Error "")
 
-external read_bitcode_file : string -> bitreader_result
-                           = "llvm_read_bitcode_file"
+external get_module_provider : Llvm.llmemorybuffer -> Llvm.llmoduleprovider
+                             = "llvm_get_module_provider"
+external parse_bitcode : Llvm.llmemorybuffer -> Llvm.llmodule
+                       = "llvm_parse_bitcode"
index 37750bc..bc5efc8 100644 (file)
  *===----------------------------------------------------------------------===*)
 
 
-type bitreader_result =
-| Bitreader_success of Llvm.llmodule
-| Bitreader_failure of string
+exception Error of string
 
+(** [read_bitcode_file path] reads the bitcode for a new module [m] from the
+    file at [path]. Returns [Success m] if successful, and [Failure msg]
+    otherwise, where [msg] is a description of the error encountered.
+    See the function [llvm::getBitcodeModuleProvider]. **)
+external get_module_provider : Llvm.llmemorybuffer -> Llvm.llmoduleprovider
+                             = "llvm_get_module_provider"
 
-(** [read_bitcode_file path] reads the bitcode for module [m] from the file at
-    [path]. Returns [Reader_success m] if successful, and [Reader_failure msg]
-    otherwise, where [msg] is a description of the error encountered. **)
-external read_bitcode_file : string -> bitreader_result
-                           = "llvm_read_bitcode_file"
+(** [parse_bitcode mb] parses the bitcode for a new module [m] from the memory
+    buffer [mb]. Returns [Success m] if successful, and [Failure msg] otherwise,
+    where [msg] is a description of the error encountered.
+    See the function [llvm::ParseBitcodeFile]. **)
+external parse_bitcode : Llvm.llmemorybuffer -> Llvm.llmodule
+                       = "llvm_parse_bitcode"
index 5a5f4e7..58d9d50 100644 (file)
@@ -15,6 +15,7 @@ type llvalue
 type llbasicblock
 type llbuilder
 type llmoduleprovider
+type llmemorybuffer
 
 type type_kind =
   Void_type
@@ -84,6 +85,11 @@ type real_predicate =
 | Fcmp_une
 | Fcmp_true
 
+exception IoError of string
+
+external register_exns : exn -> unit = "llvm_register_core_exns"
+let _ = register_exns (IoError "")
+
 
 (*===-- Modules -----------------------------------------------------------===*)
 
@@ -432,10 +438,21 @@ external build_shufflevector : llvalue -> llvalue -> llvalue -> string ->
 
 
 (*===-- Module providers --------------------------------------------------===*)
-external create_module_provider : llmodule -> llmoduleprovider
-                                = "LLVMCreateModuleProviderForExistingModule"
-external dispose_module_provider : llmoduleprovider -> unit
-                                 = "llvm_dispose_module_provider"
+
+module ModuleProvider = struct
+  external create : llmodule -> llmoduleprovider
+                  = "LLVMCreateModuleProviderForExistingModule"
+  external dispose : llmoduleprovider -> unit = "llvm_dispose_module_provider"
+end
+  
+
+(*===-- Memory buffers ----------------------------------------------------===*)
+
+module MemoryBuffer = struct
+  external of_file : string -> llmemorybuffer = "llvm_memorybuffer_of_file"
+  external of_stdin : unit -> llmemorybuffer = "llvm_memorybuffer_of_stdin"
+  external dispose : llmemorybuffer -> unit = "llvm_memorybuffer_dispose"
+end
 
 
 (*===-- Non-Externs -------------------------------------------------------===*)
index 4646c57..546ab45 100644 (file)
@@ -40,9 +40,14 @@ type llbasicblock
     class. **)
 type llbuilder
 
-(** Used to provide a module to JIT or interpreter. **)
+(** Used to provide a module to JIT or interpreter.
+    See the [llvm::ModuleProvider] class. **)
 type llmoduleprovider
 
+(** Used to efficiently handle large buffers of read-only binary data.
+    See the [llvm::MemoryBuffer] class. **)
+type llmemorybuffer
+
 (** The kind of an [lltype], the result of [classify_type ty]. See the 
     [llvm::Type::TypeID] enumeration. **)
 type type_kind =
@@ -129,6 +134,8 @@ type real_predicate =
 | Fcmp_une
 | Fcmp_true
 
+exception IoError of string
+
 
 (*===-- Modules -----------------------------------------------------------===*)
 
@@ -1235,13 +1242,30 @@ external build_shufflevector : llvalue -> llvalue -> llvalue -> string ->
 
 (*===-- Module providers --------------------------------------------------===*)
 
-(** [create_module_provider m] encapsulates [m] in a module provider and takes
-    ownership of the module. See the constructor 
-    [llvm::ExistingModuleProvider::ExistingModuleProvider]. **)
-external create_module_provider : llmodule -> llmoduleprovider
-                                = "LLVMCreateModuleProviderForExistingModule"
-
-(** [dispose_module_provider mp] destroys the module provider [mp] as well as
-    the contained module. **)
-external dispose_module_provider : llmoduleprovider -> unit
-                                 = "llvm_dispose_module_provider"
+module ModuleProvider : sig
+  (** [create_module_provider m] encapsulates [m] in a module provider and takes
+      ownership of the module. See the constructor 
+      [llvm::ExistingModuleProvider::ExistingModuleProvider]. **)
+  external create : llmodule -> llmoduleprovider
+                  = "LLVMCreateModuleProviderForExistingModule"
+
+  (** [dispose_module_provider mp] destroys the module provider [mp] as well as
+      the contained module. **)
+  external dispose : llmoduleprovider -> unit = "llvm_dispose_module_provider"
+end
+  
+
+(*===-- Memory buffers ----------------------------------------------------===*)
+
+module MemoryBuffer : sig
+  (** [of_file p] is the memory buffer containing the contents of the file at 
+      path [p]. If the file could not be read, then [IoError msg] is raised. **)
+  external of_file : string -> llmemorybuffer = "llvm_memorybuffer_of_file"
+  
+  (** [stdin ()] is the memory buffer containing the contents of standard input.
+      If standard input is empty, then [IoError msg] is raised. **)
+  external of_stdin : unit -> llmemorybuffer = "llvm_memorybuffer_of_stdin"
+  
+  (** Disposes of a memory buffer. **)
+  external dispose : llmemorybuffer -> unit = "llvm_memorybuffer_dispose"
+end
index 43b6167..5cd9526 100644 (file)
 #include "caml/custom.h"
 #include "caml/mlvalues.h"
 #include "caml/memory.h"
+#include "caml/fail.h"
+#include "caml/callback.h"
 #include "llvm/Config/config.h"
 #include <assert.h>
+#include <stdlib.h>
+
+
+/* Can't use the recommended caml_named_value mechanism for backwards
+   compatibility reasons. This is largely equivalent. */
+static value llvm_ioerror_exn;
+
+CAMLprim value llvm_register_core_exns(value IoError) {
+  llvm_ioerror_exn = Field(IoError, 0);
+  register_global_root(&llvm_ioerror_exn);
+  return Val_unit;
+}
+
+void llvm_raise(value Prototype, char *Message) {
+  CAMLparam1(Prototype);
+  CAMLlocal1(CamlMessage);
+  
+  CamlMessage = copy_string(Message);
+  LLVMDisposeMessage(Message);
+  
+  raise_with_arg(Prototype, CamlMessage);
+  CAMLnoreturn;
+}
 
 
 /*===-- Modules -----------------------------------------------------------===*/
@@ -1071,3 +1096,39 @@ CAMLprim value llvm_dispose_module_provider(LLVMModuleProviderRef MP) {
   LLVMDisposeModuleProvider(MP);
   return Val_unit;
 }
+
+
+/*===-- Memory buffers ----------------------------------------------------===*/
+
+/* string -> llmemorybuffer
+   raises IoError msg on error */
+CAMLprim value llvm_memorybuffer_of_file(value Path) {
+  CAMLparam1(Path);
+  char *Message;
+  LLVMMemoryBufferRef MemBuf;
+  
+  if (LLVMCreateMemoryBufferWithContentsOfFile(String_val(Path),
+                                               &MemBuf, &Message))
+    llvm_raise(llvm_ioerror_exn, Message);
+  
+  CAMLreturn((value) MemBuf);
+}
+
+/* unit -> llmemorybuffer
+   raises IoError msg on error */
+CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_stdin(value Unit) {
+  char *Message;
+  LLVMMemoryBufferRef MemBuf;
+  
+  if (LLVMCreateMemoryBufferWithSTDIN(&MemBuf, &Message))
+    llvm_raise(llvm_ioerror_exn, Message);
+  
+  return MemBuf;
+}
+
+/* llmemorybuffer -> unit */
+CAMLprim value llvm_memorybuffer_dispose(LLVMMemoryBufferRef MemBuf) {
+  LLVMDisposeMemoryBuffer(MemBuf);
+  return Val_unit;
+}
+
index b57577b..f93e18a 100644 (file)
@@ -34,13 +34,11 @@ typedef enum {
 
 
 /* Verifies that a module is valid, taking the specified action if not.
-   Optionally returns a human-readable description of any invalid constructs. */
+   Optionally returns a human-readable description of any invalid constructs.
+   OutMessage must be disposed with LLVMDisposeMessage. */
 int LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action,
                      char **OutMessage);
 
-/* Disposes of the message allocated by the verifier, if any. */ 
-void LLVMDisposeVerifierMessage(char *Message);
-
 /* Verifies that a single function is valid, taking the specified action. Useful
    for debugging. */
 int LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action);
index ba77988..f821d68 100644 (file)
@@ -26,21 +26,18 @@ extern "C" {
 #endif
 
 
-/* Reads a module from the specified path, returning a reference to the module
-   via the OutModule parameter. Returns 0 on success. Optionally returns a
-   human-readable error message. */ 
-int LLVMReadBitcodeFromFile(const char *Path, LLVMModuleRef *OutModule,
-                            char **OutMessage);
-
-/* Reads a module from the specified path, returning a reference to a lazy
-   module provider via the OutModule parameter. Returns 0 on success. Optionally
-   returns a human-readable error message. */ 
-int LLVMCreateModuleProviderFromFile(const char *Path,
-                                     LLVMModuleProviderRef *OutMP,
-                                     char **OutMessage);
-
-/* Disposes of the message allocated by the bitcode reader, if any. */ 
-void LLVMDisposeBitcodeReaderMessage(char *Message);
+/* Builds a module from the bitcode in the specified memory buffer, returning a
+   reference to the module via the OutModule parameter. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */ 
+int LLVMParseBitcode(LLVMMemoryBufferRef MemBuf,
+                     LLVMModuleRef *OutModule, char **OutMessage);
+
+/* Reads a module from the specified path, returning via the OutMP parameter
+   a module provider which performs lazy deserialization. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */ 
+int LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf,
+                                 LLVMModuleProviderRef *OutMP,
+                                 char **OutMessage);
 
 
 #ifdef __cplusplus
index 4ed2bd0..e216572 100644 (file)
@@ -51,8 +51,17 @@ typedef struct LLVMOpaqueTypeHandle *LLVMTypeHandleRef;
 typedef struct LLVMOpaqueValue *LLVMValueRef;
 typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef;
 typedef struct LLVMOpaqueBuilder *LLVMBuilderRef;
+
+/* Used to provide a module to JIT or interpreter.
+ * See the llvm::ModuleProvider class.
+ */
 typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef;
 
+/* Used to provide a module to JIT or interpreter.
+ * See the llvm::MemoryBuffer class.
+ */
+typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef;
+
 typedef enum {
   LLVMVoidTypeKind,        /* type with no size */
   LLVMFloatTypeKind,       /* 32 bit floating point type */
@@ -129,6 +138,11 @@ typedef enum {
 } LLVMRealPredicate;
 
 
+/*===-- Error handling ----------------------------------------------------===*/
+
+void LLVMDisposeMessage(char *Message);
+
+
 /*===-- Modules -----------------------------------------------------------===*/
 
 /* Create and destroy modules. */ 
@@ -491,6 +505,7 @@ LLVMValueRef LLVMBuildShuffleVector(LLVMBuilderRef, LLVMValueRef V1,
                                     LLVMValueRef V2, LLVMValueRef Mask,
                                     const char *Name);
 
+
 /*===-- Module providers --------------------------------------------------===*/
 
 /* Encapsulates the module M in a module provider, taking ownership of the
@@ -505,28 +520,45 @@ LLVMCreateModuleProviderForExistingModule(LLVMModuleRef M);
  */
 void LLVMDisposeModuleProvider(LLVMModuleProviderRef MP);
 
+
+/*===-- Memory buffers ----------------------------------------------------===*/
+
+int LLVMCreateMemoryBufferWithContentsOfFile(const char *Path,
+                                             LLVMMemoryBufferRef *OutMemBuf,
+                                             char **OutMessage);
+int LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf,
+                                    char **OutMessage);
+void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf);
+
 #ifdef __cplusplus
 }
 
 namespace llvm {
   class ModuleProvider;
+  class MemoryBuffer;
   
-  /* Opaque module conversions
-   */ 
-  inline Module *unwrap(LLVMModuleRef M) {
-    return reinterpret_cast<Module*>(M);
-  }
+  #define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref)   \
+    inline ty *unwrap(ref P) {                          \
+      return reinterpret_cast<ty*>(P);                  \
+    }                                                   \
+                                                        \
+    inline ref wrap(const ty *P) {                      \
+      return reinterpret_cast<ref>(const_cast<ty*>(P)); \
+    }
   
-  inline LLVMModuleRef wrap(Module *M) {
-    return reinterpret_cast<LLVMModuleRef>(M);
-  }
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Type,           LLVMTypeRef          )
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Value,          LLVMValueRef         )
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module,         LLVMModuleRef        )
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock,     LLVMBasicBlockRef    )
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMBuilder,    LLVMBuilderRef       )
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PATypeHolder,   LLVMTypeHandleRef    )
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ModuleProvider, LLVMModuleProviderRef)
+  DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer,   LLVMMemoryBufferRef  )
   
-  /* Opaque type conversions
-   */ 
-  inline Type *unwrap(LLVMTypeRef Ty) {
-    return reinterpret_cast<Type*>(Ty);
-  }
+  #undef DEFINE_SIMPLE_CONVERSION_FUNCTIONS
   
+  /* Specialized opaque type conversions.
+   */
   template<typename T>
   inline T *unwrap(LLVMTypeRef Ty) {
     return cast<T>(unwrap(Ty));
@@ -536,20 +568,12 @@ namespace llvm {
     return reinterpret_cast<Type**>(Tys);
   }
   
-  inline LLVMTypeRef wrap(const Type *Ty) {
-    return reinterpret_cast<LLVMTypeRef>(const_cast<Type*>(Ty));
-  }
-  
   inline LLVMTypeRef *wrap(const Type **Tys) {
     return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys));
   }
   
-  /* Opaque value conversions
+  /* Specialized opaque value conversions.
    */ 
-  inline Value *unwrap(LLVMValueRef Val) {
-    return reinterpret_cast<Value*>(Val);
-  }
-  
   template<typename T>
   inline T *unwrap(LLVMValueRef Val) {
     return cast<T>(unwrap(Val));
@@ -568,53 +592,9 @@ namespace llvm {
     return reinterpret_cast<T**>(Vals);
   }
   
-  inline LLVMValueRef wrap(const Value *Val) {
-    return reinterpret_cast<LLVMValueRef>(const_cast<Value*>(Val));
-  }
-  
   inline LLVMValueRef *wrap(const Value **Vals) {
     return reinterpret_cast<LLVMValueRef*>(const_cast<Value**>(Vals));
   }
-  
-  /* Basic block conversions
-   */ 
-  inline BasicBlock *unwrap(LLVMBasicBlockRef BBRef) {
-    return reinterpret_cast<BasicBlock*>(BBRef);
-  }
-  
-  inline LLVMBasicBlockRef wrap(const BasicBlock *BB) {
-    return reinterpret_cast<LLVMBasicBlockRef>(const_cast<BasicBlock*>(BB));
-  }
-  
-  /* Opaque builder conversions.
-   */ 
-  inline LLVMBuilder *unwrap(LLVMBuilderRef B) {
-    return reinterpret_cast<LLVMBuilder*>(B);
-  }
-  
-  inline LLVMBuilderRef wrap(LLVMBuilder *B) {
-    return reinterpret_cast<LLVMBuilderRef>(B);
-  }
-  
-  /* Opaque type handle conversions.
-   */ 
-  inline PATypeHolder *unwrap(LLVMTypeHandleRef B) {
-    return reinterpret_cast<PATypeHolder*>(B);
-  }
-  
-  inline LLVMTypeHandleRef wrap(PATypeHolder *B) {
-    return reinterpret_cast<LLVMTypeHandleRef>(B);
-  }
-  
-  /* Opaque module provider conversions.
-   */ 
-  inline ModuleProvider *unwrap(LLVMModuleProviderRef P) {
-    return reinterpret_cast<ModuleProvider*>(P);
-  }
-  
-  inline LLVMModuleProviderRef wrap(ModuleProvider *P) {
-    return reinterpret_cast<LLVMModuleProviderRef>(P);
-  }
 }
 
 #endif /* !defined(__cplusplus) */
index 6403f2d..685c754 100644 (file)
@@ -27,10 +27,6 @@ int LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action,
   return Result;
 }
 
-void LLVMDisposeVerifierMessage(char *Message) {
-  free(Message);
-}
-
 int LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action) {
   return verifyFunction(*unwrap<Function>(Fn),
                         static_cast<VerifierFailureAction>(Action));
index c660088..c7c3869 100644 (file)
 
 using namespace llvm;
 
-
-int LLVMReadBitcodeFromFile(const char *Path, LLVMModuleRef *OutModule,
-                            char **OutMessage) {
+/* Builds a module from the bitcode in the specified memory buffer, returning a
+   reference to the module via the OutModule parameter. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */ 
+int LLVMParseBitcode(LLVMMemoryBufferRef MemBuf,
+                     LLVMModuleRef *OutModule, char **OutMessage) {
   std::string Message;
   
-  MemoryBuffer *buf = MemoryBuffer::getFile(Path, strlen(Path), &Message);
-  if (!buf) {
-    if (!OutMessage)
+  *OutModule = wrap(ParseBitcodeFile(unwrap(MemBuf), &Message));
+  if (!*OutModule) {
+    if (OutMessage)
       *OutMessage = strdup(Message.c_str());
     return 1;
   }
   
-  *OutModule = wrap(ParseBitcodeFile(buf, &Message));
-  if (!*OutModule) {
+  return 0;
+}
+
+/* Reads a module from the specified path, returning via the OutModule parameter
+   a module provider which performs lazy deserialization. Returns 0 on success.
+   Optionally returns a human-readable error message via OutMessage. */ 
+int LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf,
+                                 LLVMModuleProviderRef *OutMP,
+                                 char **OutMessage) {
+  std::string Message;
+  
+  *OutMP = wrap(getBitcodeModuleProvider(unwrap(MemBuf), &Message));
+  if (!*OutMP) {
     if (OutMessage)
       *OutMessage = strdup(Message.c_str());
     return 1;
@@ -35,8 +48,3 @@ int LLVMReadBitcodeFromFile(const char *Path, LLVMModuleRef *OutModule,
   
   return 0;
 }
-
-void LLVMDisposeBitcodeReaderMessage(char *Message) {
-  if (Message)
-    free(Message);
-}
index 4c56e55..2b54fb3 100644 (file)
 #include "llvm/GlobalVariable.h"
 #include "llvm/TypeSymbolTable.h"
 #include "llvm/ModuleProvider.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include <cassert>
+#include <cstdlib>
 
 using namespace llvm;
 
 
+/*===-- Error handling ----------------------------------------------------===*/
+
+void LLVMDisposeMessage(char *Message) {
+  free(Message);
+}
+
+
 /*===-- Operations on modules ---------------------------------------------===*/
 
 LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID) {
@@ -1048,3 +1057,33 @@ void LLVMDisposeModuleProvider(LLVMModuleProviderRef MP) {
   delete unwrap(MP);
 }
 
+
+/*===-- Memory buffers ----------------------------------------------------===*/
+
+int LLVMCreateMemoryBufferWithContentsOfFile(const char *Path,
+                                             LLVMMemoryBufferRef *OutMemBuf,
+                                             char **OutMessage) {
+  std::string Error;
+  if (MemoryBuffer *MB = MemoryBuffer::getFile(Path, strlen(Path), &Error)) {
+    *OutMemBuf = wrap(MB);
+    return 0;
+  }
+  
+  *OutMessage = strdup(Error.c_str());
+  return 1;
+}
+
+int LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf,
+                                    char **OutMessage) {
+  if (MemoryBuffer *MB = MemoryBuffer::getSTDIN()) {
+    *OutMemBuf = wrap(MB);
+    return 0;
+  }
+  
+  *OutMessage = strdup("stdin is empty.");
+  return 1;
+}
+
+void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf) {
+  delete unwrap(MemBuf);
+}
index 0bf8c00..05bbd28 100644 (file)
@@ -18,6 +18,58 @@ let _ =
   
   Llvm.dispose_module m;
   
-  test (match Llvm_bitreader.read_bitcode_file fn with
-  | Llvm_bitreader.Bitreader_success m -> Llvm.dispose_module m; true
-  | Llvm_bitreader.Bitreader_failure _ -> false)
+  (* parse_bitcode *)
+  begin
+    let mb = Llvm.MemoryBuffer.of_file fn in
+    begin try
+      let m = Llvm_bitreader.parse_bitcode mb in
+      Llvm.dispose_module m
+    with x ->
+      Llvm.MemoryBuffer.dispose;
+      raise x
+    end
+  end;
+  
+  (* MemoryBuffer.of_file *)
+  test begin try
+    let mb = Llvm.MemoryBuffer.of_file (fn ^ ".bogus") in
+    Llvm.MemoryBuffer.dispose mb;
+    false
+  with Llvm.IoError _ ->
+    true
+  end;
+  
+  (* get_module_provider *)
+  begin
+    let mb = Llvm.MemoryBuffer.of_file fn in
+    let mp = begin try
+      Llvm_bitreader.get_module_provider mb
+    with x ->
+      Llvm.MemoryBuffer.dispose mb;
+      raise x
+    end in
+    Llvm.ModuleProvider.dispose mp
+  end;
+  
+  (* corrupt the bitcode *)
+  let fn = fn ^ ".txt" in
+  begin let oc = open_out fn in
+    output_string oc "not a bitcode file\n";
+    close_out oc
+  end;
+  
+  (* test get_module_provider exceptions *)
+  test begin
+    try
+      let mb = Llvm.MemoryBuffer.of_file fn in
+      let mp = begin try
+        Llvm_bitreader.get_module_provider mb
+      with x ->
+        Llvm.MemoryBuffer.dispose mb;
+        raise x
+      end in
+      Llvm.ModuleProvider.dispose mp;
+      false
+    with Llvm_bitreader.Error _ ->
+      true
+  end
index 65d8a31..04b8086 100644 (file)
@@ -805,8 +805,8 @@ let test_builder () =
 
 let test_module_provider () =
   let m = create_module "test" in
-  let mp = create_module_provider m in
-  dispose_module_provider mp
+  let mp = ModuleProvider.create m in
+  ModuleProvider.dispose mp
 
 
 (*===-- Writer ------------------------------------------------------------===*)