Commit 3f84b6c80e

mlugg <mlugg@mlugg.co.uk>
2025-09-24 01:36:17
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.
1 parent dbda011
Changed files (2)
lib
stage1
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) {
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) {