summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Henriksen <gordonhenriksen@mac.com>2007-12-19 22:30:40 +0000
committerGordon Henriksen <gordonhenriksen@mac.com>2007-12-19 22:30:40 +0000
commitda1435f86ebc9886dd7704294e01d192d79e069c (patch)
tree6bfc10578fca9bc86214295b290bec5b0821be8f
parent696f768daf61044abff279b20326cf0138d02e1a (diff)
downloadllvm-da1435f86ebc9886dd7704294e01d192d79e069c.tar.gz
llvm-da1435f86ebc9886dd7704294e01d192d79e069c.tar.bz2
llvm-da1435f86ebc9886dd7704294e01d192d79e069c.tar.xz
Adding bindings for memory buffers and module providers. Switching
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
-rw-r--r--Xcode/LLVM.xcodeproj/project.pbxproj2
-rw-r--r--bindings/ocaml/analysis/analysis_ocaml.c2
-rw-r--r--bindings/ocaml/bitreader/bitreader_ocaml.c53
-rw-r--r--bindings/ocaml/bitreader/llvm_bitreader.ml12
-rw-r--r--bindings/ocaml/bitreader/llvm_bitreader.mli21
-rw-r--r--bindings/ocaml/llvm/llvm.ml25
-rw-r--r--bindings/ocaml/llvm/llvm.mli46
-rw-r--r--bindings/ocaml/llvm/llvm_ocaml.c61
-rw-r--r--include/llvm-c/Analysis.h6
-rw-r--r--include/llvm-c/BitReader.h27
-rw-r--r--include/llvm-c/Core.h112
-rw-r--r--lib/Analysis/Analysis.cpp4
-rw-r--r--lib/Bitcode/Reader/BitReader.cpp34
-rw-r--r--lib/VMCore/Core.cpp39
-rw-r--r--test/Bindings/Ocaml/bitreader.ml58
-rw-r--r--test/Bindings/Ocaml/vmcore.ml4
16 files changed, 351 insertions, 155 deletions
diff --git a/Xcode/LLVM.xcodeproj/project.pbxproj b/Xcode/LLVM.xcodeproj/project.pbxproj
index 3920a8c77b..8c7762e0cc 100644
--- a/Xcode/LLVM.xcodeproj/project.pbxproj
+++ b/Xcode/LLVM.xcodeproj/project.pbxproj
@@ -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>"; };
@@ -1241,6 +1242,7 @@
isa = PBXGroup;
children = (
9F7C2C4F0CB9496C00498408 /* analysis.ml */,
+ 9F6B2CC00D0F6E56000F00FD /* bitreader.ml */,
9F7C2C520CB9496C00498408 /* bitwriter.ml */,
9F7C2C5D0CB9496C00498408 /* vmcore.ml */,
);
diff --git a/bindings/ocaml/analysis/analysis_ocaml.c b/bindings/ocaml/analysis/analysis_ocaml.c
index c77fa73667..9286b4cf7b 100644
--- a/bindings/ocaml/analysis/analysis_ocaml.c
+++ b/bindings/ocaml/analysis/analysis_ocaml.c
@@ -37,7 +37,7 @@ CAMLprim value llvm_verify_module(LLVMModuleRef M) {
Store_field(Option, 0, String);
}
- LLVMDisposeVerifierMessage(Message);
+ LLVMDisposeMessage(Message);
CAMLreturn(Option);
}
diff --git a/bindings/ocaml/bitreader/bitreader_ocaml.c b/bindings/ocaml/bitreader/bitreader_ocaml.c
index 7088fa5a47..87477f6312 100644
--- a/bindings/ocaml/bitreader/bitreader_ocaml.c
+++ b/bindings/ocaml/bitreader/bitreader_ocaml.c
@@ -16,31 +16,46 @@
#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);
}
diff --git a/bindings/ocaml/bitreader/llvm_bitreader.ml b/bindings/ocaml/bitreader/llvm_bitreader.ml
index 39d0434df7..266ff153f3 100644
--- a/bindings/ocaml/bitreader/llvm_bitreader.ml
+++ b/bindings/ocaml/bitreader/llvm_bitreader.ml
@@ -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"
diff --git a/bindings/ocaml/bitreader/llvm_bitreader.mli b/bindings/ocaml/bitreader/llvm_bitreader.mli
index 37750bcdb3..bc5efc880f 100644
--- a/bindings/ocaml/bitreader/llvm_bitreader.mli
+++ b/bindings/ocaml/bitreader/llvm_bitreader.mli
@@ -13,13 +13,18 @@
*===----------------------------------------------------------------------===*)
-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"
diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml
index 5a5f4e7cfe..58d9d5013e 100644
--- a/bindings/ocaml/llvm/llvm.ml
+++ b/bindings/ocaml/llvm/llvm.ml
@@ -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 -------------------------------------------------------===*)
diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli
index 4646c57615..546ab4579f 100644
--- a/bindings/ocaml/llvm/llvm.mli
+++ b/bindings/ocaml/llvm/llvm.mli
@@ -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
diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c
index 43b6167bdc..5cd9526f56 100644
--- a/bindings/ocaml/llvm/llvm_ocaml.c
+++ b/bindings/ocaml/llvm/llvm_ocaml.c
@@ -20,8 +20,33 @@
#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;
+}
+
diff --git a/include/llvm-c/Analysis.h b/include/llvm-c/Analysis.h
index b57577b058..f93e18aeca 100644
--- a/include/llvm-c/Analysis.h
+++ b/include/llvm-c/Analysis.h
@@ -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);
diff --git a/include/llvm-c/BitReader.h b/include/llvm-c/BitReader.h
index ba77988a74..f821d68670 100644
--- a/include/llvm-c/BitReader.h
+++ b/include/llvm-c/BitReader.h
@@ -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
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index 4ed2bd0c60..e216572153 100644
--- a/include/llvm-c/Core.h
+++ b/include/llvm-c/Core.h
@@ -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) */
diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp
index 6403f2d7fa..685c754ff6 100644
--- a/lib/Analysis/Analysis.cpp
+++ b/lib/Analysis/Analysis.cpp
@@ -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));
diff --git a/lib/Bitcode/Reader/BitReader.cpp b/lib/Bitcode/Reader/BitReader.cpp
index c6600887bc..c7c38690c5 100644
--- a/lib/Bitcode/Reader/BitReader.cpp
+++ b/lib/Bitcode/Reader/BitReader.cpp
@@ -14,20 +14,33 @@
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);
-}
diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp
index 4c56e556eb..2b54fb3152 100644
--- a/lib/VMCore/Core.cpp
+++ b/lib/VMCore/Core.cpp
@@ -19,11 +19,20 @@
#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);
+}
diff --git a/test/Bindings/Ocaml/bitreader.ml b/test/Bindings/Ocaml/bitreader.ml
index 0bf8c00bc1..05bbd28e06 100644
--- a/test/Bindings/Ocaml/bitreader.ml
+++ b/test/Bindings/Ocaml/bitreader.ml
@@ -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
diff --git a/test/Bindings/Ocaml/vmcore.ml b/test/Bindings/Ocaml/vmcore.ml
index 65d8a316e9..04b80868c4 100644
--- a/test/Bindings/Ocaml/vmcore.ml
+++ b/test/Bindings/Ocaml/vmcore.ml
@@ -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 ------------------------------------------------------------===*)