about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-06-28 11:39:22 -0400
committerRalf Jung <post@ralfj.de>2022-07-03 09:56:31 -0400
commit595dd976bdcf54f9de336fcf4665d87e426ffc35 (patch)
treeb00a3c1b7efb0091ce4825d2c27aaffbcd28e40f
parentbaf382e63c023259fa1f9042f8f479f183ca6ed3 (diff)
downloadrust-595dd976bdcf54f9de336fcf4665d87e426ffc35.tar.gz
rust-595dd976bdcf54f9de336fcf4665d87e426ffc35.zip
interpret: don't rely on ScalarPair for overflowed arithmetic
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs18
1 files changed, 16 insertions, 2 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 85ee88e9e47..5d044a7fcd1 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -5,6 +5,7 @@ use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, FloatTy, Ty};
+use rustc_target::abi::Abi;
 
 use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
 
@@ -25,8 +26,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             "type mismatch for result of {:?}",
             op,
         );
-        let val = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
-        self.write_immediate(val, dest)
+        if let Abi::ScalarPair(..) = dest.layout.abi {
+            // We can use the optimized path and avoid `place_field` (which might do
+            // `force_allocation`).
+            let pair = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into());
+            self.write_immediate(pair, dest)?;
+        } else {
+            // With randomized layout, `(int, bool)` might cease to be a `ScalarPair`, so we have to
+            // do a component-wise write here. This code path is slower than the above because
+            // `place_field` will have to `force_allocate` locals here.
+            let val_field = self.place_field(&dest, 0)?;
+            self.write_scalar(val, &val_field)?;
+            let overflowed_field = self.place_field(&dest, 1)?;
+            self.write_scalar(Scalar::from_bool(overflowed), &overflowed_field)?;
+        }
+        Ok(())
     }
 
     /// Applies the binary operation `op` to the arguments and writes the result to the