Copyright | (c) Moritz Kiefer 2018 Stephen Diehl 2018 Benjamin Scarlett 2016 |
---|---|
Maintainer | moritz.kiefer@purelyfunctional.org |
Safe Haskell | None |
Language | Haskell2010 |
Synopsis
- module LLVM.Module
Documentation
module LLVM.Module
Overview of the llvm-hs
library ecosystem
The main two libraries in the llvm-hs
ecosystem are llvm-hs-pure
and llvm-hs
.
llvm-hs-pure
defines a pure Haskell representation of the LLVM AST. It has no dependency on the LLVM C/C++ libraries so even if you have trouble installing those or want to avoid that dependency, you should be able to use it. The documentation in LLVM.AST describes the different options for constructing the AST.llvm-hs
then builds uponllvm-hs-pure
and provides the actual FFI bindings to LLVM’s C++ libraries. Most importantly this includes bidirectional conversions from the Haskell representation of an LLVM module to the C++ representation and the other way around.
Once you have constructed the C++ representation, there are two main options:
In addition to llvm-hs
and llvm-hs-pure
, there are a couple of
other libraries that you be interested in:
- llvm-hs-pretty
a pure Haskell prettyprinter for the AST in
llvm-hs-pure
. This is useful if you just want to render your AST to LLVM’s textual IR format either for debugging purposes (llc
will usually give pretty good error messages for invalid IR) or because you prefer to call the LLVM CLI tools over the linking against the LLVM libraries. - llvm-hs-typed contains a
strongly-typed wrapper for the AST in
llvm-hs-pure
which makes it harder to accidentally construct invalid LLVM IR. - llvm-hs-quote contains a Haskell quasiquoter that can be used for splicing larger chunks of existing LLVM IR into your Haskell code.
Finally, there is a translation of
LLVM’s official Kaleidoscope tutorial to llvm-hs
and you can find
small, self-contained examples covering various parts of the API in
the llvm-hs-examples
repository.
Constructing the C++ representation of an LLVM module
Interacting with the LLVM libraries requires that you first construct
the C++ representation of an LLVM Module
.
The most common way of doing that is to first construct the Haskell
representation of an LLVM module using llvm-hs-pure
. You can then
use withModuleFromAST
to convert the Haskell AST to the C++
representation.
Alternatively, you can also construct a module from LLVM’s textual IR
or the binary bitcode format using withModuleFromLLVMAssembly
and
withModuleFromBitcode
.
Generating object code
Once you have constructed the C++ representation of an LLVM Module
,
you can generate an object file using moduleObject
which will give
you a ByteString
or write it to a file using
writeObjectToFile
. To construct the TargetMachine
for these
functions you can use withHostTargetMachine
if you want
to generate object code for the machine you are currently running on
or use withTargetMachine
and customize the target
machine based on your needs.
JIT compilation
In addition to generating object code, you can also JIT-compile LLVM
modules and call functions in the resulting Module
from Haskell.
LLVM has several JIT compilers but ORC JIT is the one that is actively
being developed and the one best supported by llvm-hs
.
To use ORC JIT you first have to create a
CompileLayer
. You can then use withModule
to add an LLVM module to the compile layer and finally use
findSymbol
to get the address of a
symbol in the module. In most cases, you want to lookup the address
of a function so you have to first convert the WordPtr
to a FunPtr
using wordPtrToPtr
and
castPtrToFunPtr
. Then you can use a foreign dynamic
import to construct a Haskell function which will call the function
located at the FunPtr
.