test(asm): round-trip example — asm calls back into an sx function
Adds examples/1655-platform-asm-callback-into-sx.sx: a global-asm trampoline (_caller) that `bl _cb` back into an `export`ed sx function. Demonstrates the sx → asm → sx round trip and that `export` (external linkage + stable C symbol + C ABI) is what makes the callback symbol resolvable — `callconv(.c)` alone leaves it internal and it DCE's away. Runs under the JIT on aarch64-macos (→ 42); ir-only elsewhere. Locks current behavior; no compiler change.
This commit is contained in:
35
examples/1655-platform-asm-callback-into-sx.sx
Normal file
35
examples/1655-platform-asm-callback-into-sx.sx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// ASM stream — the round trip: sx → asm → sx. A global-asm routine (`_caller`)
|
||||||
|
// CALLS BACK into an sx function (`cb`) by its symbol, then returns. For the asm
|
||||||
|
// `bl _cb` to resolve, the sx callback needs EXTERNAL LINKAGE and a stable C
|
||||||
|
// symbol — that is exactly what `export` provides (it also implies the C ABI, so
|
||||||
|
// no hidden context parameter). `callconv(.c)` alone is NOT enough: it sets the
|
||||||
|
// ABI but leaves the function `internal`, so it is dead-code-eliminated (nothing
|
||||||
|
// in the IR references it — the `bl` is opaque to the optimizer) and `_cb` is
|
||||||
|
// undefined at link. macOS gives `export "cb"` the symbol `_cb` (leading
|
||||||
|
// underscore), which the template references. aarch64-macos-pinned; runs under
|
||||||
|
// the JIT here (sx run), ir-only elsewhere.
|
||||||
|
|
||||||
|
// The sx callback — `export` gives it external linkage + the `_cb` symbol + C ABI.
|
||||||
|
cb :: (n: i64) -> i64 export "cb" {
|
||||||
|
return n + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A global-asm trampoline that calls back into `cb`. It saves/restores the link
|
||||||
|
// register (x30) around the `bl` — it was itself reached via `bl`, so the return
|
||||||
|
// address must survive the nested call.
|
||||||
|
asm {
|
||||||
|
#string ASM
|
||||||
|
.global _caller
|
||||||
|
_caller:
|
||||||
|
stp x29, x30, [sp, #-16]!
|
||||||
|
bl _cb // x0 = cb(x0) — back into sx
|
||||||
|
ldp x29, x30, [sp], #16
|
||||||
|
ret
|
||||||
|
ASM,
|
||||||
|
};
|
||||||
|
|
||||||
|
caller :: (n: i64) -> i64 extern;
|
||||||
|
|
||||||
|
main :: () -> i64 {
|
||||||
|
return caller(41); // sx main → asm caller → bl _cb → sx cb → 42
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{ "target": "macos" }
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
42
|
||||||
28
examples/expected/1655-platform-asm-callback-into-sx.ir
Normal file
28
examples/expected/1655-platform-asm-callback-into-sx.ir
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
module asm ".global _caller"
|
||||||
|
module asm "_caller:"
|
||||||
|
module asm " stp x29, x30, [sp, #-16]!"
|
||||||
|
module asm " bl _cb // x0 = cb(x0) \E2\80\94 back into sx"
|
||||||
|
module asm " ldp x29, x30, [sp], #16"
|
||||||
|
module asm " ret"
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define i64 @cb(i64 %0) #0 {
|
||||||
|
entry:
|
||||||
|
%alloca = alloca i64, align 8
|
||||||
|
store i64 %0, ptr %alloca, align 8
|
||||||
|
%load = load i64, ptr %alloca, align 8
|
||||||
|
%add = add i64 %load, 1
|
||||||
|
ret i64 %add
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
declare i64 @caller(i64) #0
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define i32 @main() #0 {
|
||||||
|
entry:
|
||||||
|
%call = call i64 @caller(i64 41)
|
||||||
|
%ca.tr = trunc i64 %call to i32
|
||||||
|
ret i32 %ca.tr
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
Reference in New Issue
Block a user