about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJake Goulding <jake.goulding@gmail.com>2016-05-06 09:31:11 -0400
committerJake Goulding <jake.goulding@gmail.com>2016-05-19 13:55:13 -0400
commitbc7595c8abbf4e3b737e926d61814686e0ebda77 (patch)
tree3ead763b6c18622639409543dc3a46ba1e6374c1
parent2fb6f8e2c94a7041877ed8460f2621974c5233f7 (diff)
downloadrust-bc7595c8abbf4e3b737e926d61814686e0ebda77.tar.gz
rust-bc7595c8abbf4e3b737e926d61814686e0ebda77.zip
Support 16-bit pointers as well as i/usize
This is based on the original work of Dylan McKay for the
[avr-rust project][ar].

[ar]: https://github.com/avr-rust/rust
-rw-r--r--src/liballoc/raw_vec.rs6
-rw-r--r--src/libcore/fmt/num.rs4
-rw-r--r--src/libcore/mem.rs11
-rw-r--r--src/libcore/num/isize.rs2
-rw-r--r--src/libcore/num/mod.rs21
-rw-r--r--src/libcore/num/usize.rs2
-rw-r--r--src/libcore/num/wrapping.rs6
-rw-r--r--src/libcoretest/mem.rs14
-rw-r--r--src/librustc/session/config.rs1
-rw-r--r--src/librustc/ty/layout.rs2
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc_const_eval/eval.rs3
-rw-r--r--src/librustc_const_math/int.rs39
-rw-r--r--src/librustc_const_math/is.rs4
-rw-r--r--src/librustc_const_math/us.rs4
-rw-r--r--src/librustc_trans/expr.rs2
-rw-r--r--src/librustc_trans/intrinsic.rs2
-rw-r--r--src/librustc_trans/type_.rs1
18 files changed, 123 insertions, 3 deletions
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 8b3168b29aa..58c841151c0 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -578,9 +578,9 @@ impl<T> Drop for RawVec<T> {
 // * We don't overflow `usize::MAX` and actually allocate too little
 //
 // On 64-bit we just need to check for overflow since trying to allocate
-// `> isize::MAX` bytes will surely fail. On 32-bit we need to add an extra
-// guard for this in case we're running on a platform which can use all 4GB in
-// user-space. e.g. PAE or x32
+// `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add
+// an extra guard for this in case we're running on a platform which can use
+// all 4GB in user-space. e.g. PAE or x32
 
 #[inline]
 fn alloc_guard(alloc_size: usize) {
diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index a944c996c1a..d55e0317a94 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -29,6 +29,7 @@ trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
            Sub<Output=Self> + Copy {
     fn from_u8(u: u8) -> Self;
     fn to_u8(&self) -> u8;
+    fn to_u16(&self) -> u16;
     fn to_u32(&self) -> u32;
     fn to_u64(&self) -> u64;
 }
@@ -37,6 +38,7 @@ macro_rules! doit {
     ($($t:ident)*) => ($(impl Int for $t {
         fn from_u8(u: u8) -> $t { u as $t }
         fn to_u8(&self) -> u8 { *self as u8 }
+        fn to_u16(&self) -> u16 { *self as u16 }
         fn to_u32(&self) -> u32 { *self as u32 }
         fn to_u64(&self) -> u64 { *self as u64 }
     })*)
@@ -256,6 +258,8 @@ macro_rules! impl_Display {
 
 impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
 impl_Display!(i64, u64: to_u64);
+#[cfg(target_pointer_width = "16")]
+impl_Display!(isize, usize: to_u16);
 #[cfg(target_pointer_width = "32")]
 impl_Display!(isize, usize: to_u32);
 #[cfg(target_pointer_width = "64")]
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index a0f2a2adcb6..5c2179ccf33 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -518,6 +518,10 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn drop<T>(_x: T) { }
 
+macro_rules! repeat_u8_as_u16 {
+    ($name:expr) => { (($name as u16) <<  8 |
+                       ($name as u16)) }
+}
 macro_rules! repeat_u8_as_u32 {
     ($name:expr) => { (($name as u32) << 24 |
                        ($name as u32) << 16 |
@@ -543,11 +547,18 @@ macro_rules! repeat_u8_as_u64 {
 pub const POST_DROP_U8: u8 = 0x1d;
 #[unstable(feature = "filling_drop", issue = "5016")]
 #[allow(missing_docs)]
+pub const POST_DROP_U16: u16 = repeat_u8_as_u16!(POST_DROP_U8);
+#[unstable(feature = "filling_drop", issue = "5016")]
+#[allow(missing_docs)]
 pub const POST_DROP_U32: u32 = repeat_u8_as_u32!(POST_DROP_U8);
 #[unstable(feature = "filling_drop", issue = "5016")]
 #[allow(missing_docs)]
 pub const POST_DROP_U64: u64 = repeat_u8_as_u64!(POST_DROP_U8);
 
+#[cfg(target_pointer_width = "16")]
+#[unstable(feature = "filling_drop", issue = "5016")]
+#[allow(missing_docs)]
+pub const POST_DROP_USIZE: usize = POST_DROP_U16 as usize;
 #[cfg(target_pointer_width = "32")]
 #[unstable(feature = "filling_drop", issue = "5016")]
 #[allow(missing_docs)]
diff --git a/src/libcore/num/isize.rs b/src/libcore/num/isize.rs
index de5b1777f93..86bcef4011d 100644
--- a/src/libcore/num/isize.rs
+++ b/src/libcore/num/isize.rs
@@ -14,6 +14,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[cfg(target_pointer_width = "16")]
+int_module! { isize, 16 }
 #[cfg(target_pointer_width = "32")]
 int_module! { isize, 32 }
 #[cfg(target_pointer_width = "64")]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 9b6f6698def..5988a6375d4 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1176,6 +1176,15 @@ impl i64 {
         intrinsics::mul_with_overflow }
 }
 
+#[cfg(target_pointer_width = "16")]
+#[lang = "isize"]
+impl isize {
+    int_impl! { i16, u16, 16,
+        intrinsics::add_with_overflow,
+        intrinsics::sub_with_overflow,
+        intrinsics::mul_with_overflow }
+}
+
 #[cfg(target_pointer_width = "32")]
 #[lang = "isize"]
 impl isize {
@@ -2188,6 +2197,18 @@ impl u64 {
         intrinsics::mul_with_overflow }
 }
 
+#[cfg(target_pointer_width = "16")]
+#[lang = "usize"]
+impl usize {
+    uint_impl! { u16, 16,
+        intrinsics::ctpop,
+        intrinsics::ctlz,
+        intrinsics::cttz,
+        intrinsics::bswap,
+        intrinsics::add_with_overflow,
+        intrinsics::sub_with_overflow,
+        intrinsics::mul_with_overflow }
+}
 #[cfg(target_pointer_width = "32")]
 #[lang = "usize"]
 impl usize {
diff --git a/src/libcore/num/usize.rs b/src/libcore/num/usize.rs
index 0c7d16a41bc..685c52e271e 100644
--- a/src/libcore/num/usize.rs
+++ b/src/libcore/num/usize.rs
@@ -14,6 +14,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[cfg(target_pointer_width = "16")]
+uint_module! { usize, 16 }
 #[cfg(target_pointer_width = "32")]
 uint_module! { usize, 32 }
 #[cfg(target_pointer_width = "64")]
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
index 04e8bc4913b..4857817e84e 100644
--- a/src/libcore/num/wrapping.rs
+++ b/src/libcore/num/wrapping.rs
@@ -292,6 +292,12 @@ wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
 mod shift_max {
     #![allow(non_upper_case_globals)]
 
+    #[cfg(target_pointer_width = "16")]
+    mod platform {
+        pub const usize: u32 = super::u16;
+        pub const isize: u32 = super::i16;
+    }
+
     #[cfg(target_pointer_width = "32")]
     mod platform {
         pub const usize: u32 = super::u32;
diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs
index 5bc08376d25..01bafe49a7a 100644
--- a/src/libcoretest/mem.rs
+++ b/src/libcoretest/mem.rs
@@ -19,6 +19,13 @@ fn size_of_basic() {
 }
 
 #[test]
+#[cfg(target_pointer_width = "16")]
+fn size_of_16() {
+    assert_eq!(size_of::<usize>(), 2);
+    assert_eq!(size_of::<*const usize>(), 2);
+}
+
+#[test]
 #[cfg(target_pointer_width = "32")]
 fn size_of_32() {
     assert_eq!(size_of::<usize>(), 4);
@@ -48,6 +55,13 @@ fn align_of_basic() {
 }
 
 #[test]
+#[cfg(target_pointer_width = "16")]
+fn align_of_16() {
+    assert_eq!(align_of::<usize>(), 2);
+    assert_eq!(align_of::<*const usize>(), 2);
+}
+
+#[test]
 #[cfg(target_pointer_width = "32")]
 fn align_of_32() {
     assert_eq!(align_of::<usize>(), 4);
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 7bb96c5ab2b..d455d4afda2 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -795,6 +795,7 @@ pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
     };
 
     let (int_type, uint_type) = match &target.target_pointer_width[..] {
+        "16" => (ast::IntTy::I16, ast::UintTy::U16),
         "32" => (ast::IntTy::I32, ast::UintTy::U32),
         "64" => (ast::IntTy::I64, ast::UintTy::U64),
         w    => panic!(sp.fatal(&format!("target specification was invalid: \
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 82a3b0b8db2..07156c67a22 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -170,6 +170,7 @@ impl TargetDataLayout {
     /// address space on 64-bit ARMv8 and x86_64.
     pub fn obj_size_bound(&self) -> u64 {
         match self.pointer_size.bits() {
+            16 => 1 << 15,
             32 => 1 << 31,
             64 => 1 << 47,
             bits => bug!("obj_size_bound: unknown pointer bit size {}", bits)
@@ -178,6 +179,7 @@ impl TargetDataLayout {
 
     pub fn ptr_sized_integer(&self) -> Integer {
         match self.pointer_size.bits() {
+            16 => I16,
             32 => I32,
             64 => I64,
             bits => bug!("ptr_sized_integer: unknown pointer bit size {}", bits)
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 4f6188ea3c5..a1006aa535a 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -62,6 +62,7 @@ impl IntTypeExt for attr::IntType {
             SignedInt(ast::IntTy::I32)   => ConstInt::I32(0),
             SignedInt(ast::IntTy::I64)   => ConstInt::I64(0),
             SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type {
+                ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16(0)),
                 ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)),
                 ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64(0)),
                 _ => bug!(),
@@ -71,6 +72,7 @@ impl IntTypeExt for attr::IntType {
             UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0),
             UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0),
             UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type {
+                ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(0)),
                 ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)),
                 ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(0)),
                 _ => bug!(),
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 9db24fa4770..ad3292489c5 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -584,6 +584,9 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) |
                     (&LitKind::Int(n, Signed(IntTy::Is)), _) => {
                         match tcx.sess.target.int_type {
+                            IntTy::I16 => if n == I16_OVERFLOW {
+                                return Ok(Integral(Isize(Is16(::std::i16::MIN))));
+                            },
                             IntTy::I32 => if n == I32_OVERFLOW {
                                 return Ok(Integral(Isize(Is32(::std::i32::MIN))));
                             },
diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs
index 64f03be3b5f..28a58878472 100644
--- a/src/librustc_const_math/int.rs
+++ b/src/librustc_const_math/int.rs
@@ -77,12 +77,14 @@ impl ConstInt {
             (Infer(a @ 0...as_u64::I16MAX), I16(_)) => I16(a as i64 as i16),
             (Infer(a @ 0...as_u64::I32MAX), I32(_)) => I32(a as i64 as i32),
             (Infer(a @ 0...as_u64::I64MAX), I64(_)) => I64(a as i64),
+            (Infer(a @ 0...as_u64::I16MAX), Isize(Is16(_))) => Isize(Is16(a as i64 as i16)),
             (Infer(a @ 0...as_u64::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)),
             (Infer(a @ 0...as_u64::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)),
             (Infer(a @ 0...as_u64::U8MAX), U8(_)) => U8(a as u8),
             (Infer(a @ 0...as_u64::U16MAX), U16(_)) => U16(a as u16),
             (Infer(a @ 0...as_u64::U32MAX), U32(_)) => U32(a as u32),
             (Infer(a), U64(_)) => U64(a),
+            (Infer(a @ 0...as_u64::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
             (Infer(a @ 0...as_u64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
             (Infer(a), Usize(Us64(_))) => Usize(Us64(a)),
 
@@ -92,6 +94,9 @@ impl ConstInt {
             (InferSigned(a @ as_i64::I16MIN...as_i64::I16MAX), I16(_)) => I16(a as i16),
             (InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), I32(_)) => I32(a as i32),
             (InferSigned(a), I64(_)) => I64(a),
+            (InferSigned(a @ as_i64::I16MIN...as_i64::I16MAX), Isize(Is16(_))) => {
+                Isize(Is16(a as i16))
+            },
             (InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), Isize(Is32(_))) => {
                 Isize(Is32(a as i32))
             },
@@ -100,6 +105,7 @@ impl ConstInt {
             (InferSigned(a @ 0...as_i64::U16MAX), U16(_)) => U16(a as u16),
             (InferSigned(a @ 0...as_i64::U32MAX), U32(_)) => U32(a as u32),
             (InferSigned(a @ 0...as_i64::I64MAX), U64(_)) => U64(a as u64),
+            (InferSigned(a @ 0...as_i64::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
             (InferSigned(a @ 0...as_i64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
             (InferSigned(a @ 0...as_i64::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
             (InferSigned(_), _) => return Err(ConstMathErr::NotInRange),
@@ -117,6 +123,7 @@ impl ConstInt {
             I16(i) if i < 0 => InferSigned(i as i64),
             I32(i) if i < 0 => InferSigned(i as i64),
             I64(i) if i < 0 => InferSigned(i as i64),
+            Isize(Is16(i)) if i < 0 => InferSigned(i as i64),
             Isize(Is32(i)) if i < 0 => InferSigned(i as i64),
             Isize(Is64(i)) if i < 0 => InferSigned(i as i64),
             InferSigned(i) => Infer(i as u64),
@@ -124,12 +131,14 @@ impl ConstInt {
             I16(i) => Infer(i as u64),
             I32(i) => Infer(i as u64),
             I64(i) => Infer(i as u64),
+            Isize(Is16(i)) => Infer(i as u64),
             Isize(Is32(i)) => Infer(i as u64),
             Isize(Is64(i)) => Infer(i as u64),
             U8(i) => Infer(i as u64),
             U16(i) => Infer(i as u64),
             U32(i) => Infer(i as u64),
             U64(i) => Infer(i as u64),
+            Usize(Us16(i)) => Infer(i as u64),
             Usize(Us32(i)) => Infer(i as u64),
             Usize(Us64(i)) => Infer(i),
         }
@@ -173,6 +182,7 @@ impl ConstInt {
             | Isize(Is64(v))
             | I64(v) if v >= 0 && v <= ::std::u32::MAX as i64 => Some(v as u32),
             Isize(Is32(v)) if v >= 0 => Some(v as u32),
+            Isize(Is16(v)) if v >= 0 => Some(v as u32),
             U8(v) => Some(v as u32),
             U16(v) => Some(v as u32),
             U32(v) => Some(v),
@@ -180,6 +190,7 @@ impl ConstInt {
             | Usize(Us64(v))
             | U64(v) if v <= ::std::u32::MAX as u64 => Some(v as u32),
             Usize(Us32(v)) => Some(v),
+            Usize(Us16(v)) => Some(v as u32),
             _ => None,
         }
     }
@@ -193,12 +204,14 @@ impl ConstInt {
             I16(v) if v >= 0 => Some(v as u64),
             I32(v) if v >= 0 => Some(v as u64),
             I64(v) if v >= 0 => Some(v as u64),
+            Isize(Is16(v)) if v >= 0 => Some(v as u64),
             Isize(Is32(v)) if v >= 0 => Some(v as u64),
             Isize(Is64(v)) if v >= 0 => Some(v as u64),
             U8(v) => Some(v as u64),
             U16(v) => Some(v as u64),
             U32(v) => Some(v as u64),
             U64(v) => Some(v),
+            Usize(Us16(v)) => Some(v as u64),
             Usize(Us32(v)) => Some(v as u64),
             Usize(Us64(v)) => Some(v),
             _ => None,
@@ -211,6 +224,7 @@ impl ConstInt {
             I16(v) => v < 0,
             I32(v) => v < 0,
             I64(v) => v < 0,
+            Isize(Is16(v)) => v < 0,
             Isize(Is32(v)) => v < 0,
             Isize(Is64(v)) => v < 0,
             InferSigned(v) => v < 0,
@@ -225,12 +239,14 @@ impl ConstInt {
             (I16(a), I16(b)) => Ok(a.cmp(&b)),
             (I32(a), I32(b)) => Ok(a.cmp(&b)),
             (I64(a), I64(b)) => Ok(a.cmp(&b)),
+            (Isize(Is16(a)), Isize(Is16(b))) => Ok(a.cmp(&b)),
             (Isize(Is32(a)), Isize(Is32(b))) => Ok(a.cmp(&b)),
             (Isize(Is64(a)), Isize(Is64(b))) => Ok(a.cmp(&b)),
             (U8(a), U8(b)) => Ok(a.cmp(&b)),
             (U16(a), U16(b)) => Ok(a.cmp(&b)),
             (U32(a), U32(b)) => Ok(a.cmp(&b)),
             (U64(a), U64(b)) => Ok(a.cmp(&b)),
+            (Usize(Us16(a)), Usize(Us16(b))) => Ok(a.cmp(&b)),
             (Usize(Us32(a)), Usize(Us32(b))) => Ok(a.cmp(&b)),
             (Usize(Us64(a)), Usize(Us64(b))) => Ok(a.cmp(&b)),
             (Infer(a), Infer(b)) => Ok(a.cmp(&b)),
@@ -249,12 +265,14 @@ impl ConstInt {
             ConstInt::I16(i) => ConstInt::I16(add1!(i)),
             ConstInt::I32(i) => ConstInt::I32(add1!(i)),
             ConstInt::I64(i) => ConstInt::I64(add1!(i)),
+            ConstInt::Isize(ConstIsize::Is16(i)) => ConstInt::Isize(ConstIsize::Is16(add1!(i))),
             ConstInt::Isize(ConstIsize::Is32(i)) => ConstInt::Isize(ConstIsize::Is32(add1!(i))),
             ConstInt::Isize(ConstIsize::Is64(i)) => ConstInt::Isize(ConstIsize::Is64(add1!(i))),
             ConstInt::U8(i) => ConstInt::U8(add1!(i)),
             ConstInt::U16(i) => ConstInt::U16(add1!(i)),
             ConstInt::U32(i) => ConstInt::U32(add1!(i)),
             ConstInt::U64(i) => ConstInt::U64(add1!(i)),
+            ConstInt::Usize(ConstUsize::Us16(i)) => ConstInt::Usize(ConstUsize::Us16(add1!(i))),
             ConstInt::Usize(ConstUsize::Us32(i)) => ConstInt::Usize(ConstUsize::Us32(add1!(i))),
             ConstInt::Usize(ConstUsize::Us64(i)) => ConstInt::Usize(ConstUsize::Us64(add1!(i))),
             ConstInt::Infer(_) | ConstInt::InferSigned(_) => panic!("no type info for const int"),
@@ -301,12 +319,14 @@ impl ::std::fmt::Display for ConstInt {
             I64(i) => write!(fmt, "{}i64", i),
             Isize(ConstIsize::Is64(i)) => write!(fmt, "{}isize", i),
             Isize(ConstIsize::Is32(i)) => write!(fmt, "{}isize", i),
+            Isize(ConstIsize::Is16(i)) => write!(fmt, "{}isize", i),
             U8(i) => write!(fmt, "{}u8", i),
             U16(i) => write!(fmt, "{}u16", i),
             U32(i) => write!(fmt, "{}u32", i),
             U64(i) => write!(fmt, "{}u64", i),
             Usize(ConstUsize::Us64(i)) => write!(fmt, "{}usize", i),
             Usize(ConstUsize::Us32(i)) => write!(fmt, "{}usize", i),
+            Usize(ConstUsize::Us16(i)) => write!(fmt, "{}usize", i),
         }
     }
 }
@@ -331,12 +351,14 @@ macro_rules! impl_binop {
                     (I16(a), I16(b)) => a.$checked_func(b).map(I16),
                     (I32(a), I32(b)) => a.$checked_func(b).map(I32),
                     (I64(a), I64(b)) => a.$checked_func(b).map(I64),
+                    (Isize(Is16(a)), Isize(Is16(b))) => a.$checked_func(b).map(Is16).map(Isize),
                     (Isize(Is32(a)), Isize(Is32(b))) => a.$checked_func(b).map(Is32).map(Isize),
                     (Isize(Is64(a)), Isize(Is64(b))) => a.$checked_func(b).map(Is64).map(Isize),
                     (U8(a), U8(b)) => a.$checked_func(b).map(U8),
                     (U16(a), U16(b)) => a.$checked_func(b).map(U16),
                     (U32(a), U32(b)) => a.$checked_func(b).map(U32),
                     (U64(a), U64(b)) => a.$checked_func(b).map(U64),
+                    (Usize(Us16(a)), Usize(Us16(b))) => a.$checked_func(b).map(Us16).map(Usize),
                     (Usize(Us32(a)), Usize(Us32(b))) => a.$checked_func(b).map(Us32).map(Usize),
                     (Usize(Us64(a)), Usize(Us64(b))) => a.$checked_func(b).map(Us64).map(Usize),
                     (Infer(a), Infer(b)) => a.$checked_func(b).map(Infer),
@@ -358,12 +380,14 @@ macro_rules! derive_binop {
                     (I16(a), I16(b)) => Ok(I16(a.$func(b))),
                     (I32(a), I32(b)) => Ok(I32(a.$func(b))),
                     (I64(a), I64(b)) => Ok(I64(a.$func(b))),
+                    (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a.$func(b)))),
                     (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a.$func(b)))),
                     (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a.$func(b)))),
                     (U8(a), U8(b)) => Ok(U8(a.$func(b))),
                     (U16(a), U16(b)) => Ok(U16(a.$func(b))),
                     (U32(a), U32(b)) => Ok(U32(a.$func(b))),
                     (U64(a), U64(b)) => Ok(U64(a.$func(b))),
+                    (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a.$func(b)))),
                     (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a.$func(b)))),
                     (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a.$func(b)))),
                     (Infer(a), Infer(b)) => Ok(Infer(a.$func(b))),
@@ -393,6 +417,7 @@ fn check_division(
         (I16(_), I16(0)) => Err(zerr),
         (I32(_), I32(0)) => Err(zerr),
         (I64(_), I64(0)) => Err(zerr),
+        (Isize(_), Isize(Is16(0))) => Err(zerr),
         (Isize(_), Isize(Is32(0))) => Err(zerr),
         (Isize(_), Isize(Is64(0))) => Err(zerr),
         (InferSigned(_), InferSigned(0)) => Err(zerr),
@@ -401,6 +426,7 @@ fn check_division(
         (U16(_), U16(0)) => Err(zerr),
         (U32(_), U32(0)) => Err(zerr),
         (U64(_), U64(0)) => Err(zerr),
+        (Usize(_), Usize(Us16(0))) => Err(zerr),
         (Usize(_), Usize(Us32(0))) => Err(zerr),
         (Usize(_), Usize(Us64(0))) => Err(zerr),
         (Infer(_), Infer(0)) => Err(zerr),
@@ -409,6 +435,7 @@ fn check_division(
         (I16(::std::i16::MIN), I16(-1)) => Err(Overflow(op)),
         (I32(::std::i32::MIN), I32(-1)) => Err(Overflow(op)),
         (I64(::std::i64::MIN), I64(-1)) => Err(Overflow(op)),
+        (Isize(Is16(::std::i16::MIN)), Isize(Is16(-1))) => Err(Overflow(op)),
         (Isize(Is32(::std::i32::MIN)), Isize(Is32(-1))) => Err(Overflow(op)),
         (Isize(Is64(::std::i64::MIN)), Isize(Is64(-1))) => Err(Overflow(op)),
         (InferSigned(::std::i64::MIN), InferSigned(-1)) => Err(Overflow(op)),
@@ -427,6 +454,7 @@ impl ::std::ops::Div for ConstInt {
             (I16(a), I16(b)) => Ok(I16(a/b)),
             (I32(a), I32(b)) => Ok(I32(a/b)),
             (I64(a), I64(b)) => Ok(I64(a/b)),
+            (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a/b))),
             (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a/b))),
             (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a/b))),
             (InferSigned(a), InferSigned(b)) => Ok(InferSigned(a/b)),
@@ -435,6 +463,7 @@ impl ::std::ops::Div for ConstInt {
             (U16(a), U16(b)) => Ok(U16(a/b)),
             (U32(a), U32(b)) => Ok(U32(a/b)),
             (U64(a), U64(b)) => Ok(U64(a/b)),
+            (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a/b))),
             (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a/b))),
             (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a/b))),
             (Infer(a), Infer(b)) => Ok(Infer(a/b)),
@@ -455,6 +484,7 @@ impl ::std::ops::Rem for ConstInt {
             (I16(a), I16(b)) => Ok(I16(a%b)),
             (I32(a), I32(b)) => Ok(I32(a%b)),
             (I64(a), I64(b)) => Ok(I64(a%b)),
+            (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a%b))),
             (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a%b))),
             (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a%b))),
             (InferSigned(a), InferSigned(b)) => Ok(InferSigned(a%b)),
@@ -463,6 +493,7 @@ impl ::std::ops::Rem for ConstInt {
             (U16(a), U16(b)) => Ok(U16(a%b)),
             (U32(a), U32(b)) => Ok(U32(a%b)),
             (U64(a), U64(b)) => Ok(U64(a%b)),
+            (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a%b))),
             (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a%b))),
             (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a%b))),
             (Infer(a), Infer(b)) => Ok(Infer(a%b)),
@@ -481,12 +512,14 @@ impl ::std::ops::Shl<ConstInt> for ConstInt {
             I16(a) => Ok(I16(overflowing!(a.overflowing_shl(b), Op::Shl))),
             I32(a) => Ok(I32(overflowing!(a.overflowing_shl(b), Op::Shl))),
             I64(a) => Ok(I64(overflowing!(a.overflowing_shl(b), Op::Shl))),
+            Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             U8(a) => Ok(U8(overflowing!(a.overflowing_shl(b), Op::Shl))),
             U16(a) => Ok(U16(overflowing!(a.overflowing_shl(b), Op::Shl))),
             U32(a) => Ok(U32(overflowing!(a.overflowing_shl(b), Op::Shl))),
             U64(a) => Ok(U64(overflowing!(a.overflowing_shl(b), Op::Shl))),
+            Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             Infer(a) => Ok(Infer(overflowing!(a.overflowing_shl(b), Op::Shl))),
@@ -504,12 +537,14 @@ impl ::std::ops::Shr<ConstInt> for ConstInt {
             I16(a) => Ok(I16(overflowing!(a.overflowing_shr(b), Op::Shr))),
             I32(a) => Ok(I32(overflowing!(a.overflowing_shr(b), Op::Shr))),
             I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shr))),
