Index: bindings/ocaml/executionengine/executionengine_ocaml.c =================================================================== --- bindings/ocaml/executionengine/executionengine_ocaml.c +++ bindings/ocaml/executionengine/executionengine_ocaml.c @@ -120,3 +120,8 @@ LLVMExecutionEngineRef EE) { return caml_copy_int64((int64_t) LLVMGetPointerToGlobal(EE, Global)); } + +CAMLprim value llvm_ee_get_function_address(value Name, + LLVMExecutionEngineRef EE) { + return caml_copy_int64((int64_t) LLVMGetFunctionAddress(EE, String_val(Name))); +} Index: bindings/ocaml/executionengine/llvm_executionengine.ml =================================================================== --- bindings/ocaml/executionengine/llvm_executionengine.ml +++ bindings/ocaml/executionengine/llvm_executionengine.ml @@ -47,6 +47,8 @@ = "llvm_ee_add_global_mapping" external get_pointer_to_global_ : Llvm.llvalue -> llexecutionengine -> int64 = "llvm_ee_get_pointer_to_global" +external get_function_address_ : string -> llexecutionengine -> int64 + = "llvm_ee_get_function_address" let add_global_mapping llval ptr ee = add_global_mapping_ llval (Ctypes.raw_address_of_ptr (Ctypes.to_voidp ptr)) ee @@ -55,6 +57,13 @@ Ctypes.coerce (let open Ctypes in ptr void) typ (Ctypes.ptr_of_raw_address (get_pointer_to_global_ llval ee)) +let get_function_address name typ ee = + let ptr = get_function_address_ name ee in + if Int64.to_int ptr <> 0 then + Ctypes.coerce (let open Ctypes in ptr void) typ (Ctypes.ptr_of_raw_address ptr) + else + raise (Error ("Function " ^ name ^ " not found")) + (* The following are not bound. Patches are welcome. target_machine : llexecutionengine -> Llvm_target.TargetMachine.t *) Index: bindings/ocaml/executionengine/llvm_executionengine.mli =================================================================== --- bindings/ocaml/executionengine/llvm_executionengine.mli +++ bindings/ocaml/executionengine/llvm_executionengine.mli @@ -82,3 +82,10 @@ a function (e.g. [(int -> int) typ]) type for functions, and which will be live as long as [gv] and [ee] are. *) val get_pointer_to_global : Llvm.llvalue -> 'a Ctypes.typ -> llexecutionengine -> 'a + +(** [get_function_address name typ ee] returns the value of the global + variable [gv] in the execution engine [ee] as type [typ], which may + be a pointer type (e.g. [int ptr typ]) for global variables or + a function (e.g. [(int -> int) typ]) type for functions, and which + will be live as long as [gv] and [ee] are. *) +val get_function_address : string -> 'a Ctypes.typ -> llexecutionengine -> 'a Index: test/Bindings/OCaml/executionengine.ml =================================================================== --- test/Bindings/OCaml/executionengine.ml +++ test/Bindings/OCaml/executionengine.ml @@ -42,6 +42,22 @@ ignore (build_ret add b); fn +let define_ooo1 m = + let fn = define_function "ooo1" (function_type i32_type [| i32_type; + i32_type |]) m in + let b = builder_at_end (global_context ()) (entry_block fn) in + let add = build_add (param fn 0) (param fn 1) "sum" b in + ignore (build_ret add b); + fn + +let define_ooo2 m = + let fn = define_function "ooo2" (function_type i32_type [| i32_type; + i32_type |]) m in + let b = builder_at_end (global_context ()) (entry_block fn) in + let add = build_sub (param fn 0) (param fn 1) "diff" b in + ignore (build_ret add b); + fn + let test_executionengine () = let open Ctypes in @@ -78,6 +94,15 @@ let cplus = get_pointer_to_global plus cplusty ee in if 4l <> cplus 2l 2l then bomb "plus didn't work"; + (* define and execute out of order *) + ignore (define_ooo1 m); + dump_module m; + let cooo1 = get_function_address "ooo1" cplusty ee in + if 4l <> cooo1 2l 2l then bomb "ooo1 didn't work"; + ignore (define_ooo2 m); + let cooo2 = get_function_address "ooo2" cplusty ee in + if 0l <> cooo2 2l 2l then bomb "ooo2 didn't work"; + (* call getglobal *) (* let cgetglobalty = Foreign.funptr (void @-> returning int32_t) in let cgetglobal = get_pointer_to_global getglobal cgetglobalty ee in