Ragel primops and the GHC stack
Quite a few people have been asking about a follow up to an old post, specifically on dealing with passing return values on the stack from our C/LLVM based primop. I ended up with some unexpected free time today on the Caltrain waiting for a crushed tractor-trailer to get cleared off the tracks and dusted off a semi-functional feed parser in the style of Tsuru’s code sample. Sample data for is much easier to find than NASDAQ’s ITCH feed, I hope it’s also easier for you to get started with.
As with C, allocating from GHC’s stack is almost as simple as bumping a pointer. Unlike (most) C code, Haskell applications must explicitly check the stack to verify there is space available before performing the allocation. This is quite a bit more of a pain to deal with in C compared to C— or Haskell because stack allocations are done via tail-calls, we will ignore this detail for now and just assume the stack is large enough.
extern void
QuoteParser_run(
int64_t* restrict baseReg,
int64_t* restrict sp,
...)
{
// TODO: check to see if sp has room for 4 more values
// allocate space for 4 values on the stack
int64_t* nextSp = &sp[-4];
// assign some value to each unboxed primitive
sp[-1] = 0xfdfdfdfdfdfdfdfd;
sp[-2] = 0xabababababababab;
sp[-3] = 0x1717171717177171;
sp[-4] = 0x3535353535353535;
// pass the updated stack pointer along to a function
// expecting 10 integers to be returned from this primop:
// 6 in registers R1-R6 and 4 on the stack
nextFunction(baseReg, nextSp, ...);
}
The full code is available on Github for your forking pleasure.