// ASM stream — symbol operand (`"s"`): feed a function/global SYMBOL into the // template so a DIRECT `bl %[fn]` (PC-relative — one fewer indirection than a // register-indirect `blr`: no pointer load, a relative reloc, a predictable // branch) goes straight to it. The backend emits the platform-mangled name // (`_cb` on macOS, `cb` on Linux), so the template stays portable — no hardcoded // underscore. Round trip: sx → asm → `bl _cb` → sx → 42. aarch64-macos-pinned; // runs under the JIT here, ir-only elsewhere (the `.ir` locks `"s"`/`ptr @cb`). cb :: (n: i64) -> i64 export "cb" { return n + 1; } tramp :: (n: i64) -> i64 { return asm volatile { #string ASM stp x29, x30, [sp, #-16]! mov x0, %[arg] bl %[fn] mov %[res], x0 ldp x29, x30, [sp], #16 ASM, [res] "=r" -> i64, [arg] "r" = n, [fn] "s" = cb, // symbol operand → direct `bl _cb` clobbers(.x0, .x30, .memory), }; } main :: () -> i64 { return tramp(41); }