Update FFI and use runFnX

Maybe this is the pattern we should encourage everywhere for FFIs, as now the implementations are safe from any further codegen changes too (unless we do something crazy).

Ideally we could be cleverer with `runFnX`, as none of the calls in here will be inlined as the application isn't complete, but if we could inline definitions like `readPrimType`, `readMaybeImpl'` where they just call `runFnX` then there's a better chance the full optimization will be applied later.