Skip to content

Commit 38b5812

Browse files
committed
allow 128 bit cmpxchg on x86_64
1 parent ceec239 commit 38b5812

File tree

4 files changed

+91
-3
lines changed

4 files changed

+91
-3
lines changed

src/ir.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24735,10 +24735,11 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
2473524735
operand_type->data.integral.bit_count));
2473624736
return ira->codegen->builtin_types.entry_invalid;
2473724737
}
24738-
if (operand_type->data.integral.bit_count > ira->codegen->pointer_size_bytes * 8) {
24738+
uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch);
24739+
if (operand_type->data.integral.bit_count > max_atomic_bits) {
2473924740
ir_add_error(ira, op,
24740-
buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type",
24741-
operand_type->data.integral.bit_count));
24741+
buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type",
24742+
max_atomic_bits, operand_type->data.integral.bit_count));
2474224743
return ira->codegen->builtin_types.entry_invalid;
2474324744
}
2474424745
if (!is_power_of_2(operand_type->data.integral.bit_count)) {

src/target.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,71 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) {
863863
zig_unreachable();
864864
}
865865

866+
uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) {
867+
switch (arch) {
868+
case ZigLLVM_UnknownArch:
869+
zig_unreachable();
870+
871+
case ZigLLVM_avr:
872+
case ZigLLVM_msp430:
873+
return 16;
874+
875+
case ZigLLVM_arc:
876+
case ZigLLVM_arm:
877+
case ZigLLVM_armeb:
878+
case ZigLLVM_hexagon:
879+
case ZigLLVM_le32:
880+
case ZigLLVM_mips:
881+
case ZigLLVM_mipsel:
882+
case ZigLLVM_nvptx:
883+
case ZigLLVM_ppc:
884+
case ZigLLVM_r600:
885+
case ZigLLVM_riscv32:
886+
case ZigLLVM_sparc:
887+
case ZigLLVM_sparcel:
888+
case ZigLLVM_tce:
889+
case ZigLLVM_tcele:
890+
case ZigLLVM_thumb:
891+
case ZigLLVM_thumbeb:
892+
case ZigLLVM_x86:
893+
case ZigLLVM_xcore:
894+
case ZigLLVM_amdil:
895+
case ZigLLVM_hsail:
896+
case ZigLLVM_spir:
897+
case ZigLLVM_kalimba:
898+
case ZigLLVM_lanai:
899+
case ZigLLVM_shave:
900+
case ZigLLVM_wasm32:
901+
case ZigLLVM_renderscript32:
902+
return 32;
903+
904+
case ZigLLVM_aarch64:
905+
case ZigLLVM_aarch64_be:
906+
case ZigLLVM_amdgcn:
907+
case ZigLLVM_bpfel:
908+
case ZigLLVM_bpfeb:
909+
case ZigLLVM_le64:
910+
case ZigLLVM_mips64:
911+
case ZigLLVM_mips64el:
912+
case ZigLLVM_nvptx64:
913+
case ZigLLVM_ppc64:
914+
case ZigLLVM_ppc64le:
915+
case ZigLLVM_riscv64:
916+
case ZigLLVM_sparcv9:
917+
case ZigLLVM_systemz:
918+
case ZigLLVM_amdil64:
919+
case ZigLLVM_hsail64:
920+
case ZigLLVM_spir64:
921+
case ZigLLVM_wasm64:
922+
case ZigLLVM_renderscript64:
923+
return 64;
924+
925+
case ZigLLVM_x86_64:
926+
return 128;
927+
}
928+
zig_unreachable();
929+
}
930+
866931
uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
867932
switch (target->os) {
868933
case OsFreestanding:
@@ -1693,3 +1758,4 @@ bool target_supports_libunwind(const ZigTarget *target) {
16931758
}
16941759
return true;
16951760
}
1761+

src/target.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ const char *target_arch_musl_name(ZigLLVM_ArchType arch);
192192
bool target_supports_libunwind(const ZigTarget *target);
193193

194194
uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
195+
uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch);
195196

196197
size_t target_libc_count(void);
197198
void target_libc_enum(size_t index, ZigTarget *out_target);

test/stage1/behavior/atomics.zig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,23 @@ test "cmpxchg with ptr" {
6969
expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
7070
expect(x == &data2);
7171
}
72+
73+
test "128-bit cmpxchg" {
74+
if (builtin.arch != .x86_64) {
75+
return error.SkipZigTest;
76+
}
77+
var x: u128 align(16) = 1234; // TODO: https://github.com/ziglang/zig/issues/2987
78+
if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| {
79+
expect(x1 == 1234);
80+
} else {
81+
@panic("cmpxchg should have failed");
82+
}
83+
84+
while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| {
85+
expect(x1 == 1234);
86+
}
87+
expect(x == 5678);
88+
89+
expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null);
90+
expect(x == 42);
91+
}

0 commit comments

Comments
 (0)