Hi all,

LLVM.jl <https://github.com/maleadt/LLVM.jl> wraps the C API of the LLVM 
compiler toolkit. I've decided to wrap this API because is more stable than 
the C++ one, and easier to use (ie. with Cxx.jl currently being relatively 
hard to build).

It forms a relatively shallow wrapper around the API (where Jake Bolewski's 
LLVM.jl <https://github.com/jakebolewski/LLVM.jl> provides a much 
higher-level interface), only exposing it with somewhat more idiomatic 
Julia constructs. For example, reimplementing the example from here 
<https://pauladamsmith.com/blog/2015/01/how-to-get-started-with-llvm-c-api.html>
:

mod = LLVM.Module("my_module")

param_types = [LLVM.Int32Type(), LLVM.Int32Type()]
ret_type = LLVM.FunctionType(LLVM.Int32Type(), param_types)
sum = LLVM.Function(mod, "sum", ret_type)

Builder() do builder
    entry = BasicBlock(sum, "entry")
    position!(builder, entry)

    tmp = add!(builder, parameters(sum)[1], parameters(sum)[2], "tmp")
    ret!(builder, tmp)

    println(mod)
    verify(mod)
end

Interpreter(mod) do engine
    x, y = parse.([Int], ARGS[1:2])
    args = [GenericValue(LLVM.Int32Type(), x),
            GenericValue(LLVM.Int32Type(), y)]

    res = LLVM.run(engine, sum, args)
    println(convert(Int, res))

    dispose.(args)
    dispose(res)
end

For documentation, refer to the LLVM docs 
<http://llvm.org/docs/doxygen/html/group__LLVMC.html>. Even though it'll 
require users to have a look at code or tests, the wrapper is fairly 
shallow and I don't have the time to redocument the entire API. Note that a 
lot of API functions aren't covered yet 
<https://github.com/maleadt/LLVM.jl/blob/master/COVERAGE.md>, and our API 
might still change.

The package requires LLVM 3.9 but also supports 4.0 (for now), and works 
with Julia 0.5 and current nightly. Do note that we require a _full_ LLVM 
installation, ie. not only libLLVM.so but also llvm-config and its headers, 
to compile sources with additional C API functions. Both these requirements 
make it currently impossible to use this package on a binary Julia 
installation (shipping only libLLVM-3.7.so) without an external LLVM, but I 
hope to improve that situation in the future. For now, use this package on 
a Julia source installation compiled with LLVM_VER=3.9, or on a system with 
LLVM 3.9+ installed. If running Pkg.build with environment variable DEBUG=1, 
you'll get more information about the different installations it picked up 
and ended up selecting.

An interesting technical detail: the C API flattens the C++ type hierarchy, 
but exposes enums to differentiate between generically-typed pointers. We 
use that information to reconstruct the type hierarchy (only when 
necessary, sometimes the return subtype is known by definition), making the 
API somewhat more type-safe again.

Main user of this package is CUDAnative, to implement the PTX JIT in Julia 
<https://github.com/JuliaGPU/CUDAnative.jl/blob/5bb2f9e4e170394d6fdf6106b7a8cbba100a58cf/src/jit.jl#L39-L190>.
 
Next version will also support writing LLVM passes in Julia (sneak peek 
<https://github.com/maleadt/LLVM.jl/blob/14785411ad962ad16cf728622ac5932ac7e1deef/test/pass.jl#L15-L52>
).

Best,
Tim

Reply via email to