How to declare and use sprintf

So my Fib program is segfaulting and I'm not sure why. I think it might be
because my declaration and use of sprintf is wrong.

I notice llvm-gcc produces declarations containing "..." like:

  declare int %printf(sbyte*, ...)

but I'm not sure how to do this so I've used:

   let sprintf =
     declare_function "sprintf"
       (function_type (pointer_type i8_type) [| pointer_type i8_type;
            pointer_type i8_type;
            i32_type |]) m in

which gives:

  declare i8* @sprintf(i8*, i8*, i32)

What is the correct way to do this?

The type you want is:

let sp = pointer_type i8_type in
   var_arg_function_type sp [| sp; sp |]

— Gordon

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... :slight_smile:

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

Wow, it's “Lambda Calculus Gone Wild!”

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.

That'll be fun. Code generation in Ocaml is really elegant thanks to the matching and variant types. It would be nice to have that representation for the LLVM IR as well, but alas, it is not to be—no deconstruction for abstract types.

Looks really good though... :slight_smile:

Very cool.

— Gordon