about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2019-06-12 20:54:38 +0200
committerbjorn3 <bjorn3@users.noreply.github.com>2019-07-26 11:28:04 +0200
commitde32ddad23abbc831ae60d5efefab0df84e8910b (patch)
tree1c71f8ade410be7506733fdff2a254768e0955ca
parentbf3ec3be3e595780d842ac3069bb07f3c50f54b8 (diff)
downloadrust-de32ddad23abbc831ae60d5efefab0df84e8910b.tar.gz
rust-de32ddad23abbc831ae60d5efefab0df84e8910b.zip
[WIP] Basic i128 support
-rw-r--r--Cargo.lock60
-rw-r--r--Cargo.toml10
-rw-r--r--example/mini_core.rs8
-rw-r--r--example/mini_core_hello_world.rs136
-rw-r--r--src/abi.rs2
-rw-r--r--src/base.rs145
-rw-r--r--src/common.rs4
-rw-r--r--src/value_and_place.rs28
8 files changed, 144 insertions, 249 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6e9f0955a92..6752108006f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -117,28 +117,25 @@ dependencies = [
 [[package]]
 name = "cranelift"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 dependencies = [
- "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-frontend 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift-codegen 0.36.0",
+ "cranelift-frontend 0.36.0",
 ]
 
 [[package]]
 name = "cranelift-bforest"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 dependencies = [
- "cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift-entity 0.36.0",
 ]
 
 [[package]]
 name = "cranelift-codegen"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 dependencies = [
- "cranelift-bforest 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-codegen-meta 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift-bforest 0.36.0",
+ "cranelift-codegen-meta 0.36.0",
+ "cranelift-entity 0.36.0",
  "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -148,23 +145,20 @@ dependencies = [
 [[package]]
 name = "cranelift-codegen-meta"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 dependencies = [
- "cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift-entity 0.36.0",
 ]
 
 [[package]]
 name = "cranelift-entity"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 
 [[package]]
 name = "cranelift-faerie"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 dependencies = [
- "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-module 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift-codegen 0.36.0",
+ "cranelift-module 0.36.0",
  "faerie 0.10.1 (git+https://github.com/m4b/faerie.git)",
  "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "goblin 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -174,9 +168,8 @@ dependencies = [
 [[package]]
 name = "cranelift-frontend"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 dependencies = [
- "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift-codegen 0.36.0",
  "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -184,10 +177,9 @@ dependencies = [
 [[package]]
 name = "cranelift-module"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 dependencies = [
- "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift-codegen 0.36.0",
+ "cranelift-entity 0.36.0",
  "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -195,9 +187,8 @@ dependencies = [
 [[package]]
 name = "cranelift-native"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 dependencies = [
- "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift-codegen 0.36.0",
  "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "target-lexicon 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -205,11 +196,10 @@ dependencies = [
 [[package]]
 name = "cranelift-simplejit"
 version = "0.36.0"
-source = "git+https://github.com/CraneStation/cranelift.git#e7f2b719eebfb9280c3e38eae42a9ee25221a4e3"
 dependencies = [
- "cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-module 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-native 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift-codegen 0.36.0",
+ "cranelift-module 0.36.0",
+ "cranelift-native 0.36.0",
  "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "region 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -611,10 +601,10 @@ dependencies = [
  "ar 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "cranelift 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-faerie 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-module 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
- "cranelift-simplejit 0.36.0 (git+https://github.com/CraneStation/cranelift.git)",
+ "cranelift 0.36.0",
+ "cranelift-faerie 0.36.0",
+ "cranelift-module 0.36.0",
+ "cranelift-simplejit 0.36.0",
  "faerie 0.10.1 (git+https://github.com/m4b/faerie.git)",
  "gimli 0.19.0 (git+https://github.com/gimli-rs/gimli.git)",
  "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -882,16 +872,6 @@ dependencies = [
 "checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
 "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
 "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
-"checksum cranelift 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
-"checksum cranelift-bforest 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
-"checksum cranelift-codegen 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
-"checksum cranelift-codegen-meta 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
-"checksum cranelift-entity 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
-"checksum cranelift-faerie 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
-"checksum cranelift-frontend 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
-"checksum cranelift-module 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
-"checksum cranelift-native 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
-"checksum cranelift-simplejit 0.36.0 (git+https://github.com/CraneStation/cranelift.git)" = "<none>"
 "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
 "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
 "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e"
diff --git a/Cargo.toml b/Cargo.toml
index 59d66d07fa9..64126d917f3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,11 +28,11 @@ indexmap = "1.0.2"
 object = "0.12.0"
 
 # Uncomment to use local checkout of cranelift
-#[patch."https://github.com/CraneStation/cranelift.git"]
-#cranelift = { path = "../cranelift/cranelift-umbrella" }
-#cranelift-module = { path = "../cranelift/cranelift-module" }
-#cranelift-simplejit = { path = "../cranelift/cranelift-simplejit" }
-#cranelift-faerie = { path = "../cranelift/cranelift-faerie" }
+[patch."https://github.com/CraneStation/cranelift.git"]
+cranelift = { path = "../cranelift/cranelift-umbrella" }
+cranelift-module = { path = "../cranelift/cranelift-module" }
+cranelift-simplejit = { path = "../cranelift/cranelift-simplejit" }
+cranelift-faerie = { path = "../cranelift/cranelift-faerie" }
 
 #[patch."https://github.com/gimli-rs/gimli.git"]
 #gimli = { path = "../" }
diff --git a/example/mini_core.rs b/example/mini_core.rs
index 8c372450abd..745e86de485 100644
--- a/example/mini_core.rs
+++ b/example/mini_core.rs
@@ -144,6 +144,14 @@ impl Add for usize {
     }
 }
 
+impl Add for u128 {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self {
+        self + rhs
+    }
+}
+
 #[lang = "sub"]
 pub trait Sub<RHS = Self> {
     type Output;
diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs
index 15f0442b624..23a92c73780 100644
--- a/example/mini_core_hello_world.rs
+++ b/example/mini_core_hello_world.rs
@@ -118,139 +118,5 @@ fn take_f32(_f: f32) {}
 fn take_unique(_u: Unique<()>) {}
 
 fn main() {
-    take_unique(Unique {
-        pointer: 0 as *const (),
-        _marker: PhantomData,
-    });
-    take_f32(0.1);
-
-    //return;
-
-    unsafe {
-        printf("Hello %s\n\0" as *const str as *const i8, "printf\0" as *const str as *const i8);
-
-        let hello: &[u8] = b"Hello\0" as &[u8; 6];
-        let ptr: *const u8 = hello as *const [u8] as *const u8;
-        puts(ptr);
-
-        let world: Box<&str> = box "World!\0";
-        puts(*world as *const str as *const u8);
-        world as Box<SomeTrait>;
-
-        assert_eq!(intrinsics::bitreverse(0b10101000u8), 0b00010101u8);
-
-        assert_eq!(intrinsics::bswap(0xabu8), 0xabu8);
-        assert_eq!(intrinsics::bswap(0xddccu16), 0xccddu16);
-        assert_eq!(intrinsics::bswap(0xffee_ddccu32), 0xccdd_eeffu32);
-        assert_eq!(intrinsics::bswap(0x1234_5678_ffee_ddccu64), 0xccdd_eeff_7856_3412u64);
-
-        assert_eq!(intrinsics::size_of_val(hello) as u8, 6);
-
-        let chars = &['C', 'h', 'a', 'r', 's'];
-        let chars = chars as &[char];
-        assert_eq!(intrinsics::size_of_val(chars) as u8, 4 * 5);
-
-        let a: &dyn SomeTrait = &"abc\0";
-        a.object_safe();
-
-        assert_eq!(intrinsics::size_of_val(a) as u8, 16);
-        assert_eq!(intrinsics::size_of_val(&0u32) as u8, 4);
-
-        assert_eq!(intrinsics::min_align_of::<u16>() as u8, 2);
-        assert_eq!(intrinsics::min_align_of_val(&a) as u8, intrinsics::min_align_of::<&str>() as u8);
-
-        assert!(!intrinsics::needs_drop::<u8>());
-        assert!(intrinsics::needs_drop::<NoisyDrop>());
-
-        Unique {
-            pointer: 0 as *const &str,
-            _marker: PhantomData,
-        } as Unique<dyn SomeTrait>;
-
-        struct MyDst<T: ?Sized>(T);
-
-        intrinsics::size_of_val(&MyDst([0u8; 4]) as &MyDst<[u8]>);
-
-        struct Foo {
-            x: u8,
-            y: !,
-        }
-
-        unsafe fn zeroed<T>() -> T {
-            intrinsics::init::<T>()
-        }
-
-        unsafe fn uninitialized<T>() -> T {
-            MaybeUninit { uninit: () }.value
-        }
-
-        zeroed::<(u8, u8)>();
-        #[allow(unreachable_code)]
-        {
-            if false {
-                zeroed::<!>();
-                zeroed::<Foo>();
-                uninitialized::<Foo>();
-            }
-        }
-    }
-
-    let _ = box NoisyDrop {
-        text: "Boxed outer got dropped!\0",
-        inner: NoisyDropInner,
-    } as Box<SomeTrait>;
-
-    const FUNC_REF: Option<fn()> = Some(main);
-    match FUNC_REF {
-        Some(_) => {},
-        None => assert!(false),
-    }
-
-    match Ordering::Less {
-        Ordering::Less => {},
-        _ => assert!(false),
-    }
-
-    [NoisyDropInner, NoisyDropInner];
-
-    let x = &[0u32, 42u32] as &[u32];
-    match x {
-        [] => assert_eq!(0u32, 1),
-        [_, ref y..] => assert_eq!(&x[1] as *const u32 as usize, &y[0] as *const u32 as usize),
-    }
-
-    assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
-
-    extern {
-        #[linkage = "weak"]
-        static ABC: *const u8;
-    }
-
-    {
-        extern {
-            #[linkage = "weak"]
-            static ABC: *const u8;
-        }
-    }
-
-    unsafe { assert_eq!(ABC as usize, 0); }
-
-    &mut (|| Some(0 as *const ())) as &mut FnMut() -> Option<*const ()>;
-
-    // checked binops
-    let zeroi8 = 0i8;
-    let oneu8 = 1u8;
-    let onei8 = 1i8;
-    zeroi8 - 1;
-    oneu8 - 1;
-    zeroi8 - -2i8;
-    #[allow(unreachable_code)]
-    {
-        if false {
-            let minustwoi8 = -2i8;
-            oneu8 + 255;
-            onei8 + 127;
-            minustwoi8 - 127;
-        }
-    }
+    assert_eq!((1u128 + 2) as u16, 3);
 }
diff --git a/src/abi.rs b/src/abi.rs
index 2397da9be26..b7e7d0a830a 100644
--- a/src/abi.rs
+++ b/src/abi.rs
@@ -87,7 +87,7 @@ pub fn scalar_to_clif_type(tcx: TyCtxt, scalar: Scalar) -> Type {
             Integer::I16 => types::I16,
             Integer::I32 => types::I32,
             Integer::I64 => types::I64,
-            Integer::I128 => unimpl!("u/i128"),
+            Integer::I128 => types::I128,
         },
         Primitive::Float(flt) => match flt {
             FloatTy::F32 => types::F32,
diff --git a/src/base.rs b/src/base.rs
index 7b29d15e56b..f8bd5672346 100644
--- a/src/base.rs
+++ b/src/base.rs
@@ -899,6 +899,19 @@ pub fn trans_int_binop<'a, 'tcx: 'a>(
             "int binop requires lhs and rhs of same type"
         );
     }
+
+    if out_ty == fx.tcx.types.u128 || out_ty == fx.tcx.types.i128 {
+        return match (bin_op, signed) {
+            _ => {
+                let layout = fx.layout_of(out_ty);
+                let a = fx.bcx.ins().iconst(types::I64, 42);
+                let b = fx.bcx.ins().iconst(types::I64, 0);
+                let val = fx.bcx.ins().iconcat(a, b);
+                CValue::by_val(val, layout)
+            }
+        }
+    }
+
     binop_match! {
         fx, bin_op, signed, lhs, rhs, out_ty, "int/uint";
         Add (_) iadd;
@@ -948,69 +961,79 @@ pub fn trans_checked_int_binop<'a, 'tcx: 'a>(
 
     let lhs = in_lhs.load_scalar(fx);
     let rhs = in_rhs.load_scalar(fx);
-    let (res, has_overflow) = match bin_op {
-        BinOp::Add => {
-            /*let (val, c_out) = fx.bcx.ins().iadd_cout(lhs, rhs);
-            (val, c_out)*/
-            // FIXME(CraneStation/cranelift#849) legalize iadd_cout for i8 and i16
-            let val = fx.bcx.ins().iadd(lhs, rhs);
-            let has_overflow = if !signed {
-                fx.bcx.ins().icmp(IntCC::UnsignedLessThan, val, lhs)
-            } else {
-                let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
-                let slt = fx.bcx.ins().icmp(IntCC::SignedLessThan, val, lhs);
-                fx.bcx.ins().bxor(rhs_is_negative, slt)
-            };
-            (val, has_overflow)
-        }
-        BinOp::Sub => {
-            /*let (val, b_out) = fx.bcx.ins().isub_bout(lhs, rhs);
-            (val, b_out)*/
-            // FIXME(CraneStation/cranelift#849) legalize isub_bout for i8 and i16
-            let val = fx.bcx.ins().isub(lhs, rhs);
-            let has_overflow = if !signed {
-                fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, val, lhs)
-            } else {
-                let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
-                let sgt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, val, lhs);
-                fx.bcx.ins().bxor(rhs_is_negative, sgt)
-            };
-            (val, has_overflow)
-        }
-        BinOp::Mul => {
-            let val = fx.bcx.ins().imul(lhs, rhs);
-            /*let val_hi = if !signed {
-                fx.bcx.ins().umulhi(lhs, rhs)
-            } else {
-                fx.bcx.ins().smulhi(lhs, rhs)
-            };
-            let has_overflow = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0);*/
-            // TODO: check for overflow
-            let has_overflow = fx.bcx.ins().bconst(types::B1, false);
-            (val, has_overflow)
-        }
-        BinOp::Shl => {
-            let val = fx.bcx.ins().ishl(lhs, rhs);
-            // TODO: check for overflow
-            let has_overflow = fx.bcx.ins().bconst(types::B1, false);
-            (val, has_overflow)
+    let (res, has_overflow) = if in_lhs.layout().ty == fx.tcx.types.u128 || in_lhs.layout().ty == fx.tcx.types.i128 {
+        match (bin_op, signed) {
+            _ => {
+                let a = fx.bcx.ins().iconst(types::I64, 42);
+                let b = fx.bcx.ins().iconst(types::I64, 0);
+                (fx.bcx.ins().iconcat(a, b), fx.bcx.ins().bconst(types::B1, false))
+            }
         }
-        BinOp::Shr => {
-            let val = if !signed {
-                fx.bcx.ins().ushr(lhs, rhs)
-            } else {
-                fx.bcx.ins().sshr(lhs, rhs)
-            };
-            // TODO: check for overflow
-            let has_overflow = fx.bcx.ins().bconst(types::B1, false);
-            (val, has_overflow)
+    } else {
+        match bin_op {
+            BinOp::Add => {
+                /*let (val, c_out) = fx.bcx.ins().iadd_cout(lhs, rhs);
+                (val, c_out)*/
+                // FIXME(CraneStation/cranelift#849) legalize iadd_cout for i8 and i16
+                let val = fx.bcx.ins().iadd(lhs, rhs);
+                let has_overflow = if !signed {
+                    fx.bcx.ins().icmp(IntCC::UnsignedLessThan, val, lhs)
+                } else {
+                    let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
+                    let slt = fx.bcx.ins().icmp(IntCC::SignedLessThan, val, lhs);
+                    fx.bcx.ins().bxor(rhs_is_negative, slt)
+                };
+                (val, has_overflow)
+            }
+            BinOp::Sub => {
+                /*let (val, b_out) = fx.bcx.ins().isub_bout(lhs, rhs);
+                (val, b_out)*/
+                // FIXME(CraneStation/cranelift#849) legalize isub_bout for i8 and i16
+                let val = fx.bcx.ins().isub(lhs, rhs);
+                let has_overflow = if !signed {
+                    fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, val, lhs)
+                } else {
+                    let rhs_is_negative = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, rhs, 0);
+                    let sgt = fx.bcx.ins().icmp(IntCC::SignedGreaterThan, val, lhs);
+                    fx.bcx.ins().bxor(rhs_is_negative, sgt)
+                };
+                (val, has_overflow)
+            }
+            BinOp::Mul => {
+                let val = fx.bcx.ins().imul(lhs, rhs);
+                /*let val_hi = if !signed {
+                    fx.bcx.ins().umulhi(lhs, rhs)
+                } else {
+                    fx.bcx.ins().smulhi(lhs, rhs)
+                };
+                let has_overflow = fx.bcx.ins().icmp_imm(IntCC::NotEqual, val_hi, 0);*/
+                // TODO: check for overflow
+                let has_overflow = fx.bcx.ins().bconst(types::B1, false);
+                (val, has_overflow)
+            }
+            BinOp::Shl => {
+                let val = fx.bcx.ins().ishl(lhs, rhs);
+                // TODO: check for overflow
+                let has_overflow = fx.bcx.ins().bconst(types::B1, false);
+                (val, has_overflow)
+            }
+            BinOp::Shr => {
+                let val = if !signed {
+                    fx.bcx.ins().ushr(lhs, rhs)
+                } else {
+                    fx.bcx.ins().sshr(lhs, rhs)
+                };
+                // TODO: check for overflow
+                let has_overflow = fx.bcx.ins().bconst(types::B1, false);
+                (val, has_overflow)
+            }
+            _ => bug!(
+                "binop {:?} on checked int/uint lhs: {:?} rhs: {:?}",
+                bin_op,
+                in_lhs,
+                in_rhs
+            ),
         }
-        _ => bug!(
-            "binop {:?} on checked int/uint lhs: {:?} rhs: {:?}",
-            bin_op,
-            in_lhs,
-            in_rhs
-        ),
     };
 
     let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
diff --git a/src/common.rs b/src/common.rs
index bffa526c8b4..30f343d02b2 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -28,7 +28,7 @@ pub fn clif_type_from_ty<'tcx>(
             UintTy::U16 => types::I16,
             UintTy::U32 => types::I32,
             UintTy::U64 => types::I64,
-            UintTy::U128 => unimpl!("u128"),
+            UintTy::U128 => types::I128,
             UintTy::Usize => pointer_ty(tcx),
         },
         ty::Int(size) => match size {
@@ -36,7 +36,7 @@ pub fn clif_type_from_ty<'tcx>(
             IntTy::I16 => types::I16,
             IntTy::I32 => types::I32,
             IntTy::I64 => types::I64,
-            IntTy::I128 => unimpl!("i128"),
+            IntTy::I128 => types::I128,
             IntTy::Isize => pointer_ty(tcx),
         },
         ty::Char => types::I32,
diff --git a/src/value_and_place.rs b/src/value_and_place.rs
index 716a81c5d8a..6bd82265bc1 100644
--- a/src/value_and_place.rs
+++ b/src/value_and_place.rs
@@ -34,6 +34,16 @@ enum CValueInner {
     ByValPair(Value, Value),
 }
 
+fn store_scalar<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx, impl Backend>, value: Value, addr: Value, offset: i32) {
+    if fx.bcx.func.dfg.value_type(value) == types::I128 {
+        let (a, b) = fx.bcx.ins().isplit(value);
+        fx.bcx.ins().store(MemFlags::new(), a, addr, offset);
+        fx.bcx.ins().store(MemFlags::new(), b, addr, offset + 8);
+    } else {
+        fx.bcx.ins().store(MemFlags::new(), value, addr, offset);
+    }
+}
+
 impl<'tcx> CValue<'tcx> {
     pub fn by_ref(value: Value, layout: TyLayout<'tcx>) -> CValue<'tcx> {
         CValue(CValueInner::ByRef(value), layout)
@@ -147,7 +157,15 @@ impl<'tcx> CValue<'tcx> {
     {
         let clif_ty = fx.clif_type(ty).unwrap();
         let layout = fx.layout_of(ty);
-        CValue::by_val(fx.bcx.ins().iconst(clif_ty, const_val), layout)
+        let val = if clif_ty == types::I128 {
+            // FIXME don't assume little-endian arch
+            let lsb = fx.bcx.ins().iconst(types::I64, const_val);
+            let msb = fx.bcx.ins().iconst(types::I64, 0);
+            fx.bcx.ins().iconcat(lsb, msb)
+        } else {
+            fx.bcx.ins().iconst(clif_ty, const_val)
+        };
+        CValue::by_val(val, layout)
     }
 
     pub fn unchecked_cast_to(self, layout: TyLayout<'tcx>) -> Self {
@@ -343,15 +361,15 @@ impl<'a, 'tcx: 'a> CPlace<'tcx> {
 
         match from.0 {
             CValueInner::ByVal(val) => {
-                fx.bcx.ins().store(MemFlags::new(), val, addr, 0);
+                store_scalar(fx, val, addr, 0);
             }
             CValueInner::ByValPair(value, extra) => {
                 match dst_layout.abi {
                     Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
                         let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
-                        fx.bcx.ins().store(MemFlags::new(), value, addr, 0);
-                        fx.bcx.ins().store(
-                            MemFlags::new(),
+                        store_scalar(fx, value, addr, 0);
+                        store_scalar(
+                            fx,
                             extra,
                             addr,
                             b_offset,