authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-03-11 12:02:05+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-03-11 12:02:05+02:00
log1f66435a6b0c5ccf6e4e96df0ed96732480ab4db
treec273dfcd75aed849d234e2f532e8507cd494bde8
parent64e60d8ae2c06689a2e0533eb43a1c6a8ff01259
signaturelock-open Commit is signed but in an unrecognized format.

support cmpxchg at comptime


2 files changed, 39 insertions(+), 35 deletions(-)

src/ir.cpp+16-16
...@@ -25212,7 +25212,20 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch...@@ -25212,7 +25212,20 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
2521225212
25213 if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar &&25213 if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
25214 instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) {25214 instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) {
25215 zig_panic("TODO compile-time execution of cmpxchg");25215 IrInstGen *result = ir_get_deref(ira, &instruction->base.base, casted_ptr, nullptr);
25216 ZigValue *op1_val = ir_resolve_const(ira, result, UndefBad);
25217 ZigValue *op2_val = ir_resolve_const(ira, casted_cmp_value, UndefBad);
25218 bool eql = const_values_equal(ira->codegen, op1_val, op2_val);
25219 ZigValue *val = ira->codegen->pass1_arena->allocate<ZigValue>(1);
25220 val->special = ConstValSpecialStatic;
25221 val->type = result_type;
25222 if (eql) {
25223 ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, casted_new_value, false);
25224 set_optional_value_to_null(val);
25225 } else {
25226 set_optional_payload(val, op1_val);
25227 }
25228 return ir_const_move(ira, &instruction->base.base, val);
25216 }25229 }
2521725230
25218 IrInstGen *result_loc;25231 IrInstGen *result_loc;
...@@ -28334,7 +28347,6 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi...@@ -28334,7 +28347,6 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi
28334 int_type = operand_type;28347 int_type = operand_type;
28335 }28348 }
28336 auto bit_count = int_type->data.integral.bit_count;28349 auto bit_count = int_type->data.integral.bit_count;
28337 bool is_signed = int_type->data.integral.is_signed;
28338 uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);28350 uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
2833928351
28340 if (bit_count > max_atomic_bits) {28352 if (bit_count > max_atomic_bits) {
...@@ -28344,20 +28356,8 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi...@@ -28344,20 +28356,8 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi
28344 return ira->codegen->builtin_types.entry_invalid;28356 return ira->codegen->builtin_types.entry_invalid;
28345 }28357 }
2834628358
28347 if (bit_count < 2 || !is_power_of_2(bit_count)) {28359 if (bit_count == 1 || !is_power_of_2(bit_count)) {
28348 if (bit_count < 8) {28360 *actual_type = get_int_type(ira->codegen, int_type->data.integral.is_signed, int_type->abi_size * 8);
28349 *actual_type = get_int_type(ira->codegen, is_signed, 8);
28350 } else if (bit_count < 16) {
28351 *actual_type = get_int_type(ira->codegen, is_signed, 16);
28352 } else if (bit_count < 32) {
28353 *actual_type = get_int_type(ira->codegen, is_signed, 32);
28354 } else if (bit_count < 64) {
28355 *actual_type = get_int_type(ira->codegen, is_signed, 64);
28356 } else if (bit_count < 128) {
28357 *actual_type = get_int_type(ira->codegen, is_signed, 128);
28358 } else {
28359 zig_unreachable();
28360 }
28361 }28361 }
28362 } else if (operand_type->id == ZigTypeIdFloat) {28362 } else if (operand_type->id == ZigTypeIdFloat) {
28363 uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);28363 uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
test/stage1/behavior/atomics.zig+23-19
...@@ -2,29 +2,32 @@ const std = @import("std");...@@ -2,29 +2,32 @@ const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;3const expectEqual = std.testing.expectEqual;
4const builtin = @import("builtin");4const builtin = @import("builtin");
5const AtomicRmwOp = builtin.AtomicRmwOp;
6const AtomicOrder = builtin.AtomicOrder;
75
8test "cmpxchg" {6test "cmpxchg" {
7 testCmpxchg();
8 comptime testCmpxchg();
9}
10
11fn testCmpxchg() void {
9 var x: i32 = 1234;12 var x: i32 = 1234;
10 if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {13 if (@cmpxchgWeak(i32, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
11 expect(x1 == 1234);14 expect(x1 == 1234);
12 } else {15 } else {
13 @panic("cmpxchg should have failed");16 @panic("cmpxchg should have failed");
14 }17 }
1518
16 while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {19 while (@cmpxchgWeak(i32, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
17 expect(x1 == 1234);20 expect(x1 == 1234);
18 }21 }
19 expect(x == 5678);22 expect(x == 5678);
2023
21 expect(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);24 expect(@cmpxchgStrong(i32, &x, 5678, 42, .SeqCst, .SeqCst) == null);
22 expect(x == 42);25 expect(x == 42);
23}26}
2427
25test "fence" {28test "fence" {
26 var x: i32 = 1234;29 var x: i32 = 1234;
27 @fence(AtomicOrder.SeqCst);30 @fence(.SeqCst);
28 x = 5678;31 x = 5678;
29}32}
3033
...@@ -36,18 +39,18 @@ test "atomicrmw and atomicload" {...@@ -36,18 +39,18 @@ test "atomicrmw and atomicload" {
36}39}
3740
38fn testAtomicRmw(ptr: *u8) void {41fn testAtomicRmw(ptr: *u8) void {
39 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);42 const prev_value = @atomicRmw(u8, ptr, .Xchg, 42, .SeqCst);
40 expect(prev_value == 200);43 expect(prev_value == 200);
41 comptime {44 comptime {
42 var x: i32 = 1234;45 var x: i32 = 1234;
43 const y: i32 = 12345;46 const y: i32 = 12345;
44 expect(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);47 expect(@atomicLoad(i32, &x, .SeqCst) == 1234);
45 expect(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);48 expect(@atomicLoad(i32, &y, .SeqCst) == 12345);
46 }49 }
47}50}
4851
49fn testAtomicLoad(ptr: *u8) void {52fn testAtomicLoad(ptr: *u8) void {
50 const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);53 const x = @atomicLoad(u8, ptr, .SeqCst);
51 expect(x == 42);54 expect(x == 42);
52}55}
5356
...@@ -56,18 +59,18 @@ test "cmpxchg with ptr" {...@@ -56,18 +59,18 @@ test "cmpxchg with ptr" {
56 var data2: i32 = 5678;59 var data2: i32 = 5678;
57 var data3: i32 = 9101;60 var data3: i32 = 9101;
58 var x: *i32 = &data1;61 var x: *i32 = &data1;
59 if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {62 if (@cmpxchgWeak(*i32, &x, &data2, &data3, .SeqCst, .SeqCst)) |x1| {
60 expect(x1 == &data1);63 expect(x1 == &data1);
61 } else {64 } else {
62 @panic("cmpxchg should have failed");65 @panic("cmpxchg should have failed");
63 }66 }
6467
65 while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {68 while (@cmpxchgWeak(*i32, &x, &data1, &data3, .SeqCst, .SeqCst)) |x1| {
66 expect(x1 == &data1);69 expect(x1 == &data1);
67 }70 }
68 expect(x == &data3);71 expect(x == &data3);
6972
70 expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);73 expect(@cmpxchgStrong(*i32, &x, &data3, &data2, .SeqCst, .SeqCst) == null);
71 expect(x == &data2);74 expect(x == &data2);
72}75}
7376
...@@ -163,16 +166,17 @@ fn testAtomicRmwFloat() void {...@@ -163,16 +166,17 @@ fn testAtomicRmwFloat() void {
163}166}
164167
165test "atomics with different types" {168test "atomics with different types" {
166 // testAtomicsWithType(bool, true, false);169 testAtomicsWithType(bool, true, false);
167 // inline for (.{ u1, i5, u33 }) |T| {170 inline for (.{ u1, i5, u33 }) |T| {
168 // var x: T = 0;171 var x: T = 0;
169 // testAtomicsWithType(T, 0, 1);172 testAtomicsWithType(T, 0, 1);
170 // }173 }
171 testAtomicsWithType(u0, 0, 0);174 testAtomicsWithType(u0, 0, 0);
172 testAtomicsWithType(i0, 0, 0);175 testAtomicsWithType(i0, 0, 0);
173}176}
174177
175fn testAtomicsWithType(comptime T: type, a: T, b: T) void {178// a and b souldn't need to be comptime
179fn testAtomicsWithType(comptime T: type, comptime a: T, comptime b: T) void {
176 var x: T = b;180 var x: T = b;
177 @atomicStore(T, &x, a, .SeqCst);181 @atomicStore(T, &x, a, .SeqCst);
178 expect(x == a);182 expect(x == a);