The type you want is:
let sp = pointer_type i8_type in
var_arg_function_type sp [| sp; sp |]
Awesome stuff. Here is my most elegant Fibonacci example in OCaml so far:
open Llvm
let ( |> ) x f = f x
let int n = const_int i32_type n
let return b x = build_ret x b |> ignore
let build_fib m =
let ty = function_type i32_type [| i32_type |] in
let fibf = define_function "fib" ty m in
let bb = builder_at_end (entry_block fibf) in
let n = param fibf 0 in
let retbb = append_block "return" fibf in
let retb = builder_at_end retbb in
let recursebb = append_block "recurse" fibf in
let recurseb = builder_at_end recursebb in
let ( <= ) f g = build_icmp Icmp_sle f g "cond" bb in
build_cond_br (n <= int 2) retbb recursebb bb |> ignore;
return retb (int 1);
let apply f xs = build_call f xs "apply" recurseb in
let ( +: ) f g = build_add f g "add" recurseb in
let ( -: ) f g = build_sub f g "sub" recurseb in
return recurseb
(apply fibf [| n -: int 1 |] +: apply fibf [| n -: int 2 |]);
fibf
let main filename =
let m = create_module filename in
let string = pointer_type i8_type in
let printf =
declare_function "printf" (var_arg_function_type i32_type [|string|]) m
in
let main =
define_function "main" (function_type i32_type [| |]) m
>> entry_block
>> builder_at_end in
let str s = define_global "buf" (const_stringz s) m in
let int_spec = build_gep (str "%d\n") [| int 0; int 0 |] "int_spec" main in
let n = build_call (build_fib m) [| const_int i32_type 40 |] "" main in
let _ = build_call printf [| int_spec; n |] "" main in
build_ret (const_null i32_type) main |> ignore;
if not (Llvm_bitwriter.write_bitcode_file m filename) then exit 1;
dispose_module m
let () = match Sys.argv with
> [|_; filename|] -> main filename
> _ as a -> Printf.eprintf "Usage: %s <file>\n" a.(0)
as you can see it already uses some functional features. Next, I'll move the
hard-coded program into data and write a more generic compiler in it.
Looks really good though... 