From bc7595c8abbf4e3b737e926d61814686e0ebda77 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Fri, 6 May 2016 09:31:11 -0400 Subject: [PATCH] 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 --- src/liballoc/raw_vec.rs | 6 ++--- src/libcore/fmt/num.rs | 4 ++++ src/libcore/mem.rs | 11 ++++++++++ src/libcore/num/isize.rs | 2 ++ src/libcore/num/mod.rs | 21 ++++++++++++++++++ src/libcore/num/usize.rs | 2 ++ src/libcore/num/wrapping.rs | 6 +++++ src/libcoretest/mem.rs | 14 ++++++++++++ src/librustc/session/config.rs | 1 + src/librustc/ty/layout.rs | 2 ++ src/librustc/ty/util.rs | 2 ++ src/librustc_const_eval/eval.rs | 3 +++ src/librustc_const_math/int.rs | 39 +++++++++++++++++++++++++++++++++ src/librustc_const_math/is.rs | 4 ++++ src/librustc_const_math/us.rs | 4 ++++ src/librustc_trans/expr.rs | 2 ++ src/librustc_trans/intrinsic.rs | 2 ++ src/librustc_trans/type_.rs | 1 + 18 files changed, 123 insertions(+), 3 deletions(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 8b3168b29aa4f..58c841151c0f0 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -578,9 +578,9 @@ impl Drop for RawVec { // * 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 a944c996c1a1e..d55e0317a9492 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -29,6 +29,7 @@ trait Int: Zero + PartialEq + PartialOrd + Div + Rem + Sub + 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 a0f2a2adcb62c..5c2179ccf33a1 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -518,6 +518,10 @@ pub fn replace(dest: &mut T, mut src: T) -> T { #[stable(feature = "rust1", since = "1.0.0")] pub fn drop(_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 de5b1777f936f..86bcef4011d02 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 9b6f6698defe4..5988a6375d44e 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 0c7d16a41bc7e..685c52e271ec0 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 04e8bc4913bdc..4857817e84e4f 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 5bc08376d257c..01bafe49a7acd 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -18,6 +18,13 @@ fn size_of_basic() { assert_eq!(size_of::(), 8); } +#[test] +#[cfg(target_pointer_width = "16")] +fn size_of_16() { + assert_eq!(size_of::(), 2); + assert_eq!(size_of::<*const usize>(), 2); +} + #[test] #[cfg(target_pointer_width = "32")] fn size_of_32() { @@ -47,6 +54,13 @@ fn align_of_basic() { assert_eq!(align_of::(), 4); } +#[test] +#[cfg(target_pointer_width = "16")] +fn align_of_16() { + assert_eq!(align_of::(), 2); + assert_eq!(align_of::<*const usize>(), 2); +} + #[test] #[cfg(target_pointer_width = "32")] fn align_of_32() { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 7bb96c5ab2b44..d455d4afda23b 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 82a3b0b8db284..07156c67a2207 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 4f6188ea3c51f..a1006aa535a2b 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 9db24fa4770fe..ad3292489c5fc 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 64f03be3b5f07..28a5887847252 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 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 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 082c6510f8bc9..4d2db355eb025 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 { 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 e5a7086d43663..2b224d0646616 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 { 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 36a593a546b9c..d75516ff64837 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 640ac25a5e31c..54c825fa5face 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 35a60cd5422b4..001cd197e60b8 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),