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:
@@ -280,6 +280,40 @@ 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 cmpxchg (strong + weak)" {
|
||||
const alloc = std.testing.allocator;
|
||||
var module = Module.init(alloc);
|
||||
defer module.deinit();
|
||||
|
||||
var b = Builder.init(&module);
|
||||
|
||||
const opt_i64 = module.types.optionalOf(.i64); // ?i64 result type
|
||||
|
||||
_ = b.beginFunction(str(&module, "f"), &.{}, .i64);
|
||||
const entry = b.appendBlock(str(&module, "entry"), &.{});
|
||||
b.switchToBlock(entry);
|
||||
|
||||
const p = b.alloca(.i64);
|
||||
const exp = b.constInt(1, .i64);
|
||||
const des = b.constInt(2, .i64);
|
||||
// strong CAS
|
||||
_ = b.emit(.{ .atomic_cmpxchg = .{ .ptr = p, .cmp = exp, .new = des, .val_ty = .i64, .success_ordering = .acq_rel, .failure_ordering = .acquire, .weak = false } }, opt_i64);
|
||||
// weak CAS
|
||||
_ = b.emit(.{ .atomic_cmpxchg = .{ .ptr = p, .cmp = exp, .new = des, .val_ty = .i64, .success_ordering = .seq_cst, .failure_ordering = .seq_cst, .weak = true } }, opt_i64);
|
||||
b.ret(exp, .i64);
|
||||
b.finalize();
|
||||
|
||||
var emitter = LLVMEmitter.init(alloc, &module, "test_cas", .{});
|
||||
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, "cmpxchg") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, ir_str, "cmpxchg weak") != null); // the weak marker
|
||||
}
|
||||
|
||||
test "emit: comparison and branch" {
|
||||
const alloc = std.testing.allocator;
|
||||
var module = Module.init(alloc);
|
||||
|
||||
Reference in New Issue
Block a user