kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

tlv_thunk.h (2148B)


      1 #ifndef KIT_JIT_TLV_THUNK_H
      2 #define KIT_JIT_TLV_THUNK_H
      3 
      4 /* The JIT-time TLV thunk for Mach-O thread-local access.
      5  *
      6  * kit's codegen emits the Apple TLV access sequence whenever a Mach-O
      7  * target dereferences a `_Thread_local`:
      8  *
      9  *   adrp x0, sym@TLVPPAGE
     10  *   ldr  x0, [x0, sym@TLVPPAGEOFF]   ; x0 = descriptor
     11  *   ldr  x1, [x0]                    ; x1 = descriptor[+0]   (thunk*)
     12  *   blr  x1                          ; thunk(x0=desc) -> x0=TLV addr
     13  *
     14  * The thunk's ABI is custom: x0 in/out as the descriptor / per-thread
     15  * TLV address, every other GPR and SIMD register preserved.  In an AOT
     16  * Mach-O image dyld rewrites descriptor[+0] to a libdyld-supplied thunk
     17  * after allocating a pthread key per descriptor; the JIT image is never
     18  * walked by dyld, so we install our own thunk and patch every
     19  * descriptor's slot[0]/[1]/[2] from `kit_jit_from_image`.
     20  *
     21  * Per-image descriptor convention (post-patch):
     22  *   [+0]  : &kit_jit_tlv_thunk           (entry below)
     23  *   [+8]  : opaque KitJitTls ctx pointer (per JIT image)
     24  *   [+16] : byte offset within the per-thread TLS block (image-relative)
     25  *
     26  * Contract on the ctx pointer (set by KitJitTls.ctx_new): its first 8
     27  * bytes are a function pointer `void* (*get_block)(void* ctx)` that
     28  * returns the calling thread's TLS block (lazy-allocating + seeding
     29  * from the image's init bytes on first per-thread call).
     30  *
     31  * The thunk does roughly:
     32  *
     33  *   void* thunk(void* desc) {
     34  *     void* ctx                          = *(void**)((u8*)desc + 8);
     35  *     void* (*get_block)(void*)           = *(void**)ctx;
     36  *     void* base                          = get_block(ctx);
     37  *     return (u8*)base + *(u64*)((u8*)desc + 16);
     38  *   }
     39  *
     40  * Calling `get_block` from a context that must preserve x1..x18 / q0..q7
     41  * is the reason the thunk is implemented in asm — a normal C function
     42  * call would clobber caller-saved regs the JITed access sequence has no
     43  * idea about. */
     44 
     45 /* Declared as a function for &-of, but its calling convention is the
     46  * custom one described above: callers must come through the access
     47  * sequence, not a plain C call. */
     48 void kit_jit_tlv_thunk(void);
     49 
     50 #endif