OCaml allows C functions to be called from OCaml programs, as long as the programmer follows the instructions in the “Interfacing C with OCaml” chapter of the manual.
When following these instructions, a call to a C function is translated by the native compiler to:
movq ml_as_z_sub@GOTPCREL(%rip), %rax
call caml_c_call@PLT
(amd64 instruction set here, but looking at other architectures, the scheme seems to be rather uniform).
The function caml_c_call eventually does a computed jump call *%rax, but it does a lot of things before and after. From asmrun/amd64.S:
/* Call a C function from Caml */
FUNCTION(G(caml_c_call))
.Lcaml_c_call:
/* Record lowest stack address and return address */
popq %r12
STORE_VAR(%r12, caml_last_return_address)
STORE_VAR(%rsp, caml_bottom_of_stack)
/* Make the exception handler and alloc ptr available to the C code */
STORE_VAR(%r15, caml_young_ptr)
STORE_VAR(%r14, caml_exception_pointer)
/* Call the function (address in %rax) */
call *%rax
/* Reload alloc ptr */
LOAD_VAR(caml_young_ptr, %r15)
/* Return to caller */
pushq %r12
ret
When one wants to frequently execute a couple of instructions that neither allocate nor raise exceptions, the above is a little bit overkill.
Does anyone have any experience in calling a small assembly routine directly from OCaml, without going through the caml_c_call stub? This probably involves tricking the native compiler into thinking that it is calling an ML function, or modifying the compiler.
The question is in the context of the library Zarith, where small assembly bits of code could compute and return most results directly, without having to go through caml_c_call, and only jump to caml_c_code for the difficult arguments that require allocation or exceptions. See this file for examples of assembly bits that could be executed directly.
Maybe “noalloc” and “float” could be of some use?
PS some more related links.