Almost inline ASM in haskell with foreign import prim
With help from Reid Barton in questions here and here I discovered it’s pretty easy to call assembly from GHC haskell with minimal overhead, so I cleaned up an example of this technique and posted it here:
https://github.com/jberryman/almost-inline-asm-haskell-example
This is especially useful if you want to return multiple values from a foreign procedure, where otherwise with the traditional FFI approach you would have to do some allocation and stuff the values into a struct or something. I find the above more understandable in any case.
Here’s an example of the dumped ASM from the Main
in the example above:
...
call newCAF
addq $8,%rsp
testq %rax,%rax
je _c73k
_c73j:
movq $stg_bh_upd_frame_info,-16(%rbp)
movq %rax,-8(%rbp)
movq $block_info,-24(%rbp)
movl $4,%edi
movl $3,%esi
movl $2,%r14d
movl $1,%ebx
addq $-24,%rbp
jmp sipRound_s_x3
_c73z:
movq $104,904(%r13)
movq $block_info,-32(%rbp)
movq %r14,-24(%rbp)
movq %rsi,-16(%rbp)
movq %rdi,-8(%rbp)
movq %rbx,(%rbp)
addq $-32,%rbp
...
You can see we just prepare argument registers, do whatever with the stack pointer, do a jump, and then push the return values onto the stack. For my purposes this was almost too much overhead to make this worthwhile (you can look at notes in the code).
I thought about sketching out a ghc proposal about a way to formalize this, maybe make it safer, and maybe somehow more efficient but I don’t have the time right now and don’t really have the expertise to know if this is even a good idea or how it could work.