From 38b5812c4895eb0157f99348f51c40bbd17c3b94 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 1 Aug 2019 02:37:22 -0400 Subject: [PATCH] allow 128 bit cmpxchg on x86_64 --- src/ir.cpp | 7 ++-- src/target.cpp | 66 ++++++++++++++++++++++++++++++++ src/target.hpp | 1 + test/stage1/behavior/atomics.zig | 20 ++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index be7a8e2e5..f34c84049 100644 --- a/src/ir.cpp +++ b/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)) { diff --git a/src/target.cpp b/src/target.cpp index 6a949270a..7bb248a35 100644 --- a/src/target.cpp +++ b/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; } + diff --git a/src/target.hpp b/src/target.hpp index fcda9955b..985a4c11b 100644 --- a/src/target.hpp +++ b/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); diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig index daa463fd4..3d1caaaa1 100644 --- a/test/stage1/behavior/atomics.zig +++ b/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); +}