I found two problems with your code:
Although your signature says that you pass two Word# arguments on the Haskell side, on the LLC side you have i64* %buffer and i64 %length (note type %buffer is a pointer type!).
There is another level of indirection in sp : sp points on the stack, and the top on the stack is a continuation pointer. It seems your code is trying to interpret the stack pointer as the function pointer itself.
I donβt know LLVM, I just compiled it by looking at the blog post that you linked, knowing the GHC and playing; therefore, I had to resort to viewing the output of clang , so there may be a more efficient way to handle # 2, but in any case, this is the version that works and implements the exchange of two 64-bit numbers:
define cc10 void @primllvm(i64* %baseReg, i64* %sp, i64* %hp, i64 %x, i64 %y, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64* %spLim, float %f1, float %f2, float %f3, float %f4, double %d1, double %d2) { %1 = getelementptr inbounds i64* %sp, i64 0 %2 = load i64* %1, align 8 %cont = inttoptr i64 %2 to void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64*, float, float, float, float, double, double)* tail call cc10 void %cont(i64* %baseReg, i64* %sp, i64* %hp, i64 %y, i64 %x, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64* %spLim, float %f1, float %f2, float %f3, float %f4, double %d1, double %d2) noreturn ret void }
Haskell code for testing:
{-# LANGUAGE GHCForeignImportPrim #-} {-# LANGUAGE MagicHash, UnboxedTuples, BangPatterns #-} {-# LANGUAGE ForeignFunctionInterface, UnliftedFFITypes #-} import GHC.Prim import GHC.Word foreign import prim "primllvm" primllvm :: Word# -> Word# -> (# Word#, Word# #) main :: IO () main = do let !(W# w1) = 12 !(W# w2) = 34 !(# w1', w2' #) = primllvm w1 w2 x = W# w1' y = W# w2' print (x, y)
Construction:
llc -filetype=obj -o Define.o Define.ll ghc --make Use.hs Define.o