about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2019-11-16 16:44:26 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2019-11-16 16:44:26 +0100
commitb0bcb23eb497bbfbf20ab4b0b36b6fe37fbd7368 (patch)
treed58bbef3e6fe04267b3b28ec7d7b8d64fcc63e90
parentd2eafd858fa0d69bcdc5fca5e667ce296da9d1f5 (diff)
downloadrust-b0bcb23eb497bbfbf20ab4b0b36b6fe37fbd7368.tar.gz
rust-b0bcb23eb497bbfbf20ab4b0b36b6fe37fbd7368.zip
Fix signed cast to 128bit integer
-rw-r--r--example/std_example.rs7
-rw-r--r--src/cast.rs10
2 files changed, 13 insertions, 4 deletions
diff --git a/example/std_example.rs b/example/std_example.rs
index 50f794733e3..d6734e74498 100644
--- a/example/std_example.rs
+++ b/example/std_example.rs
@@ -53,7 +53,12 @@ fn main() {
     assert_eq!(0b100010000000000000000000000000000u128 >> 10, 0b10001000000000000000000u128);
     assert_eq!(0xFEDCBA987654321123456789ABCDEFu128 >> 64, 0xFEDCBA98765432u128);
     assert_eq!(0xFEDCBA987654321123456789ABCDEFu128 as i128 >> 64, 0xFEDCBA98765432i128);
-    assert_eq!(353985398u128 * 932490u128, 330087843781020u128);
+
+    let tmp = 353985398u128;
+    assert_eq!(tmp * 932490u128, 330087843781020u128);
+
+    let tmp = -0x1234_5678_9ABC_DEF0i64;
+    assert_eq!(tmp as i128, -0x1234_5678_9ABC_DEF0i128);
 
     // Check that all u/i128 <-> float casts work correctly.
     let houndred_u128 = 100u128;
diff --git a/src/cast.rs b/src/cast.rs
index 41503ea86c8..870c316f41d 100644
--- a/src/cast.rs
+++ b/src/cast.rs
@@ -13,15 +13,19 @@ pub fn clif_intcast(
 
         // extend
         (_, types::I128) => {
-            let wider = if from == types::I64 {
+            let lo = if from == types::I64 {
                 val
             } else if signed {
                 fx.bcx.ins().sextend(types::I64, val)
             } else {
                 fx.bcx.ins().uextend(types::I64, val)
             };
-            let zero = fx.bcx.ins().iconst(types::I64, 0);
-            fx.bcx.ins().iconcat(wider, zero)
+            let hi = if signed {
+                fx.bcx.ins().sshr_imm(lo, 63)
+            } else {
+                fx.bcx.ins().iconst(types::I64, 0)
+            };
+            fx.bcx.ins().iconcat(lo, hi)
         }
         (_, _) if to.wider_or_equal(from) => {
             if signed {