Commit 38b5812c48

Andrew Kelley <andrew@ziglang.org>
2019-08-01 08:37:22
allow 128 bit cmpxchg on x86_64
1 parent ceec239
Changed files (4)
src
test
stage1
behavior
src/ir.cpp
@@ -24735,10 +24735,11 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
                     operand_type->data.integral.bit_count));
             return ira->codegen->builtin_types.entry_invalid;
         }
-        if (operand_type->data.integral.bit_count > ira->codegen->pointer_size_bytes * 8) {
+        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) {
             ir_add_error(ira, op,
-                buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type",
-                    operand_type->data.integral.bit_count));
+                buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type",
+                    max_atomic_bits, operand_type->data.integral.bit_count));
             return ira->codegen->builtin_types.entry_invalid;
         }
         if (!is_power_of_2(operand_type->data.integral.bit_count)) {
src/target.cpp
@@ -863,6 +863,71 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) {
     zig_unreachable();
 }
 
+uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) {
+    switch (arch) {
+        case ZigLLVM_UnknownArch:
+            zig_unreachable();
+
+        case ZigLLVM_avr:
+        case ZigLLVM_msp430:
+            return 16;
+
+        case ZigLLVM_arc:
+        case ZigLLVM_arm:
+        case ZigLLVM_armeb:
+        case ZigLLVM_hexagon:
+        case ZigLLVM_le32:
+        case ZigLLVM_mips:
+        case ZigLLVM_mipsel:
+        case ZigLLVM_nvptx:
+        case ZigLLVM_ppc:
+        case ZigLLVM_r600:
+        case ZigLLVM_riscv32:
+        case ZigLLVM_sparc:
+        case ZigLLVM_sparcel:
+        case ZigLLVM_tce:
+        case ZigLLVM_tcele:
+        case ZigLLVM_thumb:
+        case ZigLLVM_thumbeb:
+        case ZigLLVM_x86:
+        case ZigLLVM_xcore:
+        case ZigLLVM_amdil:
+        case ZigLLVM_hsail:
+        case ZigLLVM_spir:
+        case ZigLLVM_kalimba:
+        case ZigLLVM_lanai:
+        case ZigLLVM_shave:
+        case ZigLLVM_wasm32:
+        case ZigLLVM_renderscript32:
+            return 32;
+
+        case ZigLLVM_aarch64:
+        case ZigLLVM_aarch64_be:
+        case ZigLLVM_amdgcn:
+        case ZigLLVM_bpfel:
+        case ZigLLVM_bpfeb:
+        case ZigLLVM_le64:
+        case ZigLLVM_mips64:
+        case ZigLLVM_mips64el:
+        case ZigLLVM_nvptx64:
+        case ZigLLVM_ppc64:
+        case ZigLLVM_ppc64le:
+        case ZigLLVM_riscv64:
+        case ZigLLVM_sparcv9:
+        case ZigLLVM_systemz:
+        case ZigLLVM_amdil64:
+        case ZigLLVM_hsail64:
+        case ZigLLVM_spir64:
+        case ZigLLVM_wasm64:
+        case ZigLLVM_renderscript64:
+            return 64;
+
+        case ZigLLVM_x86_64:
+            return 128;
+    }
+    zig_unreachable();
+}
+
 uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
     switch (target->os) {
         case OsFreestanding:
@@ -1693,3 +1758,4 @@ bool target_supports_libunwind(const ZigTarget *target) {
     }
     return true;
 }
+
src/target.hpp
@@ -192,6 +192,7 @@ const char *target_arch_musl_name(ZigLLVM_ArchType arch);
 bool target_supports_libunwind(const ZigTarget *target);
 
 uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
+uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch);
 
 size_t target_libc_count(void);
 void target_libc_enum(size_t index, ZigTarget *out_target);
test/stage1/behavior/atomics.zig
@@ -69,3 +69,23 @@ test "cmpxchg with ptr" {
     expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
     expect(x == &data2);
 }
+
+test "128-bit cmpxchg" {
+    if (builtin.arch != .x86_64) {
+        return error.SkipZigTest;
+    }
+    var x: u128 align(16) = 1234; // TODO: https://github.com/ziglang/zig/issues/2987
+    if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
+        expect(x1 == 1234);
+    } else {
+        @panic("cmpxchg should have failed");
+    }
+
+    while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
+        expect(x1 == 1234);
+    }
+    expect(x == 5678);
+
+    expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null);
+    expect(x == 42);
+}