-/*===-- llvm_ocaml.c - LLVM Ocaml Glue --------------------------*- C++ -*-===*\
+/*===-- llvm_ocaml.c - LLVM OCaml Glue --------------------------*- C++ -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
-|* This file glues LLVM's ocaml interface to its C interface. These functions *|
+|* This file glues LLVM's OCaml interface to its C interface. These functions *|
|* are by and large transparent wrappers to the corresponding C functions. *|
|* *|
|* Note that these functions intentionally take liberties with the CAMLparamX *|
|* *|
\*===----------------------------------------------------------------------===*/
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
#include "llvm-c/Core.h"
#include "caml/alloc.h"
#include "caml/custom.h"
#include "caml/memory.h"
#include "caml/fail.h"
#include "caml/callback.h"
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+value llvm_string_of_message(char* Message) {
+ value String = caml_copy_string(Message);
+ LLVMDisposeMessage(Message);
+
+ return String;
+}
+
+void llvm_raise(value Prototype, char *Message) {
+ CAMLparam1(Prototype);
+ caml_raise_with_arg(Prototype, llvm_string_of_message(Message));
+ CAMLnoreturn;
+}
+
+static value llvm_fatal_error_handler;
-/* Can't use the recommended caml_named_value mechanism for backwards
- compatibility reasons. This is largely equivalent. */
-static value llvm_ioerror_exn;
+static void llvm_fatal_error_trampoline(const char *Reason) {
+ callback(llvm_fatal_error_handler, caml_copy_string(Reason));
+}
-CAMLprim value llvm_register_core_exns(value IoError) {
- llvm_ioerror_exn = Field(IoError, 0);
- register_global_root(&llvm_ioerror_exn);
+CAMLprim value llvm_install_fatal_error_handler(value Handler) {
+ LLVMInstallFatalErrorHandler(llvm_fatal_error_trampoline);
+ llvm_fatal_error_handler = Handler;
+ caml_register_global_root(&llvm_fatal_error_handler);
return Val_unit;
}
-static void llvm_raise(value Prototype, char *Message) {
- CAMLparam1(Prototype);
- CAMLlocal1(CamlMessage);
-
- CamlMessage = copy_string(Message);
- LLVMDisposeMessage(Message);
-
- raise_with_arg(Prototype, CamlMessage);
- abort(); /* NOTREACHED */
-#ifdef CAMLnoreturn
- CAMLnoreturn; /* Silences warnings, but is missing in some versions. */
-#endif
+CAMLprim value llvm_reset_fatal_error_handler(value Unit) {
+ caml_remove_global_root(&llvm_fatal_error_handler);
+ LLVMResetFatalErrorHandler();
+ return Val_unit;
+}
+
+CAMLprim value llvm_enable_pretty_stacktrace(value Unit) {
+ LLVMEnablePrettyStackTrace();
+ return Val_unit;
+}
+
+CAMLprim value llvm_parse_command_line_options(value Overview, value Args) {
+ char *COverview;
+ if (Overview == Val_int(0)) {
+ COverview = NULL;
+ } else {
+ COverview = String_val(Field(Overview, 0));
+ }
+ LLVMParseCommandLineOptions(Wosize_val(Args), (const char* const*) Op_val(Args), COverview);
+ return Val_unit;
}
static value alloc_variant(int tag, void *Value) {
/* llmodule -> string */
CAMLprim value llvm_target_triple(LLVMModuleRef M) {
- return copy_string(LLVMGetTarget(M));
+ return caml_copy_string(LLVMGetTarget(M));
}
/* string -> llmodule -> unit */
/* llmodule -> string */
CAMLprim value llvm_data_layout(LLVMModuleRef M) {
- return copy_string(LLVMGetDataLayout(M));
+ return caml_copy_string(LLVMGetDataLayout(M));
}
/* string -> llmodule -> unit */
return Val_unit;
}
+/* string -> llmodule -> unit */
+CAMLprim value llvm_print_module(value Filename, LLVMModuleRef M) {
+ char* Message;
+
+ if(LLVMPrintModuleToFile(M, String_val(Filename), &Message))
+ llvm_raise(*caml_named_value("Llvm.IoError"), Message);
+
+ return Val_unit;
+}
+
+/* llmodule -> string */
+CAMLprim value llvm_string_of_llmodule(LLVMModuleRef M) {
+ CAMLparam0();
+ CAMLlocal1(ModuleStr);
+ char* ModuleCStr;
+
+ ModuleCStr = LLVMPrintModuleToString(M);
+ ModuleStr = caml_copy_string(ModuleCStr);
+ LLVMDisposeMessage(ModuleCStr);
+
+ CAMLreturn(ModuleStr);
+}
+
/* llmodule -> string -> unit */
CAMLprim value llvm_set_module_inline_asm(LLVMModuleRef M, value Asm) {
LLVMSetModuleInlineAsm(M, String_val(Asm));
return LLVMGetTypeContext(Ty);
}
+/* lltype -> unit */
+CAMLprim value llvm_dump_type(LLVMTypeRef Val) {
+ LLVMDumpType(Val);
+ return Val_unit;
+}
+
+/* lltype -> string */
+CAMLprim value llvm_string_of_lltype(LLVMTypeRef M) {
+ CAMLparam0();
+ CAMLlocal1(TypeStr);
+ char* TypeCStr;
+
+ TypeCStr = LLVMPrintTypeToString(M);
+ TypeStr = caml_copy_string(TypeCStr);
+ LLVMDisposeMessage(TypeCStr);
+
+ CAMLreturn(TypeStr);
+}
+
/*--... Operations on integer types ........................................--*/
/* llcontext -> lltype */
return LLVMPPCFP128TypeInContext(Context);
}
-/* llcontext -> lltype */
-CAMLprim LLVMTypeRef llvm_x86mmx_type(LLVMContextRef Context) {
- return LLVMX86MMXTypeInContext(Context);
-}
-
/*--... Operations on function types .......................................--*/
/* lltype -> lltype array -> lltype */
return LLVMLabelTypeInContext(Context);
}
+/* llcontext -> lltype */
+CAMLprim LLVMTypeRef llvm_x86_mmx_type(LLVMContextRef Context) {
+ return LLVMX86MMXTypeInContext(Context);
+}
+
CAMLprim value llvm_type_by_name(LLVMModuleRef M, value Name)
{
CAMLparam1(Name);
BlockAddress,
ConstantAggregateZero,
ConstantArray,
+ ConstantDataArray,
+ ConstantDataVector,
ConstantExpr,
ConstantFP,
ConstantInt,
DEFINE_CASE(Val, BlockAddress);
DEFINE_CASE(Val, ConstantAggregateZero);
DEFINE_CASE(Val, ConstantArray);
+ DEFINE_CASE(Val, ConstantDataArray);
+ DEFINE_CASE(Val, ConstantDataVector);
DEFINE_CASE(Val, ConstantExpr);
DEFINE_CASE(Val, ConstantFP);
DEFINE_CASE(Val, ConstantInt);
/* llvalue -> string */
CAMLprim value llvm_value_name(LLVMValueRef Val) {
- return copy_string(LLVMGetValueName(Val));
+ return caml_copy_string(LLVMGetValueName(Val));
}
/* string -> llvalue -> unit */
return Val_unit;
}
+/* llvalue -> string */
+CAMLprim value llvm_string_of_llvalue(LLVMValueRef M) {
+ CAMLparam0();
+ CAMLlocal1(ValueStr);
+ char* ValueCStr;
+
+ ValueCStr = LLVMPrintValueToString(M);
+ ValueStr = caml_copy_string(ValueCStr);
+ LLVMDisposeMessage(ValueCStr);
+
+ CAMLreturn(ValueStr);
+}
+
+/* llvalue -> llvalue -> unit */
+CAMLprim value llvm_replace_all_uses_with(LLVMValueRef OldVal,
+ LLVMValueRef NewVal) {
+ LLVMReplaceAllUsesWith(OldVal, NewVal);
+ return Val_unit;
+}
+
/*--... Operations on users ................................................--*/
/* llvalue -> int -> llvalue */
return LLVMGetOperand(V, Int_val(I));
}
+/* llvalue -> int -> lluse */
+CAMLprim LLVMUseRef llvm_operand_use(LLVMValueRef V, value I) {
+ return LLVMGetOperandUse(V, Int_val(I));
+}
+
/* llvalue -> int -> llvalue -> unit */
CAMLprim value llvm_set_operand(LLVMValueRef U, value I, LLVMValueRef V) {
LLVMSetOperand(U, Int_val(I), V);
CAMLreturn(Val_int(0));
}
-CAMLprim value llvm_get_namedmd(LLVMModuleRef M, value name)
+/* llmodule -> string -> llvalue array */
+CAMLprim value llvm_get_namedmd(LLVMModuleRef M, value Name)
{
- CAMLparam1(name);
+ CAMLparam1(Name);
CAMLlocal1(Nodes);
- Nodes = alloc(LLVMGetNamedMetadataNumOperands(M, String_val(name)), 0);
- LLVMGetNamedMetadataOperands(M, String_val(name), (LLVMValueRef *) Nodes);
+ Nodes = alloc(LLVMGetNamedMetadataNumOperands(M, String_val(Name)), 0);
+ LLVMGetNamedMetadataOperands(M, String_val(Name), (LLVMValueRef *) Nodes);
CAMLreturn(Nodes);
}
+
+/* llmodule -> string -> llvalue -> unit */
+CAMLprim value llvm_append_namedmd(LLVMModuleRef M, value Name, LLVMValueRef Val) {
+ LLVMAddNamedMetadataOperand(M, String_val(Name), Val);
+ return Val_unit;
+}
+
/*--... Operations on scalar constants .....................................--*/
/* lltype -> int -> llvalue */
CAMLprim LLVMValueRef llvm_const_int(LLVMTypeRef IntTy, value N) {
- return LLVMConstInt(IntTy, (long long) Int_val(N), 1);
+ return LLVMConstInt(IntTy, (long long) Long_val(N), 1);
}
/* lltype -> Int64.t -> bool -> llvalue */
return LLVMConstReal(RealTy, Double_val(N));
}
+
+/* llvalue -> float */
+CAMLprim value llvm_float_of_const(LLVMValueRef Const)
+{
+ CAMLparam0();
+ CAMLlocal1(Option);
+ LLVMBool LosesInfo;
+ double Result;
+
+ if (LLVMIsAConstantFP(Const)) {
+ Result = LLVMConstRealGetDouble(Const, &LosesInfo);
+ if (LosesInfo)
+ CAMLreturn(Val_int(0));
+
+ Option = alloc(1, 0);
+ Field(Option, 0) = caml_copy_double(Result);
+ CAMLreturn(Option);
+ }
+
+ CAMLreturn(Val_int(0));
+}
+
/* lltype -> string -> llvalue */
CAMLprim LLVMValueRef llvm_const_float_of_string(LLVMTypeRef RealTy, value S) {
return LLVMConstRealOfStringAndSize(RealTy, String_val(S),
Wosize_val(ElementVals));
}
+/* llvalue -> string option */
+CAMLprim value llvm_string_of_const(LLVMValueRef Const) {
+ const char *S;
+ size_t Len;
+ CAMLparam0();
+ CAMLlocal2(Option, Str);
+
+ if(LLVMIsAConstantDataSequential(Const) && LLVMIsConstantString(Const)) {
+ S = LLVMGetAsString(Const, &Len);
+ Str = caml_alloc_string(Len);
+ memcpy(String_val(Str), S, Len);
+
+ Option = alloc(1, 0);
+ Field(Option, 0) = Str;
+ CAMLreturn(Option);
+ } else {
+ CAMLreturn(Val_int(0));
+ }
+}
+
+/* llvalue -> int -> llvalue */
+CAMLprim LLVMValueRef llvm_const_element(LLVMValueRef Const, value N) {
+ return LLVMGetElementAsConstant(Const, Int_val(N));
+}
+
/*--... Constant expressions ...............................................--*/
/* Icmp.t -> llvalue -> llvalue -> llvalue */
Wosize_val(Indices));
}
+/* llvalue -> lltype -> is_signed:bool -> llvalue */
+CAMLprim LLVMValueRef llvm_const_intcast(LLVMValueRef CV, LLVMTypeRef T,
+ value IsSigned) {
+ return LLVMConstIntCast(CV, T, Bool_val(IsSigned));
+}
+
/* llvalue -> int array -> llvalue */
CAMLprim LLVMValueRef llvm_const_extractvalue(LLVMValueRef Aggregate,
value Indices) {
/* llvalue -> string */
CAMLprim value llvm_section(LLVMValueRef Global) {
- return copy_string(LLVMGetSection(Global));
+ return caml_copy_string(LLVMGetSection(Global));
}
/* string -> llvalue -> unit */
return Val_unit;
}
+/* llvalue -> DLLStorageClass.t */
+CAMLprim value llvm_dll_storage_class(LLVMValueRef Global) {
+ return Val_int(LLVMGetDLLStorageClass(Global));
+}
+
+/* DLLStorageClass.t -> llvalue -> unit */
+CAMLprim value llvm_set_dll_storage_class(value Viz, LLVMValueRef Global) {
+ LLVMSetDLLStorageClass(Global, Int_val(Viz));
+ return Val_unit;
+}
+
/* llvalue -> int */
CAMLprim value llvm_alignment(LLVMValueRef Global) {
return Val_int(LLVMGetAlignment(Global));
LLVMPointerType(Ty, Int_val(AddressSpace)));
return GlobalVar;
}
- return LLVMAddGlobal(M, Ty, String_val(Name));
+ return LLVMAddGlobalInAddressSpace(M, Ty, String_val(Name),
+ Int_val(AddressSpace));
}
/* string -> llmodule -> llvalue option */
return Val_unit;
}
+/* llvalue -> ThreadLocalMode.t */
+CAMLprim value llvm_thread_local_mode(LLVMValueRef GlobalVar) {
+ return Val_int(LLVMGetThreadLocalMode(GlobalVar));
+}
+
+/* ThreadLocalMode.t -> llvalue -> unit */
+CAMLprim value llvm_set_thread_local_mode(value ThreadLocalMode,
+ LLVMValueRef GlobalVar) {
+ LLVMSetThreadLocalMode(GlobalVar, Int_val(ThreadLocalMode));
+ return Val_unit;
+}
+
+/* llvalue -> bool */
+CAMLprim value llvm_is_externally_initialized(LLVMValueRef GlobalVar) {
+ return Val_bool(LLVMIsExternallyInitialized(GlobalVar));
+}
+
+/* bool -> llvalue -> unit */
+CAMLprim value llvm_set_externally_initialized(value IsExternallyInitialized,
+ LLVMValueRef GlobalVar) {
+ LLVMSetExternallyInitialized(GlobalVar, Bool_val(IsExternallyInitialized));
+ return Val_unit;
+}
+
/* llvalue -> bool */
CAMLprim value llvm_is_global_constant(LLVMValueRef GlobalVar) {
return Val_bool(LLVMIsGlobalConstant(GlobalVar));
const char *GC;
CAMLparam0();
CAMLlocal2(Name, Option);
-
+
if ((GC = LLVMGetGC(Fn))) {
- Name = copy_string(GC);
-
+ Name = caml_copy_string(GC);
+
Option = alloc(1, 0);
Field(Option, 0) = Name;
CAMLreturn(Option);
return Val_unit;
}
+/* llvalue -> string -> string -> unit */
+CAMLprim value llvm_add_target_dependent_function_attr(
+ LLVMValueRef Arg, value A, value V) {
+ LLVMAddTargetDependentFunctionAttr(Arg, String_val(A), String_val(V));
+ return Val_unit;
+}
+
/* llvalue -> int32 */
CAMLprim value llvm_function_attr(LLVMValueRef Fn)
{
return Val_unit;
}
+/* llbasicblock -> unit */
+CAMLprim value llvm_remove_block(LLVMBasicBlockRef BB) {
+ LLVMRemoveBasicBlockFromParent(BB);
+ return Val_unit;
+}
+
+/* llbasicblock -> llbasicblock -> unit */
+CAMLprim value llvm_move_block_before(LLVMBasicBlockRef Pos, LLVMBasicBlockRef BB) {
+ LLVMMoveBasicBlockBefore(BB, Pos);
+ return Val_unit;
+}
+
+/* llbasicblock -> llbasicblock -> unit */
+CAMLprim value llvm_move_block_after(LLVMBasicBlockRef Pos, LLVMBasicBlockRef BB) {
+ LLVMMoveBasicBlockAfter(BB, Pos);
+ return Val_unit;
+}
+
/* string -> llvalue -> llbasicblock */
CAMLprim LLVMBasicBlockRef llvm_append_block(LLVMContextRef Context, value Name,
LLVMValueRef Fn) {
return Val_int(o);
}
-/* llvalue -> ICmp.t */
+/* llvalue -> ICmp.t option */
CAMLprim value llvm_instr_icmp_predicate(LLVMValueRef Val) {
CAMLparam0();
int x = LLVMGetICmpPredicate(Val);
CAMLreturn(Val_int(0));
}
+/* llvalue -> FCmp.t option */
+CAMLprim value llvm_instr_fcmp_predicate(LLVMValueRef Val) {
+ CAMLparam0();
+ int x = LLVMGetFCmpPredicate(Val);
+ if (x) {
+ value Option = alloc(1, 0);
+ Field(Option, 0) = Val_int(x - LLVMRealPredicateFalse);
+ CAMLreturn(Option);
+ }
+ CAMLreturn(Val_int(0));
+}
+
+/* llvalue -> llvalue */
+CAMLprim LLVMValueRef llvm_instr_clone(LLVMValueRef Inst) {
+ if (!LLVMIsAInstruction(Inst))
+ failwith("Not an instruction");
+ return LLVMInstructionClone(Inst);
+}
+
/*--... Operations on call sites ...........................................--*/
return Val_unit;
}
+/*--... Operations on load/store instructions (only)........................--*/
+
+/* llvalue -> bool */
+CAMLprim value llvm_is_volatile(LLVMValueRef MemoryInst) {
+ return Val_bool(LLVMGetVolatile(MemoryInst));
+}
+
+/* bool -> llvalue -> unit */
+CAMLprim value llvm_set_volatile(value IsVolatile,
+ LLVMValueRef MemoryInst) {
+ LLVMSetVolatile(MemoryInst, Bool_val(IsVolatile));
+ return Val_unit;
+}
+
+
+/*--.. Operations on terminators ...........................................--*/
+
+/* llvalue -> int -> llbasicblock */
+CAMLprim LLVMBasicBlockRef llvm_successor(LLVMValueRef V, value I) {
+ return LLVMGetSuccessor(V, Int_val(I));
+}
+
+/* llvalue -> int -> llvalue -> unit */
+CAMLprim value llvm_set_successor(LLVMValueRef U, value I, LLVMBasicBlockRef B) {
+ LLVMSetSuccessor(U, Int_val(I), B);
+ return Val_unit;
+}
+
+/* llvalue -> int */
+CAMLprim value llvm_num_successors(LLVMValueRef V) {
+ return Val_int(LLVMGetNumSuccessors(V));
+}
+
+/*--.. Operations on branch ................................................--*/
+
+/* llvalue -> llvalue */
+CAMLprim LLVMValueRef llvm_condition(LLVMValueRef V) {
+ return LLVMGetCondition(V);
+}
+
+/* llvalue -> llvalue -> unit */
+CAMLprim value llvm_set_condition(LLVMValueRef B, LLVMValueRef C) {
+ LLVMSetCondition(B, C);
+ return Val_unit;
+}
+
+/* llvalue -> bool */
+CAMLprim value llvm_is_conditional(LLVMValueRef V) {
+ return Val_bool(LLVMIsConditional(V));
+}
+
/*--... Operations on phi nodes ............................................--*/
/* (llvalue * llbasicblock) -> llvalue -> unit */
unsigned I;
CAMLparam0();
CAMLlocal3(Hd, Tl, Tmp);
-
+
/* Build a tuple list of them. */
Tl = Val_int(0);
for (I = LLVMCountIncoming(PhiNode); I != 0; ) {
Hd = alloc(2, 0);
Store_field(Hd, 0, (value) LLVMGetIncomingValue(PhiNode, --I));
Store_field(Hd, 1, (value) LLVMGetIncomingBlock(PhiNode, I));
-
+
Tmp = alloc(2, 0);
Store_field(Tmp, 0, Hd);
Store_field(Tmp, 1, Tl);
Tl = Tmp;
}
-
+
CAMLreturn(Tl);
}
}
static struct custom_operations builder_ops = {
- (char *) "IRBuilder",
+ (char *) "Llvm.llbuilder",
llvm_finalize_builder,
custom_compare_default,
custom_hash_default,
custom_serialize_default,
- custom_deserialize_default
+ custom_deserialize_default,
+ custom_compare_ext_default
};
static value alloc_builder(LLVMBuilderRef B) {
CAMLprim LLVMBasicBlockRef llvm_insertion_block(value B) {
LLVMBasicBlockRef InsertBlock = LLVMGetInsertBlock(Builder_val(B));
if (!InsertBlock)
- raise_not_found();
+ caml_raise_not_found();
return InsertBlock;
}
return LLVMBuildStore(Builder_val(B), Value, Pointer);
}
+/* AtomicRMWBinOp.t -> llvalue -> llvalue -> AtomicOrdering.t ->
+ bool -> llbuilder -> llvalue */
+CAMLprim LLVMValueRef llvm_build_atomicrmw_native(value BinOp, LLVMValueRef Ptr,
+ LLVMValueRef 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));
+ LLVMSetValueName(Instr, String_val(Name));
+ return Instr;
+}
+
+CAMLprim 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]);
+}
+
/* llvalue -> llvalue array -> string -> llbuilder -> llvalue */
CAMLprim LLVMValueRef llvm_build_gep(LLVMValueRef Pointer, value Indices,
value Name, value B) {
CAMLprim LLVMValueRef 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);
PhiNode = LLVMBuildPhi(Builder_val(B), LLVMTypeOf(FirstValue),
LLVMAddIncoming(PhiNode, (LLVMValueRef*) &Field(Hd, 0),
(LLVMBasicBlockRef*) &Field(Hd, 1), 1);
}
-
+
return PhiNode;
}
LLVMValueRef Element,
LLVMValueRef Idx,
value Name, value B) {
- return LLVMBuildInsertElement(Builder_val(B), Vec, Element, Idx,
+ return LLVMBuildInsertElement(Builder_val(B), Vec, Element, Idx,
String_val(Name));
}
return LLVMBuildPtrDiff(Builder_val(B), LHS, RHS, String_val(Name));
}
-
/*===-- Memory buffers ----------------------------------------------------===*/
/* string -> llmemorybuffer
CAMLparam1(Path);
char *Message;
LLVMMemoryBufferRef MemBuf;
-
+
if (LLVMCreateMemoryBufferWithContentsOfFile(String_val(Path),
&MemBuf, &Message))
- llvm_raise(llvm_ioerror_exn, Message);
-
+ llvm_raise(*caml_named_value("Llvm.IoError"), Message);
+
CAMLreturn((value) MemBuf);
}
CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_stdin(value Unit) {
char *Message;
LLVMMemoryBufferRef MemBuf;
-
+
if (LLVMCreateMemoryBufferWithSTDIN(&MemBuf, &Message))
- llvm_raise(llvm_ioerror_exn, Message);
-
+ llvm_raise(*caml_named_value("Llvm.IoError"), Message);
+
+ return MemBuf;
+}
+
+/* ?name:string -> string -> llmemorybuffer */
+CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_string(value Name, value String) {
+ LLVMMemoryBufferRef MemBuf;
+ const char *NameCStr;
+
+ if(Name == Val_int(0))
+ NameCStr = "";
+ else
+ NameCStr = String_val(Field(Name, 0));
+
+ MemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy(
+ String_val(String), caml_string_length(String), NameCStr);
+
return MemBuf;
}
+/* llmemorybuffer -> string */
+CAMLprim value llvm_memorybuffer_as_string(LLVMMemoryBufferRef MemBuf) {
+ value String = caml_alloc_string(LLVMGetBufferSize(MemBuf));
+ memcpy(String_val(String), LLVMGetBufferStart(MemBuf),
+ LLVMGetBufferSize(MemBuf));
+
+ return String;
+}
+
/* llmemorybuffer -> unit */
CAMLprim value llvm_memorybuffer_dispose(LLVMMemoryBufferRef MemBuf) {
LLVMDisposeMemoryBuffer(MemBuf);