atomics A.3b: real swap (xchg) + fence emission + unit test (green)
emitAtomicRmw xchg arm (swap) and emitAtomicFence (LLVMBuildFence) now real. examples/1703 (swap old=7/now=42, 'atomicrmw xchg') + 1704 (fence release/acquire/ seq_cst) green. Unit test 'emit: atomic swap (xchg) + fence'. Stream A (atomics) is feature-complete: load/store, RMW (add/sub/and/or/xor/min/max), compare_exchange[_weak], swap, fence. Suite green (721/0).
This commit is contained in:
@@ -124,3 +124,9 @@ follow-up, not an atomics blocker.
|
||||
- **A.1** — RMW: atomic_rmw op + RmwKind + recognizer (rmwKindFromName, integer-only) +
|
||||
7 fetch_* methods/intrinsics. A.1a bail-lock → A.1b real LLVMBuildAtomicRMW (signed|unsigned
|
||||
min/max). comptime_vm real RMW. 1701 + unit test. Suite green (716/0).
|
||||
- **A.2** — CAS: atomic_cmpxchg op + recognizer (dual-ordering validation) + emit (?T from
|
||||
{actual,!success}) + comptime VM. compare_exchange/_weak methods. examples 1702 + 1186.
|
||||
Review agent died; self-verified comptime↔runtime agreement, sub-8, ordering edges.
|
||||
(Commits dca396e/79895be; A.2 has_value fix folded into A.3a.)
|
||||
- **A.3** — swap (atomicrmw xchg) + fence (new atomic_fence op). A.3a bail-lock → A.3b real.
|
||||
examples 1703/1704/1187 + unit test. Stream A feature-complete. Suite green (721/0).
|
||||
|
||||
@@ -1 +1 @@
|
||||
1
|
||||
0
|
||||
|
||||
@@ -1 +1 @@
|
||||
error: atomic swap (xchg) LLVM emission not yet implemented (Stream A, A.3b)
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
|
||||
swap old: 7
|
||||
swap now: 42
|
||||
|
||||
@@ -1 +1 @@
|
||||
1
|
||||
0
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
error: atomic fence LLVM emission not yet implemented (Stream A, A.3b)
|
||||
error: atomic fence LLVM emission not yet implemented (Stream A, A.3b)
|
||||
error: atomic fence LLVM emission not yet implemented (Stream A, A.3b)
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
|
||||
after fences: 3
|
||||
|
||||
@@ -416,14 +416,6 @@ pub const Ops = struct {
|
||||
}
|
||||
|
||||
pub fn emitAtomicRmw(self: Ops, instruction: *const Inst, a: AtomicRmw) void {
|
||||
// A.3a lock: the new `xchg` (swap) kind BAILS until A.3b. The other RMW
|
||||
// kinds (A.1) keep working.
|
||||
if (a.kind == .xchg) {
|
||||
std.debug.print("error: atomic swap (xchg) LLVM emission not yet implemented (Stream A, A.3b)\n", .{});
|
||||
self.e.comptime_failed = true;
|
||||
self.e.mapRef(c.LLVMGetUndef(self.e.toLLVMType(if (instruction.ty == .void) .i64 else instruction.ty)));
|
||||
return;
|
||||
}
|
||||
const ptr = self.e.resolveRef(a.ptr);
|
||||
const val = self.e.resolveRef(a.operand);
|
||||
const ptr_kind = c.LLVMGetTypeKind(c.LLVMTypeOf(ptr));
|
||||
@@ -475,11 +467,8 @@ pub const Ops = struct {
|
||||
}
|
||||
|
||||
// Standalone memory fence — void result, no address. singleThread = 0.
|
||||
// A.3a lock: BAILS until A.3b wires LLVMBuildFence.
|
||||
pub fn emitAtomicFence(self: Ops, a: AtomicFence) void {
|
||||
_ = a;
|
||||
std.debug.print("error: atomic fence LLVM emission not yet implemented (Stream A, A.3b)\n", .{});
|
||||
self.e.comptime_failed = true;
|
||||
_ = c.LLVMBuildFence(self.e.builder, llvmOrdering(a.ordering), 0, "");
|
||||
self.e.advanceRefCounter();
|
||||
}
|
||||
|
||||
|
||||
@@ -280,6 +280,35 @@ test "emit: atomic rmw (add + signed/unsigned min)" {
|
||||
try std.testing.expect(std.mem.indexOf(u8, ir_str, "atomicrmw umin") != null); // unsigned u64
|
||||
}
|
||||
|
||||
test "emit: atomic swap (xchg) + fence" {
|
||||
const alloc = std.testing.allocator;
|
||||
var module = Module.init(alloc);
|
||||
defer module.deinit();
|
||||
|
||||
var b = Builder.init(&module);
|
||||
|
||||
_ = b.beginFunction(str(&module, "f"), &.{}, .i64);
|
||||
const entry = b.appendBlock(str(&module, "entry"), &.{});
|
||||
b.switchToBlock(entry);
|
||||
|
||||
const p = b.alloca(.i64);
|
||||
const five = b.constInt(5, .i64);
|
||||
const old = b.emit(.{ .atomic_rmw = .{ .ptr = p, .operand = five, .val_ty = .i64, .ordering = .acq_rel, .kind = .xchg } }, .i64);
|
||||
b.emitVoid(.{ .atomic_fence = .{ .ordering = .seq_cst } }, .void);
|
||||
b.ret(old, .i64);
|
||||
b.finalize();
|
||||
|
||||
var emitter = LLVMEmitter.init(alloc, &module, "test_swap_fence", .{});
|
||||
defer emitter.deinit();
|
||||
emitter.emit();
|
||||
|
||||
try std.testing.expect(emitter.verify());
|
||||
|
||||
const ir_str = emitter.dumpToString();
|
||||
try std.testing.expect(std.mem.indexOf(u8, ir_str, "atomicrmw xchg") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, ir_str, "fence seq_cst") != null);
|
||||
}
|
||||
|
||||
test "emit: atomic cmpxchg (strong + weak)" {
|
||||
const alloc = std.testing.allocator;
|
||||
var module = Module.init(alloc);
|
||||
|
||||
Reference in New Issue
Block a user