Files
sx/examples/1801-concurrency-pure-generic.sx
agra 4b384788e6 fibers B1.0b: abi(.pure) emits a real LLVM naked function (green)
Flip the B1.0a emit bail to real emission. The emit_llvm declaration
pass now adds LLVM's naked + noinline + nounwind attributes for an
is_pure function and skips frame-pointer=all (incompatible with a
frameless function); Pass 2 emits the body normally, and the naked
attribute makes the backend emit it verbatim (the inline asm + its own
ret) with no prologue/epilogue.

IR shape verified:
  ; Function Attrs: naked noinline nounwind
  define internal i64 @answer() #0 {
  entry:
    call void asm sideeffect "...ret...", ""()
    unreachable
  }
The caller invokes it as an ordinary () -> i64 call (.pure is
call_conv == .default).

- examples/1800-concurrency-pure-asm.sx: now green, aarch64-pinned
  (.build macos) -> exit 42 + .ir snapshot.
- examples/1801-concurrency-pure-generic.sx (renamed from -bail): the
  generic .pure now emits a correct naked answer__i64 (exit 42),
  proving generic.zig produces a naked body, not a framed one.
- examples/1802-concurrency-pure-asm-x86.sx: x86_64 cross sibling
  (.build x86_64-linux, ir-only here); .ir locks naked + movl $42,%eax.
- unit test in emit_llvm.test.zig asserts the naked attribute is present
  and frame-pointer absent on an abi(.pure) function.

Suite green (724/0).
2026-06-20 16:36:12 +03:00

23 lines
1008 B
Plaintext

// Stream B1 (fibers) — `abi(.pure)` on a GENERIC function emits a correct naked
// body (regression for an adversarial-review finding).
//
// A generic function is monomorphized through a different Function-creation path
// (lower/generic.zig) than a plain decl. That path originally left `is_pure`
// unset, so a generic `abi(.pure)` instance silently shipped a FRAMED body — it
// returned 42 but leaked the prologue's stack adjustment (the exact SP-in ≠
// SP-out corruption the `.pure` ABI exists to avoid). generic.zig (and the
// sibling pack-expansion path in pack.zig) now set `is_pure` and emit the
// asm-only naked body. This pins that: the monomorphized `answer__i64` is a
// proper naked function (no frame), returning 42. aarch64-pinned (the asm body
// is per-arch); runs end-to-end on a matching host, ir-only elsewhere.
answer :: ($T: Type) -> i64 abi(.pure) {
asm volatile {
#string A
mov x0, #42
ret
A
};
}
main :: () -> i64 { return answer(i64); }