special case atomic operations on zero bit types
This commit is contained in:
parent
21809c3300
commit
64e60d8ae2
37
src/ir.cpp
37
src/ir.cpp
@ -25199,12 +25199,22 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
|
|||||||
return ira->codegen->invalid_inst_gen;
|
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 &&
|
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)) {
|
instr_is_comptime(casted_cmp_value) && instr_is_comptime(casted_new_value)) {
|
||||||
zig_panic("TODO compile-time execution of cmpxchg");
|
zig_panic("TODO compile-time execution of cmpxchg");
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigType *result_type = get_optional_type(ira->codegen, operand_type);
|
|
||||||
IrInstGen *result_loc;
|
IrInstGen *result_loc;
|
||||||
if (handle_is_ptr(ira->codegen, result_type)) {
|
if (handle_is_ptr(ira->codegen, result_type)) {
|
||||||
result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
|
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;
|
*actual_type = nullptr;
|
||||||
if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
|
if (operand_type->id == ZigTypeIdInt || operand_type->id == ZigTypeIdEnum) {
|
||||||
|
ZigType *int_type;
|
||||||
if (operand_type->id == ZigTypeIdEnum) {
|
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);
|
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,
|
ir_add_error(ira, &op->base,
|
||||||
buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type",
|
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;
|
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 < 2 || !is_power_of_2(bit_count)) {
|
||||||
if (bit_count < 8) {
|
if (bit_count < 8) {
|
||||||
*actual_type = get_int_type(ira->codegen, is_signed, 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;
|
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)
|
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,
|
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;
|
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)) {
|
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);
|
IrInstGen *result = ir_analyze_store_ptr(ira, &instruction->base.base, casted_ptr, value, false);
|
||||||
result->value->type = ira->codegen->builtin_types.entry_void;
|
result->value->type = ira->codegen->builtin_types.entry_void;
|
||||||
|
@ -162,12 +162,23 @@ fn testAtomicRmwFloat() void {
|
|||||||
expect(x == 4);
|
expect(x == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "atomics with bool" {
|
test "atomics with different types" {
|
||||||
var x = false;
|
// testAtomicsWithType(bool, true, false);
|
||||||
@atomicStore(bool, &x, true, .SeqCst);
|
// inline for (.{ u1, i5, u33 }) |T| {
|
||||||
expect(x == true);
|
// var x: T = 0;
|
||||||
expect(@atomicLoad(bool, &x, .SeqCst) == true);
|
// testAtomicsWithType(T, 0, 1);
|
||||||
expect(@atomicRmw(bool, &x, .Xchg, false, .SeqCst) == true);
|
// }
|
||||||
expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst) == null);
|
testAtomicsWithType(u0, 0, 0);
|
||||||
expect(@cmpxchgStrong(bool, &x, false, true, .SeqCst, .SeqCst).? == true);
|
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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user