atomics A.2a: CAS ops + recognizer + methods, emit bails (lock)
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, failure carries the actual value for retry). print arm; emit dispatch
-> emitAtomicCmpxchg (BAILS). comptime_vm arm does real single-thread CAS (read
actual / compare / store-on-equal / build ?T: success->none, failure->some;
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 a rejected ordering pair.
Suite green (718/0).
This commit is contained in:
@@ -715,6 +715,32 @@ pub const Vm = struct {
|
||||
try self.writeField(table, frame.get(a.ptr.index()), vty, new_val);
|
||||
return .{ .value = old };
|
||||
},
|
||||
// Compare-exchange at comptime (single-thread): read actual, compare
|
||||
// to cmp, and on equality store new. The ordering is a no-op; `weak`
|
||||
// behaves as a strong exchange (no spurious failure with one thread).
|
||||
// Result is `?T` (ins.ty): SUCCESS → none, FAILURE → some(actual).
|
||||
// Integer T only (the recognizer's guard rules out pointer optionals),
|
||||
// so the optional is laid out as payload@0 + has_value flag — exactly
|
||||
// like the `optional_wrap` arm below.
|
||||
.atomic_cmpxchg => |a| {
|
||||
const table = try self.requireTable();
|
||||
const elem_ty = if (a.val_ty != .void) a.val_ty else return self.failMsg("comptime compare_exchange: missing element type");
|
||||
const ptr = frame.get(a.ptr.index());
|
||||
const actual = try self.readField(table, ptr, elem_ty);
|
||||
const cmp_val = frame.get(a.cmp.index());
|
||||
const success = actual == cmp_val;
|
||||
if (success) try self.writeField(table, ptr, elem_ty, frame.get(a.new.index()));
|
||||
// Build the `?T` result in VM memory.
|
||||
const opt_ty = ins.ty; // ?T
|
||||
const addr = self.machine.allocBytes(table.typeSizeBytes(opt_ty), table.typeAlignBytes(opt_ty));
|
||||
if (success) {
|
||||
try self.machine.writeWord(addr + table.typeSizeBytes(elem_ty), 0, 1); // has_value = 0 (null)
|
||||
} else {
|
||||
try self.writeField(table, addr, elem_ty, actual); // payload = actual
|
||||
try self.machine.writeWord(addr + table.typeSizeBytes(elem_ty), 1, 1); // has_value = 1
|
||||
}
|
||||
return .{ .value = addr };
|
||||
},
|
||||
.struct_init => |agg| {
|
||||
const table = try self.requireTable();
|
||||
const sty = ins.ty;
|
||||
|
||||
Reference in New Issue
Block a user