Such large. Very 128. Much bits.

This commit introduces 128-bit integers. Stage 2 builds and produces a working compiler which
understands and supports 128-bit integers throughout.

The general strategy used is to have rustc_i128 module which provides aliases for iu128, equal to
iu64 in stage9 and iu128 later. Since nowhere in rustc we rely on large numbers being supported,
this strategy is good enough to get past the first bootstrap stages to end up with a fully working
128-bit capable compiler.

In order for this strategy to work, number of locations had to be changed to use associated
max_value/min_value instead of MAX/MIN constants as well as the min_value (or was it max_value?)
had to be changed to use xor instead of shift so both 64-bit and 128-bit based consteval works
(former not necessarily producing the right results in stage1).

This commit includes manual merge conflict resolution changes from a rebase by @est31.
This commit is contained in:
Simonas Kazlauskas 2016-08-23 03:56:52 +03:00 committed by est31
parent 7f2d2afa91
commit b0e55a83a8
87 changed files with 941 additions and 351 deletions

View File

@ -153,12 +153,16 @@ clone_impl! { i8 }
clone_impl! { i16 }
clone_impl! { i32 }
clone_impl! { i64 }
#[cfg(not(stage0))]
clone_impl! { i128 }
clone_impl! { usize }
clone_impl! { u8 }
clone_impl! { u16 }
clone_impl! { u32 }
clone_impl! { u64 }
#[cfg(not(stage0))]
clone_impl! { u128 }
clone_impl! { f32 }
clone_impl! { f64 }

View File

