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:
45
library/modules/std/atomic.sx
Normal file
45
library/modules/std/atomic.sx
Normal file
@@ -0,0 +1,45 @@
|
||||
// Atomics — `Atomic($T)` wrapper + `Ordering`, over the compiler's atomic
|
||||
// load/store (later: rmw/cas/fence) IR ops. Consumers reach these through
|
||||
// std.sx (`Atomic` / `Ordering` re-exports), never by importing this file.
|
||||
//
|
||||
// Atomicity is a property of the OPERATION, not the storage: `Atomic(T)` is a
|
||||
// transparent 1-field wrapper with `T`'s exact layout/size/align. The ops are
|
||||
// `#builtin` intrinsics recognized by name at lower-time
|
||||
// (`tryLowerAtomicIntrinsic`, src/ir/lower/call.zig) and emitted as dedicated
|
||||
// atomic IR ops; the `Ordering` argument MUST be a constant enum literal.
|
||||
#import "modules/std/core.sx";
|
||||
|
||||
Ordering :: enum {
|
||||
relaxed; // → LLVM Monotonic
|
||||
acquire; // → LLVM Acquire
|
||||
release; // → LLVM Release
|
||||
acq_rel; // → LLVM AcquireRelease
|
||||
seq_cst; // → LLVM SequentiallyConsistent
|
||||
}
|
||||
|
||||
// Compiler intrinsics. Not called directly by users — `Atomic(T)`'s methods
|
||||
// forward to them. Recognized by name in lowering; the `Ordering` arg MUST be a
|
||||
// constant enum literal (a non-literal is a loud diagnostic).
|
||||
atomic_load :: ($T: Type, ptr: *T, o: Ordering) -> T #builtin;
|
||||
atomic_store :: ($T: Type, ptr: *T, v: T, o: Ordering) #builtin;
|
||||
|
||||
// NOTE (A.0): the methods bake a literal `.seq_cst` (strongest, conservative)
|
||||
// rather than taking an `o: Ordering` parameter. A runtime ordering param can't
|
||||
// reach the intrinsic as the compile-time constant LLVM requires, and comptime
|
||||
// enum value params don't exist yet — so explicit orderings (`a.load(.acquire)`)
|
||||
// land in A.0.5 once that capability does. See current/PLAN-ATOMICS.md.
|
||||
Atomic :: struct ($T: Type) {
|
||||
value: T;
|
||||
|
||||
init :: (v: T) -> Atomic(T) {
|
||||
return .{ value = v };
|
||||
}
|
||||
|
||||
load :: (self: *Atomic(T)) -> T {
|
||||
return atomic_load(T, @self.value, .seq_cst);
|
||||
}
|
||||
|
||||
store :: (self: *Atomic(T), v: T) {
|
||||
atomic_store(T, @self.value, v, .seq_cst);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user