+            Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             U8(a) => Ok(U8(overflowing!(a.overflowing_shr(b), Op::Shr))),
             U16(a) => Ok(U16(overflowing!(a.overflowing_shr(b), Op::Shr))),
             U32(a) => Ok(U32(overflowing!(a.overflowing_shr(b), Op::Shr))),
             U64(a) => Ok(U64(overflowing!(a.overflowing_shr(b), Op::Shr))),
+            Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             Infer(a) => Ok(Infer(overflowing!(a.overflowing_shr(b), Op::Shr))),
@@ -526,12 +561,14 @@ impl ::std::ops::Neg for ConstInt {
             I16(a) => Ok(I16(overflowing!(a.overflowing_neg(), Op::Neg))),
             I32(a) => Ok(I32(overflowing!(a.overflowing_neg(), Op::Neg))),
             I64(a) => Ok(I64(overflowing!(a.overflowing_neg(), Op::Neg))),
+            Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_neg(), Op::Neg)))),
             Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_neg(), Op::Neg)))),
             Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_neg(), Op::Neg)))),
             U8(0) => Ok(U8(0)),
             U16(0) => Ok(U16(0)),
             U32(0) => Ok(U32(0)),
             U64(0) => Ok(U64(0)),
+            Usize(Us16(0)) => Ok(Usize(Us16(0))),
             Usize(Us32(0)) => Ok(Usize(Us32(0))),
             Usize(Us64(0)) => Ok(Usize(Us64(0))),
             U8(_) => Err(UnsignedNegation),
