From 8153729f91e925902490a995c72537208b0232aa Mon Sep 17 00:00:00 2001 From: "Enzo \"raskyld\" Nocera" Date: Sun, 6 Oct 2024 03:45:06 +0200 Subject: [PATCH 1/2] fix(int): avoid infinite recursion on left shift Please, see this discussion for the full context: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/.5Bwasm32.5D.20Infinite.20recursion.20.60compiler-builtins.60.20.60__multi3.60 Signed-off-by: Enzo "raskyld" Nocera We determined that some recursion problems on SPARC and WASM were due to infinite recusion. This was introduced at 9c6fcb56e8 ("Split Int into Int and MinInt") when moving the implementation of `widen_hi` from something on each `impl` block to a default on the trait. The reasoning is not fully understood, but undoing this portion of the change seems to resolve the issue. [ add the above context - Trevor ] Signed-off-by: Trevor Gross --- library/compiler-builtins/src/int/big.rs | 8 ++++++++ library/compiler-builtins/src/int/mod.rs | 7 ++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/library/compiler-builtins/src/int/big.rs b/library/compiler-builtins/src/int/big.rs index e565da897203..0ef3caaedffc 100644 --- a/library/compiler-builtins/src/int/big.rs +++ b/library/compiler-builtins/src/int/big.rs @@ -222,6 +222,10 @@ impl HInt for u128 { fn widen_mul(self, rhs: Self) -> Self::D { self.zero_widen_mul(rhs) } + + fn widen_hi(self) -> Self::D { + self.widen() << ::BITS + } } impl HInt for i128 { @@ -247,6 +251,10 @@ impl HInt for i128 { fn widen_mul(self, rhs: Self) -> Self::D { unimplemented!("signed i128 widening multiply is not used") } + + fn widen_hi(self) -> Self::D { + self.widen() << ::BITS + } } impl DInt for u256 { diff --git a/library/compiler-builtins/src/int/mod.rs b/library/compiler-builtins/src/int/mod.rs index 5f56c6b6ee13..c7ca45e713e2 100644 --- a/library/compiler-builtins/src/int/mod.rs +++ b/library/compiler-builtins/src/int/mod.rs @@ -319,9 +319,7 @@ pub(crate) trait HInt: Int { /// around problems with associated type bounds (such as `Int`) being unstable fn zero_widen(self) -> Self::D; /// Widens the integer to have double bit width and shifts the integer into the higher bits - fn widen_hi(self) -> Self::D { - self.widen() << ::BITS - } + fn widen_hi(self) -> Self::D; /// Widening multiplication with zero widening. This cannot overflow. fn zero_widen_mul(self, rhs: Self) -> Self::D; /// Widening multiplication. This cannot overflow. @@ -364,6 +362,9 @@ macro_rules! impl_h_int { fn widen_mul(self, rhs: Self) -> Self::D { self.widen().wrapping_mul(rhs.widen()) } + fn widen_hi(self) -> Self::D { + (self as $X) << ::BITS + } } )* }; From 996799a896c9d64f5d7d6e5f9c959b0268a0e693 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 5 Oct 2024 20:55:47 -0500 Subject: [PATCH 2/2] Add a note about avoiding default implemenations in some places Link: https://github.com/rust-lang/compiler-builtins/pull/707 --- library/compiler-builtins/src/int/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/compiler-builtins/src/int/mod.rs b/library/compiler-builtins/src/int/mod.rs index c7ca45e713e2..e6f31c530132 100644 --- a/library/compiler-builtins/src/int/mod.rs +++ b/library/compiler-builtins/src/int/mod.rs @@ -313,6 +313,10 @@ pub(crate) trait HInt: Int { /// Integer that is double the bit width of the integer this trait is implemented for type D: DInt + MinInt; + // NB: some of the below methods could have default implementations (e.g. `widen_hi`), but for + // unknown reasons this can cause infinite recursion when optimizations are disabled. See + // for context. + /// Widens (using default extension) the integer to have double bit width fn widen(self) -> Self::D; /// Widens (zero extension only) the integer to have double bit width. This is needed to get