Commit a52e472307

LemonBoy <thatlemon@gmail.com>
2021-05-14 08:31:22
stage1: Widen non byte-sized atomic loads/stores
Checking if the size is a power of two is not enough, should also check if it's a multiple of 8. Closes #7976
1 parent 2d4d4ba
Changed files (2)
src
test
stage1
behavior
src/stage1/codegen.cpp
@@ -5485,8 +5485,8 @@ static enum ZigLLVM_AtomicRMWBinOp to_ZigLLVMAtomicRMWBinOp(AtomicRmwOp op, bool
 }
 
 static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) {
-    // If the operand type of an atomic operation is not a power of two sized
-    // we need to widen it before using it and then truncate the result.
+    // If the operand type of an atomic operation is not byte sized we need to
+    // widen it before using it and then truncate the result.
 
     ir_assert(instruction->value->type->id == ZigTypeIdPointer, instruction);
     ZigType *operand_type = instruction->value->type->data.pointer.child_type;
@@ -5498,7 +5498,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) {
         bool is_signed = operand_type->data.integral.is_signed;
 
         ir_assert(bit_count != 0, instruction);
-        if (bit_count == 1 || !is_power_of_2(bit_count)) {
+        if (!is_power_of_2(bit_count) || bit_count % 8) {
             return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8));
         } else {
             return nullptr;
test/stage1/behavior/atomics.zig
@@ -199,7 +199,7 @@ fn testAtomicRmwInt() !void {
 
 test "atomics with different types" {
     try testAtomicsWithType(bool, true, false);
-    inline for (.{ u1, i5, u15 }) |T| {
+    inline for (.{ u1, i4, u5, i15, u24 }) |T| {
         var x: T = 0;
         try testAtomicsWithType(T, 0, 1);
     }