atomics A.0a: lib + IR ops + recognizer, emit bails (lock commit)

Stream A (atomics) foundation. Net-new atomic load/store codegen path, wired
end-to-end except LLVM emission, which deliberately bails loudly so the example
locks to a clean diagnostic (A.0b turns it green — cadence: no commit both adds a
test and makes it pass).

- library/modules/std/atomic.sx: Ordering enum, Atomic($T) transparent wrapper
  (init/load/store, seq_cst-only for now), atomic_load/atomic_store #builtin
  intrinsics. Opt-in import, NOT in the universal std facade (Ordering in the
  prelude grows every program's type table + churns 37 .ir snapshots).
- IR: atomic_load/atomic_store ops + AtomicOrdering (all 5) + structs (inst.zig);
  print arms; comptime_vm arms reuse load/store (single-thread correct);
  recognizer tryLowerAtomicIntrinsic (const-ordering + scalar-size guards, both
  loud); emit dispatch -> emitAtomicLoad/Store bail via comptime_failed.
- examples/1700-atomics-load-store.sx locked to the bail diagnostic.

Full ordering surface (a.load(.acquire)) blocked on comptime-constant ordering
propagation (comptime enum value params) — A.0.5, migrated not legacy.
This commit is contained in:
agra
2026-06-20 08:47:07 +03:00
parent ad1687c692
commit 22af40413d
14 changed files with 473 additions and 0 deletions

View File

@@ -161,6 +161,10 @@ pub const Op = union(enum) {
load: UnaryOp, // load from pointer
store: Store, // store value to pointer
// ── Atomics ─────────────────────────────────────────────────────
atomic_load: AtomicLoad, // atomic load from pointer with memory ordering
atomic_store: AtomicStore, // atomic store to pointer with memory ordering
// ── Struct ops ──────────────────────────────────────────────────
struct_init: Aggregate, // construct struct from field values
struct_get: FieldAccess, // read struct field by index
@@ -294,6 +298,27 @@ pub const Store = struct {
val_ty: TypeId = .void,
};
/// Memory ordering for atomic ops. The sx-surface `Ordering` enum
/// (`relaxed`/`acquire`/`release`/`acq_rel`/`seq_cst`) is read statically at
/// lower-time (the arg MUST be a constant enum literal) and baked here, so the
/// op carries no runtime ordering operand. The LLVM mapping is EXPLICIT (LLVM's
/// `LLVMAtomicOrdering` is non-contiguous: Monotonic=2/Acquire=4/…/SeqCst=7) —
/// never an identity cast.
pub const AtomicOrdering = enum { relaxed, acquire, release, acq_rel, seq_cst };
pub const AtomicLoad = struct {
ptr: Ref,
ordering: AtomicOrdering,
};
pub const AtomicStore = struct {
ptr: Ref,
val: Ref,
/// Declared type of the stored value (same role as `Store.val_ty`).
val_ty: TypeId = .void,
ordering: AtomicOrdering,
};
pub const Conversion = struct {
operand: Ref,
from: TypeId,