about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2021-02-21 14:39:31 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2021-02-21 16:51:40 +0100
commit7fc34839acfe1d69df83f79c4c2c8802dea17cdc (patch)
tree6a015839014992f2cd89dddbd5e88bdc68307163 /src
parent0610490c8dc71868ba886efbb8707cb77fc35928 (diff)
downloadrust-7fc34839acfe1d69df83f79c4c2c8802dea17cdc.tar.gz
rust-7fc34839acfe1d69df83f79c4c2c8802dea17cdc.zip
Revert "Remove shift amount masking"
This reverts commit c5f98b586f9c835e8e3ebecf3db260d2f0ad402a.

It turns out to be necessary anyway
Diffstat (limited to 'src')
-rw-r--r--src/num.rs26
1 files changed, 20 insertions, 6 deletions
diff --git a/src/num.rs b/src/num.rs
index 850ff3561f7..2022614841d 100644
--- a/src/num.rs
+++ b/src/num.rs
@@ -168,12 +168,20 @@ pub(crate) fn codegen_int_binop<'tcx>(
         BinOp::BitXor => b.bxor(lhs, rhs),
         BinOp::BitAnd => b.band(lhs, rhs),
         BinOp::BitOr => b.bor(lhs, rhs),
-        BinOp::Shl => fx.bcx.ins().ishl(lhs, rhs),
+        BinOp::Shl => {
+            let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
+            let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
+            let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
+            fx.bcx.ins().ishl(lhs, actual_shift)
+        }
         BinOp::Shr => {
+            let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
+            let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
+            let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
             if signed {
-                fx.bcx.ins().sshr(lhs, rhs)
+                fx.bcx.ins().sshr(lhs, actual_shift)
             } else {
-                fx.bcx.ins().ushr(lhs, rhs)
+                fx.bcx.ins().ushr(lhs, actual_shift)
             }
         }
         // Compare binops handles by `codegen_binop`.
@@ -295,7 +303,10 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
             }
         }
         BinOp::Shl => {
-            let val = fx.bcx.ins().ishl(lhs, rhs);
+            let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
+            let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
+            let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
+            let val = fx.bcx.ins().ishl(lhs, actual_shift);
             let ty = fx.bcx.func.dfg.value_type(val);
             let max_shift = i64::from(ty.bits()) - 1;
             let has_overflow = fx
@@ -305,10 +316,13 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
             (val, has_overflow)
         }
         BinOp::Shr => {
+            let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
+            let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
+            let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
             let val = if !signed {
-                fx.bcx.ins().ushr(lhs, rhs)
+                fx.bcx.ins().ushr(lhs, actual_shift)
             } else {
-                fx.bcx.ins().sshr(lhs, rhs)
+                fx.bcx.ins().sshr(lhs, actual_shift)
             };
             let ty = fx.bcx.func.dfg.value_type(val);
             let max_shift = i64::from(ty.bits()) - 1;