4 ms·
I worked on NSInvocation during Apple's 64 bit transition. NSInvocation is an FFI: it allows you to construct calls to ObjC methods given a runtime signature, w
by ridiculous_fish 4y ago
I worked on NSInvocation during Apple's 64 bit transition. NSInvocation is an FFI: it allows you to construct calls to ObjC methods given a runtime signature, which means implementing the calling conventions of four platforms (PPC and x86, 32 and 64 bit).
My approach was to write a script which generated functions for all possible signatures, up to N parameters. The functions verified the values they were passed both natively and through NSInvocation.
This flushed out a huge number of weird, undocumented ABI corner cases. For example on PPC, when returning a struct containing a bitfield, sometimes the bits are aligned at the top (MSB) of the register, other times at the bottom, depending on the width of the bitfield! This was just an old gcc bug, but it can't be fixed without breaking the ABI.
The resulting C code was so large it also unearthed a PPC64 compiler bug! PPC jump instructions have a 24-bit immediate offset. If the offset needs to be larger than 24 bits, it's supposed to load the offset into a register and emit an indirect jump. This just didn't work, but nobody noticed, since you'd need to branch past ~33MB of code in a single function to hit it.
- pmarreck 4y ago> If the offset needs to be larger than 24 bits, it's supposed to load the offset into a register and emit an indirect jump imagine unit tests existing for claimed functionalities :: eye roll ::
- mmastrac 4y ago> The resulting C code was so large > you'd need to branch past ~33MB of code in a single function to hit it. That's... an impressive amount of C code.
- ranger_danger 4y agoNot really... many modern desktop applications are >100MB when built statically.
- saagarjha 4y agoOf course, these days the compiler stresses ARM’s 2 GB relative jumps :)
- kazinator 4y ago> This was just an old gcc bug, but it can't be fixed without breaking the ABI But that actually works? As in that the call generated by GCC correctly captures the structure returned by the function compiled by GCC, in spite of the misplaced bitfield? Libffi did a stupid thing on PPC64 with returns. Quantities less than 64 bits are on the wrong end of the word, as if the register value were lifted from a big endian piece of memory. E.g a char value of 'A' gets returned as 0x4100_0000_0000_0000. You can't just cast that to a char and be done.