From b0e55a83a82bae26851f442859acace2b94f5028 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Tue, 23 Aug 2016 03:56:52 +0300 Subject: Such large. Very 128. Much bits. This commit introduces 128-bit integers. Stage 2 builds and produces a working compiler which understands and supports 128-bit integers throughout. The general strategy used is to have rustc_i128 module which provides aliases for iu128, equal to iu64 in stage9 and iu128 later. Since nowhere in rustc we rely on large numbers being supported, this strategy is good enough to get past the first bootstrap stages to end up with a fully working 128-bit capable compiler. In order for this strategy to work, number of locations had to be changed to use associated max_value/min_value instead of MAX/MIN constants as well as the min_value (or was it max_value?) had to be changed to use xor instead of shift so both 64-bit and 128-bit based consteval works (former not necessarily producing the right results in stage1). This commit includes manual merge conflict resolution changes from a rebase by @est31. --- src/libsyntax/Cargo.toml | 1 + src/libsyntax/ast.rs | 28 ++++++++++++++++++++-------- src/libsyntax/attr.rs | 5 ++++- src/libsyntax/ext/build.rs | 14 +++++++++----- src/libsyntax/ext/quote.rs | 6 ++++-- src/libsyntax/lib.rs | 3 ++- src/libsyntax/parse/mod.rs | 8 ++++++-- src/libsyntax/parse/parser.rs | 4 +++- src/libsyntax/print/pprust.rs | 5 +++-- 9 files changed, 52 insertions(+), 22 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index 0b38f5450b6..a200da6c293 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -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" } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f72985fd91a..d1257a02a58 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -33,6 +33,8 @@ use std::u32; use serialize::{self, Encodable, Decodable, Encoder, Decoder}; +use rustc_i128::{u128, i128}; + /// An identifier contains a Name (index into the interner /// table) and a SyntaxContext to track renaming and /// macro expansion per Flatt et al., "Macros That Work Together" @@ -1062,7 +1064,7 @@ pub enum LitKind { /// A character literal (`'a'`) Char(char), /// An integer literal (`1`) - Int(u64, LitIntType), + Int(u128, LitIntType), /// A float literal (`1f64` or `1E10f64`) Float(Symbol, FloatTy), /// A float literal without a suffix (`1.0 or 1.0E10`) @@ -1171,6 +1173,7 @@ pub enum IntTy { I16, I32, I64, + I128, } impl fmt::Debug for IntTy { @@ -1192,15 +1195,16 @@ impl IntTy { IntTy::I8 => "i8", IntTy::I16 => "i16", IntTy::I32 => "i32", - IntTy::I64 => "i64" + IntTy::I64 => "i64", + IntTy::I128 => "i128", } } - pub fn val_to_string(&self, val: i64) -> String { + pub fn val_to_string(&self, val: i128) -> String { // cast to a u64 so we can correctly print INT64_MIN. All integral types // are parsed as u64, so we wouldn't want to print an extra negative // sign. - format!("{}{}", val as u64, self.ty_to_string()) + format!("{}{}", val as u128, self.ty_to_string()) } pub fn ty_max(&self) -> u64 { @@ -1208,7 +1212,9 @@ impl IntTy { IntTy::I8 => 0x80, IntTy::I16 => 0x8000, IntTy::Is | IntTy::I32 => 0x80000000, // FIXME: actually ni about Is - IntTy::I64 => 0x8000000000000000 + IntTy::I64 => 0x8000000000000000, + // FIXME: i128 + IntTy::I128 => !0u64, } } @@ -1219,6 +1225,7 @@ impl IntTy { IntTy::I16 => 16, IntTy::I32 => 32, IntTy::I64 => 64, + IntTy::I128 => 128, }) } } @@ -1230,6 +1237,7 @@ pub enum UintTy { U16, U32, U64, + U128, } impl UintTy { @@ -1239,11 +1247,12 @@ impl UintTy { UintTy::U8 => "u8", UintTy::U16 => "u16", UintTy::U32 => "u32", - UintTy::U64 => "u64" + UintTy::U64 => "u64", + UintTy::U128 => "u128", } } - pub fn val_to_string(&self, val: u64) -> String { + pub fn val_to_string(&self, val: u128) -> String { format!("{}{}", val, self.ty_to_string()) } @@ -1252,7 +1261,9 @@ impl UintTy { UintTy::U8 => 0xff, UintTy::U16 => 0xffff, UintTy::Us | UintTy::U32 => 0xffffffff, // FIXME: actually ni about Us - UintTy::U64 => 0xffffffffffffffff + UintTy::U64 => 0xffffffffffffffff, + // FIXME: i128 + UintTy::U128 => 0xffffffffffffffff, } } @@ -1263,6 +1274,7 @@ impl UintTy { UintTy::U16 => 16, UintTy::U32 => 32, UintTy::U64 => 64, + UintTy::U128 => 128, }) } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index c31bcfbd869..ab8a49b41f2 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -899,6 +899,8 @@ fn int_type_of_word(s: &str) -> Option { "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 } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 7584fa3916d..28f0c297303 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -16,6 +16,7 @@ use codemap::{dummy_spanned, respan, Spanned}; use ext::base::ExtCtxt; use ptr::P; use symbol::{Symbol, keywords}; +use rustc_i128::u128; // Transitional reexports so qquote can find the paths it is looking for mod syntax { @@ -712,23 +713,26 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr(sp, ast::ExprKind::Lit(P(respan(sp, lit)))) } fn expr_usize(&self, span: Span, i: usize) -> P { - self.expr_lit(span, ast::LitKind::Int(i as u64, ast::LitIntType::Unsigned(ast::UintTy::Us))) + self.expr_lit(span, ast::LitKind::Int(i as u128, + ast::LitIntType::Unsigned(ast::UintTy::Us))) } fn expr_isize(&self, sp: Span, i: isize) -> P { if i < 0 { - let i = (-i) as u64; + let i = (-i) as u128; let lit_ty = ast::LitIntType::Signed(ast::IntTy::Is); let lit = self.expr_lit(sp, ast::LitKind::Int(i, lit_ty)); self.expr_unary(sp, ast::UnOp::Neg, lit) } else { - self.expr_lit(sp, ast::LitKind::Int(i as u64, ast::LitIntType::Signed(ast::IntTy::Is))) + self.expr_lit(sp, ast::LitKind::Int(i as u128, + ast::LitIntType::Signed(ast::IntTy::Is))) } } fn expr_u32(&self, sp: Span, u: u32) -> P { - self.expr_lit(sp, ast::LitKind::Int(u as u64, ast::LitIntType::Unsigned(ast::UintTy::U32))) + self.expr_lit(sp, ast::LitKind::Int(u as u128, + ast::LitIntType::Unsigned(ast::UintTy::U32))) } fn expr_u8(&self, sp: Span, u: u8) -> P { - self.expr_lit(sp, ast::LitKind::Int(u as u64, ast::LitIntType::Unsigned(ast::UintTy::U8))) + self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U8))) } fn expr_bool(&self, sp: Span, value: bool) -> P { self.expr_lit(sp, ast::LitKind::Bool(value)) diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index aa777a19a9b..d2eb2636e6b 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -19,6 +19,7 @@ use parse::token; use ptr::P; use tokenstream::{self, TokenTree}; + /// Quasiquoting works via token trees. /// /// This is registered as a set of expression syntax extension called quote! @@ -40,6 +41,7 @@ pub mod rt { pub use parse::new_parser_from_tts; pub use syntax_pos::{BytePos, Span, DUMMY_SP}; pub use codemap::{dummy_spanned}; + use rustc_i128::{u128}; pub trait ToTokens { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec; @@ -288,7 +290,7 @@ pub mod rt { } else { *self }; - let lit = ast::LitKind::Int(val as u64, ast::LitIntType::Signed($tag)); + let lit = ast::LitKind::Int(val as u128, ast::LitIntType::Signed($tag)); let lit = P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Lit(P(dummy_spanned(lit))), @@ -310,7 +312,7 @@ pub mod rt { (unsigned, $t:ty, $tag:expr) => ( impl ToTokens for $t { fn to_tokens(&self, cx: &ExtCtxt) -> Vec { - let lit = ast::LitKind::Int(*self as u64, ast::LitIntType::Unsigned($tag)); + let lit = ast::LitKind::Int(*self as u128, ast::LitIntType::Unsigned($tag)); dummy_spanned(lit).to_tokens(cx) } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index b3b0ee6093d..5d6808284f6 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -46,8 +46,9 @@ pub extern crate rustc_errors as errors; extern crate syntax_pos; extern crate rustc_data_structures; -extern crate serialize as rustc_serialize; // used by deriving +extern crate rustc_i128; +extern crate serialize as rustc_serialize; // used by deriving // A variant of 'try!' that panics on an Err. This is used as a crutch on the // way towards a non-panic!-prone parser. It should be used for fatal parsing diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 24178e1f675..32b61a88ac1 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -28,6 +28,8 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; use std::str; +use rustc_i128::u128; + pub type PResult<'a, T> = Result>; #[macro_use] @@ -557,18 +559,20 @@ pub fn integer_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> a "i16" => ast::LitIntType::Signed(ast::IntTy::I16), "i32" => ast::LitIntType::Signed(ast::IntTy::I32), "i64" => ast::LitIntType::Signed(ast::IntTy::I64), + "i128" => ast::LitIntType::Signed(ast::IntTy::I128), "usize" => ast::LitIntType::Unsigned(ast::UintTy::Us), "u8" => ast::LitIntType::Unsigned(ast::UintTy::U8), "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16), "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32), "u64" => ast::LitIntType::Unsigned(ast::UintTy::U64), + "u128" => ast::LitIntType::Unsigned(ast::UintTy::U128), suf => { // i and u look like widths, so lets // give an error message along those lines if looks_like_width_suffix(&['i', 'u'], suf) { sd.struct_span_err(sp, &format!("invalid width `{}` for integer literal", &suf[1..])) - .help("valid widths are 8, 16, 32 and 64") + .help("valid widths are 8, 16, 32, 64 and 128") .emit(); } else { sd.struct_span_err(sp, &format!("invalid suffix `{}` for numeric literal", suf)) @@ -585,7 +589,7 @@ pub fn integer_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> a debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \ string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix); - match u64::from_str_radix(s, base) { + match u128::from_str_radix(s, base) { Ok(r) => ast::LitKind::Int(r, ty), Err(_) => { // small bases are lexed as if they were base 10, e.g, the string diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a0ed50b33a4..2bb38433a26 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -64,6 +64,8 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; use std::slice; +use rustc_i128::u128; + bitflags! { flags Restrictions: u8 { const RESTRICTION_STMT_EXPR = 1 << 0, @@ -2044,7 +2046,7 @@ impl<'a> Parser<'a> { pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinVec) -> P { let span = &self.span; let lv_lit = P(codemap::Spanned { - node: LitKind::Int(i as u64, ast::LitIntType::Unsigned(UintTy::U32)), + node: LitKind::Int(i as u128, ast::LitIntType::Unsigned(UintTy::U32)), span: *span }); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 7558f0256da..60e1882fcf5 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -30,6 +30,8 @@ use std_inject; use symbol::{Symbol, keywords}; use tokenstream::{self, TokenTree}; +use rustc_i128::i128; + use std::ascii; use std::io::{self, Write, Read}; use std::iter; @@ -647,8 +649,7 @@ pub trait PrintState<'a> { ast::LitKind::Int(i, t) => { match t { ast::LitIntType::Signed(st) => { - word(self.writer(), - &st.val_to_string(i as i64)) + word(self.writer(), &st.val_to_string(i as i128)) } ast::LitIntType::Unsigned(ut) => { word(self.writer(), &ut.val_to_string(i)) -- cgit 1.4.1-3-g733a5