fibers B1.0a: plumb abi(.pure), emit bails (lock)

First implementation step of Stream B1 (fibers). Make the inert abi(.pure)
ABI carry an is_pure flag through lowering, with LLVM emission deliberately
bailing loudly until B1.0b — the lock half of the lock->green cadence.

- IR Function.is_pure, set from fd.abi == .pure at both declareFunction
  decl sites.
- funcWantsImplicitCtx skips .pure (no synthetic __sx_ctx, mirroring the
  .c skip): a pure fn reads args from ABI registers, an implicit ctx would
  occupy a register slot the asm doesn't expect.
- both body-lowering paths bypass lowerValueBody for .pure: lower the asm
  body as statements + cap with unreachable. A pure body has no sx return
  (the asm rets itself), so the implicit-return diagnostic must not fire.
- emit_llvm Pass 2 bails loudly when func.is_pure (build-gating nonzero
  exit) rather than emit a framed body, whose epilogue would corrupt a
  context switch's deliberate SP-in != SP-out.

examples/1800-concurrency-pure-asm.sx: one host example (no .build pin --
the bail fires before instruction selection, so it is host-independent),
locked to the bail snapshot. B1.0b flips emit to LLVM's naked attribute +
asm-only body and pins the example per-arch.

The sx-facing name is "pure" throughout (field, diagnostic); LLVM's naked
attribute is only the B1.0b lowering mechanism. Suite green (722/0).
This commit is contained in:
agra
2026-06-20 14:34:53 +03:00
parent 7044b8133b
commit dd363ca877
9 changed files with 207 additions and 100 deletions

View File

@@ -0,0 +1,24 @@
// Stream B1 (fibers) step B1.0a — LOCK commit for `abi(.pure)`.
//
// An `abi(.pure)` function has no calling-convention prologue/epilogue/frame
// and no implicit `__sx_ctx`: its body is a single asm block that sets the
// return register and emits its own `ret`. This is the substrate the per-arch
// fiber context-switch is built on (design §4.6) — a `.c` epilogue would
// restore SP from the wrong stack across a switch (SP-in ≠ SP-out by design).
//
// This commit only plumbs the `is_pure` flag through lowering; LLVM emission
// (the `naked` attribute + asm-only body) is NOT implemented yet, so emit bails
// LOUDLY (build-gating, nonzero exit) rather than emit a framed body. The bail
// is at the function level, before any asm/instruction selection, so it is
// host-independent (no `.build` target pin needed until B1.0b adds emission).
// B1.0b flips this to a green, aarch64-pinned end-to-end run.
answer :: () -> i64 abi(.pure) {
asm volatile {
#string ASM
mov x0, #42
ret
ASM
};
}
main :: () -> i64 { return answer(); }

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1 @@
error: `abi(.pure)` function 'answer' LLVM emission not yet implemented

View File

@@ -0,0 +1 @@