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).
25 lines
1.1 KiB
Plaintext
25 lines
1.1 KiB
Plaintext
// 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(); }
|