atomics A.2b: real CAS emission (cmpxchg) + unit test (green)

emitAtomicCmpxchg: LLVMBuildAtomicCmpXchg (success/failure orderings,
singleThread=0) returns a {T, i1} pair; LLVMSetWeak for the weak variant. The
sx ?T result (null = SUCCESS) is built as { extractvalue 0 (actual value),
xor(extractvalue 1 (success), true) } -- has_value = NOT success. Integer-only
(recognizer guard), so never a pointer/niche optional.

examples/1702 green: successful CAS returns null (value updated), failing CAS
returns the actual value (unchanged), weak retry loop increments a counter
(100 -> 105). LLVM IR shows `cmpxchg ... acq_rel acquire` and `cmpxchg weak`.
Unit test `emit: atomic cmpxchg (strong + weak)` locks `cmpxchg` + the weak
marker. Suite green (718/0).
This commit is contained in:
agra
2026-06-20 10:57:01 +03:00
parent dca396ed1f
commit 79895be401
6 changed files with 91 additions and 26 deletions

View File

@@ -4,17 +4,19 @@ Companion to [PLAN-ATOMICS.md](PLAN-ATOMICS.md). Update after every step (one st
time, per the cadence rule). New corpus category: `17xx`.
## Last completed step
**A.2a (CAS lock) — DONE**. `compare_exchange`/`_weak` wired end-to-end EXCEPT LLVM emission
(bails loudly; A.2b makes it real). New IR op `atomic_cmpxchg` + `AtomicCmpxchg{ptr, cmp, new,
val_ty, success_ordering, failure_ordering, weak}`; result type = `?T` (null = success). print
arm; emit dispatch → `emitAtomicCmpxchg` (BAILS). comptime_vm arm implements real single-thread
CAS (read actual / compare / store-on-equal / build `?T`: success→none, failure→some(actual);
weak == strong at comptime). Recognizer extended (`atomic_cmpxchg`/`_weak`, 6 args) — CAS
restricted to INTEGER T (loud reject); BOTH orderings resolved via `atomicOrderingFromNode`;
dual-ordering validation (failure may not be release/acq_rel nor stronger than success, via
`atomicOrderingRank`). Methods `compare_exchange`/`_weak` on `Atomic($T)` with comptime
`$success`/`$failure: Ordering`. `examples/1702` locked to the bail; `examples/1186` locks the
rejected ordering pair (failure=.seq_cst > success=.relaxed). Suite green (718/0).
**A.2 (CAS) — DONE** (A.2a lock + A.2b green). `compare_exchange`/`_weak` → LLVM `cmpxchg`
(result **`?T`, null = SUCCESS**; failure carries the actual value for retry). New IR op
`atomic_cmpxchg` + `AtomicCmpxchg{ptr, cmp, new, val_ty, success_ordering, failure_ordering,
weak}`. `emitAtomicCmpxchg`: `LLVMBuildAtomicCmpXchg` (success/failure orderings, singleThread=0)
`{T, i1}` pair; `LLVMSetWeak` for weak; `?T` result = `{ extractvalue 0 (actual),
xor(extractvalue 1, true) }` (has_value = NOT success). comptime_vm arm does real single-thread
CAS (read/compare/store-on-equal, build `?T`; weak == strong at comptime). Recognizer
(`atomic_cmpxchg`/`_weak`, 6 args) — CAS restricted to INTEGER T; BOTH orderings via
`atomicOrderingFromNode`; dual-ordering validation (failure may not be release/acq_rel nor
stronger than success, `atomicOrderingRank`). Methods `compare_exchange`/`_weak` on `Atomic($T)`
with comptime `$success`/`$failure: Ordering`. `examples/1702` green (CAS ok→20 / fail actual=20 /
weak retry loop 100→105); `examples/1186` locks a rejected ordering pair; unit test `emit: atomic
cmpxchg (strong + weak)` asserts `cmpxchg` + `cmpxchg weak`. Suite green (718/0).
### A.1 (RMW) — DONE (A.1a lock + A.1b green)
`fetch_add/sub/and/or/xor` + `fetch_min/max` → LLVM `atomicrmw` (returns OLD value). New IR op
@@ -24,10 +26,10 @@ rejected loudly); all five orderings valid for RMW. comptime_vm does real single
`examples/1701` green; unit test locks `atomicrmw add` + signed `min` vs unsigned `umin`.
## Next step
**A.2bCAS green**: replace the `emitAtomicCmpxchg` bail with real `LLVMBuildAtomicCmpXchg`
(success/failure orderings; `LLVMSetWeak` for weak). Build the `?T` result: `extractvalue 1` =
success (i1); `has = xor(success, true)` (null = success); `insertvalue {actual, has}`. Green
`examples/1702`; unit test asserting `cmpxchg` + the weak marker.
**A.3fence** (`atomic_fence($o: Ordering)` → LLVM `fence`), per PLAN-ATOMICS. No value
result; ordering must be acquire/release/acq_rel/seq_cst (relaxed is meaningless for a fence —
reject loudly). New IR op `atomic_fence` + dispatch/print/comptime_vm (no-op single-thread) +
`LLVMBuildFence`. Lock-then-green cadence as before.
### Earlier — A.0c (guard hardening)
Adversarial review of A.0 found two CRITICAL silent-wrong defects (raw LLVM verifier errors