authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-03-11 10:29:15+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-03-11 10:29:15+02:00
log64e60d8ae2c06689a2e0533eb43a1c6a8ff01259
treed0def260a4fe64767bc66dd869a63ad58970ebf8
parent21809c33001cc53c8fb3b56b25264e8d9076bed9
signaturelock-open Commit is signed but in an unrecognized format.

special case atomic operations on zero bit types


2 files changed, 50 insertions(+), 14 deletions(-)

src/ir.cpp+31-6
......@@ -25199,12 +25199,22 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
2519925199 return ira->codegen->invalid_inst_gen;
2520025200 }
2520125201
25202 ZigType *result_type = get_optional_type(ira->codegen, operand_type);
25203
25204 // special case zero bit types
25205 if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
25206 ZigValue *val = ira->codegen->pass1_arena->allocate<ZigValue>(1);
25207 val->special = ConstValSpecialStatic;
25208 val->type = result_type;
25209 set_optional_value_to_null(val);
25210 return ir_const_move(ira, &instruction->base.base, val);
25211 }
25212
2520225213 if (instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut != ConstPtrMutRuntimeVar &&
2520325214 instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) {
2520425215 zig_panic("TODO compile-time execution of cmpxchg");
2520525216 }
2520625217
25207 ZigType *result_type = get_optional_type(ira->codegen, operand_type);
2520825218 IrInstGen *result_loc;
2520925219 if (handle_is_ptr(ira->codegen, result_type)) {
2521025220 result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
......@@ -28317,18 +28327,23 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op, Zi
2831728327
2831828328 *actual_type = nullptr;
2831928329 if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
28330 ZigType *int_type;
2832028331 if (operand_type->id == ZigTypeIdEnum) {
28321 operand_type = operand_type->data.enumeration.tag_int_type;
28332 int_type = operand_type->data.enumeration.tag_int_type;
28333 } else {
28334 int_type = operand_type;
2832228335 }
28336 auto bit_count = int_type->data.integral.bit_count;
28337 bool is_signed = int_type->data.integral.is_signed;
2832328338 uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
28324 if (operand_type->data.integral.bit_count > max_atomic_bits) {
28339
28340 if (bit_count > max_atomic_bits) {
2832528341 ir_add_error(ira, &op->base,
2832628342 buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type",
28327 max_atomic_bits, operand_type->data.integral.bit_count));
28343 max_atomic_bits, bit_count));
2832828344 return ira->codegen->builtin_types.entry_invalid;
2832928345 }
28330 auto bit_count = operand_type->data.integral.bit_count;
28331 bool is_signed = operand_type->data.integral.is_signed;
28346
2833228347 if (bit_count < 2 || !is_power_of_2(bit_count)) {
2833328348 if (bit_count < 8) {
2833428349 *actual_type = get_int_type(ira->codegen, is_signed, 8);
......@@ -28423,6 +28438,11 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
2842328438 return ira->codegen->invalid_inst_gen;
2842428439 }
2842528440
28441 // special case zero bit types
28442 if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
28443 return ir_const_move(ira, &instruction->base.base, get_the_one_possible_value(ira->codegen, operand_type));
28444 }
28445
2842628446 if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar)
2842728447 {
2842828448 ir_add_error(ira, &instruction->base.base,
......@@ -28504,6 +28524,11 @@ static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcA
2850428524 return ira->codegen->invalid_inst_gen;
2850528525 }
2850628526
28527 // special case zero bit types
28528 if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
28529 return ir_const_void(ira, &instruction->base.base);
28530 }
28531
2850728532 if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) {
2850828533 IrInstGen *result = ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, value, false);
2850928534 result->value->type = ira->codegen->builtin_types.entry_void;
test/stage1/behavior/atomics.zig+19-8
......@@ -162,12 +162,23 @@ fn testAtomicRmwFloat() void {
162162 expect(x == 4);
163163}
164164
165test "atomics with bool" {
166 var x = false;
167 @atomicStore(bool, &x, true, .SeqCst);
168 expect(x == true);
169 expect(@atomicLoad(bool, &x, .SeqCst) == true);
170 expect(@atomicRmw(bool, &x, .Xchg, false, .SeqCst) == true);
171 expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst) == null);
172 expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst).? == true);
165test "atomics with different types" {
166 // testAtomicsWithType(bool, true, false);
167 // inline for (.{ u1, i5, u33 }) |T| {
168 // var x: T = 0;
169 // testAtomicsWithType(T, 0, 1);
170 // }
171 testAtomicsWithType(u0, 0, 0);
172 testAtomicsWithType(i0, 0, 0);
173}
174
175fn testAtomicsWithType(comptime T: type, a: T, b: T) void {
176 var x: T = b;
177 @atomicStore(T, &x, a, .SeqCst);
178 expect(x == a);
179 expect(@atomicLoad(T, &x, .SeqCst) == a);
180 expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
181 expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
182 if (@sizeOf(T) != 0)
183 expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
173184}