Binding FFI and DSL

In Haskell LLVM bindings, I am trying to define a function with a variable number of arguments (actually I mean a constant number that is not known at compile time). I found this question and I am trying to follow the answer.

I do not want to fall back completely to using the FFI for generating LLVM, I want to use the DSL as much as I could and use FFI to only do the things I cannot do via the DSL.

I managed to define a type via functionType, I am still unable to add a function to a module created by calling defineModule. I also think that the next step is to add the basic blocks to the function via FFI.appendBasicBlock which I think is easy, but how do I get the arguments via FFI.getParam inside of a do block in the CodeGenFunction monad.


Solution 1:

If the size of the argument list isn't known 'till runtime, you would need to convert the function to something operating on a list anyway. Note that the (IORef [Word32]) type means that an IO action will read/write a (mutable) Word32 list during program execution. Haskell programs only have to say how to mutate/read/write the list -- hence the IO() monad.

There's an examples/List.hs file in the LLVM git project you referenced. It constructs an LLVM assembly routine "arrayLoop",

arrayLoop ::
   (Phi a, IsType b,
    Num i, IsConst i, IsInteger i, IsFirstClass i, CmpRet i Bool) =>
   Value i -> Value (Ptr b) -> a ->
   (Value (Ptr b) -> a -> CodeGenFunction r a) ->
   CodeGenFunction r a
arrayLoop len ptr start loopBody = do

that increments a pointer to a list of ints, p, and decrements the remaining length, i, in each invocation of the 'body' block. That block repeatedly calls 'loopBody' and stores the result in 'vars', which is eventually returned (untouched at zero) to 's' inside the mList function:

mList ::
   CodeGenModule (Function
      (StablePtr (IORef [Word32]) -> Word32 -> Ptr Word32 -> IO Int32))
mList =
   createFunction ExternalLinkage $ \ ref size ptr -> do
     next <- staticFunction nelem
     let _ = next :: Function (StablePtr (IORef [Word32]) -> IO Word32)
     s <- arrayLoop size ptr (valueOf 0) $ \ ptri y -> do
       flip store ptri =<< call next ref
       return y
     ret (s :: Value Int32)

All the extra stuff about nelem/NextListElement is used inside their example for 'loopBody,' which shifts the list once to the left. That repo also mentions a mailing list: [email protected].

GHC7 can compile using LLVM, but I guess this would not help in a Haskell program interpreting a language unless GHC also does JIT compilation - anyone know if this is the case?