@ -681,6 +681,8 @@ mod impls {
partial_eq_impl! {
bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64
}
#[cfg(not(stage0))]
partial_eq_impl! { u128 i128 }
macro_rules! eq_impl {
($($t:ty)*) => ($(
@ -690,6 +692,8 @@ mod impls {
}
eq_impl! { () bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
eq_impl! { u128 i128 }
macro_rules! partial_ord_impl {
($($t:ty)*) => ($(
@ -779,6 +783,8 @@ mod impls {
}
ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
ord_impl! { u128 i128 }
#[unstable(feature = "never_type_impls", issue = "35121")]
impl PartialEq for ! {

View File

@ -144,12 +144,16 @@ default_impl! { u8, 0 }
default_impl! { u16, 0 }
default_impl! { u32, 0 }
default_impl! { u64, 0 }
#[cfg(not(stage0))]
default_impl! { u128, 0 }
default_impl! { isize, 0 }
default_impl! { i8, 0 }
default_impl! { i16, 0 }
default_impl! { i32, 0 }
default_impl! { i64, 0 }
#[cfg(not(stage0))]
default_impl! { i128, 0 }
default_impl! { f32, 0.0f32 }
default_impl! { f64, 0.0f64 }

View File

@ -30,6 +30,8 @@ trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
fn to_u16(&self) -> u16;
fn to_u32(&self) -> u32;
fn to_u64(&self) -> u64;
#[cfg(not(stage0))]
fn to_u128(&self) -> u128;
}
macro_rules! doit {
@ -39,9 +41,13 @@ macro_rules! doit {
fn to_u16(&self) -> u16 { *self as u16 }
fn to_u32(&self) -> u32 { *self as u32 }
fn to_u64(&self) -> u64 { *self as u64 }
#[cfg(not(stage0))]
fn to_u128(&self) -> u128 { *self as u128 }
})*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
#[cfg(not(stage0))]
doit! { i128 u128 }
/// A type that represents a specific radix
#[doc(hidden)]
@ -59,11 +65,11 @@ trait GenericRadix {
/// Format an integer using the radix using a formatter.
fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
// The radix can be as low as 2, so we need a buffer of at least 64
// The radix can be as low as 2, so we need a buffer of at least 128
// characters for a base 2 number.
let zero = T::zero();
let is_nonnegative = x >= zero;
let mut buf = [0; 64];
let mut buf = [0; 128];
let mut curr = buf.len();
let base = T::from_u8(self.base());
if is_nonnegative {
@ -182,6 +188,8 @@ integer! { i8, u8 }
integer! { i16, u16 }
integer! { i32, u32 }
integer! { i64, u64 }
#[cfg(not(stage0))]
integer! { i128, u128 }
const DEC_DIGITS_LUT: &'static[u8] =
b"0001020304050607080910111213141516171819\
@ -203,14 +211,15 @@ macro_rules! impl_Display {
// convert the negative num to positive by summing 1 to it's 2 complement
(!self.$conv_fn()).wrapping_add(1)
};
let mut buf: [u8; 20] = unsafe { mem::uninitialized() };
let mut buf: [u8; 40] = unsafe { mem::uninitialized() };
let mut curr = buf.len() as isize;
let buf_ptr = buf.as_mut_ptr();
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
unsafe {
// eagerly decode 4 characters at a time
if <$t>::max_value() as u64 >= 10000 {
// need at least 16 bits for the 4-characters-at-a-time to work.
if ::mem::size_of::<$t>() >= 2 {
// eagerly decode 4 characters at a time
while n >= 10000 {
let rem = (n % 10000) as isize;
n /= 10000;
@ -256,6 +265,8 @@ macro_rules! impl_Display {
impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
impl_Display!(i64, u64: to_u64);
#[cfg(not(stage0))]
impl_Display!(i128, u128: to_u128);
#[cfg(target_pointer_width = "16")]
impl_Display!(isize, usize: to_u16);
#[cfg(target_pointer_width = "32")]

View File

@ -186,6 +186,13 @@ pub trait Hasher {
fn write_u64(&mut self, i: u64) {
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
}
#[cfg(not(stage0))]
/// Writes a single `u128` into this hasher.
#[inline]
#[unstable(feature = "i128", issue = "35118")]
fn write_u128(&mut self, i: u128) {
self.write(&unsafe { mem::transmute::<_, [u8; 16]>(i) })
}
/// Writes a single `usize` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
@ -220,6 +227,13 @@ pub trait Hasher {
fn write_i64(&mut self, i: i64) {
self.write_u64(i as u64)
}
#[cfg(not(stage0))]
/// Writes a single `i128` into this hasher.
#[inline]
#[unstable(feature = "i128", issue = "35118")]
fn write_i128(&mut self, i: i128) {
self.write_u128(i as u128)
}
/// Writes a single `isize` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
@ -362,6 +376,11 @@ mod impls {
(i64, write_i64),
(isize, write_isize),
}
#[cfg(not(stage0))]
impl_write! {
(u128, write_u128),
(i128, write_i128),
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Hash for bool {

View File

@ -120,12 +120,20 @@ mod uint_macros;
#[path = "num/i32.rs"] pub mod i32;
#[path = "num/i64.rs"] pub mod i64;
// SNAP
#[cfg(not(stage0))]
#[path = "num/i128.rs"] pub mod i128;
#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"] pub mod u8;
#[path = "num/u16.rs"] pub mod u16;
#[path = "num/u32.rs"] pub mod u32;
#[path = "num/u64.rs"] pub mod u64;
// SNAP
#[cfg(not(stage0))]
#[path = "num/u128.rs"] pub mod u128;
#[path = "num/f32.rs"] pub mod f32;
#[path = "num/f64.rs"] pub mod f64;

View File

@ -30,6 +30,10 @@ unsafe impl Zeroable for i32 {}
unsafe impl Zeroable for u32 {}
unsafe impl Zeroable for i64 {}
unsafe impl Zeroable for u64 {}
#[cfg(not(stage0))]
unsafe impl Zeroable for i128 {}
#[cfg(not(stage0))]
unsafe impl Zeroable for u128 {}
/// A wrapper type for raw pointers and integers that will never be
/// NULL or 0 that might allow certain optimizations.

17
src/libcore/num/i128.rs Normal file
View File

@ -0,0 +1,17 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! The 128-bit signed integer type.
//!
//! *[See also the `i128` primitive type](../../std/primitive.i128.html).*
#![unstable(feature = "i128", issue="35118")]
int_module! { i128 }

View File

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
int_module! { i16, 16 }
int_module! { i16 }

View File

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
int_module! { i32, 32 }
int_module! { i32 }

View File

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
int_module! { i64, 64 }
int_module! { i64 }

View File

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
int_module! { i8, 8 }
int_module! { i8 }

View File

@ -10,7 +10,7 @@
#![doc(hidden)]
macro_rules! int_module { ($T:ident, $bits:expr) => (
macro_rules! int_module { ($T:ident) => (
/// The smallest value that can be represented by this integer type.
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -14,9 +14,4 @@
#![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")]
int_module! { isize, 64 }
int_module! { isize }

View File

@ -145,6 +145,8 @@ macro_rules! zero_one_impl {
)*)
}
zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
#[cfg(not(stage0))]
zero_one_impl! { u128 i128 }
macro_rules! zero_one_impl_float {
($($t:ty)*) => ($(
@ -191,7 +193,7 @@ macro_rules! int_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub const fn min_value() -> Self {
(-1 as Self) << ($BITS - 1)
!0 ^ ((!0 as $UnsignedT) >> 1) as Self
}
/// Returns the largest value that can be represented by this integer type.
@ -1298,6 +1300,16 @@ impl i64 {
intrinsics::mul_with_overflow }
}
// SNAP
#[cfg(not(stage0))]
#[lang = "i128"]
impl i128 {
int_impl! { i128, u128, 128,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
}
#[cfg(target_pointer_width = "16")]
#[lang = "isize"]
impl isize {
@ -2330,6 +2342,20 @@ impl u64 {
intrinsics::mul_with_overflow }
}
// SNAP
#[cfg(not(stage0))]
#[lang = "u128"]
impl u128 {
uint_impl! { u128, 128,
intrinsics::ctpop,
intrinsics::ctlz,
intrinsics::cttz,
intrinsics::bswap,
intrinsics::add_with_overflow,
intrinsics::sub_with_overflow,
intrinsics::mul_with_overflow }
}
#[cfg(target_pointer_width = "16")]
#[lang = "usize"]
impl usize {
@ -2543,6 +2569,8 @@ macro_rules! from_str_radix_int_impl {
)*}
}
from_str_radix_int_impl! { isize i8 i16 i32 i64 usize u8 u16 u32 u64 }
#[cfg(not(stage0))]
from_str_radix_int_impl! { u128 i128 }
/// The error type returned when a checked integral type conversion fails.
#[unstable(feature = "try_from", issue = "33417")]
@ -2567,7 +2595,7 @@ impl fmt::Display for TryFromIntError {
}
}
macro_rules! same_sign_from_int_impl {
macro_rules! same_sign_try_from_int_impl {
($storage:ty, $target:ty, $($source:ty),*) => {$(
#[unstable(feature = "try_from", issue = "33417")]
impl TryFrom<$source> for $target {
@ -2586,16 +2614,30 @@ macro_rules! same_sign_from_int_impl {
)*}
}
same_sign_from_int_impl!(u64, u8, u8, u16, u32, u64, usize);
same_sign_from_int_impl!(i64, i8, i8, i16, i32, i64, isize);
same_sign_from_int_impl!(u64, u16, u8, u16, u32, u64, usize);
same_sign_from_int_impl!(i64, i16, i8, i16, i32, i64, isize);
same_sign_from_int_impl!(u64, u32, u8, u16, u32, u64, usize);
same_sign_from_int_impl!(i64, i32, i8, i16, i32, i64, isize);
same_sign_from_int_impl!(u64, u64, u8, u16, u32, u64, usize);
same_sign_from_int_impl!(i64, i64, i8, i16, i32, i64, isize);
same_sign_from_int_impl!(u64, usize, u8, u16, u32, u64, usize);
same_sign_from_int_impl!(i64, isize, i8, i16, i32, i64, isize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u8, u8, u16, u32, u64, u128, usize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i8, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u16, u8, u16, u32, u64, u128, usize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i16, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u32, u8, u16, u32, u64, u128, usize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i32, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u64, u8, u16, u32, u64, u128, usize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i64, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, u128, u8, u16, u32, u64, u128, usize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, i128, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(u128, usize, u8, u16, u32, u64, u128, usize);
#[cfg(not(stage0))]
same_sign_try_from_int_impl!(i128, isize, i8, i16, i32, i64, i128, isize);
macro_rules! cross_sign_from_int_impl {
($unsigned:ty, $($signed:ty),*) => {$(
@ -2629,12 +2671,30 @@ macro_rules! cross_sign_from_int_impl {
)*}
}
#[cfg(stage0)]
cross_sign_from_int_impl!(u8, i8, i16, i32, i64, isize);
#[cfg(stage0)]
cross_sign_from_int_impl!(u16, i8, i16, i32, i64, isize);
#[cfg(stage0)]
cross_sign_from_int_impl!(u32, i8, i16, i32, i64, isize);
#[cfg(stage0)]
cross_sign_from_int_impl!(u64, i8, i16, i32, i64, isize);
#[cfg(stage0)]
cross_sign_from_int_impl!(usize, i8, i16, i32, i64, isize);
#[cfg(not(stage0))]
cross_sign_from_int_impl!(u8, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
cross_sign_from_int_impl!(u16, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
cross_sign_from_int_impl!(u32, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
cross_sign_from_int_impl!(u64, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
cross_sign_from_int_impl!(u128, i8, i16, i32, i64, i128, isize);
#[cfg(not(stage0))]
cross_sign_from_int_impl!(usize, i8, i16, i32, i64, i128, isize);
#[doc(hidden)]
trait FromStrRadixHelper: PartialOrd + Copy {
fn min_value() -> Self;
@ -2662,6 +2722,8 @@ macro_rules! doit {
})*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
#[cfg(not(stage0))]
doit! { i128 u128 }
fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
use self::IntErrorKind::*;
@ -2795,27 +2857,51 @@ macro_rules! impl_from {
impl_from! { u8, u16 }
impl_from! { u8, u32 }
impl_from! { u8, u64 }
#[cfg(not(stage0))]
impl_from! { u8, u128 }
impl_from! { u8, usize }
impl_from! { u16, u32 }
impl_from! { u16, u64 }
#[cfg(not(stage0))]
impl_from! { u16, u128 }
impl_from! { u32, u64 }
#[cfg(not(stage0))]
impl_from! { u32, u128 }
#[cfg(not(stage0))]
impl_from! { u64, u128 }
// Signed -> Signed
impl_from! { i8, i16 }
impl_from! { i8, i32 }
impl_from! { i8, i64 }
#[cfg(not(stage0))]
impl_from! { i8, i128 }
impl_from! { i8, isize }
impl_from! { i16, i32 }
impl_from! { i16, i64 }
#[cfg(not(stage0))]
impl_from! { i16, i128 }
impl_from! { i32, i64 }
#[cfg(not(stage0))]
impl_from! { i32, i128 }
#[cfg(not(stage0))]
impl_from! { i64, i128 }
// Unsigned -> Signed
impl_from! { u8, i16 }
impl_from! { u8, i32 }
impl_from! { u8, i64 }
#[cfg(not(stage0))]
impl_from! { u8, i128 }
impl_from! { u16, i32 }
impl_from! { u16, i64 }
#[cfg(not(stage0))]
impl_from! { u16, i128 }
impl_from! { u32, i64 }
#[cfg(not(stage0))]
impl_from! { u32, i128 }
#[cfg(not(stage0))]
impl_from! { u64, i128 }
// Note: integers can only be represented with full precision in a float if
// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.

16
src/libcore/num/u128.rs Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! The 128-bit unsigned integer type.
//!
//! *[See also the `u128` primitive type](../../std/primitive.u128.html).*
#![unstable(feature = "i128", issue="35118")]
uint_module! { u128 }

View File

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
uint_module! { u16, 16 }
uint_module! { u16 }

View File

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
uint_module! { u32, 32 }
uint_module! { u32 }

View File

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
uint_module! { u64, 64 }
uint_module! { u64 }

View File

@ -14,4 +14,4 @@
#![stable(feature = "rust1", since = "1.0.0")]
uint_module! { u8, 8 }
uint_module! { u8 }

View File

@ -10,7 +10,7 @@
#![doc(hidden)]
macro_rules! uint_module { ($T:ident, $bits:expr) => (
macro_rules! uint_module { ($T:ident) => (
/// The smallest value that can be represented by this integer type.
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -14,9 +14,4 @@
#![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")]
uint_module! { usize, 64 }
uint_module! { usize }

View File

@ -268,6 +268,8 @@ macro_rules! add_impl {
}
add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[cfg(not(stage0))]
add_impl! { u128 i128 }
/// The `Sub` trait is used to specify the functionality of `-`.
///
@ -341,6 +343,8 @@ macro_rules! sub_impl {
}
sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[cfg(not(stage0))]
sub_impl! { u128 i128 }
/// The `Mul` trait is used to specify the functionality of `*`.
///
@ -463,6 +467,8 @@ macro_rules! mul_impl {
}
mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[cfg(not(stage0))]
mul_impl! { u128 i128 }
/// The `Div` trait is used to specify the functionality of `/`.
///
@ -592,6 +598,8 @@ macro_rules! div_impl_integer {
}
div_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
div_impl_integer! { u128 i128 }
macro_rules! div_impl_float {
($($t:ty)*) => ($(
@ -671,6 +679,9 @@ macro_rules! rem_impl_integer {
}
rem_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
rem_impl_integer! { u128 i128 }
macro_rules! rem_impl_float {
($($t:ty)*) => ($(
@ -766,6 +777,8 @@ macro_rules! neg_impl_unsigned {
// neg_impl_unsigned! { usize u8 u16 u32 u64 }
neg_impl_numeric! { isize i8 i16 i32 i64 f32 f64 }
#[cfg(not(stage0))]
neg_impl_numeric! { i128 }
/// The `Not` trait is used to specify the functionality of unary `!`.
///
@ -824,6 +837,8 @@ macro_rules! not_impl {
}
not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
not_impl! { u128 i128 }
/// The `BitAnd` trait is used to specify the functionality of `&`.
///
@ -907,6 +922,8 @@ macro_rules! bitand_impl {
}
bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
bitand_impl! { u128 i128 }
/// The `BitOr` trait is used to specify the functionality of `|`.
///
@ -990,6 +1007,8 @@ macro_rules! bitor_impl {
}
bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
bitor_impl! { u128 i128 }
/// The `BitXor` trait is used to specify the functionality of `^`.
///
@ -1076,6 +1095,8 @@ macro_rules! bitxor_impl {
}
bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
bitxor_impl! { u128 i128 }
/// The `Shl` trait is used to specify the functionality of `<<`.
///
@ -1166,17 +1187,23 @@ macro_rules! shl_impl_all {
shl_impl! { $t, u16 }
shl_impl! { $t, u32 }
shl_impl! { $t, u64 }
#[cfg(not(stage0))]
shl_impl! { $t, u128 }
shl_impl! { $t, usize }
shl_impl! { $t, i8 }
shl_impl! { $t, i16 }
shl_impl! { $t, i32 }
shl_impl! { $t, i64 }
#[cfg(not(stage0))]
shl_impl! { $t, i128 }
shl_impl! { $t, isize }
)*)
}
shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
#[cfg(not(stage0))]
shl_impl_all! { u128 i128 }
/// The `Shr` trait is used to specify the functionality of `>>`.
///
@ -1267,17 +1294,23 @@ macro_rules! shr_impl_all {
shr_impl! { $t, u16 }
shr_impl! { $t, u32 }
shr_impl! { $t, u64 }
#[cfg(not(stage0))]
shr_impl! { $t, u128 }
shr_impl! { $t, usize }
shr_impl! { $t, i8 }
shr_impl! { $t, i16 }
shr_impl! { $t, i32 }
shr_impl! { $t, i64 }
#[cfg(not(stage0))]
shr_impl! { $t, i128 }
shr_impl! { $t, isize }
)*)
}
shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
#[cfg(not(stage0))]
shr_impl_all! { u128 i128 }
/// The `AddAssign` trait is used to specify the functionality of `+=`.
///
@ -1334,6 +1367,8 @@ macro_rules! add_assign_impl {
}
add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[cfg(not(stage0))]
add_assign_impl! { u128 i128 }
/// The `SubAssign` trait is used to specify the functionality of `-=`.
///
@ -1390,6 +1425,8 @@ macro_rules! sub_assign_impl {
}
sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[cfg(not(stage0))]
sub_assign_impl! { u128 i128 }
/// The `MulAssign` trait is used to specify the functionality of `*=`.
///
@ -1435,6 +1472,8 @@ macro_rules! mul_assign_impl {
}
mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[cfg(not(stage0))]
mul_assign_impl! { u128 i128 }
/// The `DivAssign` trait is used to specify the functionality of `/=`.
///
@ -1479,6 +1518,8 @@ macro_rules! div_assign_impl {
}
div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[cfg(not(stage0))]
div_assign_impl! { u128 i128 }
/// The `RemAssign` trait is used to specify the functionality of `%=`.
///
@ -1523,6 +1564,8 @@ macro_rules! rem_assign_impl {
}
rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[cfg(not(stage0))]
rem_assign_impl! { u128 i128 }
/// The `BitAndAssign` trait is used to specify the functionality of `&=`.
///
@ -1609,6 +1652,8 @@ macro_rules! bitand_assign_impl {
}
bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
bitand_assign_impl! { u128 i128 }
/// The `BitOrAssign` trait is used to specify the functionality of `|=`.
///
@ -1653,6 +1698,8 @@ macro_rules! bitor_assign_impl {
}
bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
bitor_assign_impl! { u128 i128 }
/// The `BitXorAssign` trait is used to specify the functionality of `^=`.
///
@ -1697,6 +1744,8 @@ macro_rules! bitxor_assign_impl {
}
bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[cfg(not(stage0))]
bitxor_assign_impl! { u128 i128 }
/// The `ShlAssign` trait is used to specify the functionality of `<<=`.
///
@ -1749,17 +1798,23 @@ macro_rules! shl_assign_impl_all {
shl_assign_impl! { $t, u16 }
shl_assign_impl! { $t, u32 }
shl_assign_impl! { $t, u64 }
#[cfg(not(stage0))]
shl_assign_impl! { $t, u128 }
shl_assign_impl! { $t, usize }
shl_assign_impl! { $t, i8 }
shl_assign_impl! { $t, i16 }
shl_assign_impl! { $t, i32 }
shl_assign_impl! { $t, i64 }
#[cfg(not(stage0))]
shl_assign_impl! { $t, i128 }
shl_assign_impl! { $t, isize }
)*)
}
shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
#[cfg(not(stage0))]
shl_assign_impl_all! { u128 i128 }
/// The `ShrAssign` trait is used to specify the functionality of `>>=`.
///
@ -1812,17 +1867,23 @@ macro_rules! shr_assign_impl_all {
shr_assign_impl! { $t, u16 }
shr_assign_impl! { $t, u32 }
shr_assign_impl! { $t, u64 }
#[cfg(not(stage0))]
shr_assign_impl! { $t, u128 }
shr_assign_impl! { $t, usize }
shr_assign_impl! { $t, i8 }
shr_assign_impl! { $t, i16 }
shr_assign_impl! { $t, i32 }
shr_assign_impl! { $t, i64 }
#[cfg(not(stage0))]
shr_assign_impl! { $t, i128 }
shr_assign_impl! { $t, isize }
)*)
}
shr_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
#[cfg(not(stage0))]
shr_assign_impl_all! { u128 i128 }
/// The `Index` trait is used to specify the functionality of indexing operations
/// like `container[index]` when used in an immutable context.

View File

@ -9,3 +9,4 @@ crate-type = ["dylib"]
[dependencies]
syntax = { path = "../libsyntax" }
rustc_i128 = { path = "../librustc_i128" }

View File

@ -20,6 +20,7 @@ rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_llvm = { path = "../librustc_llvm" }
rustc_i128 = { path = "../librustc_i128" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }

View File

@ -62,6 +62,9 @@ extern crate rustc_errors as errors;
extern crate serialize as rustc_serialize; // used by deriving
// SNAP:
extern crate rustc_i128;
#[cfg(test)]
extern crate test;

View File

@ -260,11 +260,13 @@ language_item_table! {
I16ImplItem, "i16", i16_impl;
I32ImplItem, "i32", i32_impl;
I64ImplItem, "i64", i64_impl;
I128ImplItem, "i128", i128_impl;
IsizeImplItem, "isize", isize_impl;
U8ImplItem, "u8", u8_impl;
U16ImplItem, "u16", u16_impl;
U32ImplItem, "u32", u32_impl;
U64ImplItem, "u64", u64_impl;
U128ImplItem, "u128", u128_impl;
UsizeImplItem, "usize", usize_impl;
F32ImplItem, "f32", f32_impl;
F64ImplItem, "f64", f64_impl;

View File

@ -194,11 +194,13 @@ pub struct CommonTypes<'tcx> {
pub i16: Ty<'tcx>,
pub i32: Ty<'tcx>,
pub i64: Ty<'tcx>,
pub i128: Ty<'tcx>,
pub usize: Ty<'tcx>,
pub u8: Ty<'tcx>,
pub u16: Ty<'tcx>,
pub u32: Ty<'tcx>,
pub u64: Ty<'tcx>,
pub u128: Ty<'tcx>,
pub f32: Ty<'tcx>,
pub f64: Ty<'tcx>,
pub never: Ty<'tcx>,
@ -359,11 +361,13 @@ impl<'tcx> CommonTypes<'tcx> {
i16: mk(TyInt(ast::IntTy::I16)),
i32: mk(TyInt(ast::IntTy::I32)),
i64: mk(TyInt(ast::IntTy::I64)),
i128: mk(TyInt(ast::IntTy::I128)),
usize: mk(TyUint(ast::UintTy::Us)),
u8: mk(TyUint(ast::UintTy::U8)),
u16: mk(TyUint(ast::UintTy::U16)),
u32: mk(TyUint(ast::UintTy::U32)),
u64: mk(TyUint(ast::UintTy::U64)),
u128: mk(TyUint(ast::UintTy::U128)),
f32: mk(TyFloat(ast::FloatTy::F32)),
f64: mk(TyFloat(ast::FloatTy::F64)),
}
@ -1304,6 +1308,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
ast::IntTy::I16 => self.types.i16,
ast::IntTy::I32 => self.types.i32,
ast::IntTy::I64 => self.types.i64,
ast::IntTy::I128 => self.types.i128,
}
}
@ -1314,6 +1319,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
ast::UintTy::U16 => self.types.u16,
ast::UintTy::U32 => self.types.u32,
ast::UintTy::U64 => self.types.u64,
ast::UintTy::U128 => self.types.u128,
}
}

View File

@ -20,6 +20,7 @@ use ty::{self, Ty, TyCtxt, TypeFoldable};
use syntax::ast::{FloatTy, IntTy, UintTy};
use syntax::attr;
use syntax_pos::DUMMY_SP;
use rustc_i128::{i128, u128};
use std::cmp;
use std::fmt;
@ -35,6 +36,7 @@ pub struct TargetDataLayout {
pub i16_align: Align,
pub i32_align: Align,
pub i64_align: Align,
pub i128_align: Align,
pub f32_align: Align,
pub f64_align: Align,
pub pointer_size: Size,
@ -55,6 +57,8 @@ impl Default for TargetDataLayout {
i16_align: Align::from_bits(16, 16).unwrap(),
i32_align: Align::from_bits(32, 32).unwrap(),
i64_align: Align::from_bits(32, 64).unwrap(),
// FIXME: i128 is correct?
i128_align: Align::from_bits(64, 128).unwrap(),
f32_align: Align::from_bits(32, 32).unwrap(),
f64_align: Align::from_bits(64, 64).unwrap(),
pointer_size: Size::from_bits(64),
@ -117,6 +121,7 @@ impl TargetDataLayout {
Ok(16) => &mut dl.i16_align,
Ok(32) => &mut dl.i32_align,
Ok(64) => &mut dl.i64_align,
Ok(128) => &mut dl.i128_align,
Ok(_) => continue,
Err(_) => {
size(&s[1..], "i"); // For the user error.
@ -325,7 +330,8 @@ pub enum Integer {
I8,
I16,
I32,
I64
I64,
I128,
}
impl Integer {
@ -368,22 +374,24 @@ impl Integer {
/// Find the smallest Integer type which can represent the signed value.
pub fn fit_signed(x: i64) -> Integer {
match x {
-0x0000_0001...0x0000_0000 => I1,
-0x0000_0080...0x0000_007f => I8,
-0x0000_8000...0x0000_7fff => I16,
-0x8000_0000...0x7fff_ffff => I32,
_ => I64
-0x0000_0000_0000_0001...0x0000_0000_0000_0000 => I1,
-0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8,
-0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16,
-0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32,
-0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64,
_ => I128
}
}
/// Find the smallest Integer type which can represent the unsigned value.
pub fn fit_unsigned(x: u64) -> Integer {
match x {
0...0x0000_0001 => I1,
0...0x0000_00ff => I8,
0...0x0000_ffff => I16,
0...0xffff_ffff => I32,
_ => I64
0...0x0000_0000_0000_0001 => I1,
0...0x0000_0000_0000_00ff => I8,
0...0x0000_0000_0000_ffff => I16,
0...0x0000_0000_ffff_ffff => I32,
0...0xffff_ffff_ffff_ffff => I64,
_ => I128,
}
}
@ -406,6 +414,7 @@ impl Integer {
attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16,
attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32,
attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64,
attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128,
attr::SignedInt(IntTy::Is) | attr::UnsignedInt(UintTy::Us) => {
dl.ptr_sized_integer()
}
@ -486,6 +495,7 @@ impl Primitive {
Int(I16) => Size::from_bits(16),
Int(I32) | F32 => Size::from_bits(32),
Int(I64) | F64 => Size::from_bits(64),
Int(I128) => Size::from_bits(128),
Pointer => dl.pointer_size
}
}
@ -497,6 +507,7 @@ impl Primitive {
Int(I16) => dl.i16_align,
Int(I32) => dl.i32_align,
Int(I64) => dl.i64_align,
Int(I128) => dl.i128_align,
F32 => dl.f32_align,
F64 => dl.f64_align,
Pointer => dl.pointer_align
@ -1175,19 +1186,23 @@ impl<'a, 'gcx, 'tcx> Layout {
if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
// All bodies empty -> intlike
let (mut min, mut max, mut non_zero) = (i64::MAX, i64::MIN, true);
let (mut min, mut max, mut non_zero) = (i128::max_value(), i128::min_value(), true);
for v in &def.variants {
let x = v.disr_val.to_u64_unchecked() as i64;
let x = v.disr_val.to_u128_unchecked() as i128;
if x == 0 { non_zero = false; }
if x < min { min = x; }
if x > max { max = x; }
}
let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..], min, max);
// FIXME: should take i128?
let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..],
min as i64,
max as i64);
return success(CEnum {
discr: discr,
signed: signed,
non_zero: non_zero,
// FIXME: should be u128?
min: min as u64,
max: max as u64
});
@ -1232,7 +1247,7 @@ impl<'a, 'gcx, 'tcx> Layout {
// non-empty body, explicit discriminants should have
// been rejected by a checker before this point.
for (i, v) in def.variants.iter().enumerate() {
if i as u64 != v.disr_val.to_u64_unchecked() {
if i as u128 != v.disr_val.to_u128_unchecked() {
bug!("non-C-like enum {} with specified discriminants",
tcx.item_path_str(def.did));
}

View File

@ -51,11 +51,13 @@ impl IntTypeExt for attr::IntType {
SignedInt(ast::IntTy::I16) => tcx.types.i16,
SignedInt(ast::IntTy::I32) => tcx.types.i32,
SignedInt(ast::IntTy::I64) => tcx.types.i64,
SignedInt(ast::IntTy::I128) => tcx.types.i128,
SignedInt(ast::IntTy::Is) => tcx.types.isize,
UnsignedInt(ast::UintTy::U8) => tcx.types.u8,
UnsignedInt(ast::UintTy::U16) => tcx.types.u16,
UnsignedInt(ast::UintTy::U32) => tcx.types.u32,
UnsignedInt(ast::UintTy::U64) => tcx.types.u64,
UnsignedInt(ast::UintTy::U128) => tcx.types.u128,
UnsignedInt(ast::UintTy::Us) => tcx.types.usize,
}
}
@ -66,6 +68,7 @@ impl IntTypeExt for attr::IntType {
SignedInt(ast::IntTy::I16) => ConstInt::I16(0),
SignedInt(ast::IntTy::I32) => ConstInt::I32(0),
SignedInt(ast::IntTy::I64) => ConstInt::I64(0),
SignedInt(ast::IntTy::I128) => ConstInt::I128(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)),
@ -76,6 +79,7 @@ impl IntTypeExt for attr::IntType {
UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0),
UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0),
UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0),
UnsignedInt(ast::UintTy::U128) => ConstInt::U128(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)),
@ -91,11 +95,13 @@ impl IntTypeExt for attr::IntType {
(SignedInt(ast::IntTy::I16), ConstInt::I16(_)) => {},
(SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {},
(SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {},
(SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {},
(SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => {},
(UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {},
(UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {},
(UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {},
(UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {},
(UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {},
(UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {},
_ => bug!("disr type mismatch: {:?} vs {:?}", self, val),
}

View File

@ -19,4 +19,5 @@ rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
syntax = { path = "../libsyntax" }
graphviz = { path = "../libgraphviz" }
syntax_pos = { path = "../libsyntax_pos" }
syntax_pos = { path = "../libsyntax_pos" }
rustc_i128 = { path = "../librustc_i128" }

View File

@ -43,6 +43,8 @@ use std::cmp::Ordering;
use rustc_const_math::*;
use rustc_errors::DiagnosticBuilder;
use rustc_i128::{i128, u128};
macro_rules! math {
($e:expr, $op:expr) => {
match $op {
@ -588,38 +590,43 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
if let hir::ExprLit(ref lit) = inner.node {
use syntax::ast::*;
use syntax::ast::LitIntType::*;
const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1;
const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1;
const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1;
const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1;
const I8_OVERFLOW: u128 = i8::max_value() as u128 + 1;
const I16_OVERFLOW: u128 = i16::max_value() as u128 + 1;
const I32_OVERFLOW: u128 = i32::max_value() as u128 + 1;
const I64_OVERFLOW: u128 = i64::max_value() as u128 + 1;
const I128_OVERFLOW: u128 = i128::max_value() as u128 + 1;
match (&lit.node, ety.map(|t| &t.sty)) {
(&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) |
(&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
return Ok(Integral(I8(::std::i8::MIN)))
return Ok(Integral(I8(i8::min_value())))
},
(&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) |
(&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
return Ok(Integral(I16(::std::i16::MIN)))
return Ok(Integral(I16(i16::min_value())))
},
(&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) |
(&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
return Ok(Integral(I32(::std::i32::MIN)))
return Ok(Integral(I32(i32::min_value())))
},
(&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) |
(&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
return Ok(Integral(I64(::std::i64::MIN)))
return Ok(Integral(I64(i64::min_value())))
},
(&LitKind::Int(I128_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I128))) |
(&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
return Ok(Integral(I128(i128::min_value())))
},
(&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))));
return Ok(Integral(Isize(Is16(i16::min_value()))));
},
IntTy::I32 => if n == I32_OVERFLOW {
return Ok(Integral(Isize(Is32(::std::i32::MIN))));
return Ok(Integral(Isize(Is32(i32::min_value()))));
},
IntTy::I64 => if n == I64_OVERFLOW {
return Ok(Integral(Isize(Is64(::std::i64::MIN))));
return Ok(Integral(Isize(Is64(i64::min_value()))));
},
_ => bug!(),
}
@ -973,26 +980,30 @@ fn infer<'a, 'tcx>(i: ConstInt,
(&ty::TyInt(IntTy::I16), result @ I16(_)) => Ok(result),
(&ty::TyInt(IntTy::I32), result @ I32(_)) => Ok(result),
(&ty::TyInt(IntTy::I64), result @ I64(_)) => Ok(result),
(&ty::TyInt(IntTy::I128), result @ I128(_)) => Ok(result),
(&ty::TyInt(IntTy::Is), result @ Isize(_)) => Ok(result),
(&ty::TyUint(UintTy::U8), result @ U8(_)) => Ok(result),
(&ty::TyUint(UintTy::U16), result @ U16(_)) => Ok(result),
(&ty::TyUint(UintTy::U32), result @ U32(_)) => Ok(result),
(&ty::TyUint(UintTy::U64), result @ U64(_)) => Ok(result),
(&ty::TyUint(UintTy::U128), result @ U128(_)) => Ok(result),
(&ty::TyUint(UintTy::Us), result @ Usize(_)) => Ok(result),
(&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i64 as i8)),
(&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i64 as i16)),
(&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i64 as i32)),
(&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i64)),
(&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i128 as i8)),
(&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i128 as i16)),
(&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i128 as i32)),
(&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i128 as i64)),
(&ty::TyInt(IntTy::I128), Infer(i)) => Ok(I128(i as i128)),
(&ty::TyInt(IntTy::Is), Infer(i)) => {
Ok(Isize(ConstIsize::new_truncating(i as i64, tcx.sess.target.int_type)))
Ok(Isize(ConstIsize::new_truncating(i as i128, tcx.sess.target.int_type)))
},
(&ty::TyInt(IntTy::I8), InferSigned(i)) => Ok(I8(i as i8)),
(&ty::TyInt(IntTy::I16), InferSigned(i)) => Ok(I16(i as i16)),
(&ty::TyInt(IntTy::I32), InferSigned(i)) => Ok(I32(i as i32)),
(&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i)),
(&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i as i64)),
(&ty::TyInt(IntTy::I128), InferSigned(i)) => Ok(I128(i)),
(&ty::TyInt(IntTy::Is), InferSigned(i)) => {
Ok(Isize(ConstIsize::new_truncating(i, tcx.sess.target.int_type)))
},
@ -1000,7 +1011,8 @@ fn infer<'a, 'tcx>(i: ConstInt,
(&ty::TyUint(UintTy::U8), Infer(i)) => Ok(U8(i as u8)),
(&ty::TyUint(UintTy::U16), Infer(i)) => Ok(U16(i as u16)),
(&ty::TyUint(UintTy::U32), Infer(i)) => Ok(U32(i as u32)),
(&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i)),
(&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i as u64)),
(&ty::TyUint(UintTy::U128), Infer(i)) => Ok(U128(i)),
(&ty::TyUint(UintTy::Us), Infer(i)) => {
Ok(Usize(ConstUsize::new_truncating(i, tcx.sess.target.uint_type)))
},
@ -1071,21 +1083,23 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(
}
fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty::Ty) -> CastResult {
let v = val.to_u64_unchecked();
let v = val.to_u128_unchecked();
match ty.sty {
ty::TyBool if v == 0 => Ok(Bool(false)),
ty::TyBool if v == 1 => Ok(Bool(true)),
ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i64 as i8))),
ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i64 as i16))),
ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i64 as i32))),
ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i64))),
ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i128 as i8))),
ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i128 as i16))),
ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i128 as i32))),
ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i128 as i64))),
ty::TyInt(ast::IntTy::I128) => Ok(Integral(I128(v as i128))),
ty::TyInt(ast::IntTy::Is) => {
Ok(Integral(Isize(ConstIsize::new_truncating(v as i64, tcx.sess.target.int_type))))
Ok(Integral(Isize(ConstIsize::new_truncating(v as i128, tcx.sess.target.int_type))))
},
ty::TyUint(ast::UintTy::U8) => Ok(Integral(U8(v as u8))),
ty::TyUint(ast::UintTy::U16) => Ok(Integral(U16(v as u16))),
ty::TyUint(ast::UintTy::U32) => Ok(Integral(U32(v as u32))),
ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v))),
ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v as u64))),
ty::TyUint(ast::UintTy::U128) => Ok(Integral(U128(v as u128))),
ty::TyUint(ast::UintTy::Us) => {
Ok(Integral(Usize(ConstUsize::new_truncating(v, tcx.sess.target.uint_type))))
},
@ -1115,13 +1129,13 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
match ty.sty {
ty::TyInt(_) | ty::TyUint(_) => {
let i = match val {
F32(f) if f >= 0.0 => Infer(f as u64),
F32(f) if f >= 0.0 => Infer(f as u128),
FInfer { f64: f, .. } |
F64(f) if f >= 0.0 => Infer(f as u64),
F64(f) if f >= 0.0 => Infer(f as u128),
F32(f) => InferSigned(f as i64),
F32(f) => InferSigned(f as i128),
FInfer { f64: f, .. } |
F64(f) => InferSigned(f as i64)
F64(f) => InferSigned(f as i128)
};
if let (InferSigned(_), &ty::TyUint(_)) = (i, &ty.sty) {
@ -1145,9 +1159,9 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstVal, ty: ty::Ty) -> CastResult {
match val {
Integral(i) => cast_const_int(tcx, i, ty),
Bool(b) => cast_const_int(tcx, Infer(b as u64), ty),
Bool(b) => cast_const_int(tcx, Infer(b as u128), ty),
Float(f) => cast_const_float(tcx, f, ty),
Char(c) => cast_const_int(tcx, Infer(c as u64), ty),
Char(c) => cast_const_int(tcx, Infer(c as u128), ty),
Function(_) => Err(UnimplementedConstVal("casting fn pointers")),
ByteStr(b) => match ty.sty {
ty::TyRawPtr(_) => {
@ -1185,28 +1199,29 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
LitKind::Byte(n) => Ok(Integral(U8(n))),
LitKind::Int(n, Signed(ity)) => {
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral)
infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral)
},
// FIXME: this should become u128.
LitKind::Int(n, Unsuffixed) => {
match ty_hint.map(|t| &t.sty) {
Some(&ty::TyInt(ity)) => {
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral)
infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral)
},
Some(&ty::TyUint(uty)) => {
infer(Infer(n), tcx, &ty::TyUint(uty)).map(Integral)
infer(Infer(n as u128), tcx, &ty::TyUint(uty)).map(Integral)
},
None => Ok(Integral(Infer(n))),
None => Ok(Integral(Infer(n as u128))),
Some(&ty::TyAdt(adt, _)) => {
let hints = tcx.lookup_repr_hints(adt.did);
let int_ty = tcx.enum_repr_type(hints.iter().next());
infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty).map(Integral)
infer(Infer(n as u128), tcx, &int_ty.to_ty(tcx).sty).map(Integral)
},
Some(ty_hint) => bug!("bad ty_hint: {:?}, {:?}", ty_hint, lit),
}
},
LitKind::Int(n, Unsigned(ity)) => {
infer(Infer(n), tcx, &ty::TyUint(ity)).map(Integral)
infer(Infer(n as u128), tcx, &ty::TyUint(ity)).map(Integral)
},
LitKind::Float(n, fty) => {

View File

@ -28,6 +28,7 @@
#![feature(slice_patterns)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_fn)]
extern crate arena;
#[macro_use] extern crate syntax;
@ -41,6 +42,8 @@ extern crate graphviz;
extern crate syntax_pos;
extern crate serialize as rustc_serialize; // used by deriving
extern crate rustc_i128;
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;

View File

@ -12,3 +12,4 @@ crate-type = ["dylib"]
log = { path = "../liblog" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
rustc_i128 = { path = "../librustc_i128" }

View File

@ -74,11 +74,13 @@ impl ConstMathErr {
ULitOutOfRange(ast::UintTy::U16) => "literal out of range for u16",
ULitOutOfRange(ast::UintTy::U32) => "literal out of range for u32",
ULitOutOfRange(ast::UintTy::U64) => "literal out of range for u64",
ULitOutOfRange(ast::UintTy::U128) => "literal out of range for u128",
ULitOutOfRange(ast::UintTy::Us) => "literal out of range for usize",
LitOutOfRange(ast::IntTy::I8) => "literal out of range for i8",
LitOutOfRange(ast::IntTy::I16) => "literal out of range for i16",
LitOutOfRange(ast::IntTy::I32) => "literal out of range for i32",
LitOutOfRange(ast::IntTy::I64) => "literal out of range for i64",
LitOutOfRange(ast::IntTy::I128) => "literal out of range for i128",
LitOutOfRange(ast::IntTy::Is) => "literal out of range for isize",
}
}

View File

@ -11,6 +11,7 @@
use std::cmp::Ordering;
use syntax::attr::IntType;
use syntax::ast::{IntTy, UintTy};
use rustc_i128::{i128, u128};
use super::is::*;
use super::us::*;
@ -22,42 +23,65 @@ pub enum ConstInt {
I16(i16),
I32(i32),
I64(i64),
I128(i128),
Isize(ConstIsize),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
Usize(ConstUsize),
Infer(u64),
InferSigned(i64),
// FIXME: i128
Infer(u128),
InferSigned(i128),
}
pub use self::ConstInt::*;
macro_rules! bounds {
($($t:ident $min:ident $max:ident)*) => {
mod as_u64 {
$(
#[allow(dead_code)]
pub const $min: u64 = ::std::$t::MIN as u64;
#[allow(dead_code)]
pub const $max: u64 = ::std::$t::MAX as u64;
)*
}
mod as_i64 {
$(
#[allow(dead_code)]
pub const $min: i64 = ::std::$t::MIN as i64;
#[allow(dead_code)]
pub const $max: i64 = ::std::$t::MAX as i64;
)*
}
($ct: ty, $($t:ident $min:ident $max:ident)*) => {
$(
pub const $min: $ct = $t::min_value() as $ct;
pub const $max: $ct = $t::max_value() as $ct;
)*
};
($ct: ty: $min_val: expr, $($t:ident $min:ident $max:ident)*) => {
$(
pub const $min: $ct = $min_val;
pub const $max: $ct = $t::max_value() as $ct;
)*
}
}
bounds!{
i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX isize IMIN IMAX
u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX usize UMIN UMAX
mod ubounds {
#![allow(dead_code)]
use rustc_i128::{u128, i128};
// FIXME: min are problably all wrong for signed here.
bounds!{u128: 0,
i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX u128 U128MIN U128MAX
isize IMIN IMAX usize UMIN UMAX
}
}
mod ibounds {
#![allow(dead_code)]
use rustc_i128::i128;
#[cfg(stage0)]
pub const U64MIN: i128 = 0;
#[cfg(stage0)]
pub const U64MAX: i128 = i128::max_value();
#[cfg(not(stage0))]
bounds!(i128, u64 U64MIN U64MAX);
pub const U128MIN: i128 = 0;
pub const U128MAX: i128 = i128::max_value();
bounds!{i128,
i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX
isize IMIN IMAX usize UMIN UMAX
}
}
impl ConstInt {
@ -68,46 +92,54 @@ impl ConstInt {
(InferSigned(_), InferSigned(_))
| (Infer(_), Infer(_)) => self, // no inference possible
// kindof wrong, you could have had values > I64MAX during computation of a
(Infer(a @ 0...as_u64::I64MAX), InferSigned(_)) => InferSigned(a as i64),
(Infer(a @ 0...ubounds::I64MAX), InferSigned(_)) => InferSigned(a as i128),
(Infer(_), InferSigned(_)) => return Err(ConstMathErr::NotInRange),
(_, InferSigned(_))
| (_, Infer(_)) => return other.infer(self).map(|(b, a)| (a, b)),
(Infer(a @ 0...as_u64::I8MAX), I8(_)) => I8(a as i64 as i8),
(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)),
(Infer(a @ 0...ubounds::I8MAX), I8(_)) => I8(a as i64 as i8),
(Infer(a @ 0...ubounds::I16MAX), I16(_)) => I16(a as i64 as i16),
(Infer(a @ 0...ubounds::I32MAX), I32(_)) => I32(a as i64 as i32),
(Infer(a @ 0...ubounds::I64MAX), I64(_)) => I64(a as i64),
(Infer(a @ 0...ubounds::I128MAX), I128(_)) => I128(a as i128),
(Infer(a @ 0...ubounds::I16MAX), Isize(Is16(_))) => Isize(Is16(a as i64 as i16)),
(Infer(a @ 0...ubounds::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)),
(Infer(a @ 0...ubounds::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)),
(Infer(a @ 0...ubounds::U8MAX), U8(_)) => U8(a as u8),
(Infer(a @ 0...ubounds::U16MAX), U16(_)) => U16(a as u16),
(Infer(a @ 0...ubounds::U32MAX), U32(_)) => U32(a as u32),
(Infer(a @ 0...ubounds::U64MAX), U64(_)) => U64(a as u64),
(Infer(a @ 0...ubounds::U128MAX), U128(_)) => U128(a as u128),
(Infer(a @ 0...ubounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
(Infer(a @ 0...ubounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
(Infer(a @ 0...ubounds::U64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
(Infer(_), _) => return Err(ConstMathErr::NotInRange),
(InferSigned(a @ as_i64::I8MIN...as_i64::I8MAX), I8(_)) => I8(a as i8),
(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(_))) => {
(InferSigned(a @ ibounds::I8MIN...ibounds::I8MAX), I8(_)) => I8(a as i8),
(InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), I16(_)) => I16(a as i16),
(InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), I32(_)) => I32(a as i32),
(InferSigned(a @ ibounds::I64MIN...ibounds::I64MAX), I64(_)) => I64(a as i64),
(InferSigned(a @ ibounds::I128MIN...ibounds::I128MAX), I128(_)) => I128(a as i128),
(InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), Isize(Is16(_))) => {
Isize(Is16(a as i16))
},
(InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), Isize(Is32(_))) => {
(InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), Isize(Is32(_))) => {
Isize(Is32(a as i32))
},
(InferSigned(a), Isize(Is64(_))) => Isize(Is64(a)),
(InferSigned(a @ 0...as_i64::U8MAX), U8(_)) => U8(a as u8),
(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(a @ ibounds::I64MIN...ibounds::I64MAX), Isize(Is64(_))) => {
Isize(Is64(a as i64))
},
(InferSigned(a @ 0...ibounds::U8MAX), U8(_)) => U8(a as u8),
(InferSigned(a @ 0...ibounds::U16MAX), U16(_)) => U16(a as u16),
(InferSigned(a @ 0...ibounds::U32MAX), U32(_)) => U32(a as u32),
// SNAP: replace with U64MAX
(InferSigned(a @ 0...ibounds::I64MAX), U64(_)) => U64(a as u64),
(InferSigned(a @ 0...ibounds::I128MAX), U128(_)) => U128(a as u128),
(InferSigned(a @ 0...ibounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
(InferSigned(a @ 0...ibounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
// SNAP: replace with U64MAX
(InferSigned(a @ 0...ibounds::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
(InferSigned(_), _) => return Err(ConstMathErr::NotInRange),
_ => self, // already known types
};
@ -119,28 +151,34 @@ impl ConstInt {
match self {
Infer(i) => Infer(i),
InferSigned(i) if i < 0 => InferSigned(i),
I8(i) if i < 0 => InferSigned(i as i64),
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),
I8(i) => Infer(i as u64),
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),
I8(i) if i < 0 => InferSigned(i as i128),
I16(i) if i < 0 => InferSigned(i as i128),
I32(i) if i < 0 => InferSigned(i as i128),
I64(i) if i < 0 => InferSigned(i as i128),
// FIXME: 1128, compare with i128
I128(i) if i < 0 => InferSigned(i as i128),
Isize(Is16(i)) if i < 0 => InferSigned(i as i128),
Isize(Is32(i)) if i < 0 => InferSigned(i as i128),
Isize(Is64(i)) if i < 0 => InferSigned(i as i128),
InferSigned(i) => Infer(i as u128),
I8(i) => Infer(i as u128),
I16(i) => Infer(i as u128),
I32(i) => Infer(i as u128),
I64(i) => Infer(i as u128),
// FIXME: i128
I128(i) => Infer(i as u128),
Isize(Is16(i)) => Infer(i as u128),
Isize(Is32(i)) => Infer(i as u128),
Isize(Is64(i)) => Infer(i as u128),
U8(i) => Infer(i as u128),
U16(i) => Infer(i as u128),
U32(i) => Infer(i as u128),
U64(i) => Infer(i as u128),
// FIXME: i128
U128(i) => Infer(i as u128),
Usize(Us16(i)) => Infer(i as u128),
Usize(Us32(i)) => Infer(i as u128),
Usize(Us64(i)) => Infer(i as u128),
}
}
@ -153,67 +191,66 @@ impl ConstInt {
I16(_) => "i16",
I32(_) => "i32",
I64(_) => "i64",
I128(_) => "i128",
Isize(_) => "isize",
U8(_) => "u8",
U16(_) => "u16",
U32(_) => "u32",
U64(_) => "u64",
U128(_) => "u128",
Usize(_) => "usize",
}
}
/// Erases the type and returns a u64.
/// This is not the same as `-5i8 as u64` but as `-5i8 as i64 as u64`
pub fn to_u64_unchecked(self) -> u64 {
/// Erases the type and returns a u128.
/// This is not the same as `-5i8 as u128` but as `-5i8 as i128 as u128`
pub fn to_u128_unchecked(self) -> u128 {
match self.erase_type() {
ConstInt::Infer(i) => i,
ConstInt::InferSigned(i) => i as u64,
ConstInt::InferSigned(i) => i as u128,
_ => unreachable!(),
}
}
/// Converts the value to a `u32` if it's in the range 0...std::u32::MAX
pub fn to_u32(&self) -> Option<u32> {
match *self {
I8(v) if v >= 0 => Some(v as u32),
I16(v) if v >= 0 => Some(v as u32),
I32(v) if v >= 0 => Some(v as u32),
InferSigned(v)
| 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),
Infer(v)
| 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,
}
self.to_u128().and_then(|v| if v <= u32::max_value() as u128 {
Some(v as u32)
} else {
None
})
}
/// Converts the value to a `u64` if it's >= 0
/// Converts the value to a `u64` if it's in the range 0...std::u64::MAX
pub fn to_u64(&self) -> Option<u64> {
self.to_u128().and_then(|v| if v <= u64::max_value() as u128 {
Some(v as u64)
} else {
None
})
}
/// Converts the value to a `u128` if it's in the range 0...std::u128::MAX
pub fn to_u128(&self) -> Option<u128> {
match *self {
Infer(v) => Some(v),
InferSigned(v) if v >= 0 => Some(v as u64),
I8(v) if v >= 0 => Some(v as u64),
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),
InferSigned(v) if v >= 0 => Some(v as u128),
I8(v) if v >= 0 => Some(v as u128),
I16(v) if v >= 0 => Some(v as u128),
I32(v) if v >= 0 => Some(v as u128),
I64(v) if v >= 0 => Some(v as u128),
I128(v) if v >= 0 => Some(v as u128),
Isize(Is16(v)) if v >= 0 => Some(v as u128),
Isize(Is32(v)) if v >= 0 => Some(v as u128),
Isize(Is64(v)) if v >= 0 => Some(v as u128),
U8(v) => Some(v as u128),
U16(v) => Some(v as u128),
U32(v) => Some(v as u128),
U64(v) => Some(v as u128),
U128(v) => Some(v as u128),
Usize(Us16(v)) => Some(v as u128),
Usize(Us32(v)) => Some(v as u128),
Usize(Us64(v)) => Some(v as u128),
_ => None,
}
}
@ -224,6 +261,7 @@ impl ConstInt {
I16(v) => v < 0,
I32(v) => v < 0,
I64(v) => v < 0,
I128(v) => v < 0,
Isize(Is16(v)) => v < 0,
Isize(Is32(v)) => v < 0,
Isize(Is64(v)) => v < 0,
@ -239,6 +277,7 @@ 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)),
(I128(a), I128(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)),
@ -246,6 +285,7 @@ impl ConstInt {
(U16(a), U16(b)) => Ok(a.cmp(&b)),
(U32(a), U32(b)) => Ok(a.cmp(&b)),
(U64(a), U64(b)) => Ok(a.cmp(&b)),
(U128(a), U128(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)),
@ -265,6 +305,7 @@ impl ConstInt {
ConstInt::I16(i) => ConstInt::I16(add1!(i)),
ConstInt::I32(i) => ConstInt::I32(add1!(i)),
ConstInt::I64(i) => ConstInt::I64(add1!(i)),
ConstInt::I128(i) => ConstInt::I128(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))),
@ -272,6 +313,7 @@ impl ConstInt {
ConstInt::U16(i) => ConstInt::U16(add1!(i)),
ConstInt::U32(i) => ConstInt::U32(add1!(i)),
ConstInt::U64(i) => ConstInt::U64(add1!(i)),
ConstInt::U128(i) => ConstInt::U128(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))),
@ -285,11 +327,13 @@ impl ConstInt {
ConstInt::I16(_) => Some(IntType::SignedInt(IntTy::I16)),
ConstInt::I32(_) => Some(IntType::SignedInt(IntTy::I32)),
ConstInt::I64(_) => Some(IntType::SignedInt(IntTy::I64)),
ConstInt::I128(_) => Some(IntType::SignedInt(IntTy::I128)),
ConstInt::Isize(_) => Some(IntType::SignedInt(IntTy::Is)),
ConstInt::U8(_) => Some(IntType::UnsignedInt(UintTy::U8)),
ConstInt::U16(_) => Some(IntType::UnsignedInt(UintTy::U16)),
ConstInt::U32(_) => Some(IntType::UnsignedInt(UintTy::U32)),
ConstInt::U64(_) => Some(IntType::UnsignedInt(UintTy::U64)),
ConstInt::U128(_) => Some(IntType::UnsignedInt(UintTy::U128)),
ConstInt::Usize(_) => Some(IntType::UnsignedInt(UintTy::Us)),
_ => None,
}
@ -317,6 +361,7 @@ impl ::std::fmt::Display for ConstInt {
I16(i) => write!(fmt, "{}i16", i),
I32(i) => write!(fmt, "{}i32", i),
I64(i) => write!(fmt, "{}i64", i),
I128(i) => write!(fmt, "{}i128", 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),
@ -324,6 +369,7 @@ impl ::std::fmt::Display for ConstInt {
U16(i) => write!(fmt, "{}u16", i),
U32(i) => write!(fmt, "{}u32", i),
U64(i) => write!(fmt, "{}u64", i),
U128(i) => write!(fmt, "{}u128", 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),
@ -351,6 +397,7 @@ 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),
(I128(a), I128(b)) => a.$checked_func(b).map(I128),
(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),
@ -358,6 +405,7 @@ macro_rules! impl_binop {
(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),
(U128(a), U128(b)) => a.$checked_func(b).map(U128),
(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),
@ -380,6 +428,7 @@ 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))),
(I128(a), I128(b)) => Ok(I128(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)))),
@ -387,6 +436,7 @@ macro_rules! derive_binop {
(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))),
(U128(a), U128(b)) => Ok(U128(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)))),
@ -406,6 +456,11 @@ derive_binop!(BitAnd, bitand);
derive_binop!(BitOr, bitor);
derive_binop!(BitXor, bitxor);
#[cfg(not(stage0))]
const I128_MIN: i128 = ::std::i128::MIN;
#[cfg(stage0)]
const I128_MIN: i128 = ::std::i64::MIN;
fn check_division(
lhs: ConstInt,
rhs: ConstInt,
@ -417,6 +472,7 @@ fn check_division(
(I16(_), I16(0)) => Err(zerr),
(I32(_), I32(0)) => Err(zerr),
(I64(_), I64(0)) => Err(zerr),
(I128(_), I128(0)) => Err(zerr),
(Isize(_), Isize(Is16(0))) => Err(zerr),
(Isize(_), Isize(Is32(0))) => Err(zerr),
(Isize(_), Isize(Is64(0))) => Err(zerr),
@ -426,6 +482,7 @@ fn check_division(
(U16(_), U16(0)) => Err(zerr),
(U32(_), U32(0)) => Err(zerr),
(U64(_), U64(0)) => Err(zerr),
(U128(_), U128(0)) => Err(zerr),
(Usize(_), Usize(Us16(0))) => Err(zerr),
(Usize(_), Usize(Us32(0))) => Err(zerr),
(Usize(_), Usize(Us64(0))) => Err(zerr),
@ -435,10 +492,11 @@ 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)),
(I128(I128_MIN), I128(-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)),
(InferSigned(I128_MIN), InferSigned(-1)) => Err(Overflow(op)),
_ => Ok(()),
}
@ -454,6 +512,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)),
(I128(a), I128(b)) => Ok(I128(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))),
@ -463,6 +522,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)),
(U128(a), U128(b)) => Ok(U128(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))),
@ -484,6 +544,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)),
(I128(a), I128(b)) => Ok(I128(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))),
@ -493,6 +554,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)),
(U128(a), U128(b)) => Ok(U128(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))),
@ -512,6 +574,7 @@ 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))),
I128(a) => Ok(I128(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)))),
@ -519,6 +582,7 @@ impl ::std::ops::Shl<ConstInt> for ConstInt {
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))),
U128(a) => Ok(U128(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)))),
@ -537,6 +601,7 @@ 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))),
I128(a) => Ok(I128(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)))),
@ -544,6 +609,7 @@ impl ::std::ops::Shr<ConstInt> for ConstInt {
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))),
U128(a) => Ok(U128(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)))),
@ -561,22 +627,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))),
I128(a) => Ok(I128(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),
U16(_) => Err(UnsignedNegation),
U32(_) => Err(UnsignedNegation),
U64(_) => Err(UnsignedNegation),
Usize(_) => Err(UnsignedNegation),
Infer(a @ 0...as_u64::I64MAX) => Ok(InferSigned(-(a as i64))),
a@U8(0) | a@U16(0) | a@U32(0) | a@U64(0) | a@U128(0) |
a@Usize(Us16(0)) | a@Usize(Us32(0)) | a@Usize(Us64(0)) => Ok(a),
U8(_) | U16(_) | U32(_) | U64(_) | U128(_) | Usize(_) => Err(UnsignedNegation),
Infer(a @ 0...ubounds::I64MAX) => Ok(InferSigned(-(a as i128))),
Infer(_) => Err(Overflow(Op::Neg)),
InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_neg(), Op::Neg))),
}
@ -591,6 +649,7 @@ impl ::std::ops::Not for ConstInt {
I16(a) => Ok(I16(!a)),
I32(a) => Ok(I32(!a)),
I64(a) => Ok(I64(!a)),
I128(a) => Ok(I128(!a)),
Isize(Is16(a)) => Ok(Isize(Is16(!a))),
Isize(Is32(a)) => Ok(Isize(Is32(!a))),
Isize(Is64(a)) => Ok(Isize(Is64(!a))),
@ -598,6 +657,7 @@ impl ::std::ops::Not for ConstInt {
U16(a) => Ok(U16(!a)),
U32(a) => Ok(U32(!a)),
U64(a) => Ok(U64(!a)),
U128(a) => Ok(U128(!a)),
Usize(Us16(a)) => Ok(Usize(Us16(!a))),
Usize(Us32(a)) => Ok(Usize(Us32(!a))),
Usize(Us64(a)) => Ok(Usize(Us64(!a))),

View File

@ -10,6 +10,7 @@
use syntax::ast;
use super::err::*;
use rustc_i128::i128;
/// Depending on the target only one variant is ever used in a compilation.
/// Anything else is an error. This invariant is checked at several locations
@ -41,11 +42,11 @@ impl ConstIsize {
_ => unreachable!(),
}
}
pub fn new_truncating(i: i64, target_int_ty: ast::IntTy) -> Self {
pub fn new_truncating(i: i128, target_int_ty: ast::IntTy) -> Self {
match target_int_ty {
ast::IntTy::I16 => Is16(i as i16),
ast::IntTy::I32 => Is32(i as i32),
ast::IntTy::I64 => Is64(i),
ast::IntTy::I64 => Is64(i as i64),
_ => unreachable!(),
}
}

View File

@ -25,10 +25,14 @@
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(const_fn)]
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
// SNAP: remove use of this crate
extern crate rustc_i128;
extern crate serialize as rustc_serialize; // used by deriving
mod float;

View File

@ -10,6 +10,7 @@
use syntax::ast;
use super::err::*;
use rustc_i128::u128;
/// Depending on the target only one variant is ever used in a compilation.
/// Anything else is an error. This invariant is checked at several locations
@ -41,11 +42,11 @@ impl ConstUsize {
_ => unreachable!(),
}
}
pub fn new_truncating(i: u64, target_uint_ty: ast::UintTy) -> Self {
pub fn new_truncating(i: u128, target_uint_ty: ast::UintTy) -> Self {
match target_uint_ty {
ast::UintTy::U16 => Us16(i as u16),
ast::UintTy::U32 => Us32(i as u32),
ast::UintTy::U64 => Us64(i),
ast::UintTy::U64 => Us64(i as u64),
_ => unreachable!(),
}
}

View File

@ -0,0 +1,9 @@
[package]
authors = ["The Rust Project Developers"]
name = "rustc_i128"
version = "0.0.0"
[lib]
name = "rustc_i128"
path = "lib.rs"
crate-type = ["dylib"]

16
src/librustc_i128/lib.rs Normal file
View File

@ -0,0 +1,16 @@
#![allow(non_camel_case_types)]
#[cfg(stage0)]
pub type i128 = i64;
#[cfg(stage0)]
pub type u128 = u64;
#[cfg(not(stage0))]
pub type i128 = int::_i128;
#[cfg(not(stage0))]
pub type u128 = int::_u128;
#[cfg(not(stage0))]
mod int {
pub type _i128 = i128;
pub type _u128 = u128;
}

View File

@ -14,5 +14,6 @@ log = { path = "../liblog" }
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
rustc_const_eval = { path = "../librustc_const_eval" }
rustc_i128 = { path = "../librustc_i128" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }

View File

@ -47,6 +47,8 @@ extern crate rustc_back;
extern crate rustc_const_eval;
extern crate syntax_pos;
extern crate rustc_i128;
pub use rustc::lint;
pub use rustc::middle;
pub use rustc::session;

View File

@ -33,6 +33,8 @@ use syntax::codemap;
use rustc::hir;
use rustc_i128::{i128, u128};
register_long_diagnostics! {
E0519: r##"
It is not allowed to negate an unsigned integer.
@ -147,7 +149,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
if let Some(bits) = opt_ty_bits {
let exceeding = if let hir::ExprLit(ref lit) = r.node {
if let ast::LitKind::Int(shift, _) = lit.node {
shift >= bits
shift as u64 >= bits
} else {
false
}
@ -182,12 +184,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
t
};
let (_, max) = int_ty_range(int_type);
let max = max as u128;
let negative = self.negated_expr_id == e.id;
// Detect literal value out of range [min, max] inclusive
// avoiding use of -min to prevent overflow/panic
if (negative && v > max as u64 + 1) ||
(!negative && v > max as u64) {
if (negative && v > max + 1) ||
(!negative && v > max) {
cx.span_lint(OVERFLOWING_LITERALS,
e.span,
&format!("literal out of range for {:?}", t));
@ -204,7 +207,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
t
};
let (min, max) = uint_ty_range(uint_type);
let lit_val: u64 = match lit.node {
let lit_val: u128 = match lit.node {
// _v is u8, within range by definition
ast::LitKind::Byte(_v) => return,
ast::LitKind::Int(v, _) => v,
@ -264,23 +267,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
// for isize & usize, be conservative with the warnings, so that the
// warnings are consistent between 32- and 64-bit platforms
fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) {
fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) {
match int_ty {
ast::IntTy::Is => (i64::MIN, i64::MAX),
ast::IntTy::I8 => (i8::MIN as i64, i8::MAX as i64),
ast::IntTy::I16 => (i16::MIN as i64, i16::MAX as i64),
ast::IntTy::I32 => (i32::MIN as i64, i32::MAX as i64),
ast::IntTy::I64 => (i64::MIN, i64::MAX),
ast::IntTy::Is => (i64::min_value() as i128, i64::max_value() as i128),
ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128),
ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128),
ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128),
ast::IntTy::I64 => (i64::min_value() as i128, i64::max_value() as i128),
ast::IntTy::I128 =>(i128::min_value() as i128, i128::max_value()),
}
}
fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
match uint_ty {
ast::UintTy::Us => (u64::MIN, u64::MAX),
ast::UintTy::U8 => (u8::MIN as u64, u8::MAX as u64),
ast::UintTy::U16 => (u16::MIN as u64, u16::MAX as u64),
ast::UintTy::U32 => (u32::MIN as u64, u32::MAX as u64),
ast::UintTy::U64 => (u64::MIN, u64::MAX),
ast::UintTy::Us => (u64::min_value() as u128, u64::max_value() as u128),
ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128),
ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128),
ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128),
ast::UintTy::U64 => (u64::min_value() as u128, u64::max_value() as u128),
ast::UintTy::U128 => (u128::min_value(), u128::max_value()),
}
}
@ -298,6 +303,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
ast::IntTy::I16 => 16 as u64,
ast::IntTy::I32 => 32,
ast::IntTy::I64 => 64,
ast::IntTy::I128 => 128,
}
}
@ -308,6 +314,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
ast::UintTy::U16 => 16,
ast::UintTy::U32 => 32,
ast::UintTy::U64 => 64,
ast::UintTy::U128 => 128,
}
}
@ -327,28 +334,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
match tcx.tables().node_id_to_type(expr.id).sty {
ty::TyInt(int_ty) => {
let (min, max) = int_ty_range(int_ty);
let lit_val: i64 = match lit.node {
let lit_val: i128 = match lit.node {
hir::ExprLit(ref li) => {
match li.node {
ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => v as i64,
_ => return true,
ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => v as i128,
_ => return true
}
}
_ => bug!(),
},
_ => bug!()
};
is_valid(norm_binop, lit_val, min, max)
}
ty::TyUint(uint_ty) => {
let (min, max): (u64, u64) = uint_ty_range(uint_ty);
let lit_val: u64 = match lit.node {
let (min, max) :(u128, u128) = uint_ty_range(uint_ty);
let lit_val: u128 = match lit.node {
hir::ExprLit(ref li) => {
match li.node {
ast::LitKind::Int(v, _) => v,
_ => return true,
_ => return true
}
}
_ => bug!(),
},
_ => bug!()
};
is_valid(norm_binop, lit_val, min, max)
}

View File

@ -508,6 +508,7 @@ extern "C" {
pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
pub fn LLVMInt128TypeInContext(C: ContextRef) -> TypeRef;
pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef;
pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
@ -578,6 +579,7 @@ extern "C" {
// Operations on scalar constants
pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef;
pub fn LLVMConstIntOfArbitraryPrecision(IntTy: TypeRef, Wn: c_uint, Ws: *const u64) -> ValueRef;
pub fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef;
pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;

View File

@ -18,6 +18,7 @@ rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_llvm = { path = "../librustc_llvm" }
rustc_i128 = { path = "../librustc_i128" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_ext = { path = "../libsyntax_ext" }

View File

@ -43,6 +43,8 @@ use syntax::attr;
use syntax::ast::{self, NodeId};
use syntax::codemap;
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
use syntax_pos::{self, Span, BytePos, Pos};
use rustc_i128::u128;
pub struct DecodeContext<'a, 'tcx: 'a> {
opaque: opaque::Decoder<'a>,
@ -211,12 +213,14 @@ impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> {
decoder_methods! {
read_nil -> ();
read_u128 -> u128;
read_u64 -> u64;
read_u32 -> u32;
read_u16 -> u16;
read_u8 -> u8;
read_usize -> usize;
read_i128 -> i128;
read_i64 -> i64;
read_i32 -> i32;
read_i16 -> i16;

View File

@ -45,9 +45,15 @@ extern crate rustc_back;
extern crate rustc_const_math;
extern crate rustc_data_structures;
extern crate rustc_llvm;
extern crate rustc_i128;
mod diagnostics;
pub use rustc::middle;
#[macro_use]
mod macros;
mod astencode;
mod index_builder;
mod index;

View File

@ -17,5 +17,6 @@ rustc_const_eval = { path = "../librustc_const_eval" }
rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_bitflags = { path = "../librustc_bitflags" }
rustc_i128 = { path = "../librustc_i128" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }

View File

@ -15,6 +15,7 @@ use std;
use rustc_const_math::{ConstMathErr, Op};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx;
use rustc_i128::i128;
use build::{BlockAnd, BlockAndExtension, Builder};
use build::expr::category::{Category, RvalueFunc};
@ -347,6 +348,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ast::IntTy::I16 => ConstInt::I16(-1),
ast::IntTy::I32 => ConstInt::I32(-1),
ast::IntTy::I64 => ConstInt::I64(-1),
ast::IntTy::I128 => ConstInt::I128(-1),
ast::IntTy::Is => {
let int_ty = self.hir.tcx().sess.target.int_type;
let val = ConstIsize::new(-1, int_ty).unwrap();
@ -369,10 +371,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let literal = match ty.sty {
ty::TyInt(ity) => {
let val = match ity {
ast::IntTy::I8 => ConstInt::I8(std::i8::MIN),
ast::IntTy::I16 => ConstInt::I16(std::i16::MIN),
ast::IntTy::I32 => ConstInt::I32(std::i32::MIN),
ast::IntTy::I64 => ConstInt::I64(std::i64::MIN),
ast::IntTy::I8 => ConstInt::I8(i8::min_value()),
ast::IntTy::I16 => ConstInt::I16(i16::min_value()),
ast::IntTy::I32 => ConstInt::I32(i32::min_value()),
ast::IntTy::I64 => ConstInt::I64(i64::min_value()),
// FIXME: i128
ast::IntTy::I128 => ConstInt::I128(i128::min_value()),
ast::IntTy::Is => {
let int_ty = self.hir.tcx().sess.target.int_type;
let min = match int_ty {

View File

@ -66,6 +66,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ast::UintTy::U16 => ConstInt::U16(0),
ast::UintTy::U32 => ConstInt::U32(0),
ast::UintTy::U64 => ConstInt::U64(0),
ast::UintTy::U128 => ConstInt::U128(0),
ast::UintTy::Us => {
let uint_ty = self.hir.tcx().sess.target.uint_type;
let val = ConstUsize::new(0, uint_ty).unwrap();
@ -81,6 +82,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ast::IntTy::I16 => ConstInt::I16(0),
ast::IntTy::I32 => ConstInt::I32(0),
ast::IntTy::I64 => ConstInt::I64(0),
ast::IntTy::I128 => ConstInt::I128(0),
ast::IntTy::Is => {
let int_ty = self.hir.tcx().sess.target.int_type;
let val = ConstIsize::new(0, int_ty).unwrap();

View File

@ -41,6 +41,8 @@ extern crate syntax_pos;
extern crate rustc_const_math;
extern crate rustc_const_eval;
extern crate rustc_i128;
pub mod diagnostics;
pub mod build;

View File

@ -1005,13 +1005,14 @@ impl PrimitiveTypeTable {
table.intern("i16", TyInt(IntTy::I16));
table.intern("i32", TyInt(IntTy::I32));
table.intern("i64", TyInt(IntTy::I64));
table.intern("i128", TyInt(IntTy::I128));
table.intern("str", TyStr);
table.intern("usize", TyUint(UintTy::Us));
table.intern("u8", TyUint(UintTy::U8));
table.intern("u16", TyUint(UintTy::U16));
table.intern("u32", TyUint(UintTy::U32));
table.intern("u64", TyUint(UintTy::U64));
table.intern("u128", TyUint(UintTy::U128));
table
}

View File

@ -23,7 +23,8 @@ rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_incremental = { path = "../librustc_incremental" }
rustc_llvm = { path = "../librustc_llvm" }
rustc_i128 = { path = "../librustc_i128" }
rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
syntax_pos = { path = "../libsyntax_pos" }

View File

@ -44,6 +44,8 @@ use syntax::ast;
use syntax::symbol::{Symbol, InternedString};
use syntax_pos::Span;
use rustc_i128::u128;
pub use context::{CrateContext, SharedCrateContext};
pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
@ -425,6 +427,16 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
}
}
pub fn C_big_integral(t: Type, u: u128) -> ValueRef {
if ::std::mem::size_of::<u128>() == 16 {
unsafe {
llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, &u as *const u128 as *const u64)
}
} else {
C_integral(t, u as u64, false)
}
}
pub fn C_floating_f64(f: f64, t: Type) -> ValueRef {
unsafe {
llvm::LLVMConstReal(t.to_ref(), f)

View File

@ -24,6 +24,7 @@ use monomorphize::{Instance};
use type_::Type;
use type_of;
use rustc::ty;
use rustc_i128::{i128, u128};
use rustc::hir;

View File

@ -1022,6 +1022,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
let t_i16 = Type::i16(ccx);
let t_i32 = Type::i32(ccx);
let t_i64 = Type::i64(ccx);
let t_i128 = Type::i128(ccx);
let t_f32 = Type::f32(ccx);
let t_f64 = Type::f64(ccx);
@ -1088,50 +1089,60 @@ fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);
ifn!("llvm.ctpop.i32", fn(t_i32) -> t_i32);
ifn!("llvm.ctpop.i64", fn(t_i64) -> t_i64);
ifn!("llvm.ctpop.i128", fn(t_i128) -> t_i128);
ifn!("llvm.ctlz.i8", fn(t_i8 , i1) -> t_i8);
ifn!("llvm.ctlz.i16", fn(t_i16, i1) -> t_i16);
ifn!("llvm.ctlz.i32", fn(t_i32, i1) -> t_i32);
ifn!("llvm.ctlz.i64", fn(t_i64, i1) -> t_i64);
ifn!("llvm.ctlz.i128", fn(t_i128, i1) -> t_i128);
ifn!("llvm.cttz.i8", fn(t_i8 , i1) -> t_i8);
ifn!("llvm.cttz.i16", fn(t_i16, i1) -> t_i16);
ifn!("llvm.cttz.i32", fn(t_i32, i1) -> t_i32);
ifn!("llvm.cttz.i64", fn(t_i64, i1) -> t_i64);
ifn!("llvm.cttz.i128", fn(t_i128, i1) -> t_i128);
ifn!("llvm.bswap.i16", fn(t_i16) -> t_i16);
ifn!("llvm.bswap.i32", fn(t_i32) -> t_i32);
ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64);
ifn!("llvm.bswap.i128", fn(t_i128) -> t_i128);
ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
ifn!("llvm.sadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
ifn!("llvm.sadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
ifn!("llvm.uadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
ifn!("llvm.uadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
ifn!("llvm.uadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
ifn!("llvm.uadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
ifn!("llvm.uadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
ifn!("llvm.ssub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
ifn!("llvm.ssub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
ifn!("llvm.ssub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
ifn!("llvm.ssub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
ifn!("llvm.ssub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
ifn!("llvm.usub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
ifn!("llvm.usub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
ifn!("llvm.usub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
ifn!("llvm.usub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
ifn!("llvm.usub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
ifn!("llvm.smul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
ifn!("llvm.smul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
ifn!("llvm.smul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
ifn!("llvm.smul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
ifn!("llvm.smul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
ifn!("llvm.umul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
ifn!("llvm.umul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
ifn!("llvm.umul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
ifn!("llvm.umul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
ifn!("llvm.umul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
ifn!("llvm.lifetime.start", fn(t_i64,i8p) -> void);
ifn!("llvm.lifetime.end", fn(t_i64, i8p) -> void);

View File

@ -1460,7 +1460,8 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
llvm::LLVMRustDIBuilderCreateEnumerator(
DIB(cx),
name.as_ptr(),
v.disr_val.to_u64_unchecked())
// FIXME: what if enumeration has i128 discriminant?
v.disr_val.to_u128_unchecked() as u64)
}
})
.collect();

View File

@ -26,7 +26,8 @@ impl ::std::ops::BitAnd for Disr {
impl From<::rustc::ty::Disr> for Disr {
fn from(i: ::rustc::ty::Disr) -> Disr {
Disr(i.to_u64_unchecked())
// FIXME: what if discr has 128 bit discr?
Disr(i.to_u128_unchecked() as u64)
}
}

View File

@ -1167,6 +1167,8 @@ fn generic_simd_intrinsic<'a, 'tcx>(
// Returns the width of an int TypeVariant, and if it's signed or not
// Returns None if the type is not an integer
// FIXME: theres multiple of this functions, investigate using some of the already existing
// stuffs.
fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
-> Option<(u64, bool)> {
use rustc::ty::{TyInt, TyUint};
@ -1184,6 +1186,7 @@ fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
ast::IntTy::I16 => 16,
ast::IntTy::I32 => 32,
ast::IntTy::I64 => 64,
ast::IntTy::I128 => 128,
}, true)),
TyUint(t) => Some((match t {
ast::UintTy::Us => {
@ -1198,6 +1201,7 @@ fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
ast::UintTy::U16 => 16,
ast::UintTy::U32 => 32,
ast::UintTy::U64 => 64,
ast::UintTy::U128 => 128,
}, false)),
_ => None,
}

View File

@ -57,6 +57,7 @@ extern crate rustc_const_eval;
#[macro_use]
#[no_link]
extern crate rustc_bitflags;
extern crate rustc_i128;
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;

View File

@ -25,7 +25,7 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use {abi, adt, base, Disr, machine};
use callee::Callee;
use common::{self, BlockAndBuilder, CrateContext, const_get_elt, val_ty};
use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral};
use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral, C_big_integral};
use common::{C_null, C_struct, C_str_slice, C_undef, C_uint};
use common::{const_to_opt_int, const_to_opt_uint};
use consts;
@ -36,6 +36,7 @@ use value::Value;
use syntax::ast;
use syntax_pos::Span;
use rustc_i128::u128;
use std::fmt;
use std::ptr;
@ -75,6 +76,7 @@ impl<'tcx> Const<'tcx> {
ConstVal::Integral(I16(v)) => C_integral(Type::i16(ccx), v as u64, true),
ConstVal::Integral(I32(v)) => C_integral(Type::i32(ccx), v as u64, true),
ConstVal::Integral(I64(v)) => C_integral(Type::i64(ccx), v as u64, true),
ConstVal::Integral(I128(v)) => C_big_integral(Type::i128(ccx), v as u128),
ConstVal::Integral(Isize(v)) => {
let i = v.as_i64(ccx.tcx().sess.target.int_type);
C_integral(Type::int(ccx), i as u64, true)
@ -83,6 +85,7 @@ impl<'tcx> Const<'tcx> {
ConstVal::Integral(U16(v)) => C_integral(Type::i16(ccx), v as u64, false),
ConstVal::Integral(U32(v)) => C_integral(Type::i32(ccx), v as u64, false),
ConstVal::Integral(U64(v)) => C_integral(Type::i64(ccx), v, false),
ConstVal::Integral(U128(v)) => C_big_integral(Type::i128(ccx), v),
ConstVal::Integral(Usize(v)) => {
let u = v.as_u64(ccx.tcx().sess.target.uint_type);
C_integral(Type::int(ccx), u, false)

View File

@ -711,11 +711,13 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &BlockAndBuilder, ty: Ty) -> Val
TyInt(I16) => "llvm.sadd.with.overflow.i16",
TyInt(I32) => "llvm.sadd.with.overflow.i32",
TyInt(I64) => "llvm.sadd.with.overflow.i64",
TyInt(I128) => "llvm.sadd.with.overflow.i128",
TyUint(U8) => "llvm.uadd.with.overflow.i8",
TyUint(U16) => "llvm.uadd.with.overflow.i16",
TyUint(U32) => "llvm.uadd.with.overflow.i32",
TyUint(U64) => "llvm.uadd.with.overflow.i64",
TyUint(U128) => "llvm.uadd.with.overflow.i128",
_ => unreachable!(),
},
@ -724,11 +726,13 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &BlockAndBuilder, ty: Ty) -> Val
TyInt(I16) => "llvm.ssub.with.overflow.i16",
TyInt(I32) => "llvm.ssub.with.overflow.i32",
TyInt(I64) => "llvm.ssub.with.overflow.i64",
TyInt(I128) => "llvm.ssub.with.overflow.i128",
TyUint(U8) => "llvm.usub.with.overflow.i8",
TyUint(U16) => "llvm.usub.with.overflow.i16",
TyUint(U32) => "llvm.usub.with.overflow.i32",
TyUint(U64) => "llvm.usub.with.overflow.i64",
TyUint(U128) => "llvm.usub.with.overflow.i128",
_ => unreachable!(),
},
@ -737,11 +741,13 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &BlockAndBuilder, ty: Ty) -> Val
TyInt(I16) => "llvm.smul.with.overflow.i16",
TyInt(I32) => "llvm.smul.with.overflow.i32",
TyInt(I64) => "llvm.smul.with.overflow.i64",
TyInt(I128) => "llvm.smul.with.overflow.i128",
TyUint(U8) => "llvm.umul.with.overflow.i8",
TyUint(U16) => "llvm.umul.with.overflow.i16",
TyUint(U32) => "llvm.umul.with.overflow.i32",
TyUint(U64) => "llvm.umul.with.overflow.i64",
TyUint(U128) => "llvm.umul.with.overflow.i128",
_ => unreachable!(),
},

View File

@ -397,11 +397,13 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
ty::TyInt(ast::IntTy::I16) => output.push_str("i16"),
ty::TyInt(ast::IntTy::I32) => output.push_str("i32"),
ty::TyInt(ast::IntTy::I64) => output.push_str("i64"),
ty::TyInt(ast::IntTy::I128) => output.push_str("i128"),
ty::TyUint(ast::UintTy::Us) => output.push_str("usize"),
ty::TyUint(ast::UintTy::U8) => output.push_str("u8"),
ty::TyUint(ast::UintTy::U16) => output.push_str("u16"),
ty::TyUint(ast::UintTy::U32) => output.push_str("u32"),
ty::TyUint(ast::UintTy::U64) => output.push_str("u64"),
ty::TyUint(ast::UintTy::U128) => output.push_str("u128"),
ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"),
ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"),
ty::TyAdt(adt_def, substs) => {

View File

@ -94,6 +94,10 @@ impl Type {
ty!(llvm::LLVMInt64TypeInContext(ccx.llcx()))
}
pub fn i128(ccx: &CrateContext) -> Type {
ty!(llvm::LLVMInt128TypeInContext(ccx.llcx()))
}
// Creates an integer type with the given number of bits, e.g. i24
pub fn ix(ccx: &CrateContext, num_bits: u64) -> Type {
ty!(llvm::LLVMIntTypeInContext(ccx.llcx(), num_bits as c_uint))
@ -134,7 +138,8 @@ impl Type {
ast::IntTy::I8 => Type::i8(ccx),
ast::IntTy::I16 => Type::i16(ccx),
ast::IntTy::I32 => Type::i32(ccx),
ast::IntTy::I64 => Type::i64(ccx)
ast::IntTy::I64 => Type::i64(ccx),
ast::IntTy::I128 => Type::i128(ccx),
}
}
@ -144,7 +149,8 @@ impl Type {
ast::UintTy::U8 => Type::i8(ccx),
ast::UintTy::U16 => Type::i16(ccx),
ast::UintTy::U32 => Type::i32(ccx),
ast::UintTy::U64 => Type::i64(ccx)
ast::UintTy::U64 => Type::i64(ccx),
ast::UintTy::U128 => Type::i128(ccx),
}
}

View File

@ -432,7 +432,9 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
(true, 32, &ty::TyInt(ast::IntTy::I32)) |
(false, 32, &ty::TyUint(ast::UintTy::U32)) |
(true, 64, &ty::TyInt(ast::IntTy::I64)) |
(false, 64, &ty::TyUint(ast::UintTy::U64)) => {},
(false, 64, &ty::TyUint(ast::UintTy::U64)) |
(true, 128, &ty::TyInt(ast::IntTy::I128)) |
(false, 128, &ty::TyUint(ast::UintTy::U128)) => {},
_ => simple_error(&format!("`{}`", t),
&format!("`{}{n}`",
if signed {"i"} else {"u"},

View File

@ -435,6 +435,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let lang_def_id = self.tcx.lang_items.i64_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::TyInt(ast::IntTy::I128) => {
let lang_def_id = self.tcx.lang_items.i128_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::TyInt(ast::IntTy::Is) => {
let lang_def_id = self.tcx.lang_items.isize_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
@ -455,6 +459,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let lang_def_id = self.tcx.lang_items.u64_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::TyUint(ast::UintTy::U128) => {
let lang_def_id = self.tcx.lang_items.u128_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::TyUint(ast::UintTy::Us) => {
let lang_def_id = self.tcx.lang_items.usize_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);

View File

@ -160,6 +160,13 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
"i64",
item.span);
}
ty::TyInt(ast::IntTy::I128) => {
self.check_primitive_impl(def_id,
self.tcx.lang_items.i128_impl(),
"i128",
"i128",
item.span);
}
ty::TyInt(ast::IntTy::Is) => {
self.check_primitive_impl(def_id,
self.tcx.lang_items.isize_impl(),
@ -195,6 +202,13 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
"u64",
item.span);
}
ty::TyUint(ast::UintTy::U128) => {
self.check_primitive_impl(def_id,
self.tcx.lang_items.u128_impl(),
"u128",
"u128",
item.span);
}
ty::TyUint(ast::UintTy::Us) => {
self.check_primitive_impl(def_id,
self.tcx.lang_items.usize_impl(),

View File

@ -1060,11 +1060,13 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
(attr::SignedInt(ast::IntTy::I16), ConstInt::I16(_)) |
(attr::SignedInt(ast::IntTy::I32), ConstInt::I32(_)) |
(attr::SignedInt(ast::IntTy::I64), ConstInt::I64(_)) |
(attr::SignedInt(ast::IntTy::I128), ConstInt::I128(_)) |
(attr::SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) |
(attr::UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) |
(attr::UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) |
(attr::UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) |
(attr::UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) |
(attr::UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) |
(attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => Some(i),
(_, i) => {
print_err(ConstVal::Integral(i));

View File

@ -1513,8 +1513,8 @@ pub enum Type {
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
pub enum PrimitiveType {
Isize, I8, I16, I32, I64,
Usize, U8, U16, U32, U64,
Isize, I8, I16, I32, I64, I128,
Usize, U8, U16, U32, U64, U128,
F32, F64,
Char,
Bool,
@ -1614,26 +1614,29 @@ impl PrimitiveType {
}
pub fn as_str(&self) -> &'static str {
use PrimitiveType::*;
match *self {
PrimitiveType::Isize => "isize",
PrimitiveType::I8 => "i8",
PrimitiveType::I16 => "i16",
PrimitiveType::I32 => "i32",
PrimitiveType::I64 => "i64",
PrimitiveType::Usize => "usize",
PrimitiveType::U8 => "u8",
PrimitiveType::U16 => "u16",
PrimitiveType::U32 => "u32",
PrimitiveType::U64 => "u64",
PrimitiveType::F32 => "f32",
PrimitiveType::F64 => "f64",
PrimitiveType::Str => "str",
PrimitiveType::Bool => "bool",
PrimitiveType::Char => "char",
PrimitiveType::Array => "array",
PrimitiveType::Slice => "slice",
PrimitiveType::Tuple => "tuple",
PrimitiveType::RawPointer => "pointer",
Isize => "isize",
I8 => "i8",
I16 => "i16",
I32 => "i32",
I64 => "i64",
I128 => "i128",
Usize => "usize",
U8 => "u8",
U16 => "u16",
U32 => "u32",
U64 => "u64",
U128 => "u128",
F32 => "f32",
F64 => "f64",
Str => "str",
Bool => "bool",
Char => "char",
Array => "array",
Slice => "slice",
Tuple => "tuple",
RawPointer => "pointer",
}
}
@ -2486,6 +2489,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
fn build_deref_target_impls(cx: &DocContext,
items: &[Item],
ret: &mut Vec<Item>) {
use PrimitiveType::*;
let tcx = cx.tcx;
for item in items {
@ -2505,25 +2509,27 @@ fn build_deref_target_impls(cx: &DocContext,
}
};
let did = match primitive {
PrimitiveType::Isize => tcx.lang_items.isize_impl(),
PrimitiveType::I8 => tcx.lang_items.i8_impl(),
PrimitiveType::I16 => tcx.lang_items.i16_impl(),
PrimitiveType::I32 => tcx.lang_items.i32_impl(),
PrimitiveType::I64 => tcx.lang_items.i64_impl(),
PrimitiveType::Usize => tcx.lang_items.usize_impl(),
PrimitiveType::U8 => tcx.lang_items.u8_impl(),
PrimitiveType::U16 => tcx.lang_items.u16_impl(),
PrimitiveType::U32 => tcx.lang_items.u32_impl(),
PrimitiveType::U64 => tcx.lang_items.u64_impl(),
PrimitiveType::F32 => tcx.lang_items.f32_impl(),
PrimitiveType::F64 => tcx.lang_items.f64_impl(),
PrimitiveType::Char => tcx.lang_items.char_impl(),
PrimitiveType::Bool => None,
PrimitiveType::Str => tcx.lang_items.str_impl(),
PrimitiveType::Slice => tcx.lang_items.slice_impl(),
PrimitiveType::Array => tcx.lang_items.slice_impl(),
PrimitiveType::Tuple => None,
PrimitiveType::RawPointer => tcx.lang_items.const_ptr_impl(),
Isize => tcx.lang_items.isize_impl(),
I8 => tcx.lang_items.i8_impl(),
I16 => tcx.lang_items.i16_impl(),
I32 => tcx.lang_items.i32_impl(),
I64 => tcx.lang_items.i64_impl(),
I128 => tcx.lang_items.i128_impl(),
Usize => tcx.lang_items.usize_impl(),
U8 => tcx.lang_items.u8_impl(),
U16 => tcx.lang_items.u16_impl(),
U32 => tcx.lang_items.u32_impl(),
U64 => tcx.lang_items.u64_impl(),
U128 => tcx.lang_items.u128_impl(),
F32 => tcx.lang_items.f32_impl(),
F64 => tcx.lang_items.f64_impl(),
Char => tcx.lang_items.char_impl(),
Bool => None,
Str => tcx.lang_items.str_impl(),
Slice => tcx.lang_items.slice_impl(),
Array => tcx.lang_items.slice_impl(),
Tuple => None,
RawPointer => tcx.lang_items.const_ptr_impl(),
};
if let Some(did) = did {
if !did.is_local() {

View File

@ -10,3 +10,4 @@ crate-type = ["dylib", "rlib"]
[dependencies]
log = { path = "../liblog" }
rustc_i128 = { path = "../librustc_i128" }

View File

@ -211,6 +211,8 @@ use std::string;
use std::{char, f64, fmt, str};
use std;
use rustc_i128::{i128, u128};
use Encodable;
/// Represents a json value
@ -494,12 +496,14 @@ impl<'a> ::Encoder for Encoder<'a> {
}
fn emit_usize(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u128(&mut self, _: u128) -> EncodeResult { unimplemented!() }
fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_isize(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i128(&mut self, _: i128) -> EncodeResult { unimplemented!() }
fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
@ -742,12 +746,14 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
}
fn emit_usize(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u128(&mut self, _: u128) -> EncodeResult { unimplemented!() }
fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_isize(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i128(&mut self, _: i128) -> EncodeResult { unimplemented!() }
fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
@ -2138,11 +2144,13 @@ impl ::Decoder for Decoder {
read_primitive! { read_u16, u16 }
read_primitive! { read_u32, u32 }
read_primitive! { read_u64, u64 }
read_primitive! { read_u128, u128 }
read_primitive! { read_isize, isize }
read_primitive! { read_i8, i8 }
read_primitive! { read_i16, i16 }
read_primitive! { read_i32, i32 }
read_primitive! { read_i64, i64 }
read_primitive! { read_i128, i128 }
fn read_f32(&mut self) -> DecodeResult<f32> { self.read_f64().map(|x| x as f32) }

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc_i128::{i128, u128};
#[inline]
fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
if position == vec.len() {
@ -28,7 +30,6 @@ pub fn write_unsigned_leb128_to<W>(mut value: u64, mut write: W) -> usize
where W: FnMut(usize, u8)
{
let mut position = 0;
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
@ -52,14 +53,14 @@ pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, value: u6
}
#[inline]
pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u64, usize) {
pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u128, usize) {
let mut result = 0;
let mut shift = 0;
let mut position = start_position;
loop {
let byte = data[position];
position += 1;
result |= ((byte & 0x7F) as u64) << shift;
result |= ((byte & 0x7F) as u128) << shift;
if (byte & 0x80) == 0 {
break;
}
@ -76,7 +77,7 @@ pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u64, usize)
/// The callback `write` is called once for each position
/// that is to be written to with the byte to be encoded
/// at that position.
pub fn write_signed_leb128_to<W>(mut value: i64, mut write: W) -> usize
pub fn write_signed_leb128_to<W>(mut value: i128, mut write: W) -> usize
where W: FnMut(usize, u8)
{
let mut position = 0;
@ -92,43 +93,43 @@ pub fn write_signed_leb128_to<W>(mut value: i64, mut write: W) -> usize
write(position, byte);
position += 1;
if !more {
break;
}
}
position
}
pub fn write_signed_leb128(out: &mut Vec<u8>, start_position: usize, value: i64) -> usize {
pub fn write_signed_leb128(out: &mut Vec<u8>, start_position: usize, value: i128) -> usize {
write_signed_leb128_to(value, |i, v| write_to_vec(out, start_position+i, v))
}
#[inline]
pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i64, usize) {
let mut result = 0;
let mut shift = 0;
let mut position = start_position;
let mut byte;
pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i128, usize) {
let (l, r) = read_unsigned_leb128(data, start_position);
(l as i128, r)
// let mut result = 0;
// let mut shift = 0;
// let mut position = start_position;
// let mut byte;
loop {
byte = data[position];
position += 1;
result |= ((byte & 0x7F) as i64) << shift;
shift += 7;
// loop {
// byte = data[position];
// position += 1;
// result |= ((byte & 0x7F) as i128) << shift;
// shift += 7;
if (byte & 0x80) == 0 {
break;
}
}
// if (byte & 0x80) == 0 {
// break;
// }
// }
if (shift < 64) && ((byte & 0x40) != 0) {
// sign extend
result |= -(1i64 << shift);
}
// if (shift < 64) && ((byte & 0x40) != 0) {
// // sign extend
// result |= -(1 << shift);
// }
(result, position - start_position)
// (result, position - start_position)
}
#[test]

View File

@ -44,6 +44,8 @@ Core encoding and decoding interfaces.
extern crate std_unicode;
extern crate collections;
extern crate rustc_i128;
pub use self::serialize::{Decoder, Encoder, Decodable, Encodable};
pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder};

View File

@ -13,6 +13,8 @@ use std::borrow::Cow;
use std::io::{self, Write};
use serialize;
use rustc_i128::{i128, u128};
// -----------------------------------------------------------------------------
// Encoder
// -----------------------------------------------------------------------------
@ -33,7 +35,7 @@ impl<'a> Encoder<'a> {
macro_rules! write_uleb128 {
($enc:expr, $value:expr) => {{
let pos = $enc.cursor.position() as usize;
let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u64);
let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u128);
$enc.cursor.set_position((pos + bytes_written) as u64);
Ok(())
}}
@ -42,7 +44,7 @@ macro_rules! write_uleb128 {
macro_rules! write_sleb128 {
($enc:expr, $value:expr) => {{
let pos = $enc.cursor.position() as usize;
let bytes_written = write_signed_leb128($enc.cursor.get_mut(), pos, $value as i64);
let bytes_written = write_signed_leb128($enc.cursor.get_mut(), pos, $value as i128);
$enc.cursor.set_position((pos + bytes_written) as u64);
Ok(())
}}
@ -59,6 +61,10 @@ impl<'a> serialize::Encoder for Encoder<'a> {
write_uleb128!(self, v)
}
fn emit_u128(&mut self, v: u128) -> EncodeResult {
write_uleb128!(self, v)
}
fn emit_u64(&mut self, v: u64) -> EncodeResult {
write_uleb128!(self, v)
}
@ -80,6 +86,10 @@ impl<'a> serialize::Encoder for Encoder<'a> {
write_sleb128!(self, v)
}
fn emit_i128(&mut self, v: i128) -> EncodeResult {
write_sleb128!(self, v)
}
fn emit_i64(&mut self, v: i64) -> EncodeResult {
write_sleb128!(self, v)
}
@ -184,6 +194,11 @@ impl<'a> serialize::Decoder for Decoder<'a> {
Ok(())
}
#[inline]
fn read_u128(&mut self) -> Result<u128, Self::Error> {
read_uleb128!(self, u128)
}
#[inline]
fn read_u64(&mut self) -> Result<u64, Self::Error> {
read_uleb128!(self, u64)
@ -211,6 +226,11 @@ impl<'a> serialize::Decoder for Decoder<'a> {
read_uleb128!(self, usize)
}
#[inline]
fn read_i128(&mut self) -> Result<i128, Self::Error> {
read_sleb128!(self, i128)
}
#[inline]
fn read_i64(&mut self) -> Result<i64, Self::Error> {
read_sleb128!(self, i64)

View File

@ -20,6 +20,7 @@ use std::path;
use std::rc::Rc;
use std::cell::{Cell, RefCell};
use std::sync::Arc;
use rustc_i128::{i128, u128};
pub trait Encoder {
type Error;
@ -27,11 +28,13 @@ pub trait Encoder {
// Primitive types:
fn emit_nil(&mut self) -> Result<(), Self::Error>;
fn emit_usize(&mut self, v: usize) -> Result<(), Self::Error>;
fn emit_u128(&mut self, v: u128) -> Result<(), Self::Error>;
fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>;
fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>;
fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>;
fn emit_isize(&mut self, v: isize) -> Result<(), Self::Error>;
fn emit_i128(&mut self, v: i128) -> Result<(), Self::Error>;
fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>;
fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>;
@ -144,11 +147,13 @@ pub trait Decoder {
// Primitive types:
fn read_nil(&mut self) -> Result<(), Self::Error>;
fn read_usize(&mut self) -> Result<usize, Self::Error>;
fn read_u128(&mut self) -> Result<u128, Self::Error>;
fn read_u64(&mut self) -> Result<u64, Self::Error>;
fn read_u32(&mut self) -> Result<u32, Self::Error>;
fn read_u16(&mut self) -> Result<u16, Self::Error>;
fn read_u8(&mut self) -> Result<u8, Self::Error>;
fn read_isize(&mut self) -> Result<isize, Self::Error>;
fn read_i128(&mut self) -> Result<i128, Self::Error>;
fn read_i64(&mut self) -> Result<i64, Self::Error>;
fn read_i32(&mut self) -> Result<i32, Self::Error>;
fn read_i16(&mut self) -> Result<i16, Self::Error>;
@ -328,6 +333,20 @@ impl Decodable for u64 {
}
}
#[cfg(not(stage0))]
impl Encodable for u128 {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_u128(*self)
}
}
#[cfg(not(stage0))]
impl Decodable for u128 {
fn decode<D: Decoder>(d: &mut D) -> Result<u128, D::Error> {
d.read_u128()
}
}
impl Encodable for isize {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_isize(*self)
@ -388,6 +407,20 @@ impl Decodable for i64 {
}
}
#[cfg(not(stage0))]
impl Encodable for i128 {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_i128(*self)
}
}
#[cfg(not(stage0))]
impl Decodable for i128 {
fn decode<D: Decoder>(d: &mut D) -> Result<i128, D::Error> {
d.read_i128()
}
}
impl Encodable for str {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_str(self)

View File

@ -301,6 +301,7 @@
#![feature(unwind_attributes)]
#![feature(vec_push_all)]
#![feature(zero_one)]
#![feature(i128)]
#![cfg_attr(test, feature(update_panic_count))]
// Explicitly import the prelude. The compiler uses this same unstable attribute
@ -395,6 +396,9 @@ pub use core::i16;
pub use core::i32;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::i64;
#[unstable(feature = "i128", issue = "35118")]
#[cfg(not(stage0))]
pub use core::i128;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::usize;
#[stable(feature = "rust1", since = "1.0.0")]
@ -423,6 +427,9 @@ pub use core_collections::string;
pub use core_collections::vec;
#[stable(feature = "rust1", since = "1.0.0")]
pub use std_unicode::char;
#[unstable(feature = "i128", issue = "35118")]
#[cfg(not(stage0))]
pub use core::u128;
pub mod f32;
pub mod f64;

View File

@ -15,3 +15,4 @@ rustc_bitflags = { path = "../librustc_bitflags" }
syntax_pos = { path = "../libsyntax_pos" }
rustc_errors = { path = "../librustc_errors" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_i128 = { path = "../librustc_i128" }

View File

@ -33,6 +33,8 @@ use std::u32;
use serialize::{self, Encodable, Decodable, Encoder, Decoder};
use rustc_i128::{u128, i128};
/// An identifier contains a Name (index into the interner
/// table) and a SyntaxContext to track renaming and
/// macro expansion per Flatt et al., "Macros That Work Together"
@ -1062,7 +1064,7 @@ pub enum LitKind {
/// A character literal (`'a'`)
Char(char),
/// An integer literal (`1`)
Int(u64, LitIntType),
Int(u128, LitIntType),
/// A float literal (`1f64` or `1E10f64`)
Float(Symbol, FloatTy),
/// A float literal without a suffix (`1.0 or 1.0E10`)
@ -1171,6 +1173,7 @@ pub enum IntTy {
I16,
I32,
I64,
I128,
}
impl fmt::Debug for IntTy {
@ -1192,15 +1195,16 @@ impl IntTy {
IntTy::I8 => "i8",
IntTy::I16 => "i16",
IntTy::I32 => "i32",
IntTy::I64 => "i64"
IntTy::I64 => "i64",
IntTy::I128 => "i128",
}
}
pub fn val_to_string(&self, val: i64) -> String {
pub fn val_to_string(&self, val: i128) -> String {
// cast to a u64 so we can correctly print INT64_MIN. All integral types
// are parsed as u64, so we wouldn't want to print an extra negative
// sign.
format!("{}{}", val as u64, self.ty_to_string())
format!("{}{}", val as u128, self.ty_to_string())
}
pub fn ty_max(&self) -> u64 {
@ -1208,7 +1212,9 @@ impl IntTy {
IntTy::I8 => 0x80,
IntTy::I16 => 0x8000,
IntTy::Is | IntTy::I32 => 0x80000000, // FIXME: actually ni about Is
IntTy::I64 => 0x8000000000000000
IntTy::I64 => 0x8000000000000000,
// FIXME: i128
IntTy::I128 => !0u64,
}
}
@ -1219,6 +1225,7 @@ impl IntTy {
IntTy::I16 => 16,
IntTy::I32 => 32,
IntTy::I64 => 64,
IntTy::I128 => 128,
})
}
}
@ -1230,6 +1237,7 @@ pub enum UintTy {
U16,
U32,
U64,
U128,
}
impl UintTy {
@ -1239,11 +1247,12 @@ impl UintTy {
UintTy::U8 => "u8",
UintTy::U16 => "u16",
UintTy::U32 => "u32",
UintTy::U64 => "u64"
UintTy::U64 => "u64",
UintTy::U128 => "u128",
}
}
pub fn val_to_string(&self, val: u64) -> String {
pub fn val_to_string(&self, val: u128) -> String {
format!("{}{}", val, self.ty_to_string())
}
@ -1252,7 +1261,9 @@ impl UintTy {
UintTy::U8 => 0xff,
UintTy::U16 => 0xffff,
UintTy::Us | UintTy::U32 => 0xffffffff, // FIXME: actually ni about Us
UintTy::U64 => 0xffffffffffffffff
UintTy::U64 => 0xffffffffffffffff,
// FIXME: i128
UintTy::U128 => 0xffffffffffffffff,
}
}
@ -1263,6 +1274,7 @@ impl UintTy {
UintTy::U16 => 16,
UintTy::U32 => 32,
UintTy::U64 => 64,
UintTy::U128 => 128,
})
}
}

View File

@ -899,6 +899,8 @@ fn int_type_of_word(s: &str) -> Option<IntType> {
"u32" => Some(UnsignedInt(ast::UintTy::U32)),
"i64" => Some(SignedInt(ast::IntTy::I64)),
"u64" => Some(UnsignedInt(ast::UintTy::U64)),
"i128" => Some(SignedInt(ast::IntTy::I128)),
"u128" => Some(UnsignedInt(ast::UintTy::U128)),
"isize" => Some(SignedInt(ast::IntTy::Is)),
"usize" => Some(UnsignedInt(ast::UintTy::Us)),
_ => None
@ -945,7 +947,8 @@ impl IntType {
SignedInt(ast::IntTy::I8) | UnsignedInt(ast::UintTy::U8) |
SignedInt(ast::IntTy::I16) | UnsignedInt(ast::UintTy::U16) |
SignedInt(ast::IntTy::I32) | UnsignedInt(ast::UintTy::U32) |
SignedInt(ast::IntTy::I64) | UnsignedInt(ast::UintTy::U64) => true,
SignedInt(ast::IntTy::I64) | UnsignedInt(ast::UintTy::U64) |
SignedInt(ast::IntTy::I128) | UnsignedInt(ast::UintTy::U128) => true,
SignedInt(ast::IntTy::Is) | UnsignedInt(ast::UintTy::Us) => false
}
}

View File

@ -16,6 +16,7 @@ use codemap::{dummy_spanned, respan, Spanned};
use ext::base::ExtCtxt;
use ptr::P;
use symbol::{Symbol, keywords};
use rustc_i128::u128;
// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
@ -712,23 +713,26 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
self.expr(sp, ast::ExprKind::Lit(P(respan(sp, lit))))
}
fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
self.expr_lit(span, ast::LitKind::Int(i as u64, ast::LitIntType::Unsigned(ast::UintTy::Us)))
self.expr_lit(span, ast::LitKind::Int(i as u128,
ast::LitIntType::Unsigned(ast::UintTy::Us)))
}
fn expr_isize(&self, sp: Span, i: isize) -> P<ast::Expr> {
if i < 0 {
let i = (-i) as u64;
let i = (-i) as u128;
let lit_ty = ast::LitIntType::Signed(ast::IntTy::Is);
let lit = self.expr_lit(sp, ast::LitKind::Int(i, lit_ty));
self.expr_unary(sp, ast::UnOp::Neg, lit)
} else {
self.expr_lit(sp, ast::LitKind::Int(i as u64, ast::LitIntType::Signed(ast::IntTy::Is)))
self.expr_lit(sp, ast::LitKind::Int(i as u128,
ast::LitIntType::Signed(ast::IntTy::Is)))
}
}
fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
self.expr_lit(sp, ast::LitKind::Int(u as u64, ast::LitIntType::Unsigned(ast::UintTy::U32)))
self.expr_lit(sp, ast::LitKind::Int(u as u128,
ast::LitIntType::Unsigned(ast::UintTy::U32)))
}
fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr> {
self.expr_lit(sp, ast::LitKind::Int(u as u64, ast::LitIntType::Unsigned(ast::UintTy::U8)))
self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U8)))
}
fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> {
self.expr_lit(sp, ast::LitKind::Bool(value))

View File

@ -19,6 +19,7 @@ use parse::token;
use ptr::P;
use tokenstream::{self, TokenTree};
/// Quasiquoting works via token trees.
///
/// This is registered as a set of expression syntax extension called quote!
@ -40,6 +41,7 @@ pub mod rt {
pub use parse::new_parser_from_tts;
pub use syntax_pos::{BytePos, Span, DUMMY_SP};
pub use codemap::{dummy_spanned};
use rustc_i128::{u128};
pub trait ToTokens {
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree>;
@ -288,7 +290,7 @@ pub mod rt {
} else {
*self
};
let lit = ast::LitKind::Int(val as u64, ast::LitIntType::Signed($tag));
let lit = ast::LitKind::Int(val as u128, ast::LitIntType::Signed($tag));
let lit = P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Lit(P(dummy_spanned(lit))),
@ -310,7 +312,7 @@ pub mod rt {
(unsigned, $t:ty, $tag:expr) => (
impl ToTokens for $t {
fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
let lit = ast::LitKind::Int(*self as u64, ast::LitIntType::Unsigned($tag));
let lit = ast::LitKind::Int(*self as u128, ast::LitIntType::Unsigned($tag));
dummy_spanned(lit).to_tokens(cx)
}
}

View File

@ -46,8 +46,9 @@ pub extern crate rustc_errors as errors;
extern crate syntax_pos;
extern crate rustc_data_structures;
extern crate serialize as rustc_serialize; // used by deriving
extern crate rustc_i128;
extern crate serialize as rustc_serialize; // used by deriving
// A variant of 'try!' that panics on an Err. This is used as a crutch on the
// way towards a non-panic!-prone parser. It should be used for fatal parsing

View File

@ -28,6 +28,8 @@ use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::str;
use rustc_i128::u128;
pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
#[macro_use]
@ -557,18 +559,20 @@ pub fn integer_lit(s: &str, suffix: Option<Symbol>, sd: &Handler, sp: Span) -> a
"i16" => ast::LitIntType::Signed(ast::IntTy::I16),
"i32" => ast::LitIntType::Signed(ast::IntTy::I32),
"i64" => ast::LitIntType::Signed(ast::IntTy::I64),
"i128" => ast::LitIntType::Signed(ast::IntTy::I128),
"usize" => ast::LitIntType::Unsigned(ast::UintTy::Us),
"u8" => ast::LitIntType::Unsigned(ast::UintTy::U8),
"u16" => ast::LitIntType::Unsigned(ast::UintTy::U16),
"u32" => ast::LitIntType::Unsigned(ast::UintTy::U32),
"u64" => ast::LitIntType::Unsigned(ast::UintTy::U64),
"u128" => ast::LitIntType::Unsigned(ast::UintTy::U128),
suf => {
// i<digits> and u<digits> look like widths, so lets
// give an error message along those lines
if looks_like_width_suffix(&['i', 'u'], suf) {
sd.struct_span_err(sp, &format!("invalid width `{}` for integer literal",
&suf[1..]))
.help("valid widths are 8, 16, 32 and 64")
.help("valid widths are 8, 16, 32, 64 and 128")
.emit();
} else {
sd.struct_span_err(sp, &format!("invalid suffix `{}` for numeric literal", suf))
@ -585,7 +589,7 @@ pub fn integer_lit(s: &str, suffix: Option<Symbol>, sd: &Handler, sp: Span) -> a
debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \
string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix);
match u64::from_str_radix(s, base) {
match u128::from_str_radix(s, base) {
Ok(r) => ast::LitKind::Int(r, ty),
Err(_) => {
// small bases are lexed as if they were base 10, e.g, the string

View File

@ -64,6 +64,8 @@ use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::slice;
use rustc_i128::u128;
bitflags! {
flags Restrictions: u8 {
const RESTRICTION_STMT_EXPR = 1 << 0,
@ -2044,7 +2046,7 @@ impl<'a> Parser<'a> {
pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinVec<Attribute>) -> P<Expr> {
let span = &self.span;
let lv_lit = P(codemap::Spanned {
node: LitKind::Int(i as u64, ast::LitIntType::Unsigned(UintTy::U32)),
node: LitKind::Int(i as u128, ast::LitIntType::Unsigned(UintTy::U32)),
span: *span
});

View File

@ -30,6 +30,8 @@ use std_inject;
use symbol::{Symbol, keywords};
use tokenstream::{self, TokenTree};
use rustc_i128::i128;
use std::ascii;
use std::io::{self, Write, Read};
use std::iter;
@ -647,8 +649,7 @@ pub trait PrintState<'a> {
ast::LitKind::Int(i, t) => {
match t {
ast::LitIntType::Signed(st) => {
word(self.writer(),
&st.val_to_string(i as i64))
word(self.writer(), &st.val_to_string(i as i128))
}
ast::LitIntType::Unsigned(ut) => {
word(self.writer(), &ut.val_to_string(i))

View File

@ -782,12 +782,13 @@ fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &
attr::ReprInt(attr::SignedInt(ast::IntTy::I16)) => "i16",
attr::ReprInt(attr::SignedInt(ast::IntTy::I32)) => "i32",
attr::ReprInt(attr::SignedInt(ast::IntTy::I64)) => "i64",
attr::ReprInt(attr::SignedInt(ast::IntTy::I128)) => "i128",
attr::ReprInt(attr::UnsignedInt(ast::UintTy::Us)) => "usize",
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U8)) => "u8",
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U16)) => "u16",
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U32)) => "u32",
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U64)) => "u64",
attr::ReprInt(attr::UnsignedInt(ast::UintTy::U128)) => "u128",
}
}
}