mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Auto merge of #38482 - est31:i128, r=eddyb
i128 and u128 support Brings i128 and u128 support to nightly rust, behind a feature flag. The goal of this PR is to do the bulk of the work for 128 bit integer support. Smaller but just as tricky features needed for stabilisation like 128 bit enum discriminants are left for future PRs. Rebased version of #37900, which in turn was a rebase + improvement of #35954 . Sadly I couldn't reopen #37900 due to github. There goes my premium position in the homu queue... [plugin-breaking-change] cc #35118 (tracking issue)
This commit is contained in:
commit
38bd207626
25
mk/crates.mk
25
mk/crates.mk
@ -54,7 +54,7 @@ TARGET_CRATES := libc std term \
|
||||
compiler_builtins core alloc \
|
||||
std_unicode rustc_bitflags \
|
||||
alloc_system alloc_jemalloc \
|
||||
panic_abort panic_unwind unwind
|
||||
panic_abort panic_unwind unwind rustc_i128
|
||||
RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \
|
||||
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
|
||||
rustc_data_structures rustc_platform_intrinsics rustc_errors \
|
||||
@ -92,23 +92,26 @@ DEPS_getopts := std
|
||||
DEPS_graphviz := std
|
||||
DEPS_log := std
|
||||
DEPS_num := std
|
||||
DEPS_serialize := std log
|
||||
DEPS_serialize := std log rustc_i128
|
||||
DEPS_term := std
|
||||
DEPS_test := std getopts term native:rust_test_helpers
|
||||
DEPS_rustc_i128 = std
|
||||
|
||||
DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors syntax_pos rustc_data_structures
|
||||
DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors \
|
||||
syntax_pos rustc_data_structures rustc_i128
|
||||
DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros proc_macro
|
||||
DEPS_proc_macro := syntax syntax_pos rustc_plugin log
|
||||
DEPS_syntax_pos := serialize
|
||||
DEPS_proc_macro_tokens := syntax syntax_pos log
|
||||
DEPS_proc_macro_plugin := syntax syntax_pos rustc_plugin log proc_macro_tokens
|
||||
|
||||
DEPS_rustc_const_math := std syntax log serialize
|
||||
DEPS_rustc_const_math := std syntax log serialize rustc_i128
|
||||
DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \
|
||||
rustc_back graphviz syntax_pos
|
||||
rustc_back graphviz syntax_pos rustc_i128
|
||||
|
||||
DEPS_rustc := syntax fmt_macros flate arena serialize getopts \
|
||||
log graphviz rustc_llvm rustc_back rustc_data_structures\
|
||||
rustc_const_math syntax_pos rustc_errors
|
||||
rustc_const_math syntax_pos rustc_errors rustc_i128
|
||||
DEPS_rustc_back := std syntax flate log libc
|
||||
DEPS_rustc_borrowck := rustc log graphviz syntax syntax_pos rustc_errors rustc_mir
|
||||
DEPS_rustc_data_structures := std log serialize libc
|
||||
@ -119,19 +122,20 @@ DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_bo
|
||||
rustc_passes rustc_save_analysis rustc_const_eval \
|
||||
rustc_incremental syntax_pos rustc_errors proc_macro rustc_data_structures
|
||||
DEPS_rustc_errors := log libc serialize syntax_pos
|
||||
DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval
|
||||
DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval rustc_i128
|
||||
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
|
||||
DEPS_proc_macro := std syntax
|
||||
DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \
|
||||
proc_macro syntax_ext
|
||||
proc_macro syntax_ext rustc_i128
|
||||
DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors
|
||||
DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags
|
||||
DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags \
|
||||
rustc_i128
|
||||
DEPS_rustc_resolve := arena rustc log syntax syntax_pos rustc_errors
|
||||
DEPS_rustc_platform_intrinsics := std
|
||||
DEPS_rustc_plugin := rustc rustc_metadata syntax syntax_pos rustc_errors
|
||||
DEPS_rustc_privacy := rustc log syntax syntax_pos
|
||||
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
|
||||
log syntax serialize rustc_llvm rustc_platform_intrinsics \
|
||||
log syntax serialize rustc_llvm rustc_platform_intrinsics rustc_i128 \
|
||||
rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos
|
||||
DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
|
||||
DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
|
||||
@ -159,6 +163,7 @@ ONLY_RLIB_alloc := 1
|
||||
ONLY_RLIB_rand := 1
|
||||
ONLY_RLIB_collections := 1
|
||||
ONLY_RLIB_std_unicode := 1
|
||||
ONLY_RLIB_rustc_i128 := 1
|
||||
ONLY_RLIB_rustc_bitflags := 1
|
||||
ONLY_RLIB_alloc_system := 1
|
||||
ONLY_RLIB_alloc_jemalloc := 1
|
||||
|
15
src/Cargo.lock
generated
15
src/Cargo.lock
generated
@ -249,6 +249,7 @@ dependencies = [
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
@ -308,6 +309,7 @@ dependencies = [
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
@ -318,6 +320,7 @@ name = "rustc_const_math"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"log 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
]
|
||||
@ -327,6 +330,7 @@ name = "rustc_data_structures"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"log 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
]
|
||||
|
||||
@ -372,6 +376,10 @@ dependencies = [
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_i128"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_incremental"
|
||||
version = "0.0.0"
|
||||
@ -380,6 +388,7 @@ dependencies = [
|
||||
"log 0.0.0",
|
||||
"rustc 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
@ -393,6 +402,7 @@ dependencies = [
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_const_eval 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
@ -418,6 +428,7 @@ dependencies = [
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
@ -437,6 +448,7 @@ dependencies = [
|
||||
"rustc_const_eval 0.0.0",
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
@ -519,6 +531,7 @@ dependencies = [
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"rustc_incremental 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"rustc_platform_intrinsics 0.0.0",
|
||||
@ -574,6 +587,7 @@ name = "serialize"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"log 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -619,6 +633,7 @@ dependencies = [
|
||||
"rustc_bitflags 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_i128 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
@ -16,4 +16,787 @@
|
||||
issue = "0")]
|
||||
#![crate_name = "compiler_builtins"]
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(staged_api)]
|
||||
#![allow(unused_features)]
|
||||
#![feature(staged_api, core_intrinsics, repr_simd,
|
||||
i128_type, core_float, abi_unadjusted, associated_consts)]
|
||||
#![allow(non_camel_case_types, unused_variables, unused_imports)]
|
||||
#![cfg_attr(stage0, allow(dead_code))]
|
||||
|
||||
#[cfg(any(target_pointer_width="32", target_pointer_width="16", target_os="windows",
|
||||
target_arch="mips64"))]
|
||||
pub mod reimpls {
|
||||
|
||||
#![allow(unused_comparisons)]
|
||||
|
||||
use core::intrinsics::unchecked_div;
|
||||
use core::intrinsics::unchecked_rem;
|
||||
use core::ptr;
|
||||
|
||||
// C API is expected to tolerate some amount of size mismatch in ABI. Hopefully the amount of
|
||||
// handling is sufficient for bootstrapping.
|
||||
#[cfg(stage0)]
|
||||
type u128_ = u64;
|
||||
#[cfg(stage0)]
|
||||
type i128_ = i64;
|
||||
#[cfg(not(stage0))]
|
||||
type u128_ = u128;
|
||||
#[cfg(not(stage0))]
|
||||
type i128_ = i128;
|
||||
|
||||
macro_rules! ashl {
|
||||
($a:expr, $b:expr, $ty:ty) => {{
|
||||
let (a, b) = ($a, $b);
|
||||
let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
|
||||
let half_bits = bits >> 1;
|
||||
if b & half_bits != 0 {
|
||||
<$ty>::from_parts(0, a.low().wrapping_shl(
|
||||
b.wrapping_sub(half_bits) as u32))
|
||||
} else if b == 0 {
|
||||
a
|
||||
} else {
|
||||
<$ty>::from_parts(a.low().wrapping_shl(b as u32),
|
||||
a.high().wrapping_shl(b as u32)
|
||||
| a.low()
|
||||
.wrapping_shr(half_bits.wrapping_sub(b) as u32))
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#[export_name="__ashlti3"]
|
||||
pub extern "C" fn shl(a: u128_, b: u128_) -> u128_ {
|
||||
ashl!(a, b, u128_)
|
||||
}
|
||||
|
||||
macro_rules! ashr {
|
||||
($a: expr, $b: expr, $ty:ty) => {{
|
||||
let (a, b) = ($a, $b);
|
||||
let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
|
||||
let half_bits = bits >> 1;
|
||||
if b & half_bits != 0 {
|
||||
<$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32)
|
||||
as <$ty as LargeInt>::LowHalf,
|
||||
a.high().wrapping_shr(half_bits.wrapping_sub(1) as u32))
|
||||
} else if b == 0 {
|
||||
a
|
||||
} else {
|
||||
let high_unsigned = a.high() as <$ty as LargeInt>::LowHalf;
|
||||
<$ty>::from_parts(high_unsigned.wrapping_shl(half_bits.wrapping_sub(b) as u32)
|
||||
| a.low().wrapping_shr(b as u32),
|
||||
a.high().wrapping_shr(b as u32))
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#[export_name="__ashrti3"]
|
||||
pub extern "C" fn shr(a: i128_, b: i128_) -> i128_ {
|
||||
ashr!(a, b, i128_)
|
||||
}
|
||||
|
||||
macro_rules! lshr {
|
||||
($a: expr, $b: expr, $ty:ty) => {{
|
||||
let (a, b) = ($a, $b);
|
||||
let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
|
||||
let half_bits = bits >> 1;
|
||||
if b & half_bits != 0 {
|
||||
<$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32), 0)
|
||||
} else if b == 0 {
|
||||
a
|
||||
} else {
|
||||
<$ty>::from_parts(a.high().wrapping_shl(half_bits.wrapping_sub(b) as u32)
|
||||
| a.low().wrapping_shr(b as u32),
|
||||
a.high().wrapping_shr(b as u32))
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
#[export_name="__lshrti3"]
|
||||
pub extern "C" fn lshr(a: u128_, b: u128_) -> u128_ {
|
||||
lshr!(a, b, u128_)
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ {
|
||||
unsafe {
|
||||
if !rem.is_null() {
|
||||
*rem = unchecked_rem(n, d);
|
||||
}
|
||||
unchecked_div(n, d)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ {
|
||||
// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
|
||||
unsafe {
|
||||
// special cases, X is unknown, K != 0
|
||||
if n.high() == 0 {
|
||||
if d.high() == 0 {
|
||||
// 0 X
|
||||
// ---
|
||||
// 0 X
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from(unchecked_rem(n.low(), d.low()));
|
||||
}
|
||||
return u128::from(unchecked_div(n.low(), d.low()));
|
||||
} else {
|
||||
// 0 X
|
||||
// ---
|
||||
// K X
|
||||
if !rem.is_null() {
|
||||
*rem = n;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
let mut sr;
|
||||
let mut q;
|
||||
let mut r;
|
||||
|
||||
if d.low() == 0 {
|
||||
if d.high() == 0 {
|
||||
// K X
|
||||
// ---
|
||||
// 0 0
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from(unchecked_rem(n.high(), d.low()));
|
||||
}
|
||||
return u128::from(unchecked_div(n.high(), d.low()));
|
||||
}
|
||||
|
||||
if n.low() == 0 {
|
||||
// K 0
|
||||
// ---
|
||||
// K 0
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from_parts(0, unchecked_rem(n.high(), d.high()));
|
||||
}
|
||||
return u128::from(unchecked_div(n.high(), d.high()));
|
||||
}
|
||||
|
||||
// K K
|
||||
// ---
|
||||
// K 0
|
||||
|
||||
if d.high().is_power_of_two() {
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from_parts(n.low(),
|
||||
n.high() & (d.high().wrapping_sub(1)));
|
||||
}
|
||||
return u128::from(n.high().wrapping_shr(d.high().trailing_zeros()));
|
||||
}
|
||||
|
||||
// K K
|
||||
// ---
|
||||
// K 0
|
||||
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
|
||||
|
||||
// D > N
|
||||
if sr > 64 - 2 {
|
||||
if !rem.is_null() {
|
||||
*rem = n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sr = sr.wrapping_add(1);
|
||||
|
||||
// 1 <= sr <= u64::bits() - 1
|
||||
q = n.wrapping_shl(64u32.wrapping_sub(sr));
|
||||
r = n.wrapping_shr(sr);
|
||||
} else {
|
||||
if d.high() == 0 {
|
||||
// K X
|
||||
// ---
|
||||
// 0 K
|
||||
if d.low().is_power_of_two() {
|
||||
if !rem.is_null() {
|
||||
*rem = u128::from(n.low() & (d.low().wrapping_sub(1)));
|
||||
}
|
||||
|
||||
if d.low() == 1 {
|
||||
return n;
|
||||
} else {
|
||||
let sr = d.low().trailing_zeros();
|
||||
return n.wrapping_shr(sr);
|
||||
};
|
||||
}
|
||||
|
||||
sr = (1 + 64u32)
|
||||
.wrapping_add(d.low().leading_zeros())
|
||||
.wrapping_sub(n.high().leading_zeros());
|
||||
|
||||
// 2 <= sr <= u64::bits() - 1
|
||||
q = n.wrapping_shl(128u32.wrapping_sub(sr));
|
||||
r = n.wrapping_shr(sr);
|
||||
// FIXME the C compiler-rt implementation has something here
|
||||
// that looks like a speed optimisation.
|
||||
// It would be worth a try to port it to Rust too and
|
||||
// compare the speed.
|
||||
} else {
|
||||
// K X
|
||||
// ---
|
||||
// K K
|
||||
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
|
||||
|
||||
// D > N
|
||||
if sr > 64 - 1 {
|
||||
if !rem.is_null() {
|
||||
*rem = n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sr = sr.wrapping_add(1);
|
||||
|
||||
// 1 <= sr <= u32::bits()
|
||||
q = n.wrapping_shl(128u32.wrapping_sub(sr));
|
||||
r = n.wrapping_shr(sr);
|
||||
}
|
||||
}
|
||||
|
||||
// Not a special case
|
||||
// q and r are initialized with
|
||||
// q = n << (u64::bits() - sr)
|
||||
// r = n >> sr
|
||||
// 1 <= sr <= u64::bits() - 1
|
||||
let mut carry = 0;
|
||||
|
||||
// FIXME: replace this with a for loop
|
||||
// (atm not doable as this generates call to
|
||||
// eh_personality when optimisations are turned off,
|
||||
// which in turn gives a linker error in later
|
||||
// compilation steps)
|
||||
while sr > 0 {
|
||||
// r:q = ((r:q) << 1) | carry
|
||||
r = r.wrapping_shl(1) | q.wrapping_shr(128 - 1);
|
||||
q = q.wrapping_shl(1) | carry as u128;
|
||||
|
||||
// carry = 0
|
||||
// if r >= d {
|
||||
// r -= d;
|
||||
// carry = 1;
|
||||
// }
|
||||
let s = ((d.wrapping_sub(r).wrapping_sub(1)) as i128).wrapping_shr(128 - 1);
|
||||
carry = (s & 1) as u64;
|
||||
r = r.wrapping_sub(d & s as u128);
|
||||
sr = sr.wrapping_sub(1);
|
||||
}
|
||||
|
||||
if !rem.is_null() {
|
||||
*rem = r;
|
||||
}
|
||||
(q.wrapping_shl(1)) | carry as u128
|
||||
}
|
||||
}
|
||||
|
||||
fn i128_mod(a: i128_, b: i128_) -> i128_ {
|
||||
let b = b.uabs();
|
||||
let sa = a.signum();
|
||||
let a = a.uabs();
|
||||
unsafe {
|
||||
let mut r = ::core::mem::zeroed();
|
||||
u128_div_mod(a, b, &mut r);
|
||||
if sa == -1 { (r as i128_).unchecked_neg() } else { r as i128_ }
|
||||
}
|
||||
}
|
||||
|
||||
fn i128_div(a: i128_, b: i128_) -> i128_ {
|
||||
let sa = a.signum();
|
||||
let sb = b.signum();
|
||||
let a = a.uabs();
|
||||
let b = b.uabs();
|
||||
let sr = sa.wrapping_mul(sb); // sign of quotient
|
||||
(if sr == -1 {
|
||||
(u128_div_mod(a, b, ptr::null_mut()) as i128_).unchecked_neg()
|
||||
} else {
|
||||
u128_div_mod(a, b, ptr::null_mut()) as i128_
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[export_name="__udivti3"]
|
||||
pub extern "C" fn u128_div(a: u128_, b: u128_) -> u128_ {
|
||||
(a / b)
|
||||
}
|
||||
|
||||
macro_rules! mulo {
|
||||
($a:expr, $b:expr, $o: expr, $ty: ty) => {{
|
||||
let (a, b, overflow) = ($a, $b, $o);
|
||||
*overflow = 0;
|
||||
let result = a.wrapping_mul(b);
|
||||
if a == <$ty>::min_value() {
|
||||
if b != 0 && b != 1 {
|
||||
*overflow = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if b == <$ty>::min_value() {
|
||||
if a != 0 && a != 1 {
|
||||
*overflow = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
let sa = a.signum();
|
||||
let abs_a = a.iabs();
|
||||
let sb = b.signum();
|
||||
let abs_b = b.iabs();
|
||||
if abs_a < 2 || abs_b < 2 {
|
||||
return result;
|
||||
}
|
||||
if sa == sb {
|
||||
if abs_a > unchecked_div(<$ty>::max_value(), abs_b) {
|
||||
*overflow = 1;
|
||||
}
|
||||
} else {
|
||||
if abs_a > unchecked_div(<$ty>::min_value(), abs_b.unchecked_neg()) {
|
||||
*overflow = 1;
|
||||
}
|
||||
}
|
||||
result
|
||||
}}
|
||||
}
|
||||
|
||||
pub trait LargeInt {
|
||||
type LowHalf;
|
||||
type HighHalf;
|
||||
|
||||
fn low(self) -> Self::LowHalf;
|
||||
fn high(self) -> Self::HighHalf;
|
||||
fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
|
||||
}
|
||||
impl LargeInt for u64 {
|
||||
type LowHalf = u32;
|
||||
type HighHalf = u32;
|
||||
|
||||
fn low(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
fn high(self) -> u32 {
|
||||
(self.wrapping_shr(32)) as u32
|
||||
}
|
||||
fn from_parts(low: u32, high: u32) -> u64 {
|
||||
low as u64 | (high as u64).wrapping_shl(32)
|
||||
}
|
||||
}
|
||||
impl LargeInt for i64 {
|
||||
type LowHalf = u32;
|
||||
type HighHalf = i32;
|
||||
|
||||
fn low(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
fn high(self) -> i32 {
|
||||
self.wrapping_shr(32) as i32
|
||||
}
|
||||
fn from_parts(low: u32, high: i32) -> i64 {
|
||||
low as i64 | (high as i64).wrapping_shl(32)
|
||||
}
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
impl LargeInt for u128 {
|
||||
type LowHalf = u64;
|
||||
type HighHalf = u64;
|
||||
|
||||
fn low(self) -> u64 {
|
||||
self as u64
|
||||
}
|
||||
fn high(self) -> u64 {
|
||||
unsafe { *(&self as *const u128 as *const u64).offset(1) }
|
||||
}
|
||||
fn from_parts(low: u64, high: u64) -> u128 {
|
||||
#[repr(C, packed)] struct Parts(u64, u64);
|
||||
unsafe { ::core::mem::transmute(Parts(low, high)) }
|
||||
}
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
impl LargeInt for i128 {
|
||||
type LowHalf = u64;
|
||||
type HighHalf = i64;
|
||||
|
||||
fn low(self) -> u64 {
|
||||
self as u64
|
||||
}
|
||||
fn high(self) -> i64 {
|
||||
unsafe { *(&self as *const i128 as *const i64).offset(1) }
|
||||
}
|
||||
fn from_parts(low: u64, high: i64) -> i128 {
|
||||
u128::from_parts(low, high as u64) as i128
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! mul {
|
||||
($a:expr, $b:expr, $ty: ty, $tyh: ty) => {{
|
||||
let (a, b) = ($a, $b);
|
||||
let half_bits = ((::core::mem::size_of::<$tyh>() * 8) / 2) as u32;
|
||||
let lower_mask = (!0u64).wrapping_shr(half_bits);
|
||||
let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask);
|
||||
let mut t = low.wrapping_shr(half_bits);
|
||||
low &= lower_mask;
|
||||
t = t.wrapping_add(a.low().wrapping_shr(half_bits)
|
||||
.wrapping_mul(b.low() & lower_mask));
|
||||
low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
|
||||
let mut high = t.wrapping_shr(half_bits) as $tyh;
|
||||
t = low.wrapping_shr(half_bits);
|
||||
low &= lower_mask;
|
||||
t = t.wrapping_add(b.low().wrapping_shr(half_bits)
|
||||
.wrapping_mul(a.low() & lower_mask));
|
||||
low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
|
||||
high = high.wrapping_add(t.wrapping_shr(half_bits) as $tyh);
|
||||
high = high.wrapping_add(a.low().wrapping_shr(half_bits)
|
||||
.wrapping_mul(b.low().wrapping_shr(half_bits)) as $tyh);
|
||||
high = high
|
||||
.wrapping_add(a.high()
|
||||
.wrapping_mul(b.low() as $tyh))
|
||||
.wrapping_add((a.low() as $tyh)
|
||||
.wrapping_mul(b.high()));
|
||||
<$ty>::from_parts(low, high)
|
||||
}}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[export_name="__multi3"]
|
||||
pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ {
|
||||
((a as i64).wrapping_mul(b as i64) as i128_)
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[export_name="__multi3"]
|
||||
pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ {
|
||||
mul!(a, b, i128_, i64)
|
||||
}
|
||||
|
||||
trait AbsExt: Sized {
|
||||
fn uabs(self) -> u128_ {
|
||||
self.iabs() as u128_
|
||||
}
|
||||
fn iabs(self) -> i128_;
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
impl AbsExt for i128_ {
|
||||
fn iabs(self) -> i128_ {
|
||||
let s = self >> 63;
|
||||
((self ^ s).wrapping_sub(s))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
impl AbsExt for i128_ {
|
||||
fn iabs(self) -> i128_ {
|
||||
let s = self >> 127;
|
||||
((self ^ s).wrapping_sub(s))
|
||||
}
|
||||
}
|
||||
|
||||
trait NegExt: Sized {
|
||||
fn unchecked_neg(self) -> i128_;
|
||||
}
|
||||
|
||||
impl NegExt for i128_ {
|
||||
fn unchecked_neg(self) -> i128_ {
|
||||
(!self).wrapping_add(1)
|
||||
}
|
||||
}
|
||||
|
||||
trait FloatStuff: Sized {
|
||||
type ToBytes;
|
||||
|
||||
const MANTISSA_BITS: u32;
|
||||
const MAX_EXP: i32;
|
||||
const EXP_MASK: Self::ToBytes;
|
||||
const MANTISSA_MASK: Self::ToBytes;
|
||||
const MANTISSA_LEAD_BIT: Self::ToBytes;
|
||||
|
||||
fn to_bytes(self) -> Self::ToBytes;
|
||||
fn get_exponent(self) -> i32;
|
||||
}
|
||||
|
||||
impl FloatStuff for f32 {
|
||||
type ToBytes = u32;
|
||||
const MANTISSA_BITS: u32 = 23;
|
||||
const MAX_EXP: i32 = 127;
|
||||
const EXP_MASK: u32 = 0x7F80_0000;
|
||||
const MANTISSA_MASK: u32 = 0x007F_FFFF;
|
||||
const MANTISSA_LEAD_BIT: u32 = 0x0080_0000;
|
||||
|
||||
fn to_bytes(self) -> u32 { unsafe { ::core::mem::transmute(self) } }
|
||||
fn get_exponent(self) -> i32 {
|
||||
((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
|
||||
.wrapping_sub(Self::MAX_EXP)
|
||||
}
|
||||
}
|
||||
|
||||
impl FloatStuff for f64 {
|
||||
type ToBytes = u64;
|
||||
const MANTISSA_BITS: u32 = 52;
|
||||
const MAX_EXP: i32 = 1023;
|
||||
const EXP_MASK: u64 = 0x7FF0_0000_0000_0000;
|
||||
const MANTISSA_MASK: u64 = 0x000F_FFFF_FFFF_FFFF;
|
||||
const MANTISSA_LEAD_BIT: u64 = 0x0010_0000_0000_0000;
|
||||
|
||||
fn to_bytes(self) -> u64 { unsafe { ::core::mem::transmute(self) } }
|
||||
fn get_exponent(self) -> i32 {
|
||||
((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
|
||||
.wrapping_sub(Self::MAX_EXP)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! float_as_unsigned {
|
||||
($from: expr, $fromty: ty, $outty: ty) => { {
|
||||
use core::num::Float;
|
||||
let repr = $from.to_bytes();
|
||||
let sign = $from.signum();
|
||||
let exponent = $from.get_exponent();
|
||||
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
|
||||
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
|
||||
if sign == -1.0 || exponent < 0 { return 0 as u128_; }
|
||||
if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
|
||||
return !(0 as u128_);
|
||||
}
|
||||
(if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
|
||||
(mantissa as $outty)
|
||||
.wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
|
||||
.wrapping_sub(exponent) as u32)
|
||||
} else {
|
||||
(mantissa as $outty)
|
||||
.wrapping_shl(exponent.wrapping_sub(
|
||||
<$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
|
||||
})
|
||||
} }
|
||||
}
|
||||
|
||||
macro_rules! float_as_signed {
|
||||
($from: expr, $fromty: ty, $outty: ty) => {{
|
||||
use core::num::Float;
|
||||
let repr = $from.to_bytes();
|
||||
let sign = $from.signum();
|
||||
let exponent = $from.get_exponent();
|
||||
let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
|
||||
let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
|
||||
|
||||
if exponent < 0 { return 0 as i128_; }
|
||||
if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
|
||||
let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() };
|
||||
return ret
|
||||
}
|
||||
let r = if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
|
||||
(mantissa as $outty)
|
||||
.wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
|
||||
.wrapping_sub(exponent) as u32)
|
||||
} else {
|
||||
(mantissa as $outty)
|
||||
.wrapping_shl(exponent.wrapping_sub(
|
||||
<$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
|
||||
};
|
||||
(if sign >= 0.0 { r } else { r.unchecked_neg() })
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
fn i128_as_f64(a: i128_) -> f64 {
|
||||
match a.signum() {
|
||||
1 => u128_as_f64(a.uabs()),
|
||||
0 => 0.0,
|
||||
_ => -u128_as_f64(a.uabs()),
|
||||
}
|
||||
}
|
||||
|
||||
fn i128_as_f32(a: i128_) -> f32 {
|
||||
match a.signum() {
|
||||
1 => u128_as_f32(a.uabs()),
|
||||
0 => 0.0,
|
||||
_ => -u128_as_f32(a.uabs()),
|
||||
}
|
||||
}
|
||||
|
||||
fn u128_as_f64(mut a: u128_) -> f64 {
|
||||
use ::core::f64::MANTISSA_DIGITS;
|
||||
if a == 0 { return 0.0; }
|
||||
let sd = 128u32.wrapping_sub(a.leading_zeros());
|
||||
let mut e = sd.wrapping_sub(1);
|
||||
const MD1 : u32 = MANTISSA_DIGITS + 1;
|
||||
const MD2 : u32 = MANTISSA_DIGITS + 2;
|
||||
|
||||
// SNAP: replace this with !0u128
|
||||
let negn :u128_ = !0;
|
||||
|
||||
if sd > MANTISSA_DIGITS {
|
||||
a = match sd {
|
||||
MD1 => a.wrapping_shl(1),
|
||||
MD2 => a,
|
||||
_ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
|
||||
(if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
|
||||
.wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 })
|
||||
};
|
||||
a |= if (a & 4) == 0 { 0 } else { 1 };
|
||||
a = a.wrapping_add(1);
|
||||
a = a.wrapping_shr(2);
|
||||
if a & (1 << MANTISSA_DIGITS) != 0 {
|
||||
a = a.wrapping_shr(1);
|
||||
e = e.wrapping_add(1);
|
||||
}
|
||||
} else {
|
||||
a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
|
||||
}
|
||||
unsafe {
|
||||
::core::mem::transmute((e as u64).wrapping_add(1023).wrapping_shl(52)
|
||||
| (a as u64 & 0x000f_ffff_ffff_ffff))
|
||||
}
|
||||
}
|
||||
|
||||
fn u128_as_f32(mut a: u128_) -> f32 {
|
||||
use ::core::f32::MANTISSA_DIGITS;
|
||||
if a == 0 { return 0.0; }
|
||||
let sd = 128u32.wrapping_sub(a.leading_zeros());
|
||||
let mut e = sd.wrapping_sub(1);
|
||||
const MD1 : u32 = MANTISSA_DIGITS + 1;
|
||||
const MD2 : u32 = MANTISSA_DIGITS + 2;
|
||||
|
||||
// SNAP: replace this with !0u128
|
||||
let negn :u128_ = !0;
|
||||
|
||||
if sd > MANTISSA_DIGITS {
|
||||
a = match sd {
|
||||
MD1 => a.wrapping_shl(1),
|
||||
MD2 => a,
|
||||
_ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
|
||||
(if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
|
||||
.wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 })
|
||||
};
|
||||
a |= if (a & 4) == 0 { 0 } else { 1 };
|
||||
a = a.wrapping_add(1);
|
||||
a = a.wrapping_shr(2);
|
||||
if a & (1 << MANTISSA_DIGITS) != 0 {
|
||||
a = a.wrapping_shr(1);
|
||||
e = e.wrapping_add(1);
|
||||
}
|
||||
} else {
|
||||
a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
|
||||
}
|
||||
unsafe {
|
||||
::core::mem::transmute((e as u32).wrapping_add(127).wrapping_shl(23)
|
||||
| (a as u32 & 0x007f_ffff))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
macro_rules! why_are_abi_strings_checked_by_parser { ($cret:ty, $conv:expr, $unadj:tt) => {
|
||||
mod imp {
|
||||
use super::{i128_, u128_, LargeInt, FloatStuff, NegExt, AbsExt};
|
||||
use super::{i128_as_f64, i128_as_f32, u128_as_f64, u128_as_f32,
|
||||
i128_div, i128_mod, u128_div_mod, unchecked_div, ptr};
|
||||
// For x64
|
||||
// rdx:rcx, r9:r8, stack -> rdx:rax
|
||||
// aka.
|
||||
// define i128 @__muloti4(i128, i128, i32*)
|
||||
#[export_name="__muloti4"]
|
||||
pub unsafe extern $unadj fn i128_mul_oflow(a: i128_, b: i128_, o: *mut i32) -> i128_ {
|
||||
mulo!(a, b, o, i128_)
|
||||
}
|
||||
|
||||
// For x64
|
||||
// rdx:rax -> xmm0
|
||||
// aka.
|
||||
// define double @__muloti4(i128)
|
||||
#[export_name="__floattidf"]
|
||||
pub extern $unadj fn i128_as_f64_(a: i128_) -> f64 {
|
||||
i128_as_f64(a)
|
||||
}
|
||||
#[export_name="__floattisf"]
|
||||
pub extern $unadj fn i128_as_f32_(a: i128_) -> f32 {
|
||||
i128_as_f32(a)
|
||||
}
|
||||
#[export_name="__floatuntidf"]
|
||||
pub extern $unadj fn u128_as_f64_(a: u128_) -> f64 {
|
||||
u128_as_f64(a)
|
||||
}
|
||||
#[export_name="__floatuntisf"]
|
||||
pub extern $unadj fn u128_as_f32_(a: u128_) -> f32 {
|
||||
u128_as_f32(a)
|
||||
}
|
||||
|
||||
// For x64
|
||||
// xmm0 -> rdx:rax
|
||||
// aka.
|
||||
// define i128 @stuff(double)
|
||||
#[export_name="__fixunsdfti"]
|
||||
pub extern $unadj fn f64_as_u128(a: f64) -> u128_ {
|
||||
float_as_unsigned!(a, f64, u128_)
|
||||
}
|
||||
|
||||
#[export_name="__fixunssfti"]
|
||||
pub extern "unadjusted" fn f32_as_u128(a: f32) -> u128_ {
|
||||
float_as_unsigned!(a, f32, u128_)
|
||||
}
|
||||
|
||||
#[export_name="__fixdfti"]
|
||||
pub extern "unadjusted" fn f64_as_i128(a: f64) -> i128_ {
|
||||
float_as_signed!(a, f64, i128_)
|
||||
}
|
||||
|
||||
#[export_name="__fixsfti"]
|
||||
pub extern "unadjusted" fn f32_as_i128(a: f32) -> i128_ {
|
||||
float_as_signed!(a, f32, i128_)
|
||||
}
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct u64x2(u64, u64);
|
||||
|
||||
// For x64
|
||||
// pointers -> xmm0
|
||||
// aka.
|
||||
// define <2 x u64> @stuff(i128*, i128*, i128*)
|
||||
//
|
||||
// That almost matches the C ABI, so we simply use the C ABI
|
||||
#[export_name="__udivmodti4"]
|
||||
pub extern "C" fn u128_div_mod_(n: u128_, d: u128_, rem: *mut u128_) -> $cret {
|
||||
let x = u128_div_mod(n, d, rem);
|
||||
($conv)(x)
|
||||
}
|
||||
|
||||
#[export_name="__udivti3"]
|
||||
pub extern "C" fn u128_div_(a: u128_, b: u128_) -> $cret {
|
||||
let x = u128_div_mod(a, b, ptr::null_mut());
|
||||
($conv)(x)
|
||||
}
|
||||
|
||||
#[export_name="__umodti3"]
|
||||
pub extern "C" fn u128_mod_(a: u128_, b: u128_) -> $cret {
|
||||
unsafe {
|
||||
let mut r = ::core::mem::zeroed();
|
||||
u128_div_mod(a, b, &mut r);
|
||||
($conv)(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[export_name="__divti3"]
|
||||
pub extern "C" fn i128_div_(a: i128_, b: i128_) -> $cret {
|
||||
let x = i128_div(a, b);
|
||||
($conv)(x as u128_)
|
||||
}
|
||||
|
||||
#[export_name="__modti3"]
|
||||
pub extern "C" fn i128_mod_(a: i128_, b: i128_) -> $cret {
|
||||
let x = i128_mod(a, b);
|
||||
($conv)(x as u128_)
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
// LLVM expectations for ABI on windows x64 are pure madness.
|
||||
#[cfg(not(stage0))]
|
||||
#[cfg(all(windows, target_pointer_width="64"))]
|
||||
why_are_abi_strings_checked_by_parser!(u64x2,
|
||||
|i: u128_| u64x2(i.low(), i.high()),
|
||||
"unadjusted");
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[cfg(not(all(windows, target_pointer_width="64")))]
|
||||
why_are_abi_strings_checked_by_parser!(u128_, |i|{ i }, "C");
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub use self::imp::*;
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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 ! {
|
||||
|
@ -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 }
|
||||
|
@ -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; 39] = 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")]
|
||||
|
@ -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 {
|
||||
|
@ -242,6 +242,8 @@ step_impl_signed!(i64);
|
||||
// assume here that it is less than 64-bits.
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
step_impl_no_between!(u64 i64);
|
||||
#[cfg(not(stage0))]
|
||||
step_impl_no_between!(u128 i128);
|
||||
|
||||
/// An adapter for stepping range iterators by a custom amount.
|
||||
///
|
||||
|
@ -90,6 +90,7 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(never_type)]
|
||||
#![cfg_attr(not(stage0), feature(i128_type))]
|
||||
#![feature(prelude_import)]
|
||||
|
||||
#[prelude_import]
|
||||
@ -120,12 +121,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;
|
||||
|
||||
|
@ -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
17
src/libcore/num/i128.rs
Normal 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 }
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
int_module! { i16, 16 }
|
||||
int_module! { i16 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
int_module! { i32, 32 }
|
||||
int_module! { i32 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
int_module! { i64, 64 }
|
||||
int_module! { i64 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
int_module! { i8, 8 }
|
||||
int_module! { i8 }
|
||||
|
@ -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")]
|
||||
|
@ -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 }
|
||||
|
@ -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,51 @@ 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(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, u8, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(i64, i8, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, u16, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(i64, i16, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, u32, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(i64, i32, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, u64, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(i64, i64, i8, i16, i32, i64, isize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_from_int_impl!(u64, usize, u8, u16, u32, u64, usize);
|
||||
#[cfg(stage0)]
|
||||
same_sign_try_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 +2692,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 +2743,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 +2878,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
16
src/libcore/num/u128.rs
Normal 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 }
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
uint_module! { u16, 16 }
|
||||
uint_module! { u16 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
uint_module! { u32, 32 }
|
||||
uint_module! { u32 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
uint_module! { u64, 64 }
|
||||
uint_module! { u64 }
|
||||
|
@ -14,4 +14,4 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
uint_module! { u8, 8 }
|
||||
uint_module! { u8 }
|
||||
|
@ -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")]
|
||||
|
@ -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 }
|
||||
|
@ -298,6 +298,8 @@ macro_rules! wrapping_impl {
|
||||
}
|
||||
|
||||
wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
#[cfg(not(stage0))]
|
||||
wrapping_impl! { u128 i128 }
|
||||
|
||||
mod shift_max {
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
@ -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.
|
||||
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@ use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use syntax::ast::{FloatTy, IntTy, UintTy};
|
||||
use syntax::attr;
|
||||
use syntax_pos::DUMMY_SP;
|
||||
use rustc_i128::u128;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
@ -35,6 +37,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 +58,7 @@ 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(),
|
||||
i128_align: Align::from_bits(32, 64).unwrap(),
|
||||
f32_align: Align::from_bits(32, 32).unwrap(),
|
||||
f64_align: Align::from_bits(64, 64).unwrap(),
|
||||
pointer_size: Size::from_bits(64),
|
||||
@ -99,6 +103,7 @@ impl TargetDataLayout {
|
||||
};
|
||||
|
||||
let mut dl = TargetDataLayout::default();
|
||||
let mut i128_align_src = 64;
|
||||
for spec in sess.target.target.data_layout.split("-") {
|
||||
match &spec.split(":").collect::<Vec<_>>()[..] {
|
||||
&["e"] => dl.endian = Endian::Little,
|
||||
@ -111,19 +116,28 @@ impl TargetDataLayout {
|
||||
dl.pointer_align = align(a, p);
|
||||
}
|
||||
&[s, ref a..] if s.starts_with("i") => {
|
||||
let ty_align = match s[1..].parse::<u64>() {
|
||||
Ok(1) => &mut dl.i8_align,
|
||||
Ok(8) => &mut dl.i8_align,
|
||||
Ok(16) => &mut dl.i16_align,
|
||||
Ok(32) => &mut dl.i32_align,
|
||||
Ok(64) => &mut dl.i64_align,
|
||||
Ok(_) => continue,
|
||||
let bits = match s[1..].parse::<u64>() {
|
||||
Ok(bits) => bits,
|
||||
Err(_) => {
|
||||
size(&s[1..], "i"); // For the user error.
|
||||
continue;
|
||||
}
|
||||
};
|
||||
*ty_align = align(a, s);
|
||||
let a = align(a, s);
|
||||
match bits {
|
||||
1 => dl.i1_align = a,
|
||||
8 => dl.i8_align = a,
|
||||
16 => dl.i16_align = a,
|
||||
32 => dl.i32_align = a,
|
||||
64 => dl.i64_align = a,
|
||||
_ => {}
|
||||
}
|
||||
if bits >= i128_align_src && bits <= 128 {
|
||||
// Default alignment for i128 is decided by taking the alignment of
|
||||
// largest-sized i{64...128}.
|
||||
i128_align_src = bits;
|
||||
dl.i128_align = a;
|
||||
}
|
||||
}
|
||||
&[s, ref a..] if s.starts_with("v") => {
|
||||
let v_size = size(&s[1..], "v");
|
||||
@ -325,7 +339,8 @@ pub enum Integer {
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64
|
||||
I64,
|
||||
I128,
|
||||
}
|
||||
|
||||
impl Integer {
|
||||
@ -336,6 +351,7 @@ impl Integer {
|
||||
I16 => Size::from_bytes(2),
|
||||
I32 => Size::from_bytes(4),
|
||||
I64 => Size::from_bytes(8),
|
||||
I128 => Size::from_bytes(16),
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,6 +362,7 @@ impl Integer {
|
||||
I16 => dl.i16_align,
|
||||
I32 => dl.i32_align,
|
||||
I64 => dl.i64_align,
|
||||
I128 => dl.i128_align,
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,33 +374,37 @@ impl Integer {
|
||||
(I16, false) => tcx.types.u16,
|
||||
(I32, false) => tcx.types.u32,
|
||||
(I64, false) => tcx.types.u64,
|
||||
(I128, false) => tcx.types.u128,
|
||||
(I1, true) => tcx.types.i8,
|
||||
(I8, true) => tcx.types.i8,
|
||||
(I16, true) => tcx.types.i16,
|
||||
(I32, true) => tcx.types.i32,
|
||||
(I64, true) => tcx.types.i64,
|
||||
(I128, true) => tcx.types.i128,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 +427,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 +508,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 +520,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 +1199,30 @@ 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) = (i64::max_value(),
|
||||
i64::min_value(),
|
||||
true);
|
||||
for v in &def.variants {
|
||||
let x = v.disr_val.to_u64_unchecked() as i64;
|
||||
let x = match v.disr_val.erase_type() {
|
||||
ConstInt::InferSigned(i) => i as i64,
|
||||
ConstInt::Infer(i) => i as u64 as i64,
|
||||
_ => bug!()
|
||||
};
|
||||
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 handle i128? signed-value based impl is weird and hard to
|
||||
// grok.
|
||||
let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..],
|
||||
min,
|
||||
max);
|
||||
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 +1267,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));
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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" }
|
||||
|
@ -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) => {
|
||||
|
@ -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;
|
||||
|
@ -12,3 +12,4 @@ crate-type = ["dylib"]
|
||||
log = { path = "../liblog" }
|
||||
serialize = { path = "../libserialize" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
rustc_i128 = { path = "../librustc_i128" }
|
||||
|
@ -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",
|
||||
}
|
||||
}
|
||||
|
@ -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,45 +23,98 @@ 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),
|
||||
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};
|
||||
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
|
||||
// do not add constants for isize/usize, because these are guaranteed to be wrong for
|
||||
// arbitrary host/target combinations
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// do not add constants for isize/usize, because these are guaranteed to be wrong for
|
||||
// arbitrary host/target combinations
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstInt {
|
||||
/// Creates a new unsigned ConstInt with matching type while also checking that overflow does
|
||||
/// not happen.
|
||||
pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option<ConstInt> {
|
||||
match ty {
|
||||
UintTy::U8 if val <= ubounds::U8MAX => Some(U8(val as u8)),
|
||||
UintTy::U16 if val <= ubounds::U16MAX => Some(U16(val as u16)),
|
||||
UintTy::U32 if val <= ubounds::U32MAX => Some(U32(val as u32)),
|
||||
UintTy::U64 if val <= ubounds::U64MAX => Some(U64(val as u64)),
|
||||
UintTy::Us if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok()
|
||||
.map(Usize),
|
||||
UintTy::U128 => Some(U128(val)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new unsigned ConstInt with matching type while also checking that overflow does
|
||||
/// not happen.
|
||||
pub fn new_signed(val: i128, ty: IntTy, isize_ty: IntTy) -> Option<ConstInt> {
|
||||
match ty {
|
||||
IntTy::I8 if val <= ibounds::I8MAX => Some(I8(val as i8)),
|
||||
IntTy::I16 if val <= ibounds::I16MAX => Some(I16(val as i16)),
|
||||
IntTy::I32 if val <= ibounds::I32MAX => Some(I32(val as i32)),
|
||||
IntTy::I64 if val <= ibounds::I64MAX => Some(I64(val as i64)),
|
||||
IntTy::Is if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok()
|
||||
.map(Isize),
|
||||
IntTy::I128 => Some(I128(val)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// If either value is `Infer` or `InferSigned`, try to turn the value into the type of
|
||||
/// the other value. If both values have no type, don't do anything
|
||||
pub fn infer(self, other: Self) -> Result<(Self, Self), ConstMathErr> {
|
||||
@ -68,46 +122,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 +181,31 @@ 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),
|
||||
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),
|
||||
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),
|
||||
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 +218,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 +288,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 +304,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 +312,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 +332,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 +340,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 +354,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 +388,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 +396,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 +424,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 +432,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 +455,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 +463,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 +483,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 +499,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 +509,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 +519,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 +539,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 +549,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 +571,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 +581,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 +601,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 +609,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 +628,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 +636,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 +654,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 +676,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 +684,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))),
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
@ -11,3 +11,4 @@ crate-type = ["dylib"]
|
||||
[dependencies]
|
||||
log = { path = "../liblog" }
|
||||
serialize = { path = "../libserialize" }
|
||||
rustc_i128 = { path = "../librustc_i128" }
|
||||
|
@ -44,6 +44,8 @@ extern crate serialize as rustc_serialize; // used by deriving
|
||||
#[cfg(unix)]
|
||||
extern crate libc;
|
||||
|
||||
extern crate rustc_i128;
|
||||
|
||||
pub use rustc_serialize::hex::ToHex;
|
||||
|
||||
pub mod array_vec;
|
||||
|
@ -13,13 +13,14 @@ use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use blake2b::Blake2bHasher;
|
||||
use rustc_serialize::leb128;
|
||||
use rustc_i128::{u128,i128};
|
||||
|
||||
fn write_unsigned_leb128_to_buf(buf: &mut [u8; 16], value: u64) -> usize {
|
||||
leb128::write_unsigned_leb128_to(value, |i, v| buf[i] = v)
|
||||
leb128::write_unsigned_leb128_to(value as u128, |i, v| buf[i] = v)
|
||||
}
|
||||
|
||||
fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize {
|
||||
leb128::write_signed_leb128_to(value, |i, v| buf[i] = v)
|
||||
leb128::write_signed_leb128_to(value as i128, |i, v| buf[i] = v)
|
||||
}
|
||||
|
||||
/// When hashing something that ends up affecting properties like symbol names. We
|
||||
|
8
src/librustc_i128/Cargo.toml
Normal file
8
src/librustc_i128/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
name = "rustc_i128"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
name = "rustc_i128"
|
||||
path = "lib.rs"
|
29
src/librustc_i128/lib.rs
Normal file
29
src/librustc_i128/lib.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
#![allow(non_camel_case_types)]
|
||||
#![cfg_attr(not(stage0), feature(i128_type))]
|
||||
#![no_std]
|
||||
#![crate_type="rlib"]
|
||||
#![crate_name="rustc_i128"]
|
||||
|
||||
#[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;
|
||||
}
|
@ -16,3 +16,4 @@ serialize = { path = "../libserialize" }
|
||||
log = { path = "../liblog" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
rustc_i128 = { path = "../librustc_i128" }
|
||||
|
@ -33,6 +33,8 @@ extern crate serialize as rustc_serialize;
|
||||
#[macro_use] extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
|
||||
extern crate rustc_i128;
|
||||
|
||||
const ATTR_DIRTY: &'static str = "rustc_dirty";
|
||||
const ATTR_CLEAN: &'static str = "rustc_clean";
|
||||
const ATTR_DIRTY_METADATA: &'static str = "rustc_metadata_dirty";
|
||||
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ pub enum LLVMRustResult {
|
||||
// Consts for the LLVM CallConv type, pre-cast to usize.
|
||||
|
||||
/// LLVM CallingConv::ID. Should we wrap this?
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
#[repr(C)]
|
||||
pub enum CallConv {
|
||||
CCallConv = 0,
|
||||
@ -578,9 +578,12 @@ 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;
|
||||
pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
|
||||
high: *mut u64, low: *mut u64) -> bool;
|
||||
|
||||
|
||||
// Operations on composite constants
|
||||
|
@ -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" }
|
||||
|
@ -43,6 +43,7 @@ use syntax::attr;
|
||||
use syntax::ast::{self, NodeId};
|
||||
use syntax::codemap;
|
||||
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
|
||||
use rustc_i128::{u128, i128};
|
||||
|
||||
pub struct DecodeContext<'a, 'tcx: 'a> {
|
||||
opaque: opaque::Decoder<'a>,
|
||||
@ -211,12 +212,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;
|
||||
|
@ -43,6 +43,8 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
|
||||
use rustc::hir::intravisit;
|
||||
|
||||
use rustc_i128::{u128, i128};
|
||||
|
||||
use super::index_builder::{FromId, IndexBuilder, Untracked};
|
||||
|
||||
pub struct EncodeContext<'a, 'tcx: 'a> {
|
||||
@ -75,12 +77,14 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
|
||||
|
||||
encoder_methods! {
|
||||
emit_usize(usize);
|
||||
emit_u128(u128);
|
||||
emit_u64(u64);
|
||||
emit_u32(u32);
|
||||
emit_u16(u16);
|
||||
emit_u8(u8);
|
||||
|
||||
emit_isize(isize);
|
||||
emit_i128(i128);
|
||||
emit_i64(i64);
|
||||
emit_i32(i32);
|
||||
emit_i16(i16);
|
||||
@ -259,7 +263,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
let data = VariantData {
|
||||
ctor_kind: variant.ctor_kind,
|
||||
disr: variant.disr_val.to_u64_unchecked(),
|
||||
disr: variant.disr_val.to_u128_unchecked(),
|
||||
struct_ctor: None,
|
||||
};
|
||||
|
||||
@ -386,7 +390,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
let data = VariantData {
|
||||
ctor_kind: variant.ctor_kind,
|
||||
disr: variant.disr_val.to_u64_unchecked(),
|
||||
disr: variant.disr_val.to_u128_unchecked(),
|
||||
struct_ctor: Some(def_id.index),
|
||||
};
|
||||
|
||||
@ -648,7 +652,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
};
|
||||
EntryKind::Struct(self.lazy(&VariantData {
|
||||
ctor_kind: variant.ctor_kind,
|
||||
disr: variant.disr_val.to_u64_unchecked(),
|
||||
disr: variant.disr_val.to_u128_unchecked(),
|
||||
struct_ctor: struct_ctor,
|
||||
}))
|
||||
}
|
||||
@ -657,7 +661,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
EntryKind::Union(self.lazy(&VariantData {
|
||||
ctor_kind: variant.ctor_kind,
|
||||
disr: variant.disr_val.to_u64_unchecked(),
|
||||
disr: variant.disr_val.to_u128_unchecked(),
|
||||
struct_ctor: None,
|
||||
}))
|
||||
}
|
||||
|
@ -45,9 +45,12 @@ 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;
|
||||
|
||||
mod astencode;
|
||||
mod index_builder;
|
||||
mod index;
|
||||
|
@ -27,6 +27,8 @@ use syntax_pos::{self, Span};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use rustc_i128::u128;
|
||||
|
||||
pub fn rustc_version() -> String {
|
||||
format!("rustc {}",
|
||||
option_env!("CFG_VERSION").unwrap_or("unknown version"))
|
||||
@ -264,7 +266,7 @@ pub struct FnData {
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct VariantData {
|
||||
pub ctor_kind: CtorKind,
|
||||
pub disr: u64,
|
||||
pub disr: u128,
|
||||
|
||||
/// If this is a struct's only variant, this
|
||||
/// is the index of the "struct ctor" item.
|
||||
|
@ -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" }
|
||||
|
@ -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,11 @@ 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()),
|
||||
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 {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -61,6 +61,7 @@ use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
|
||||
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
|
||||
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
use syntax::feature_gate::{emit_feature_err, GateIssue};
|
||||
|
||||
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
||||
use errors::DiagnosticBuilder;
|
||||
@ -1005,13 +1006,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
|
||||
}
|
||||
|
||||
@ -2308,8 +2310,20 @@ impl<'a> Resolver<'a> {
|
||||
PathResult::Module(..) | PathResult::Failed(..)
|
||||
if (ns == TypeNS || path.len() > 1) &&
|
||||
self.primitive_type_table.primitive_types.contains_key(&path[0].name) => {
|
||||
let prim = self.primitive_type_table.primitive_types[&path[0].name];
|
||||
match prim {
|
||||
TyUint(UintTy::U128) | TyInt(IntTy::I128) => {
|
||||
if !self.session.features.borrow().i128_type {
|
||||
emit_feature_err(&self.session.parse_sess,
|
||||
"i128_type", span, GateIssue::Language,
|
||||
"128-bit type is unstable");
|
||||
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
PathResolution {
|
||||
base_def: Def::PrimTy(self.primitive_type_table.primitive_types[&path[0].name]),
|
||||
base_def: Def::PrimTy(prim),
|
||||
depth: path.len() - 1,
|
||||
}
|
||||
}
|
||||
|
@ -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" }
|
||||
|
@ -313,7 +313,7 @@ impl ArgType {
|
||||
///
|
||||
/// I will do my best to describe this structure, but these
|
||||
/// comments are reverse-engineered and may be inaccurate. -NDM
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FnType {
|
||||
/// The LLVM types of each argument.
|
||||
pub args: Vec<ArgType>,
|
||||
@ -352,6 +352,7 @@ impl FnType {
|
||||
Fastcall => llvm::X86FastcallCallConv,
|
||||
Vectorcall => llvm::X86_VectorCall,
|
||||
C => llvm::CCallConv,
|
||||
Unadjusted => llvm::CCallConv,
|
||||
Win64 => llvm::X86_64_Win64,
|
||||
SysV64 => llvm::X86_64_SysV,
|
||||
Aapcs => llvm::ArmAapcsCallConv,
|
||||
@ -528,6 +529,8 @@ impl FnType {
|
||||
ccx: &CrateContext<'a, 'tcx>,
|
||||
abi: Abi,
|
||||
sig: &ty::FnSig<'tcx>) {
|
||||
if abi == Abi::Unadjusted { return }
|
||||
|
||||
if abi == Abi::Rust || abi == Abi::RustCall ||
|
||||
abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
|
||||
let fixup = |arg: &mut ArgType| {
|
||||
|
@ -18,16 +18,20 @@ use type_::Type;
|
||||
|
||||
pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
|
||||
let fixup = |a: &mut ArgType| {
|
||||
if a.ty.kind() == Struct {
|
||||
match llsize_of_alloc(ccx, a.ty) {
|
||||
1 => a.cast = Some(Type::i8(ccx)),
|
||||
2 => a.cast = Some(Type::i16(ccx)),
|
||||
4 => a.cast = Some(Type::i32(ccx)),
|
||||
8 => a.cast = Some(Type::i64(ccx)),
|
||||
_ => a.make_indirect(ccx)
|
||||
}
|
||||
} else {
|
||||
a.extend_integer_width_to(32);
|
||||
match a.ty.kind() {
|
||||
Struct => match llsize_of_alloc(ccx, a.ty) {
|
||||
1 => a.cast = Some(Type::i8(ccx)),
|
||||
2 => a.cast = Some(Type::i16(ccx)),
|
||||
4 => a.cast = Some(Type::i32(ccx)),
|
||||
8 => a.cast = Some(Type::i64(ccx)),
|
||||
_ => a.make_indirect(ccx)
|
||||
},
|
||||
Integer => match llsize_of_alloc(ccx, a.ty) {
|
||||
1 ... 8 => a.extend_integer_width_to(32),
|
||||
16 => a.make_indirect(ccx),
|
||||
_ => bug!(),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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,17 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_big_integral(t: Type, u: u128, sign_extend: bool) -> ValueRef {
|
||||
if ::std::mem::size_of::<u128>() == 16 {
|
||||
unsafe {
|
||||
llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, &u as *const u128 as *const u64)
|
||||
}
|
||||
} else {
|
||||
// SNAP: remove after snapshot
|
||||
C_integral(t, u as u64, sign_extend)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_floating_f64(f: f64, t: Type) -> ValueRef {
|
||||
unsafe {
|
||||
llvm::LLVMConstReal(t.to_ref(), f)
|
||||
@ -580,20 +593,29 @@ fn is_const_integral(v: ValueRef) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_to_opt_int(v: ValueRef) -> Option<i64> {
|
||||
unsafe {
|
||||
if is_const_integral(v) {
|
||||
Some(llvm::LLVMConstIntGetSExtValue(v))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
fn hi_lo_to_u128(lo: u64, _: u64) -> u128 {
|
||||
lo as u128
|
||||
}
|
||||
|
||||
pub fn const_to_opt_uint(v: ValueRef) -> Option<u64> {
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
|
||||
((hi as u128) << 64) | (lo as u128)
|
||||
}
|
||||
|
||||
pub fn const_to_opt_u128(v: ValueRef, sign_ext: bool) -> Option<u128> {
|
||||
unsafe {
|
||||
if is_const_integral(v) {
|
||||
Some(llvm::LLVMConstIntGetZExtValue(v))
|
||||
let (mut lo, mut hi) = (0u64, 0u64);
|
||||
let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
|
||||
&mut hi as *mut u64, &mut lo as *mut u64);
|
||||
if success {
|
||||
Some(hi_lo_to_u128(lo, hi))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,11 +346,12 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
|
||||
|
||||
// Choose max of two known alignments (combined value must
|
||||
// be aligned according to more restrictive of the two).
|
||||
let align = match (const_to_opt_uint(sized_align), const_to_opt_uint(unsized_align)) {
|
||||
let align = match (const_to_opt_u128(sized_align, false),
|
||||
const_to_opt_u128(unsized_align, false)) {
|
||||
(Some(sized_align), Some(unsized_align)) => {
|
||||
// If both alignments are constant, (the sized_align should always be), then
|
||||
// pick the correct alignment statically.
|
||||
C_uint(ccx, std::cmp::max(sized_align, unsized_align))
|
||||
C_uint(ccx, std::cmp::max(sized_align, unsized_align) as u64)
|
||||
}
|
||||
_ => bcx.select(bcx.icmp(llvm::IntUGT, sized_align, unsized_align),
|
||||
sized_align,
|
||||
|
@ -32,6 +32,8 @@ use syntax::symbol::Symbol;
|
||||
use rustc::session::Session;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use rustc_i128::u128;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::iter;
|
||||
|
||||
@ -1019,7 +1021,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
|
||||
in_elem, in_ty,
|
||||
ret_ty, ret_ty.simd_type(tcx));
|
||||
|
||||
let total_len = in_len as u64 * 2;
|
||||
let total_len = in_len as u128 * 2;
|
||||
|
||||
let vector = llargs[2];
|
||||
|
||||
@ -1027,7 +1029,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
|
||||
.map(|i| {
|
||||
let arg_idx = i;
|
||||
let val = const_get_elt(vector, &[i as libc::c_uint]);
|
||||
match const_to_opt_uint(val) {
|
||||
match const_to_opt_u128(val, true) {
|
||||
None => {
|
||||
emit_error!("shuffle index #{} is not a constant", arg_idx);
|
||||
None
|
||||
@ -1167,6 +1169,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: there’s 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 +1188,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 +1203,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,
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -269,7 +269,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
|
||||
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
|
||||
let cond = self.trans_operand(&bcx, cond).immediate();
|
||||
let mut const_cond = common::const_to_opt_uint(cond).map(|c| c == 1);
|
||||
let mut const_cond = common::const_to_opt_u128(cond, false).map(|c| c == 1);
|
||||
|
||||
// This case can currently arise only from functions marked
|
||||
// with #[rustc_inherit_overflow_checks] and inlined from
|
||||
@ -322,14 +322,12 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
let len = self.trans_operand(&mut bcx, len).immediate();
|
||||
let index = self.trans_operand(&mut bcx, index).immediate();
|
||||
|
||||
let const_err = common::const_to_opt_uint(len).and_then(|len| {
|
||||
common::const_to_opt_uint(index).map(|index| {
|
||||
ErrKind::IndexOutOfBounds {
|
||||
len: len,
|
||||
index: index
|
||||
}
|
||||
})
|
||||
});
|
||||
let const_err = common::const_to_opt_u128(len, false)
|
||||
.and_then(|len| common::const_to_opt_u128(index, false)
|
||||
.map(|index| ErrKind::IndexOutOfBounds {
|
||||
len: len as u64,
|
||||
index: index as u64
|
||||
}));
|
||||
|
||||
let file_line = C_struct(bcx.ccx, &[filename, line], false);
|
||||
let align = llalign_of_min(bcx.ccx, common::val_ty(file_line));
|
||||
|
@ -13,7 +13,7 @@ use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_eval::{ErrKind, ConstEvalErr, report_const_eval_err};
|
||||
use rustc_const_math::ConstInt::*;
|
||||
use rustc_const_math::ConstFloat::*;
|
||||
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstMathErr};
|
||||
use rustc_const_math::{ConstInt, ConstMathErr};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::TransNormalize;
|
||||
use rustc::mir;
|
||||
@ -25,16 +25,15 @@ 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 common::{const_to_opt_u128};
|
||||
use consts;
|
||||
use monomorphize::{self, Instance};
|
||||
use type_of;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use std::fmt;
|
||||
@ -43,6 +42,8 @@ use std::ptr;
|
||||
use super::operand::{OperandRef, OperandValue};
|
||||
use super::MirContext;
|
||||
|
||||
use rustc_i128::{u128, i128};
|
||||
|
||||
/// A sized constant rvalue.
|
||||
/// The LLVM type might not be the same for a single Rust type,
|
||||
/// e.g. each enum variant would have its own LLVM struct type.
|
||||
@ -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, true),
|
||||
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, false),
|
||||
ConstVal::Integral(Usize(v)) => {
|
||||
let u = v.as_u64(ccx.tcx().sess.target.uint_type);
|
||||
C_integral(Type::int(ccx), u, false)
|
||||
@ -428,7 +431,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
mir::ProjectionElem::Index(ref index) => {
|
||||
let llindex = self.const_operand(index, span)?.llval;
|
||||
|
||||
let iv = if let Some(iv) = common::const_to_opt_uint(llindex) {
|
||||
let iv = if let Some(iv) = common::const_to_opt_u128(llindex, false) {
|
||||
iv
|
||||
} else {
|
||||
span_bug!(span, "index is not an integer-constant expression")
|
||||
@ -436,7 +439,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
|
||||
// Produce an undef instead of a LLVM assertion on OOB.
|
||||
let len = common::const_to_uint(tr_base.len(self.ccx));
|
||||
let llelem = if iv < len {
|
||||
let llelem = if iv < len as u128 {
|
||||
const_get_elt(base.llval, &[iv as u32])
|
||||
} else {
|
||||
C_undef(type_of::type_of(self.ccx, projected_ty))
|
||||
@ -794,49 +797,14 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
|
||||
fn to_const_int(value: ValueRef, t: Ty, tcx: TyCtxt) -> Option<ConstInt> {
|
||||
match t.sty {
|
||||
ty::TyInt(int_type) => const_to_opt_int(value).and_then(|input| match int_type {
|
||||
ast::IntTy::I8 => {
|
||||
assert_eq!(input as i8 as i64, input);
|
||||
Some(ConstInt::I8(input as i8))
|
||||
},
|
||||
ast::IntTy::I16 => {
|
||||
assert_eq!(input as i16 as i64, input);
|
||||
Some(ConstInt::I16(input as i16))
|
||||
},
|
||||
ast::IntTy::I32 => {
|
||||
assert_eq!(input as i32 as i64, input);
|
||||
Some(ConstInt::I32(input as i32))
|
||||
},
|
||||
ast::IntTy::I64 => {
|
||||
Some(ConstInt::I64(input))
|
||||
},
|
||||
ast::IntTy::Is => {
|
||||
ConstIsize::new(input, tcx.sess.target.int_type)
|
||||
.ok().map(ConstInt::Isize)
|
||||
},
|
||||
}),
|
||||
ty::TyUint(uint_type) => const_to_opt_uint(value).and_then(|input| match uint_type {
|
||||
ast::UintTy::U8 => {
|
||||
assert_eq!(input as u8 as u64, input);
|
||||
Some(ConstInt::U8(input as u8))
|
||||
},
|
||||
ast::UintTy::U16 => {
|
||||
assert_eq!(input as u16 as u64, input);
|
||||
Some(ConstInt::U16(input as u16))
|
||||
},
|
||||
ast::UintTy::U32 => {
|
||||
assert_eq!(input as u32 as u64, input);
|
||||
Some(ConstInt::U32(input as u32))
|
||||
},
|
||||
ast::UintTy::U64 => {
|
||||
Some(ConstInt::U64(input))
|
||||
},
|
||||
ast::UintTy::Us => {
|
||||
ConstUsize::new(input, tcx.sess.target.uint_type)
|
||||
.ok().map(ConstInt::Usize)
|
||||
},
|
||||
}),
|
||||
_ => None,
|
||||
ty::TyInt(int_type) => const_to_opt_u128(value, true)
|
||||
.and_then(|input| ConstInt::new_signed(input as i128, int_type,
|
||||
tcx.sess.target.int_type)),
|
||||
ty::TyUint(uint_type) => const_to_opt_u128(value, false)
|
||||
.and_then(|input| ConstInt::new_unsigned(input, uint_type,
|
||||
tcx.sess.target.uint_type)),
|
||||
_ => None
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,6 +205,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
|
||||
sig: &ty::FnSig<'tcx>,
|
||||
abi: Abi,
|
||||
) {
|
||||
debug!("fn_ty: {:?}", fn_ty);
|
||||
let debug_context =
|
||||
debuginfo::create_function_debug_context(fcx.ccx, instance, sig, abi, fcx.llfn, mir);
|
||||
let bcx = fcx.get_entry_block();
|
||||
|
@ -79,7 +79,7 @@ impl<'a, 'tcx> OperandRef<'tcx> {
|
||||
pub fn immediate(self) -> ValueRef {
|
||||
match self.val {
|
||||
OperandValue::Immediate(s) => s,
|
||||
_ => bug!()
|
||||
_ => bug!("not immediate: {:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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!(),
|
||||
},
|
||||
|
@ -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) => {
|
||||
|
@ -94,6 +94,10 @@ impl Type {
|
||||
ty!(llvm::LLVMInt64TypeInContext(ccx.llcx()))
|
||||
}
|
||||
|
||||
pub fn i128(ccx: &CrateContext) -> Type {
|
||||
ty!(llvm::LLVMIntTypeInContext(ccx.llcx(), 128))
|
||||
}
|
||||
|
||||
// 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),
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,6 +313,7 @@ impl Type {
|
||||
I16 => Type::i16(cx),
|
||||
I32 => Type::i32(cx),
|
||||
I64 => Type::i64(cx),
|
||||
I128 => Type::i128(cx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"},
|
||||
|
@ -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);
|
||||
|
@ -1330,6 +1330,13 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||
}
|
||||
|
||||
let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx);
|
||||
if repr_type_ty == ccx.tcx.types.i128 || repr_type_ty == ccx.tcx.types.u128 {
|
||||
if !ccx.tcx.sess.features.borrow().i128_type {
|
||||
emit_feature_err(&ccx.tcx.sess.parse_sess,
|
||||
"i128_type", sp, GateIssue::Language, "128-bit type is unstable");
|
||||
}
|
||||
}
|
||||
|
||||
for v in vs {
|
||||
if let Some(e) = v.node.disr_expr {
|
||||
check_const_with_type(ccx, e, repr_type_ty, e.node_id);
|
||||
|
@ -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(),
|
||||
|
@ -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));
|
||||
|
@ -268,11 +268,13 @@ pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
|
||||
tcx.lang_items.i16_impl(),
|
||||
tcx.lang_items.i32_impl(),
|
||||
tcx.lang_items.i64_impl(),
|
||||
tcx.lang_items.i128_impl(),
|
||||
tcx.lang_items.usize_impl(),
|
||||
tcx.lang_items.u8_impl(),
|
||||
tcx.lang_items.u16_impl(),
|
||||
tcx.lang_items.u32_impl(),
|
||||
tcx.lang_items.u64_impl(),
|
||||
tcx.lang_items.u128_impl(),
|
||||
tcx.lang_items.f32_impl(),
|
||||
tcx.lang_items.f64_impl(),
|
||||
tcx.lang_items.char_impl(),
|
||||
|
@ -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,
|
||||
@ -1595,11 +1595,13 @@ impl PrimitiveType {
|
||||
"i16" => Some(PrimitiveType::I16),
|
||||
"i32" => Some(PrimitiveType::I32),
|
||||
"i64" => Some(PrimitiveType::I64),
|
||||
"i128" => Some(PrimitiveType::I128),
|
||||
"usize" => Some(PrimitiveType::Usize),
|
||||
"u8" => Some(PrimitiveType::U8),
|
||||
"u16" => Some(PrimitiveType::U16),
|
||||
"u32" => Some(PrimitiveType::U32),
|
||||
"u64" => Some(PrimitiveType::U64),
|
||||
"u128" => Some(PrimitiveType::U128),
|
||||
"bool" => Some(PrimitiveType::Bool),
|
||||
"char" => Some(PrimitiveType::Char),
|
||||
"str" => Some(PrimitiveType::Str),
|
||||
@ -1614,26 +1616,29 @@ impl PrimitiveType {
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
use self::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",
|
||||
}
|
||||
}
|
||||
|
||||
@ -1650,6 +1655,7 @@ impl From<ast::IntTy> for PrimitiveType {
|
||||
ast::IntTy::I16 => PrimitiveType::I16,
|
||||
ast::IntTy::I32 => PrimitiveType::I32,
|
||||
ast::IntTy::I64 => PrimitiveType::I64,
|
||||
ast::IntTy::I128 => PrimitiveType::I128,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1662,6 +1668,7 @@ impl From<ast::UintTy> for PrimitiveType {
|
||||
ast::UintTy::U16 => PrimitiveType::U16,
|
||||
ast::UintTy::U32 => PrimitiveType::U32,
|
||||
ast::UintTy::U64 => PrimitiveType::U64,
|
||||
ast::UintTy::U128 => PrimitiveType::U128,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2486,6 +2493,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
|
||||
fn build_deref_target_impls(cx: &DocContext,
|
||||
items: &[Item],
|
||||
ret: &mut Vec<Item>) {
|
||||
use self::PrimitiveType::*;
|
||||
let tcx = cx.tcx;
|
||||
|
||||
for item in items {
|
||||
@ -2505,25 +2513,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() {
|
||||
|
@ -10,3 +10,4 @@ crate-type = ["dylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
log = { path = "../liblog" }
|
||||
rustc_i128 = { path = "../librustc_i128" }
|
||||
|
@ -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, v: u128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
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, v: i128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
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, v: u128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
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, v: i128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
|
||||
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) }
|
||||
|
||||
|
@ -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() {
|
||||
@ -24,11 +26,10 @@ fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
|
||||
/// 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_unsigned_leb128_to<W>(mut value: u64, mut write: W) -> usize
|
||||
pub fn write_unsigned_leb128_to<W>(mut value: u128, mut write: W) -> usize
|
||||
where W: FnMut(usize, u8)
|
||||
{
|
||||
let mut position = 0;
|
||||
|
||||
loop {
|
||||
let mut byte = (value & 0x7F) as u8;
|
||||
value >>= 7;
|
||||
@ -47,19 +48,19 @@ pub fn write_unsigned_leb128_to<W>(mut value: u64, mut write: W) -> usize
|
||||
position
|
||||
}
|
||||
|
||||
pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, value: u64) -> usize {
|
||||
pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, value: u128) -> usize {
|
||||
write_unsigned_leb128_to(value, |i, v| write_to_vec(out, start_position+i, v))
|
||||
}
|
||||
|
||||
#[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;
|
||||
@ -86,6 +87,7 @@ pub fn write_signed_leb128_to<W>(mut value: i64, mut write: W) -> usize
|
||||
value >>= 7;
|
||||
let more = !((((value == 0) && ((byte & 0x40) == 0)) ||
|
||||
((value == -1) && ((byte & 0x40) != 0))));
|
||||
|
||||
if more {
|
||||
byte |= 0x80; // Mark this byte to show that more bytes will follow.
|
||||
}
|
||||
@ -97,16 +99,15 @@ pub fn write_signed_leb128_to<W>(mut value: i64, mut write: W) -> usize
|
||||
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) {
|
||||
pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i128, usize) {
|
||||
let mut result = 0;
|
||||
let mut shift = 0;
|
||||
let mut position = start_position;
|
||||
@ -115,7 +116,7 @@ pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i64, usize) {
|
||||
loop {
|
||||
byte = data[position];
|
||||
position += 1;
|
||||
result |= ((byte & 0x7F) as i64) << shift;
|
||||
result |= ((byte & 0x7F) as i128) << shift;
|
||||
shift += 7;
|
||||
|
||||
if (byte & 0x80) == 0 {
|
||||
@ -125,7 +126,7 @@ pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i64, usize) {
|
||||
|
||||
if (shift < 64) && ((byte & 0x40) != 0) {
|
||||
// sign extend
|
||||
result |= -(1i64 << shift);
|
||||
result |= -(1 << shift);
|
||||
}
|
||||
|
||||
(result, position - start_position)
|
||||
@ -153,22 +154,13 @@ fn test_unsigned_leb128() {
|
||||
|
||||
#[test]
|
||||
fn test_signed_leb128() {
|
||||
let mut values = Vec::new();
|
||||
|
||||
let mut i = -500;
|
||||
while i < 500 {
|
||||
values.push(i * 123457i64);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let values: Vec<_> = (-500..500).map(|i| i * 0x12345789ABCDEF).collect();
|
||||
let mut stream = Vec::new();
|
||||
|
||||
for &x in &values {
|
||||
let pos = stream.len();
|
||||
let bytes_written = write_signed_leb128(&mut stream, pos, x);
|
||||
assert_eq!(stream.len(), pos + bytes_written);
|
||||
}
|
||||
|
||||
let mut pos = 0;
|
||||
for &x in &values {
|
||||
let (value, bytes_read) = read_signed_leb128(&mut stream, pos);
|
||||
|
@ -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};
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -597,6 +597,17 @@ mod prim_i32 { }
|
||||
///
|
||||
mod prim_i64 { }
|
||||
|
||||
#[doc(primitive = "i128")]
|
||||
//
|
||||
/// The 128-bit signed integer type.
|
||||
///
|
||||
/// *[See also the `std::i128` module](i128/index.html).*
|
||||
///
|
||||
/// However, please note that examples are shared between primitive integer
|
||||
/// types. So it's normal if you see usage of types like `i8` in there.
|
||||
///
|
||||
mod prim_i128 { }
|
||||
|
||||
#[doc(primitive = "u8")]
|
||||
//
|
||||
/// The 8-bit unsigned integer type.
|
||||
@ -641,6 +652,17 @@ mod prim_u32 { }
|
||||
///
|
||||
mod prim_u64 { }
|
||||
|
||||
#[doc(primitive = "u128")]
|
||||
//
|
||||
/// The 128-bit unsigned integer type.
|
||||
///
|
||||
/// *[See also the `std::u128` module](u128/index.html).*
|
||||
///
|
||||
/// However, please note that examples are shared between primitive integer
|
||||
/// types. So it's normal if you see usage of types like `u8` in there.
|
||||
///
|
||||
mod prim_u128 { }
|
||||
|
||||
#[doc(primitive = "isize")]
|
||||
//
|
||||
/// The pointer-sized signed integer type.
|
||||
|
@ -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" }
|
||||
|
@ -50,6 +50,7 @@ pub enum Abi {
|
||||
RustIntrinsic,
|
||||
RustCall,
|
||||
PlatformIntrinsic,
|
||||
Unadjusted
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -92,6 +93,7 @@ const AbiDatas: &'static [AbiData] = &[
|
||||
AbiData {abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
|
||||
AbiData {abi: Abi::RustCall, name: "rust-call", generic: true },
|
||||
AbiData {abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true },
|
||||
AbiData {abi: Abi::Unadjusted, name: "unadjusted", generic: true },
|
||||
];
|
||||
|
||||
/// Returns the ABI with the given name (if any).
|
||||
|
@ -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,24 +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 {
|
||||
// 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
|
||||
pub fn val_to_string(&self, val: i128) -> String {
|
||||
// cast to a u128 so we can correctly print INT128_MIN. All integral types
|
||||
// are parsed as u128, so we wouldn't want to print an extra negative
|
||||
// sign.
|
||||
format!("{}{}", val as u64, self.ty_to_string())
|
||||
}
|
||||
|
||||
pub fn ty_max(&self) -> u64 {
|
||||
match *self {
|
||||
IntTy::I8 => 0x80,
|
||||
IntTy::I16 => 0x8000,
|
||||
IntTy::Is | IntTy::I32 => 0x80000000, // FIXME: actually ni about Is
|
||||
IntTy::I64 => 0x8000000000000000
|
||||
}
|
||||
format!("{}{}", val as u128, self.ty_to_string())
|
||||
}
|
||||
|
||||
pub fn bit_width(&self) -> Option<usize> {
|
||||
@ -1219,6 +1214,7 @@ impl IntTy {
|
||||
IntTy::I16 => 16,
|
||||
IntTy::I32 => 32,
|
||||
IntTy::I64 => 64,
|
||||
IntTy::I128 => 128,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1230,6 +1226,7 @@ pub enum UintTy {
|
||||
U16,
|
||||
U32,
|
||||
U64,
|
||||
U128,
|
||||
}
|
||||
|
||||
impl UintTy {
|
||||
@ -1239,23 +1236,15 @@ 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())
|
||||
}
|
||||
|
||||
pub fn ty_max(&self) -> u64 {
|
||||
match *self {
|
||||
UintTy::U8 => 0xff,
|
||||
UintTy::U16 => 0xffff,
|
||||
UintTy::Us | UintTy::U32 => 0xffffffff, // FIXME: actually ni about Us
|
||||
UintTy::U64 => 0xffffffffffffffff
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bit_width(&self) -> Option<usize> {
|
||||
Some(match *self {
|
||||
UintTy::Us => return None,
|
||||
@ -1263,6 +1252,7 @@ impl UintTy {
|
||||
UintTy::U16 => 16,
|
||||
UintTy::U32 => 32,
|
||||
UintTy::U64 => 64,
|
||||
UintTy::U128 => 128,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user