special case atomic operations on zero bit types

This commit is contained in:
Vexu 2020-03-11 10:29:15 +02:00
parent 21809c3300
commit 64e60d8ae2
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 50 additions and 14 deletions

View File

@ -25199,12 +25199,22 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
return ira->codegen->invalid_inst_gen;
}
ZigType *result_type = get_optional_type(ira->codegen, operand_type);
// special case zero bit types
if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
ZigValue *val = ira->codegen->pass1_arena->allocate<ZigValue>(1);
val->special = ConstValSpecialStatic;
val->type = result_type;
set_optional_value_to_null(val);
return ir_const_move(ira, &instruction->base.base, val);
}
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");
}
ZigType *result_type = get_optional_type(ira->codegen, operand_type);
IrInstGen *result_loc;
if (handle_is_ptr(ira->codegen, result_type)) {
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
*actual_type = nullptr;
if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
ZigType *int_type;
if (operand_type->id == ZigTypeIdEnum) {
operand_type = operand_type->data.enumeration.tag_int_type;
int_type = operand_type->data.enumeration.tag_int_type;
} else {
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 (operand_type->data.integral.bit_count > max_atomic_bits) {
if (bit_count > max_atomic_bits) {
ir_add_error(ira, &op->base,
buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type",
max_atomic_bits, operand_type->data.integral.bit_count));
max_atomic_bits, bit_count));
return ira->codegen->builtin_types.entry_invalid;
}
auto bit_count = operand_type->data.integral.bit_count;
bool is_signed = operand_type->data.integral.is_signed;
if (bit_count < 2 || !is_power_of_2(bit_count)) {
if (bit_count < 8) {
*actual_type = get_int_type(ira->codegen, is_signed, 8);
@ -28423,6 +28438,11 @@ static IrInstGen *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstSrcAto
return ira->codegen->invalid_inst_gen;
}
// special case zero bit types
if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
return ir_const_move(ira, &instruction->base.base, get_the_one_possible_value(ira->codegen, operand_type));
}
if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value->data.x_ptr.mut == ConstPtrMutComptimeVar)
{
ir_add_error(ira, &instruction->base.base,
@ -28504,6 +28524,11 @@ static IrInstGen *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstSrcA
return ira->codegen->invalid_inst_gen;
}
// special case zero bit types
if (type_has_one_possible_value(ira->codegen, operand_type) == OnePossibleValueYes) {
return ir_const_void(ira, &instruction->base.base);
}
if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) {
IrInstGen *result = ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, value, false);
result->value->type = ira->codegen->builtin_types.entry_void;

View File

@ -162,12 +162,23 @@ fn testAtomicRmwFloat() void {
expect(x == 4);
}
test "atomics with bool" {
var x = false;
@atomicStore(bool, &x, true, .SeqCst);
expect(x == true);
expect(@atomicLoad(bool, &x, .SeqCst) == true);
expect(@atomicRmw(bool, &x, .Xchg, false, .SeqCst) == true);
expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst) == null);
expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst).? == true);
test "atomics with different types" {
// 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 {
var x: T = b;
@atomicStore(T, &x, a, .SeqCst);
expect(x == a);
expect(@atomicLoad(T, &x, .SeqCst) == a);
expect(@atomicRmw(T, &x, .Xchg, b, .SeqCst) == a);
expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst) == null);
if (@sizeOf(T) != 0)
expect(@cmpxchgStrong(T, &x, b, a, .SeqCst, .SeqCst).? == a);
}