@@ -554,12 +591,14 @@ impl ::std::ops::Not for ConstInt {
             I16(a) => Ok(I16(!a)),
             I32(a) => Ok(I32(!a)),
             I64(a) => Ok(I64(!a)),
+            Isize(Is16(a)) => Ok(Isize(Is16(!a))),
             Isize(Is32(a)) => Ok(Isize(Is32(!a))),
             Isize(Is64(a)) => Ok(Isize(Is64(!a))),
             U8(a) => Ok(U8(!a)),
             U16(a) => Ok(U16(!a)),
             U32(a) => Ok(U32(!a)),
             U64(a) => Ok(U64(!a)),
+            Usize(Us16(a)) => Ok(Usize(Us16(!a))),
             Usize(Us32(a)) => Ok(Usize(Us32(!a))),
             Usize(Us64(a)) => Ok(Usize(Us64(!a))),
             Infer(a) => Ok(Infer(!a)),
diff --git a/src/librustc_const_math/is.rs b/src/librustc_const_math/is.rs
index 082c6510f8b..4d2db355eb0 100644
--- a/src/librustc_const_math/is.rs
+++ b/src/librustc_const_math/is.rs
@@ -15,6 +15,7 @@ use super::err::*;
 /// Anything else is an error. This invariant is checked at several locations
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
 pub enum ConstIsize {
+    Is16(i16),
     Is32(i32),
     Is64(i64),
 }
@@ -23,6 +24,7 @@ pub use self::ConstIsize::*;
 impl ConstIsize {
     pub fn as_i64(self, target_int_ty: ast::IntTy) -> i64 {
         match (self, target_int_ty) {
+            (Is16(i), ast::IntTy::I16) => i as i64,
             (Is32(i), ast::IntTy::I32) => i as i64,
             (Is64(i), ast::IntTy::I64) => i,
             _ => panic!("got invalid isize size for target"),
@@ -30,6 +32,8 @@ impl ConstIsize {
     }
     pub fn new(i: i64, target_int_ty: ast::IntTy) -> Result<Self, ConstMathErr> {
         match target_int_ty {
+            ast::IntTy::I16 if i as i16 as i64 == i => Ok(Is16(i as i16)),
+            ast::IntTy::I16 => Err(LitOutOfRange(ast::IntTy::Is)),
             ast::IntTy::I32 if i as i32 as i64 == i => Ok(Is32(i as i32)),
             ast::IntTy::I32 => Err(LitOutOfRange(ast::IntTy::Is)),
             ast::IntTy::I64 => Ok(Is64(i)),
diff --git a/src/librustc_const_math/us.rs b/src/librustc_const_math/us.rs
index e5a7086d436..2b224d06466 100644
--- a/src/librustc_const_math/us.rs
+++ b/src/librustc_const_math/us.rs
@@ -15,6 +15,7 @@ use super::err::*;
 /// Anything else is an error. This invariant is checked at several locations
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, Hash, Eq, PartialEq)]
 pub enum ConstUsize {
+    Us16(u16),
     Us32(u32),
     Us64(u64),
 }
@@ -23,6 +24,7 @@ pub use self::ConstUsize::*;
 impl ConstUsize {
     pub fn as_u64(self, target_uint_ty: ast::UintTy) -> u64 {
         match (self, target_uint_ty) {
+            (Us16(i), ast::UintTy::U16) => i as u64,
             (Us32(i), ast::UintTy::U32) => i as u64,
             (Us64(i), ast::UintTy::U64) => i,
             _ => panic!("got invalid usize size for target"),
@@ -30,6 +32,8 @@ impl ConstUsize {
     }
     pub fn new(i: u64, target_uint_ty: ast::UintTy) -> Result<Self, ConstMathErr> {
         match target_uint_ty {
+            ast::UintTy::U16 if i as u16 as u64 == i => Ok(Us16(i as u16)),
+            ast::UintTy::U16 => Err(ULitOutOfRange(ast::UintTy::Us)),
             ast::UintTy::U32 if i as u32 as u64 == i => Ok(Us32(i as u32)),
             ast::UintTy::U32 => Err(ULitOutOfRange(ast::UintTy::Us)),
             ast::UintTy::U64 => Ok(Us64(i)),
diff --git a/src/librustc_trans/expr.rs b/src/librustc_trans/expr.rs
index 36a593a546b..d75516ff648 100644
--- a/src/librustc_trans/expr.rs
+++ b/src/librustc_trans/expr.rs
@@ -2155,11 +2155,13 @@ impl OverflowOpViaIntrinsic {
 
         let new_sty = match ty.sty {
             TyInt(Is) => match &tcx.sess.target.target.target_pointer_width[..] {
+                "16" => TyInt(I16),
                 "32" => TyInt(I32),
                 "64" => TyInt(I64),
                 _ => bug!("unsupported target word size")
             },
             TyUint(Us) => match &tcx.sess.target.target.target_pointer_width[..] {
+                "16" => TyUint(U16),
                 "32" => TyUint(U32),
                 "64" => TyUint(U64),
                 _ => bug!("unsupported target word size")
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 640ac25a5e3..54c825fa5fa 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -1577,6 +1577,7 @@ fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
         TyInt(t) => Some((match t {
             ast::IntTy::Is => {
                 match &ccx.tcx().sess.target.target.target_pointer_width[..] {
+                    "16" => 16,
                     "32" => 32,
                     "64" => 64,
                     tws => bug!("Unsupported target word size for isize: {}", tws),
@@ -1590,6 +1591,7 @@ fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
         TyUint(t) => Some((match t {
             ast::UintTy::Us => {
                 match &ccx.tcx().sess.target.target.target_pointer_width[..] {
+                    "16" => 16,
                     "32" => 32,
                     "64" => 64,
                     tws => bug!("Unsupported target word size for usize: {}", tws),
diff --git a/src/librustc_trans/type_.rs b/src/librustc_trans/type_.rs
index 35a60cd5422..001cd197e60 100644
--- a/src/librustc_trans/type_.rs
+++ b/src/librustc_trans/type_.rs
@@ -122,6 +122,7 @@ impl Type {
 
     pub fn int(ccx: &CrateContext) -> Type {
         match &ccx.tcx().sess.target.target.target_pointer_width[..] {
+            "16" => Type::i16(ccx),
             "32" => Type::i32(ccx),
             "64" => Type::i64(ccx),
             tws => bug!("Unsupported target word size for int: {}", tws),