[PATCH] [OCaml] Build a wrapper for LLVMGetFunctionAddress

Ramkumar Ramachandra artagnon at gmail.com
Mon Dec 22 10:20:43 PST 2014


Hi whitequark,

I've verified that the LLVMGetFunctionAddress is receiving the right
string, and calling down to the MCJIT implementation of
getFunctionAddress. However, getSymbolAddress does not seem to want to
cooperate with us, and returns 0 for a perfectly valid function. Why
LLVMGetFunctionAddress works via the C API, but not via the OCaml API
after having verified that the arguments are right stumps me.

Perhaps there is some name mangling going on when OCaml emits the IR? I
can't imagine why, but it's the only explanation I've been able to reach
so far.

http://reviews.llvm.org/D6761

Files:
  bindings/ocaml/executionengine/executionengine_ocaml.c
  bindings/ocaml/executionengine/llvm_executionengine.ml
  bindings/ocaml/executionengine/llvm_executionengine.mli
  test/Bindings/OCaml/executionengine.ml

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,14 +47,23 @@
   = "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
 
 let get_pointer_to_global llval typ ee =
   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

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D6761.17565.patch
Type: text/x-patch
Size: 4334 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141222/23f8a1f2/attachment.bin>


More information about the llvm-commits mailing list