Mon Aug 8 12:47:13 CEST 2011

LLVM Haskell bindings

It's probably more educational to look at the programmatic LLVM
bindings in Haskell instead of trial-and-error programming on the
textual syntax.  I might learn a thing or two about Haskell...

A starting point adapted from [1] and [2]:

import LLVM.Core
import LLVM.ExecutionEngine
import Data.Word

mAddMul :: CodeGenModule (Function (Word32 -> Word32 -> Word32 -> IO Word32))
mAddMul = 
  createFunction ExternalLinkage $ \ x y z -> do
    t <- add x y
    r <- mul t z
    ret r

main = do
  initializeNativeTarget  -- Otherwise: error: Interpreter not linked in.
  addMul <- simpleFunction mAddMul
  a <- addMul 2 3 4
  print a

To integrate this with Symantics, the point to focus on is the type:

*Main> :t add
  :: (ABinOp a b (v c), IsArithmetic c) =>
     a -> b -> CodeGenFunction r (v c)

How to make this fit?  It should be mostly the same as the SymAsm
code, which also uses a monad.  See [5]:

  data CodeGenFunction r a
  Monad (CodeGenFunction r)

The type parameters are fixed in the mAddMul function.

  ExternalLinkage :: Linkage

  createFunction :: (FunctionArgs f g r, IsFunction f) =>
                    Linkage -> g -> CodeGenModule (Function f)

With CodeGenFunction r = M, the type can be written simpler as:

   add :: (ABinOp a b (v c), IsArithmetic c) => a -> b -> M (v c)

What is `v'?  The do notation used above only implements the monadic
chaining, but how can (v c) be fed back into a second application,
i.e. the result of `add' is taken out of the monad, bound to `t' then
passed to `mul', so it looks like types will accumulate.  Taking out
the body gives:

  _AddMul x y z = do
    t <- add x y
    r <- mul t z
    ret r

  _AddMul ::
     (ABinOp a b (v c),
      ABinOp (v c) b1 (v1 c1),
      Ret (v1 c1) r,
      IsArithmetic c,
      IsArithmetic c1) =>
     a -> b -> b1 -> CodeGenFunction r Terminate

Hmm.. what does this (v c) and (v1 c1) business actually represent?

Wild guess: `v' stands for "value-ify".  It somehow guarantees that
there is a parameterized type involved?  Looking at the instance
declarations for ABinOp[6] all instances have Value or ConstValue type
constructor wrappers.  Is this `v' there to somehow type-pattern-match
on the type constructor?

Hmm.. trying to understand.  The type classes are used to express type
checking constraints.  It doesn't seem that they have instances.  I've
seen this pattern before..  See next post.

Anyways, moving forward to matching this monadic representation with
the Symantics instance.  The following factorization makes more sense,
and is still composable, by removing `ret'.

  _AddMul x y z = do
    t <- add x y
    mul t z
  mAddMul :: CodeGenModule (Function (Word32 -> Word32 -> Word32 -> IO Word32))
  mAddMul = createFunction ExternalLinkage $ \x y z -> do
    r <- _AddMul x y z
    ret r

Let's move to unary functions to make the composition simpler.

[1] http://augustss.blogspot.com/2009/01/llvm-llvm-low-level-virtual-machine-is.html
[2] https://github.com/bos/llvm/blob/master/examples/Arith.hs
[3] http://stackoverflow.com/questions/6050721/type-problem-with-codegenfunction-codegenmodule-with-llvm-haskell
[4] http://hackage.haskell.org/packages/archive/llvm/latest/doc/html/LLVM-Core.html
[5] http://hackage.haskell.org/packages/archive/llvm/latest/doc/html/LLVM-Core.html#t:CodeGenFunction
[6] http://hackage.haskell.org/packages/archive/llvm/latest/doc/html/LLVM-Core.html#t:ABinOp