Replace the A.0a emit bail with real LLVM atomic codegen: - emitAtomicLoad: LLVMBuildLoad2 + LLVMSetOrdering + LLVMSetAlignment - emitAtomicStore: LLVMBuildStore + LLVMSetOrdering + LLVMSetAlignment (value coerced to the pointee type, mirroring emitStore) - llvmOrdering: explicit sx AtomicOrdering -> LLVMAtomicOrdering map (LLVM's enum is non-contiguous; never an identity cast) examples/1700 now prints 7/42/43; IR is 'load atomic i64, ptr .. seq_cst, align 8' + 'store atomic ..'. Unit test 'emit: atomic load/store (seq_cst, aligned)' locks the emission shape (load atomic/store atomic/seq_cst/align 8) without a fragile full-module .ir snapshot. Suite green (710 examples + units).
5.0 KiB
5.0 KiB
CHECKPOINT-ATOMICS — Stream A (atomics lowering)
Companion to PLAN-ATOMICS.md. Update after every step (one step at a
time, per the cadence rule). New corpus category: 17xx.
Last completed step
A.0b (green) — DONE. Real atomic load/store emission: LLVMBuildLoad2/LLVMBuildStore
LLVMSetOrdering+ mandatoryLLVMSetAlignment, ordering via an explicit sx-tag→LLVMAtomicOrderingswitch (llvmOrdering).examples/1700green (7/42/43); IR showsload atomic i64, ptr … seq_cst, align 8+store atomic …. Added unit testemit: atomic load/store (seq_cst, aligned)inemit_llvm.test.zig(assertsload atomic/store atomic/seq_cst/align 8). No fragile full-module.irsnapshot for 1700 (it usesprint); the unit test is the emission-shape gate. Suite green (710 + units).
Earlier — A.0a (lock commit)
Full atomic load/store plumbing with LLVM emission deliberately bailing loudly;
examples/1700 locked to the bail diagnostic.
library/modules/std/atomic.sx:Orderingenum,Atomic($T)struct (init/load/store, seq_cst-only — see capability gap below),atomic_load/atomic_store#builtindecls. Opt-in import, NOT in the universalstd.sxfacade (mirrorstrace) — puttingOrderingin the prelude grew every program's type table 378→380 and churned 37.irsnapshots; reverted.- IR ops
atomic_load/atomic_store+AtomicOrdering(all 5) + structs (inst.zig); print arms (print.zig); comptime_vm arms reuse load/store (single-thread correct); recognizertryLowerAtomicIntrinsic(call.zig) — const-ordering-literal guard + scalar-size guard, both loud; emit dispatch arms (emit_llvm.zig) →emitAtomicLoad/emitAtomicStore(ops.zig) currently BAIL viacomptime_failed.
Current state
- A.0a committed; suite green.
- The recognizer + IR + emit already handle ALL FIVE orderings; only the surface bakes a
.seq_cstliteral (the methods can't yet forward a runtime/comptime ordering — gap below). - emit bodies are the ONLY placeholder; A.0b swaps them for real builders.
Next step
A.0b — replace the emitAtomicLoad/emitAtomicStore bail with real
LLVMBuildLoad2+SetOrdering+SetAlignment / LLVMBuildStore+SetOrdering+
SetAlignment (explicit sx-tag→LLVM ordering switch); regen 1700 → green (7/42/43) + host
.ir; add emit_llvm.test.zig unit. Then adversarial review, then the comptime-enum worker
- A.0.5 migration to the full ordering surface.
Known issues / capability gaps
- Comptime-constant ordering propagation MISSING (blocks the full surface). A runtime
Orderingmethod param can't reach LLVM (orderings are instruction attributes, not operands), and comptime enum value params don't exist ($o: Ordering→ounresolved in body;resolveValueParamArgfolds integers only). So A.0 ships seq_cst-only; A.0.5 closes the gap (worker: implement comptime enum value params) and MIGRATES the methods — NO legacy left by stream end. - Latent (observed, not yet filed): calling an unrecognized bodiless
#builtinsilently returns 0 / no-ops with exit 0 (that's how 1700 behaved before recognition landed) — a silent-fallback footgun in the generic builtin-call path, independent of atomics. Flag to user; candidateissues/entry.
Decisions (Stream A specifics; surface locked in design §4.6)
Atomic($T)= pure-sx transparent 1-field struct (NO new IR type); ops =#builtinintrinsics emitted as new IR ops. Minimal compiler surface.- Ordering is compile-time-only (const enum literal), baked into the op as a Zig enum; non-literal = loud diagnostic. sx tag → LLVM ordering via explicit switch (LLVM enum is non-contiguous: 2/4/5/6/7).
- Atomic load/store REQUIRE explicit alignment (
LLVMSetAlignment) — verifier mandate. - Comptime VM treats atomics as ordinary load/store (single-thread ⇒ correct), not a bail.
- Snapshot scope corrected:
.ir(LLVM IR) is arch-invariant for atomics → ONE host.irper op, not arch-gated x86/aarch64 pairs (they'd be byte-identical). Asm-level arch divergence + weak-memory semantics are OUT of corpus scope (stress harness, Stream C).
Log
- carve — wrote PLAN-ATOMICS.md + CHECKPOINT-ATOMICS.md; grounded the intrinsic path,
switch sites, LLVM-C API (no
LLVMBuildAtomicLoad; useLLVMBuildLoad2+SetOrdering+SetAlignment), and corrected the arch-.irmisconception (sx iremits arch-invariant LLVM IR). Stream ready; A.0a is the first implementation step. - A.0a — landed lib (atomic.sx, opt-in import) + IR ops (atomic_load/atomic_store +
AtomicOrdering) + recognizer + print/vm arms + emit BAIL; locked
examples/1700to the bail diagnostic. Reverted a universal-facade wiring that churned 37.irsnapshots (Ordering would bloat every program's type table). Suite green (710/0). - A.0b — real atomic load/store emission (LLVMBuildLoad2/Store + SetOrdering +
SetAlignment; explicit sx→LLVM ordering switch). 1700 green (7/42/43,
load atomic … seq_cst, align 8). Unit test added. Suite green (710 + units).