From 3f84b6c80ed3306f040dd98b8ccba561a052167a Mon Sep 17 00:00:00 2001 From: mlugg Date: Wed, 24 Sep 2025 00:36:17 +0100 Subject: [PATCH] cbe: workaround GCC miscompilation This was causing a zig2 miscomp, which emitted slightly broken debug information, which caused extremely slow stack unwinding. We're working on fixing or reporting this upstream, but we can use this workaround for now, because GCC guarantees arithmetic signed shift. --- lib/zig.h | 8 ++++++++ stage1/zig.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/lib/zig.h b/lib/zig.h index 5c96b4bea0..5253912490 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -1510,8 +1510,16 @@ static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { } static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + // This works around a GCC miscompilation, but it has the side benefit of + // emitting better code. It is behind the `#if` because it depends on + // arithmetic right shift, which is implementation-defined in C, but should + // be guaranteed on any GCC-compatible compiler. +#if defined(zig_gnuc) + return lhs >> rhs; +#else zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; +#endif } static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { diff --git a/stage1/zig.h b/stage1/zig.h index 5c96b4bea0..5253912490 100644 --- a/stage1/zig.h +++ b/stage1/zig.h @@ -1510,8 +1510,16 @@ static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { } static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + // This works around a GCC miscompilation, but it has the side benefit of + // emitting better code. It is behind the `#if` because it depends on + // arithmetic right shift, which is implementation-defined in C, but should + // be guaranteed on any GCC-compatible compiler. +#if defined(zig_gnuc) + return lhs >> rhs; +#else zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; +#endif } static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {