From f8a02864afa2faecc3cb9cb8f81905a61a638ade Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 6 Feb 2020 13:04:51 +1100 Subject: [PATCH 01/13] Speed up `SipHasher128`. The current code in `SipHasher128::short_write` is inefficient. It uses `u8to64_le` (which is complex and slow) to extract just the right number of bytes of the input into a u64 and pad the result with zeroes. It then left-shifts that value in order to bitwise-OR it with `self.tail`. For example, imagine we have a u32 input 0xIIHH_GGFF and only need three bytes to fill up `self.tail`. The current code uses `u8to64_le` to construct 0x0000_0000_00HH_GGFF, which is just 0xIIHH_GGFF with the 0xII removed and zero-extended to a u64. The code then left-shifts that value by five bytes -- discarding the 0x00 byte that replaced the 0xII byte! -- to give 0xHHGG_FF00_0000_0000. It then then ORs that value with self.tail. There's a much simpler way to do it: zero-extend to u64 first, then left shift. E.g. 0xIIHH_GGFF is zero-extended to 0x0000_0000_IIHH_GGFF, and then left-shifted to 0xHHGG_FF00_0000_0000. We don't have to take time to exclude the unneeded 0xII byte, because it just gets shifted out anyway! It also avoids multiple occurrences of `unsafe`. There's a similar story with the setting of `self.tail` at the method's end. The current code uses `u8to64_le` to extract the remaining part of the input, but the same effect can be achieved more quickly with a right shift on the zero-extended input. All that works on little-endian. It doesn't work for big-endian, but we can just do a `to_le` before calling `short_write` and then it works. This commit changes `SipHasher128` to use the simpler shift-based approach. The code is also smaller, which means that `short_write` is now inlined where previously it wasn't, which makes things faster again. This gives big speed-ups for all incremental builds, especially "baseline" incremental builds. --- src/librustc_data_structures/sip128.rs | 111 ++++++++++++++++--------- 1 file changed, 72 insertions(+), 39 deletions(-) diff --git a/src/librustc_data_structures/sip128.rs b/src/librustc_data_structures/sip128.rs index f805be8499b63..cc653dca60c70 100644 --- a/src/librustc_data_structures/sip128.rs +++ b/src/librustc_data_structures/sip128.rs @@ -4,7 +4,6 @@ use std::cmp; use std::hash::Hasher; use std::mem; use std::ptr; -use std::slice; #[cfg(test)] mod tests; @@ -122,42 +121,76 @@ impl SipHasher128 { self.state.v1 ^= 0xee; } - // Specialized write function that is only valid for buffers with len <= 8. - // It's used to force inlining of write_u8 and write_usize, those would normally be inlined - // except for composite types (that includes slices and str hashing because of delimiter). - // Without this extra push the compiler is very reluctant to inline delimiter writes, - // degrading performance substantially for the most common use cases. + // A specialized write function for values with size <= 8. + // + // The hashing of multi-byte integers depends on endianness. E.g.: + // - little-endian: `write_u32(0xDDCCBBAA)` == `write([0xAA, 0xBB, 0xCC, 0xDD])` + // - big-endian: `write_u32(0xDDCCBBAA)` == `write([0xDD, 0xCC, 0xBB, 0xAA])` + // + // This function does the right thing for little-endian hardware. On + // big-endian hardware `x` must be byte-swapped first to give the right + // behaviour. After any byte-swapping, the input must be zero-extended to + // 64-bits. The caller is responsible for the byte-swapping and + // zero-extension. #[inline] - fn short_write(&mut self, msg: &[u8]) { - debug_assert!(msg.len() <= 8); - let length = msg.len(); - self.length += length; + fn short_write(&mut self, _x: T, x: u64) { + let size = mem::size_of::(); + self.length += size; + + // The original number must be zero-extended, not sign-extended. + debug_assert!(if size < 8 { x >> (8 * size) == 0 } else { true }); + // The number of bytes needed to fill `self.tail`. let needed = 8 - self.ntail; - let fill = cmp::min(length, needed); - if fill == 8 { - self.tail = unsafe { load_int_le!(msg, 0, u64) }; - } else { - self.tail |= unsafe { u8to64_le(msg, 0, fill) } << (8 * self.ntail); - if length < needed { - self.ntail += length; - return; - } + + // SipHash parses the input stream as 8-byte little-endian integers. + // Inputs are put into `self.tail` until 8 bytes of data have been + // collected, and then that word is processed. + // + // For example, imagine that `self.tail` is 0x0000_00EE_DDCC_BBAA, + // `self.ntail` is 5 (because 5 bytes have been put into `self.tail`), + // and `needed` is therefore 3. + // + // - Scenario 1, `self.write_u8(0xFF)`: we have already zero-extended + // the input to 0x0000_0000_0000_00FF. We now left-shift it five + // bytes, giving 0x0000_FF00_0000_0000. We then bitwise-OR that value + // into `self.tail`, resulting in 0x0000_FFEE_DDCC_BBAA. + // (Zero-extension of the original input is critical in this scenario + // because we don't want the high two bytes of `self.tail` to be + // touched by the bitwise-OR.) `self.tail` is not yet full, so we + // return early, after updating `self.ntail` to 6. + // + // - Scenario 2, `self.write_u32(0xIIHH_GGFF)`: we have already + // zero-extended the input to 0x0000_0000_IIHH_GGFF. We now + // left-shift it five bytes, giving 0xHHGG_FF00_0000_0000. We then + // bitwise-OR that value into `self.tail`, resulting in + // 0xHHGG_FFEE_DDCC_BBAA. `self.tail` is now full, and we can use it + // to update `self.state`. (As mentioned above, this assumes a + // little-endian machine; on a big-endian machine we would have + // byte-swapped 0xIIHH_GGFF in the caller, giving 0xFFGG_HHII, and we + // would then end up bitwise-ORing 0xGGHH_II00_0000_0000 into + // `self.tail`). + // + self.tail |= x << (8 * self.ntail); + if size < needed { + self.ntail += size; + return; } + + // `self.tail` is full, process it. self.state.v3 ^= self.tail; Sip24Rounds::c_rounds(&mut self.state); self.state.v0 ^= self.tail; - // Buffered tail is now flushed, process new input. - self.ntail = length - needed; - self.tail = unsafe { u8to64_le(msg, needed, self.ntail) }; - } - - #[inline(always)] - fn short_write_gen(&mut self, x: T) { - let bytes = - unsafe { slice::from_raw_parts(&x as *const T as *const u8, mem::size_of::()) }; - self.short_write(bytes); + // Continuing scenario 2: we have one byte left over from the input. We + // set `self.ntail` to 1 and `self.tail` to `0x0000_0000_IIHH_GGFF >> + // 8*3`, which is 0x0000_0000_0000_00II. (Or on a big-endian machine + // the prior byte-swapping would leave us with 0x0000_0000_0000_00FF.) + // + // The `if` is needed to avoid shifting by 64 bits, which Rust + // complains about. + self.ntail = size - needed; + self.tail = if needed < 8 { x >> (8 * needed) } else { 0 }; } #[inline] @@ -182,52 +215,52 @@ impl SipHasher128 { impl Hasher for SipHasher128 { #[inline] fn write_u8(&mut self, i: u8) { - self.short_write_gen(i); + self.short_write(i, i as u64); } #[inline] fn write_u16(&mut self, i: u16) { - self.short_write_gen(i); + self.short_write(i, i.to_le() as u64); } #[inline] fn write_u32(&mut self, i: u32) { - self.short_write_gen(i); + self.short_write(i, i.to_le() as u64); } #[inline] fn write_u64(&mut self, i: u64) { - self.short_write_gen(i); + self.short_write(i, i.to_le() as u64); } #[inline] fn write_usize(&mut self, i: usize) { - self.short_write_gen(i); + self.short_write(i, i.to_le() as u64); } #[inline] fn write_i8(&mut self, i: i8) { - self.short_write_gen(i); + self.short_write(i, i as u8 as u64); } #[inline] fn write_i16(&mut self, i: i16) { - self.short_write_gen(i); + self.short_write(i, (i as u16).to_le() as u64); } #[inline] fn write_i32(&mut self, i: i32) { - self.short_write_gen(i); + self.short_write(i, (i as u32).to_le() as u64); } #[inline] fn write_i64(&mut self, i: i64) { - self.short_write_gen(i); + self.short_write(i, (i as u64).to_le() as u64); } #[inline] fn write_isize(&mut self, i: isize) { - self.short_write_gen(i); + self.short_write(i, (i as usize).to_le() as u64); } #[inline] From 9e78ce068bb649738d489bf3cc9d701aa9a47b1e Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 10 Feb 2020 11:31:55 -0500 Subject: [PATCH 02/13] handle TerminatorKind::Yield by returning Err(Unpromotable) --- src/librustc_mir/transform/promote_consts.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 9a7f3f86a6fcd..a5d59860c3d16 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -463,6 +463,7 @@ impl<'tcx> Validator<'_, 'tcx> { let terminator = self.body[loc.block].terminator(); match &terminator.kind { TerminatorKind::Call { func, args, .. } => self.validate_call(func, args), + TerminatorKind::Yield { .. } => Err(Unpromotable), kind => { span_bug!(terminator.source_info.span, "{:?} not promotable", kind); } From fc3ecb22b9b7131ab0150672b4117ba9b53306fa Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 10 Feb 2020 12:03:49 -0500 Subject: [PATCH 03/13] add issue 69017 test --- src/test/ui/generator/issue-69017.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/test/ui/generator/issue-69017.rs diff --git a/src/test/ui/generator/issue-69017.rs b/src/test/ui/generator/issue-69017.rs new file mode 100644 index 0000000000000..7b1d87efc9443 --- /dev/null +++ b/src/test/ui/generator/issue-69017.rs @@ -0,0 +1,16 @@ +// This issue reproduces an ICE on compile +// Fails on 2020-02-08 nightly +// regressed commit: https://github.com/rust-lang/rust/commit/f8fd4624474a68bd26694eff3536b9f3a127b2d3 +// +// check-pass + +#![feature(generator_trait)] +#![feature(generators)] + +use std::ops::Generator; + +fn gen() -> impl Generator { + |_: usize| { + println!("-> {}", yield); + } +} From 8d799218ab29793b0ac08518c77cfabc8629c001 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 10 Feb 2020 20:20:01 +0300 Subject: [PATCH 04/13] parser: Remove `Parser::prev_token_kind` --- src/librustc_parse/parser/expr.rs | 29 ++++++++++------------- src/librustc_parse/parser/mod.rs | 38 +++++-------------------------- src/librustc_parse/parser/stmt.rs | 4 ++-- src/librustc_parse/parser/ty.rs | 10 ++++---- 4 files changed, 25 insertions(+), 56 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index d98321416957d..c136ffaafe7e1 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1,6 +1,6 @@ use super::pat::{GateOr, PARAM_EXPECTED}; use super::ty::{AllowPlus, RecoverQPath}; -use super::{BlockMode, Parser, PathStyle, PrevTokenKind, Restrictions, TokenType}; +use super::{BlockMode, Parser, PathStyle, Restrictions, TokenType}; use super::{SemiColonMode, SeqSep, TokenExpectType}; use crate::maybe_recover_from_interpolated_ty_qpath; @@ -166,17 +166,10 @@ impl<'a> Parser<'a> { self.expected_tokens.push(TokenType::Operator); while let Some(op) = self.check_assoc_op() { - // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what - // it refers to. Interpolated identifiers are unwrapped early and never show up here - // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process - // it as "interpolated", it doesn't change the answer for non-interpolated idents. - let lhs_span = match (self.prev_token_kind, &lhs.kind) { - (PrevTokenKind::Interpolated, _) => self.prev_span, - (PrevTokenKind::Ident, &ExprKind::Path(None, ref path)) - if path.segments.len() == 1 => - { - self.prev_span - } + // Adjust the span for interpolated LHS to point to the `$lhs` token + // and not to what it refers to. + let lhs_span = match self.unnormalized_prev_token().kind { + TokenKind::Interpolated(..) => self.prev_span, _ => lhs.span, }; @@ -535,11 +528,13 @@ impl<'a> Parser<'a> { expr: PResult<'a, P>, ) -> PResult<'a, (Span, P)> { expr.map(|e| { - if self.prev_token_kind == PrevTokenKind::Interpolated { - (self.prev_span, e) - } else { - (e.span, e) - } + ( + match self.unnormalized_prev_token().kind { + TokenKind::Interpolated(..) => self.prev_span, + _ => e.span, + }, + e, + ) }) } diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 7131eb1144e06..485e348365a17 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -83,18 +83,6 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { }; } -#[derive(Debug, Clone, Copy, PartialEq)] -enum PrevTokenKind { - DocComment, - Comma, - Plus, - Interpolated, - Eof, - Ident, - BitOr, - Other, -} - #[derive(Clone)] pub struct Parser<'a> { pub sess: &'a ParseSess, @@ -115,9 +103,6 @@ pub struct Parser<'a> { /// Preferable use is through the `unnormalized_prev_token()` getter. /// Use span from this token if you need to concatenate it with some neighbouring spans. unnormalized_prev_token: Option, - /// Equivalent to `prev_token.kind` in simplified form. - /// FIXME: Remove in favor of `(unnormalized_)prev_token().kind`. - prev_token_kind: PrevTokenKind, /// Equivalent to `unnormalized_prev_token().span`. /// FIXME: Remove in favor of `(unnormalized_)prev_token().span`. pub prev_span: Span, @@ -396,7 +381,6 @@ impl<'a> Parser<'a> { unnormalized_token: None, prev_token: Token::dummy(), unnormalized_prev_token: None, - prev_token_kind: PrevTokenKind::Other, prev_span: DUMMY_SP, restrictions: Restrictions::empty(), recurse_into_file_modules, @@ -523,10 +507,11 @@ impl<'a> Parser<'a> { self.bump(); Ok(Ident::new(name, span)) } - _ => Err(if self.prev_token_kind == PrevTokenKind::DocComment { - self.span_fatal_err(self.prev_span, Error::UselessDocComment) - } else { - self.expected_ident_found() + _ => Err(match self.prev_token.kind { + TokenKind::DocComment(..) => { + self.span_fatal_err(self.prev_span, Error::UselessDocComment) + } + _ => self.expected_ident_found(), }), } } @@ -908,7 +893,7 @@ impl<'a> Parser<'a> { /// Advance the parser by one token. pub fn bump(&mut self) { - if self.prev_token_kind == PrevTokenKind::Eof { + if self.prev_token.kind == TokenKind::Eof { // Bumping after EOF is a bad sign, usually an infinite loop. let msg = "attempted to bump the parser past EOF (may be stuck in a loop)"; self.span_bug(self.token.span, msg); @@ -920,16 +905,6 @@ impl<'a> Parser<'a> { self.unnormalized_prev_token = self.unnormalized_token.take(); // Update fields derived from the previous token. - self.prev_token_kind = match self.prev_token.kind { - token::DocComment(..) => PrevTokenKind::DocComment, - token::Comma => PrevTokenKind::Comma, - token::BinOp(token::Plus) => PrevTokenKind::Plus, - token::BinOp(token::Or) => PrevTokenKind::BitOr, - token::Interpolated(..) => PrevTokenKind::Interpolated, - token::Eof => PrevTokenKind::Eof, - token::Ident(..) => PrevTokenKind::Ident, - _ => PrevTokenKind::Other, - }; self.prev_span = self.unnormalized_prev_token().span; self.expected_tokens.clear(); @@ -949,7 +924,6 @@ impl<'a> Parser<'a> { self.unnormalized_prev_token = self.unnormalized_token.take(); // Update fields derived from the previous token. - self.prev_token_kind = PrevTokenKind::Other; self.prev_span = self.unnormalized_prev_token().span.with_hi(span.lo()); self.expected_tokens.clear(); diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index f3a69729399c1..e11cdd5dadb72 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -2,7 +2,7 @@ use super::diagnostics::Error; use super::expr::LhsExpr; use super::pat::GateOr; use super::path::PathStyle; -use super::{BlockMode, Parser, PrevTokenKind, Restrictions, SemiColonMode}; +use super::{BlockMode, Parser, Restrictions, SemiColonMode}; use crate::maybe_whole; use crate::DirectoryOwnership; @@ -190,7 +190,7 @@ impl<'a> Parser<'a> { /// Also error if the previous token was a doc comment. fn error_outer_attrs(&self, attrs: &[Attribute]) { if !attrs.is_empty() { - if self.prev_token_kind == PrevTokenKind::DocComment { + if matches!(self.prev_token.kind, TokenKind::DocComment(..)) { self.span_fatal_err(self.prev_span, Error::UselessDocComment).emit(); } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) { self.struct_span_err(self.token.span, "expected statement after outer attribute") diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 990661bf6b5b9..ed5c3dcbe400c 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -1,5 +1,5 @@ use super::item::ParamCfg; -use super::{Parser, PathStyle, PrevTokenKind, TokenType}; +use super::{Parser, PathStyle, TokenType}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; @@ -14,7 +14,7 @@ use syntax::ast::{ }; use syntax::ast::{Mac, Mutability}; use syntax::ptr::P; -use syntax::token::{self, Token}; +use syntax::token::{self, Token, TokenKind}; /// Any `?` or `?const` modifiers that appear at the start of a bound. struct BoundModifiers { @@ -196,7 +196,7 @@ impl<'a> Parser<'a> { let mut trailing_plus = false; let (ts, trailing) = self.parse_paren_comma_seq(|p| { let ty = p.parse_ty()?; - trailing_plus = p.prev_token_kind == PrevTokenKind::Plus; + trailing_plus = p.prev_token.kind == TokenKind::BinOp(token::Plus); Ok(ty) })?; @@ -317,7 +317,7 @@ impl<'a> Parser<'a> { fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds(None)?; - *impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; + *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)) } @@ -337,7 +337,7 @@ impl<'a> Parser<'a> { self.bump(); // `dyn` // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds(None)?; - *impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; + *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)) } From 53b16fb5f2dad5571dc242c3671c1d0588183cb3 Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 10 Feb 2020 13:47:52 -0500 Subject: [PATCH 05/13] add main function to issue-69017 test --- src/test/ui/generator/issue-69017.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/ui/generator/issue-69017.rs b/src/test/ui/generator/issue-69017.rs index 7b1d87efc9443..511deb60e4553 100644 --- a/src/test/ui/generator/issue-69017.rs +++ b/src/test/ui/generator/issue-69017.rs @@ -14,3 +14,5 @@ fn gen() -> impl Generator { println!("-> {}", yield); } } + +fn main() {} From 4cf0365b19ddf852375175a9679572f1e0de4eda Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 10 Feb 2020 14:20:21 -0800 Subject: [PATCH 06/13] Bump version to backtrace without the header --- src/libstd/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index c9ff93eac0295..b147aa55b2a61 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -27,7 +27,7 @@ hashbrown = { version = "0.6.2", default-features = false, features = ['rustc-de [dependencies.backtrace_rs] package = "backtrace" -version = "0.3.37" +version = "0.3.44" default-features = false # without the libstd `backtrace` feature, stub out everything features = [ "rustc-dep-of-std" ] # enable build support for integrating into libstd From 1bba9cfb9036eb44bb549f34c090cb38bd0d84fd Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Thu, 6 Feb 2020 12:32:42 +0100 Subject: [PATCH 07/13] rustbuild: include channel in sanitizers installed name Allows parallel install of different rust channels Signed-off-by: Marc-Antoine Perennou --- src/bootstrap/native.rs | 16 ++++++++++------ src/librustc_codegen_ssa/back/link.rs | 7 +++++-- src/librustc_codegen_ssa/build.rs | 4 ++++ 3 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 src/librustc_codegen_ssa/build.rs diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 1cfb4b2f63b57..5790f236cc8fd 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -571,7 +571,7 @@ impl Step for Sanitizers { } let out_dir = builder.native_dir(self.target).join("sanitizers"); - let runtimes = supported_sanitizers(&out_dir, self.target); + let runtimes = supported_sanitizers(&out_dir, self.target, &builder.config.channel); if runtimes.is_empty() { return runtimes; } @@ -635,7 +635,11 @@ pub struct SanitizerRuntime { } /// Returns sanitizers available on a given target. -fn supported_sanitizers(out_dir: &Path, target: Interned) -> Vec { +fn supported_sanitizers( + out_dir: &Path, + target: Interned, + channel: &str, +) -> Vec { let mut result = Vec::new(); match &*target { "x86_64-apple-darwin" => { @@ -644,7 +648,7 @@ fn supported_sanitizers(out_dir: &Path, target: Interned) -> Vec) -> Vec) -> Vec) -> Vec { @@ -772,13 +775,13 @@ fn link_sanitizer_runtime(sess: &Session, crate_type: config::CrateType, linker: // LLVM will link to `@rpath/*.dylib`, so we need to specify an // rpath to the library as well (the rpath should be absolute, see // PR #41352 for details). - let libname = format!("rustc_rt.{}", name); + let libname = format!("rustc{}_rt.{}", channel, name); let rpath = default_tlib.to_str().expect("non-utf8 component in path"); linker.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]); linker.link_dylib(Symbol::intern(&libname)); } "x86_64-unknown-linux-gnu" | "x86_64-fuchsia" | "aarch64-fuchsia" => { - let filename = format!("librustc_rt.{}.a", name); + let filename = format!("librustc{}_rt.{}.a", channel, name); let path = default_tlib.join(&filename); linker.link_whole_rlib(&path); } diff --git a/src/librustc_codegen_ssa/build.rs b/src/librustc_codegen_ssa/build.rs new file mode 100644 index 0000000000000..ea2af6e192e7c --- /dev/null +++ b/src/librustc_codegen_ssa/build.rs @@ -0,0 +1,4 @@ +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-env-changed=CFG_RELEASE_CHANNEL"); +} From 4e7aeaf1b52ee66ede1adb104fcd08b0463eb0f9 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Tue, 24 Dec 2019 12:47:51 +0100 Subject: [PATCH 08/13] Improve `char::is_ascii_*` code These methods explicitly check if a char is in a specific ASCII range, therefore the `is_ascii()` check is not needed, but LLVM seems to be unable to remove it. WARNING: this change improves the performance on ASCII `char`s, but complex checks such as `is_ascii_punctuation` become slower on non-ASCII `char`s. --- src/libcore/char/methods.rs | 50 +++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index 2b52c48cb9077..302400744e25d 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -1075,7 +1075,10 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_alphabetic(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_alphabetic() + match *self { + 'A'..='Z' | 'a'..='z' => true, + _ => false, + } } /// Checks if the value is an ASCII uppercase character: @@ -1108,7 +1111,10 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_uppercase(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_uppercase() + match *self { + 'A'..='Z' => true, + _ => false, + } } /// Checks if the value is an ASCII lowercase character: @@ -1141,7 +1147,10 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_lowercase(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_lowercase() + match *self { + 'a'..='z' => true, + _ => false, + } } /// Checks if the value is an ASCII alphanumeric character: @@ -1177,7 +1186,10 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_alphanumeric(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_alphanumeric() + match *self { + '0'..='9' | 'A'..='Z' | 'a'..='z' => true, + _ => false, + } } /// Checks if the value is an ASCII decimal digit: @@ -1210,7 +1222,10 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_digit(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_digit() + match *self { + '0'..='9' => true, + _ => false, + } } /// Checks if the value is an ASCII hexadecimal digit: @@ -1246,7 +1261,10 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_hexdigit(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_hexdigit() + match *self { + '0'..='9' | 'A'..='F' | 'a'..='f' => true, + _ => false, + } } /// Checks if the value is an ASCII punctuation character: @@ -1283,7 +1301,10 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_punctuation(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_punctuation() + match *self { + '!'..='/' | ':'..='@' | '['..='`' | '{'..='~' => true, + _ => false, + } } /// Checks if the value is an ASCII graphic character: @@ -1316,7 +1337,10 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_graphic(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_graphic() + match *self { + '!'..='~' => true, + _ => false, + } } /// Checks if the value is an ASCII whitespace character: @@ -1366,7 +1390,10 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_whitespace(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_whitespace() + match *self { + '\t' | '\n' | '\x0C' | '\r' | ' ' => true, + _ => false, + } } /// Checks if the value is an ASCII control character: @@ -1401,6 +1428,9 @@ impl char { #[rustc_const_unstable(feature = "const_ascii_ctype_on_intrinsics", issue = "68983")] #[inline] pub const fn is_ascii_control(&self) -> bool { - self.is_ascii() && (*self as u8).is_ascii_control() + match *self { + '\0'..='\x1F' | '\x7F' => true, + _ => false, + } } } From d2b08c7e93f68099f273743a8c7bad0d8ee28de0 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Tue, 11 Feb 2020 12:51:23 -0800 Subject: [PATCH 09/13] Update Cargo.lock --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bbfda0fa2c846..018ad3e6f98b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,9 +121,9 @@ checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "backtrace" -version = "0.3.40" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +checksum = "e4036b9bf40f3cf16aba72a3d65e8a520fc4bafcdc7079aea8f848c58c5b5536" dependencies = [ "backtrace-sys", "cfg-if", From 9aea154e7893b498b98a3d9c8e4c385c96fbe454 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 12 Feb 2020 10:36:29 +1100 Subject: [PATCH 10/13] Improve `u8to64_le`. This makes it faster and also changes it to a safe function. (Thanks to Michael Woerister for the suggestion.) `load_int_le!` is also no longer necessary. --- src/librustc_data_structures/sip128.rs | 53 ++++++-------------------- 1 file changed, 12 insertions(+), 41 deletions(-) diff --git a/src/librustc_data_structures/sip128.rs b/src/librustc_data_structures/sip128.rs index cc653dca60c70..430f2f40caa9b 100644 --- a/src/librustc_data_structures/sip128.rs +++ b/src/librustc_data_structures/sip128.rs @@ -51,46 +51,17 @@ macro_rules! compress { }}; } -/// Loads an integer of the desired type from a byte stream, in LE order. Uses -/// `copy_nonoverlapping` to let the compiler generate the most efficient way -/// to load it from a possibly unaligned address. -/// -/// Unsafe because: unchecked indexing at i..i+size_of(int_ty) -macro_rules! load_int_le { - ($buf:expr, $i:expr, $int_ty:ident) => {{ - debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); - let mut data = 0 as $int_ty; - ptr::copy_nonoverlapping( - $buf.get_unchecked($i), - &mut data as *mut _ as *mut u8, - mem::size_of::<$int_ty>(), - ); - data.to_le() - }}; -} - -/// Loads an u64 using up to 7 bytes of a byte slice. -/// -/// Unsafe because: unchecked indexing at start..start+len +/// Loads up to 8 bytes from a byte-slice into a little-endian u64. #[inline] -unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { - debug_assert!(len < 8); - let mut i = 0; // current byte index (from LSB) in the output u64 - let mut out = 0; - if i + 3 < len { - out = u64::from(load_int_le!(buf, start + i, u32)); - i += 4; - } - if i + 1 < len { - out |= u64::from(load_int_le!(buf, start + i, u16)) << (i * 8); - i += 2 - } - if i < len { - out |= u64::from(*buf.get_unchecked(start + i)) << (i * 8); - i += 1; +fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { + assert!(len <= 8 && start + len <= buf.len()); + + let mut out = 0u64; + unsafe { + let out_ptr = &mut out as *mut _ as *mut u8; + ptr::copy_nonoverlapping(buf.as_ptr().offset(start as isize), out_ptr, len); } - debug_assert_eq!(i, len); - out + out.to_le() } impl SipHasher128 { @@ -272,7 +243,7 @@ impl Hasher for SipHasher128 { if self.ntail != 0 { needed = 8 - self.ntail; - self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail); + self.tail |= u8to64_le(msg, 0, cmp::min(length, needed)) << (8 * self.ntail); if length < needed { self.ntail += length; return; @@ -290,7 +261,7 @@ impl Hasher for SipHasher128 { let mut i = needed; while i < len - left { - let mi = unsafe { load_int_le!(msg, i, u64) }; + let mi = u8to64_le(msg, i, 8); self.state.v3 ^= mi; Sip24Rounds::c_rounds(&mut self.state); @@ -299,7 +270,7 @@ impl Hasher for SipHasher128 { i += 8; } - self.tail = unsafe { u8to64_le(msg, i, left) }; + self.tail = u8to64_le(msg, i, left); self.ntail = left; } From 090a1571d8c489588e2947ddb61b79f78b5b11b3 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Tue, 11 Feb 2020 16:57:22 -0800 Subject: [PATCH 11/13] Fix failing backtrace ui tests --- src/libstd/sys_common/backtrace.rs | 1 + src/test/ui/std-backtrace.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 191add2c31b3e..289ee07babfcf 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -70,6 +70,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| { output_filename(fmt, bows, print_fmt, cwd.as_ref()) }; + write!(fmt, "stack backtrace:\n")?; let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path); bt_fmt.add_context()?; let mut idx = 0; diff --git a/src/test/ui/std-backtrace.rs b/src/test/ui/std-backtrace.rs index d84c493d53523..902a2b6f5a0e9 100644 --- a/src/test/ui/std-backtrace.rs +++ b/src/test/ui/std-backtrace.rs @@ -16,9 +16,9 @@ use std::str; fn main() { let args: Vec = env::args().collect(); if args.len() >= 2 && args[1] == "force" { - println!("{}", std::backtrace::Backtrace::force_capture()); + println!("stack backtrace:\n{}", std::backtrace::Backtrace::force_capture()); } else if args.len() >= 2 { - println!("{}", std::backtrace::Backtrace::capture()); + println!("stack backtrace:\n{}", std::backtrace::Backtrace::capture()); } else { runtest(&args[0]); println!("test ok"); From d8544ce2484553f6397d8986b582181a2e761360 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Tue, 11 Feb 2020 13:34:42 +0100 Subject: [PATCH 12/13] remove some unused objects --- src/librustc/infer/region_constraints/mod.rs | 2 -- src/librustc_driver/lib.rs | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 2c580e2e3490a..8379a73bb9ebb 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -339,8 +339,6 @@ impl TaintDirections { } } -pub struct ConstraintInfo {} - impl<'tcx> RegionConstraintCollector<'tcx> { pub fn new() -> Self { Self::default() diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 019ff431bcb97..0f1e9fe1424ac 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -123,10 +123,6 @@ pub trait Callbacks { } } -pub struct DefaultCallbacks; - -impl Callbacks for DefaultCallbacks {} - #[derive(Default)] pub struct TimePassesCallbacks { time_passes: bool, From 15adbf6e086794d197e744db815476994b9ce3d7 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 12 Feb 2020 12:06:14 +0100 Subject: [PATCH 13/13] Properly use the darwin archive format on Apple targets See https://github.com/servo/servo/issues/25550. --- src/librustc_codegen_llvm/llvm/ffi.rs | 1 + src/librustc_codegen_llvm/llvm/mod.rs | 1 + src/librustc_target/spec/apple_base.rs | 2 +- src/rustllvm/ArchiveWrapper.cpp | 3 +++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 146b7d3d76c5e..fca4b1c598c37 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -459,6 +459,7 @@ pub enum ArchiveKind { Other, K_GNU, K_BSD, + K_DARWIN, K_COFF, } diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs index eb13d6a575fe8..96014cbee5da1 100644 --- a/src/librustc_codegen_llvm/llvm/mod.rs +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -69,6 +69,7 @@ impl FromStr for ArchiveKind { match s { "gnu" => Ok(ArchiveKind::K_GNU), "bsd" => Ok(ArchiveKind::K_BSD), + "darwin" => Ok(ArchiveKind::K_DARWIN), "coff" => Ok(ArchiveKind::K_COFF), _ => Err(()), } diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index 325efd10973cd..d116ddf952aaa 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -26,7 +26,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, dll_prefix: "lib".to_string(), dll_suffix: ".dylib".to_string(), - archive_format: "bsd".to_string(), + archive_format: "darwin".to_string(), pre_link_args: LinkArgs::new(), has_elf_tls: version >= (10, 7), abi_return_struct_as_int: true, diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp index 678d787571ed7..93704638f8351 100644 --- a/src/rustllvm/ArchiveWrapper.cpp +++ b/src/rustllvm/ArchiveWrapper.cpp @@ -38,6 +38,7 @@ enum class LLVMRustArchiveKind { Other, GNU, BSD, + DARWIN, COFF, }; @@ -47,6 +48,8 @@ static Archive::Kind fromRust(LLVMRustArchiveKind Kind) { return Archive::K_GNU; case LLVMRustArchiveKind::BSD: return Archive::K_BSD; + case LLVMRustArchiveKind::DARWIN: + return Archive::K_DARWIN; case LLVMRustArchiveKind::COFF: return Archive::K_COFF; default: