LLVM bindings for Haskell

I’ve spent a bit of time over the past few days putting together some LLVM bindings for Haskell, based on Gordon Henriksen’s C bindings.

(If you don’t know what LLVM is, it’s a wonderful toybox of compiler components, from a complete toolchain supporting multiple architectures through a set of well-defined APIs and intermediate representation file formats that are designed for building interesting software.)

The C bindings are almost untyped, but the Haskell bindings re-add type safety to prevent runtime crashes and general badness.

Currently, almost the entire code generation system is implemented, with most LLVM data types supported (notably absent are structs). Also plugged in is JIT support, so you can generate code at runtime from Haskell and run it immediately. I’ve attached an example.

Please join in the hacking fun! Here’s the darcs repository:

darcs get http://darcs.serpentine.com/llvm

If you want a source tarball, fetch it from here for now. Hackage can’t yet host code that uses GHC 6.8.2’s language extension names.

There’s very light documentation at present, but it ought to be enough to get you going.

Here’s a quick example of some code “in the wild”:

buildFib :: T.Module -> IO (V.Function T.Int32 T.Int32)
buildFib m = do
  let one = C.const (1::Int32)
      two = C.const (2::Int32)
  -- the compiler infers the type for the function from our signature
  (fib, entry) <- U.defineFunction m "fib" (T.function undefined undefined)

  -- a builder is an instruction emitter
  bld <- B.createBuilder
  exit <- Core.appendBasicBlock fib "return"
  recurse <- Core.appendBasicBlock fib "recurse"
  let arg = V.params fib

  -- make the builder emit instructions in the "entry" basic block
  B.positionAtEnd bld entry
  -- if our argument is less than two, exit, else recurse
  test <- B.icmp bld "" I.IntSLE arg two
  B.condBr bld test exit recurse

  -- this is the exit basic block
  B.positionAtEnd bld exit
  B.ret bld one

  -- here's the recursion case
  B.positionAtEnd bld recurse
  x1 <- B.sub bld "" arg one
  fibx1 <- B.call bld "" fib x1

  x2 <- B.sub bld "" arg two
  fibx2 <- B.call bld "" fib x2

  B.add bld "" fibx1 fibx2 >>= B.ret bld

  -- hand the function definition back to our caller
  return fib

This emits a function definition that computes the Fibonacci series in LLVM assembly language. Run it under a JIT:

main :: IO ()
main = do
  args <- getArgs
  let args' = if null args then ["10"] else args

  m <- Core.createModule "fib"
  fib <- buildFib m
  -- print the function definition to the screen
  V.dumpValue fib

  -- create a JIT
  prov <- Core.createModuleProviderForExistingModule m
  ee <- EE.createExecutionEngine prov
  
  -- evaluate the JITted fib function over every command line argument
  forM_ args' $ \num -> do
    putStr $ "fib " ++ num ++ " = "
    parm <- EE.createGeneric (read num :: Int)
    gv <- EE.runFunction ee fib [parm]
    print (EE.fromGeneric gv :: Int)

Running this on the command line gives the following output:

$ ./Fibonacci 

define i32 @fib(i32) {
entry:
        icmp sle i32 %0, 2              ; <i1>:1 [#uses=1]
        br i1 %1, label %return, label %recurse

return:         ; preds = %entry
        ret i32 1

recurse:                ; preds = %entry
        sub i32 %0, 1           ; <i32>:2 [#uses=1]
        call i32 @fib( i32 %2 )         ; :3 [#uses=1]
        sub i32 %0, 2           ; <i32>:4 [#uses=1]
        call i32 @fib( i32 %4 )         ; <i32>:5 [#uses=1]
        add i32 %3, %5          ; <i32>:6 [#uses=1]
        ret i32 %6
}

fib 10 = 55
Posted in haskell, open source
11 comments on “LLVM bindings for Haskell
  1. Dennis says:

    Thanks for the module, Bryan! But it looks like you forgot some import statements.

    Fibonacci.hs:2:13:
    Not in scope: type constructor or class `T.Module’

    Fibonacci.hs:2:29:
    Not in scope: type constructor or class `V.Function’

    Fibonacci.hs:2:40:
    Not in scope: type constructor or class `T.Int32′

    Fibonacci.hs:2:48:
    Not in scope: type constructor or class `T.Int32′

    Fibonacci.hs:4:13: Not in scope: `C.const’

  2. Niraj says:

    Looks like more people retenpiag allegations, and not much to back it up with.Perhaps he hasn’t taken the time to understand Common Lisp and what it is and isn’t good for, perhaps he is interested in driving traffic to his site – where he (gasp) sells things, but nothing I’ve seen that he’s posted indicates to me that he is actually a spammer.That’s a pretty specific term with a pretty specific meaning, and it doesn’t match what I’ve seen of him in the last, oh, two days.He’s a smart person when it comes to some of this stuff, he’s getting at least some respect from other smart folks at MS, and he’s contributing in the LLVM community – and in a way that doesn’t appear to be a transparent play to drive traffic to his business either. He appears to be trying to build his business around something he’s interested in, which is pretty damn common in the tech industry.He also apparently has one or more people who follow him around the Internet and warn anyone he interacts with that he’s a spammer or troll. Thanks for the warning, but I’ll make up my own mind about him. I’ve dealt with both crazy and seedy people in the past and they have a certain “feel” to them that he doesn’t, at least from what I’ve seen so far. So I hope you understand if I reserve judgement, Mr. or Ms. Anonymous Internet Person, and base my reaction to Mr. Harrop on my direct observations of what he does where I can see it, rather than insinuations about how others feel about what he might or might not have done.

  3. Islam is a primitive communism, hence such closeness exists between leftists and islamists.Mohammed taught to kill a caravan owner, to enslave his women and children and steal his camels (class warfare anyone?)No wonder progressives and Muslim Brotherhood love each other.

  4. He had the lead in New Amsterdam, a sort of Law & Order: Highlander that ran for maybe half a season a few years ago. Other than that it’s mainly been bit parts or Scandinavian productions.

  5. oh gosh, I meant to comment and completely forgot; not that you needed me to, it looks like you got a working plan.My son was never a good sleeper, ever. He needs company to go to sleep – when he goes to bed at night and if he wakes in the middle of the night. We’ve just dealt with it in the best way we figured was good for him to feel secure. Let’s just say, there are nights that it’s a good thing he has a single bed.Oh, and he pees like an elephant, too. Saturates EVERYTHING! (I thought it was just the cloth diapers … maybe it’s a boy thing)

  6. For those wondering about changes other than security, the NTP button and omnibox shape are new. I do not know what else, but I like those changes.

  7. Yep, have a week off! I don’t think you need to do a long run every single weekend. Your body will appreciate a break. And you can go up to 18 or whatever the week after. Really glad to hear you’re back in the game!

  8. That’s an apt answer to an interesting question

  9. "Maybe if you could buy yourself a man and keep a chain around his neck, he'd stick around too."Go ahead and get jumped on. I'll stand right cher, popcorn and cell phone camera in hand.

  10. Discovered your content really exciting in truth. I truly loved browsing it and you also make very some excellent details. I will bookmark this web-site with the potential! Relly good write-up.

  11. http://www./ says:

    Maybe you remember where this was from, but someone asked Howard Hawks if a certain one of his films had the theme of “anti-fascism” (or something), and he replied…”to tell you the truth, I don’t even know what that means.” It was something along those lines, but that tickles me. Thanks for celebrating his birthday! I also love his nose. It just suits him.

4 Pings/Trackbacks for "LLVM bindings for Haskell"
  1. […] a comment » Brian O’Sullivan first announced the Haskell LLVM bindings on his […]

Leave a Reply

Your email address will not be published. Required fields are marked *

*