The Crystal Programming Language Forum

Obtain the address of a function

Working on GitHub - stakach/crystal-kernel: yet another crystal kernel, inspired by ffwff/lilith and it’s coming along quite well however struggling to get the memory address of a function.

When setting up the interrupt table using the code from lilith the lilith implementation does:
(->kernel_cpu_exception0).pointer.address

However in assembly the ->kernel_cpu_exception0 effectively creates a wrapper function

push rax
call kernel_cpu_exception0
pop rax
ret

So we actually have the address of this wrapper function instead of the kernel_cpu_exception0 function. The address of the actual function is important to handle interrupts as we need to preserve CPU state before calling any additional functions (stack needs to be clean too)

I tried doing

fun kernel_cpu_exception0()
  # ...
end

lib Kernel
  $kernel_cpu_exception0 : Int64
end

pointerof(Kernel.kernel_cpu_exception0).address

However it looks like the compiler tries to avoid having the symbols clash and mangles the name? so that doesn’t work.

The general protection fault that is occurring because of the wrapper (at least I think this is the reason)
I did put in this workaround to attempt to undo the affect of the call instruction

not sure it’s effective though

I think some time ago we changed ->something to always create a wrapper, because in many cases it could involve a closure. Specifically here: Compiler: fix proc of self causing multidispatch by asterite · Pull Request #9972 · crystal-lang/crystal · GitHub

Maybe it worked for lilith because it was previous to that change.

That said, it might be worth opening a feature request so that if you take do ->fun and that points to a fun, it doesn’t create a wrapper. Maybe in the general case it shouldn’t create a wrapper, but it’s hard to detect.

Also, if it’s ->foo (no args) I think it should never create a wrapper as there’s no way it could multidispatch, so another thing we could optimize there.

1 Like

Yeah I feel like the no args, no wrapper is probably the ideal solution
with a bit of a performance increase at the same time

added an issue here only wrap `->foo` pointers where scope capture might be required · Issue #11711 · crystal-lang/crystal · GitHub

2 Likes