diff --git a/src/ir.cpp b/src/ir.cpp index 2e87bd2687..338f803bbe 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -25212,7 +25212,20 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar && instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) { - zig_panic("TODO compile-time execution of cmpxchg"); + IrInstGen *result = ir_get_deref(ira, &instruction->base.base, casted_ptr, nullptr); + ZigValue *op1_val = ir_resolve_const(ira, result, UndefBad); + ZigValue *op2_val = ir_resolve_const(ira, casted_cmp_value, UndefBad); + bool eql = const_values_equal(ira->codegen, op1_val, op2_val); + ZigValue *val = ira->codegen->pass1_arena->allocate(1); + val->special = ConstValSpecialStatic; + val->type = result_type; + if (eql) { + ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, casted_new_value, false); + set_optional_value_to_null(val); + } else { + set_optional_payload(val, op1_val); + } + return ir_const_move(ira, &instruction->base.base, val); } IrInstGen *result_loc; @@ -28334,7 +28347,6 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi int_type = operand_type; } auto bit_count = int_type->data.integral.bit_count; - bool is_signed = int_type->data.integral.is_signed; uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch); if (bit_count > max_atomic_bits) { @@ -28344,20 +28356,8 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi return ira->codegen->builtin_types.entry_invalid; } - if (bit_count < 2 || !is_power_of_2(bit_count)) { - if (bit_count < 8) { - *actual_type = get_int_type(ira->codegen, is_signed, 8); - } else if (bit_count < 16) { - *actual_type = get_int_type(ira->codegen, is_signed, 16); - } else if (bit_count < 32) { - *actual_type = get_int_type(ira->codegen, is_signed, 32); - } else if (bit_count < 64) { - *actual_type = get_int_type(ira->codegen, is_signed, 64); - } else if (bit_count < 128) { - *actual_type = get_int_type(ira->codegen, is_signed, 128); - } else { - zig_unreachable(); - } + if (bit_count == 1 || !is_power_of_2(bit_count)) { + *actual_type = get_int_type(ira->codegen, int_type->data.integral.is_signed, int_type->abi_size * 8); } } else if (operand_type->id == ZigTypeIdFloat) { uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch); diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig index edc712d85b..9c75afc369 100644 --- a/test/stage1/behavior/atomics.zig +++ b/test/stage1/behavior/atomics.zig @@ -2,29 +2,32 @@ const std = @import("std"); const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const builtin = @import("builtin"); -const AtomicRmwOp = builtin.AtomicRmwOp; -const AtomicOrder = builtin.AtomicOrder; test "cmpxchg" { + testCmpxchg(); + comptime testCmpxchg(); +} + +fn testCmpxchg() void { var x: i32 = 1234; - if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { + if (@cmpxchgWeak(i32, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| { expect(x1 == 1234); } else { @panic("cmpxchg should have failed"); } - while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { + while (@cmpxchgWeak(i32, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| { expect(x1 == 1234); } expect(x == 5678); - expect(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); + expect(@cmpxchgStrong(i32, &x, 5678, 42, .SeqCst, .SeqCst) == null); expect(x == 42); } test "fence" { var x: i32 = 1234; - @fence(AtomicOrder.SeqCst); + @fence(.SeqCst); x = 5678; } @@ -36,18 +39,18 @@ test "atomicrmw and atomicload" { } fn testAtomicRmw(ptr: *u8) void { - const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst); + const prev_value = @atomicRmw(u8, ptr, .Xchg, 42, .SeqCst); expect(prev_value == 200); comptime { var x: i32 = 1234; const y: i32 = 12345; - expect(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234); - expect(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345); + expect(@atomicLoad(i32, &x, .SeqCst) == 1234); + expect(@atomicLoad(i32, &y, .SeqCst) == 12345); } } fn testAtomicLoad(ptr: *u8) void { - const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst); + const x = @atomicLoad(u8, ptr, .SeqCst); expect(x == 42); } @@ -56,18 +59,18 @@ test "cmpxchg with ptr" { var data2: i32 = 5678; var data3: i32 = 9101; var x: *i32 = &data1; - if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { + if (@cmpxchgWeak(*i32, &x, &data2, &data3, .SeqCst, .SeqCst)) |x1| { expect(x1 == &data1); } else { @panic("cmpxchg should have failed"); } - while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { + while (@cmpxchgWeak(*i32, &x, &data1, &data3, .SeqCst, .SeqCst)) |x1| { expect(x1 == &data1); } expect(x == &data3); - expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); + expect(@cmpxchgStrong(*i32, &x, &data3, &data2, .SeqCst, .SeqCst) == null); expect(x == &data2); } @@ -163,16 +166,17 @@ fn testAtomicRmwFloat() void { } test "atomics with different types" { - // testAtomicsWithType(bool, true, false); - // inline for (.{ u1, i5, u33 }) |T| { - // var x: T = 0; - // testAtomicsWithType(T, 0, 1); - // } + testAtomicsWithType(bool, true, false); + inline for (.{ u1, i5, u33 }) |T| { + var x: T = 0; + testAtomicsWithType(T, 0, 1); + } testAtomicsWithType(u0, 0, 0); testAtomicsWithType(i0, 0, 0); } -fn testAtomicsWithType(comptime T: type, a: T, b: T) void { +// a and b souldn't need to be comptime +fn testAtomicsWithType(comptime T: type, comptime a: T, comptime b: T) void { var x: T = b; @atomicStore(T, &x, a, .SeqCst); expect(x == a);