The tutorial is Kaleidoscope on OCaml. It's not intended as a fully translation of LLVM Kaleidoscope tutorial, but a demonstration of basic LLVM APIs in OCaml.
The tutorial is tested with combinations of
- opam
llvm.16+nnpand OCaml 5.1.0 (should be released soon). - opam
llvm.14.0.6and OCaml 4.14.1.
In opam packages, llvm.16+nnp uses Opaque Pointers and llvm.14.0.6 uses Typed pointers. In official LLVM, Opaque Pointers are enabled by default from LLVM 15 and Typed pointers are not supported from LLVM 17. See LLVM Opaque Pointers for details.
Since the changes in LLVM is breakable but tiny in their APIs until now, for better or for worse, there is some duplicate code in the repo. Combination 1 uses bin/kaleidoscope.ml and lib. Combination 2 uses bin/kaleidoscope.ml_14.ml and lib-14. The rest are shared.
# Install the dependenciesopam install base ctypes-foreign llvm menhir ppx_jane
# Build the shared librarydune build stubs/libbindings.so
# Add the shared library to pathexport LD_LIBRARY_PATH=_build/default/stubs# with llvm 14.0.6dune exec bin/kaleidoscope_14.exe < example/mandel.kal# with llvm 16+nnp or beyonddune exec bin/kaleidoscope.exe < example/mandel.kalSee Makefile.
# with llvm 14.0.6make build-14make link-14make demo-14make run-14# with llvm 16+nnp or beyondmake buildmake linkmake demomake runCurrently, the difference between two version of code is tiny.
The result of diff bin/kaleidoscope.ml bin/kaleidoscope_14
7c7< Kaleidoscope_lib.Toplevel.main !dest---> Kaleidoscope_lib_14.Toplevel.main !destThe result of diff lib lib-14
diff '--color=auto' lib/codegen.ml lib-14/codegen.ml57c57< | Some v -> Llvm.build_load double_type v name builder)---> | Some v -> Llvm.build_load v name builder)96,99c96< let fnty =< Llvm.function_type double_type (Array.of_list [ double_type; double_type ])< in< Llvm.build_call fnty callee [| lhs_val; rhs_val |] "binop" builder)---> Llvm.build_call callee [| lhs_val; rhs_val |] "binop" builder)112,114c109< let arg_typs = Array.map args ~f:(Fn.const double_type) in< let fnty = Llvm.function_type double_type arg_typs in< Llvm.build_call fnty callee args "calltmp" builder---> Llvm.build_call callee args "calltmp" builder211c206< let cur_var = Llvm.build_load double_type alloca var_name builder in---> let cur_var = Llvm.build_load alloca var_name builder in237,238c232< let fnty = Llvm.function_type double_type (Array.of_list [ double_type ]) in< Llvm.build_call fnty callee [| operand |] "unop" builder---> Llvm.build_call callee [| operand |] "unop" builderdiff '--color=auto' lib/dune lib-14/dune2c2< (name kaleidoscope_lib)---> (name kaleidoscope_lib_14)Thank to @Kakadu's PR.
The project is originally forked from https://github.com/adamrk/llvm-ocaml-tutorial.
- Redo testing.
- Use vanilla library instead of
Base. - Update the missing part of the official Kaleidoscope tutorial.
- Rewrite the tutorial in OCaml.