The ollvm Library

ollvm library offers an interface to manipulate LLVM IR in pure OCaml. LLVM already provides binding to its C API, but it still mainly imperative programming with heavy use of side effects.

ollvm is different in the way that you will manipulate OCaml structures (lists, records, variants, ...). An Ez interface is provided to make LLVM IR writing pleasant.

You may also want to use LLVM IR, but not the whole LLVM compiler infrastructure. ollvm allows you to stay independent from llvm library. You **may** want to bind you code to official bindings with the provided gateway, but you **do not have to**. Make your optimization passes, use your own back-end if you please.

Ressources

Ollvm on Github latest sources in the official GIT repository
Official LLVM website more details on LLVM and its itermediate representation specification.
Online documentation API documentation

Ez interface utilisation example

Input program:
open Ollvm.Ez.Value
open Ollvm.Ez.Instr
open Ollvm.Ez.Block
module M = Ollvm.Ez.Module
module T = Ollvm.Ez.Type
module P = Ollvm.Printer
let _ =
  (* module initialization *)
  let m = M.init
            "name"
            ("x86_64", "pc", "linux-gnu")
            "e-m:e-i64:64-f80:128-n8:16:32:64-S128" in
  (* variables declaration *)
  let (m, x0) =
    M.local m T.i1 "" in
  let (m, [x1; x2; x3; arg]) =
    M.locals m T.i32 [""; ""; ""; ""] in
  let (m, [entry_b; then_b; else_b]) =
    M.locals m T.label ["entry"; "then"; "else" ] in
  let (m, fact) = M.global m T.i32 "fact" in
  (* fact function definition *)
  let f = define fact [x4]
                 [ block entry_b [
                           x0 <-- eq x4 (i32 0) ;
                           br x0 then_b else_b ; ] ;
                   block then_b [
                           ret (i32 1) ; ] ;
                   block else_b [
                           x1 <-- sub x4 (i32 1) ;
                           x2 <-- call fact [x1] ;
                           x3 <-- mul x4 x2 ;
                           ret x3 ; ] ] in
  (* fact function registration in module *)
  let m = M.definition m f in
  P.modul (P.empty_env ()) Format.std_formatter m.m_module
Output:
; ModuleID = 'name'
target triple = "x86_64-pc-linux-gnu"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define i32 @fact(i32 %0) {
entry:
        %1 = icmp eq i32 %0, 0
        br i1 %1, label %then, label %else
then:
       ret i32 1
else:
       %2 = sub i32 %0, 1
       %3 = call i32 @fact(i32 %2)
       %4 = mul i32 %0, %3
       ret i32 %4
}

Install

Limitations

Ollvm is still work in progress.

Known bugs

Note that passing though Llvmgateway and printing with official binding results in a correct LLVM IR output.