A symbol operand (constraint "s") feeds a function/global symbol whose mangled name the template emits — enabling a DIRECT `bl %[fn]` (one fewer indirection than register-indirect `blr`). Until now `"s" = fn` fell through to emit and produced an LLVM-verifier crash (param type mismatch). Reject it at lowering with a clear diagnostic instead, and lock that with examples/1656-platform-asm-symbol-operand.sx. The next commit implements it and flips the example to run (→ 42).
25 lines
955 B
Plaintext
25 lines
955 B
Plaintext
// 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`) branches straight to it, with the platform-mangled
|
|
// name emitted by the backend (so the template stays portable — no hardcoded
|
|
// `_` underscore). Not yet implemented — rejected at lowering for now. The next
|
|
// commit implements it and flips this example to run (sx → asm → sx, → 42).
|
|
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); }
|