Function pointers are not always just a pointer to the instruction
Function pointers are not always just a pointer to the instruction
Posted Jul 16, 2025 19:28 UTC (Wed) by jrtc27 (subscriber, #107748)Parent article: Following up on the Python JIT
>
> typedef int (*function)(int);
> ((function)data)(42);
>
> That first line creates a type definition named "function", which is a pointer to a function that takes an integer argument and returns an integer. The second line casts the data pointer to that type and then calls the function with an argument of 42 (and ignores the return value). "It's weird, but it works."
This isn't always true. Most of the time it is, but there are a couple of cases where it's not.
Firstly, on some architectures, low bits of the address for indirect jumps, and thus function pointers, are used to indicate which execution mode the processor should use. For example, on 32-bit Arm, the LSB is 1 for T32/Thumb and 0 for A32/Arm, and on 32-bit MIPS it similarly distinguishes between MIPS32 and microMIPS32 (or the prior MIPS16e which microMIPS32 replaced).
Secondly, some ABIs use function descriptors to represent language-level function pointers. Here, the function pointer is not a pointer to the instructions to execute but is a pointer to a structure that contains such a pointer alongside one or more other pointers, typically some kind of per-library global pointer. This is the case on PA-RISC, Itanium, and 64-bit PowerPC if using version 1 of its ELF ABI (version 2 drops this, and is what most modern distributions use for 64-bit PowerPC), but also in embedded contexts multiple other ISAs have an ABI variant (sometimes called "FDPIC" for "function descriptor position-independent code") that does so, since it allows you to share a single copy of library code between processes in no-MMU systems.