diff options
Diffstat (limited to 'compiler/rustc_session')
-rw-r--r-- | compiler/rustc_session/Cargo.toml | 8 | ||||
-rw-r--r-- | compiler/rustc_session/messages.ftl (renamed from compiler/rustc_session/locales/en-US.ftl) | 0 | ||||
-rw-r--r-- | compiler/rustc_session/src/code_stats.rs | 12 | ||||
-rw-r--r-- | compiler/rustc_session/src/config.rs | 61 | ||||
-rw-r--r-- | compiler/rustc_session/src/cstore.rs | 11 | ||||
-rw-r--r-- | compiler/rustc_session/src/filesearch.rs | 131 | ||||
-rw-r--r-- | compiler/rustc_session/src/lib.rs | 4 | ||||
-rw-r--r-- | compiler/rustc_session/src/options.rs | 43 | ||||
-rw-r--r-- | compiler/rustc_session/src/output.rs | 4 | ||||
-rw-r--r-- | compiler/rustc_session/src/parse.rs | 41 | ||||
-rw-r--r-- | compiler/rustc_session/src/session.rs | 95 | ||||
-rw-r--r-- | compiler/rustc_session/src/utils.rs | 12 |
12 files changed, 262 insertions, 160 deletions
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index d8db86c5f..9e337dde9 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -24,5 +24,9 @@ termize = "0.1.1" [target.'cfg(unix)'.dependencies] libc = "0.2" -[target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["libloaderapi"] } +[target.'cfg(windows)'.dependencies.windows] +version = "0.46.0" +features = [ + "Win32_Foundation", + "Win32_System_LibraryLoader", +] diff --git a/compiler/rustc_session/locales/en-US.ftl b/compiler/rustc_session/messages.ftl index ff53f22d4..ff53f22d4 100644 --- a/compiler/rustc_session/locales/en-US.ftl +++ b/compiler/rustc_session/messages.ftl diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index 551782504..0dfee92f4 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lock; use rustc_span::Symbol; use rustc_target::abi::{Align, Size}; -use std::cmp::{self, Ordering}; +use std::cmp; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct VariantInfo { @@ -87,7 +87,7 @@ impl CodeStats { // Except for Generators, whose variants are already sorted according to // their yield points in `variant_info_for_generator`. if kind != DataTypeKind::Generator { - variants.sort_by(|info1, info2| info2.size.cmp(&info1.size)); + variants.sort_by_key(|info| cmp::Reverse(info.size)); } let info = TypeSizeInfo { kind, @@ -107,13 +107,7 @@ impl CodeStats { // Primary sort: large-to-small. // Secondary sort: description (dictionary order) - sorted.sort_by(|info1, info2| { - // (reversing cmp order to get large-to-small ordering) - match info2.overall_size.cmp(&info1.overall_size) { - Ordering::Equal => info1.type_description.cmp(&info2.type_description), - other => other, - } - }); + sorted.sort_by_key(|info| (cmp::Reverse(info.overall_size), &info.type_description)); for info in sorted { let TypeSizeInfo { type_description, overall_size, align, kind, variants, .. } = info; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index d4e4ace88..79eb31bb1 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -222,7 +222,7 @@ impl LinkerPluginLto { } /// The different settings that can be enabled via the `-Z location-detail` flag. -#[derive(Clone, PartialEq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Hash, Debug)] pub struct LocationDetail { pub file: bool, pub line: bool, @@ -260,6 +260,8 @@ pub enum SymbolManglingVersion { #[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum DebugInfo { None, + LineDirectivesOnly, + LineTablesOnly, Limited, Full, } @@ -580,6 +582,7 @@ pub enum PrintRequest { CodeModels, TlsModels, TargetSpec, + AllTargetSpecs, NativeStaticLibs, StackProtectorStrategies, LinkArgs, @@ -1137,7 +1140,7 @@ impl CrateCheckConfig { } /// Fills a `CrateCheckConfig` with well-known configuration values. - fn fill_well_known_values(&mut self) { + fn fill_well_known_values(&mut self, current_target: &Target) { if !self.well_known_values { return; } @@ -1229,6 +1232,7 @@ impl CrateCheckConfig { for target in TARGETS .iter() .map(|target| Target::expect_builtin(&TargetTriple::from_triple(target))) + .chain(iter::once(current_target.clone())) { values_target_os.insert(Symbol::intern(&target.options.os)); values_target_family @@ -1243,9 +1247,9 @@ impl CrateCheckConfig { } } - pub fn fill_well_known(&mut self) { + pub fn fill_well_known(&mut self, current_target: &Target) { self.fill_well_known_names(); - self.fill_well_known_values(); + self.fill_well_known_values(current_target); } } @@ -1254,7 +1258,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo // some default and generated configuration items. let default_cfg = default_configuration(sess); // If the user wants a test runner, then add the test cfg. - if sess.opts.test { + if sess.is_test_crate() { user_cfg.insert((sym::test, None)); } user_cfg.extend(default_cfg.iter().cloned()); @@ -1422,7 +1426,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> { opt::opt_s( "", "edition", - &*EDITION_STRING, + &EDITION_STRING, EDITION_NAME_LIST, ), opt::multi_s( @@ -1438,8 +1442,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> { "Compiler information to print on stdout", "[crate-name|file-names|sysroot|target-libdir|cfg|calling-conventions|\ target-list|target-cpus|target-features|relocation-models|code-models|\ - tls-models|target-spec-json|native-static-libs|stack-protector-strategies|\ - link-args]", + tls-models|target-spec-json|all-target-specs-json|native-static-libs|\ + stack-protector-strategies|link-args]", ), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), @@ -1886,6 +1890,7 @@ fn collect_print_requests( ("native-static-libs", PrintRequest::NativeStaticLibs), ("stack-protector-strategies", PrintRequest::StackProtectorStrategies), ("target-spec-json", PrintRequest::TargetSpec), + ("all-target-specs-json", PrintRequest::AllTargetSpecs), ("link-args", PrintRequest::LinkArgs), ("split-debuginfo", PrintRequest::SplitDebuginfo), ]; @@ -1899,7 +1904,18 @@ fn collect_print_requests( early_error( error_format, "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option", + enable the target-spec-json print option", + ); + } + } + Some((_, PrintRequest::AllTargetSpecs)) => { + if unstable_opts.unstable_options { + PrintRequest::AllTargetSpecs + } else { + early_error( + error_format, + "the `-Z unstable-options` flag must also be passed to \ + enable the all-target-specs-json print option", ); } } @@ -1978,11 +1994,7 @@ fn parse_opt_level( } } -fn select_debuginfo( - matches: &getopts::Matches, - cg: &CodegenOptions, - error_format: ErrorOutputType, -) -> DebugInfo { +fn select_debuginfo(matches: &getopts::Matches, cg: &CodegenOptions) -> DebugInfo { let max_g = matches.opt_positions("g").into_iter().max(); let max_c = matches .opt_strs_pos("C") @@ -1992,24 +2004,7 @@ fn select_debuginfo( if let Some("debuginfo") = s.split('=').next() { Some(i) } else { None } }) .max(); - if max_g > max_c { - DebugInfo::Full - } else { - match cg.debuginfo { - 0 => DebugInfo::None, - 1 => DebugInfo::Limited, - 2 => DebugInfo::Full, - arg => { - early_error( - error_format, - &format!( - "debug info level needs to be between \ - 0-2 (instead was `{arg}`)" - ), - ); - } - } - } + if max_g > max_c { DebugInfo::Full } else { cg.debuginfo } } pub(crate) fn parse_assert_incr_state( @@ -2497,7 +2492,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) // for more details. let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); - let debuginfo = select_debuginfo(matches, &cg, error_format); + let debuginfo = select_debuginfo(matches, &cg); let mut search_paths = vec![]; for s in &matches.opt_strs("L") { diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 868ffdf0f..dd1721801 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -6,7 +6,7 @@ use crate::search_paths::PathKind; use crate::utils::NativeLibKind; use crate::Session; use rustc_ast as ast; -use rustc_data_structures::sync::{self, AppendOnlyVec, MetadataRef, RwLock}; +use rustc_data_structures::sync::{self, AppendOnlyIndexVec, MetadataRef, RwLock}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions}; use rustc_span::hygiene::{ExpnHash, ExpnId}; @@ -67,12 +67,11 @@ pub enum LinkagePreference { #[derive(Debug, Encodable, Decodable, HashStable_Generic)] pub struct NativeLib { pub kind: NativeLibKind, - pub name: Option<Symbol>, + pub name: Symbol, /// If packed_bundled_libs enabled, actual filename of library is stored. pub filename: Option<Symbol>, pub cfg: Option<ast::MetaItem>, pub foreign_module: Option<DefId>, - pub wasm_import_module: Option<Symbol>, pub verbatim: Option<bool>, pub dll_imports: Vec<DllImport>, } @@ -81,6 +80,10 @@ impl NativeLib { pub fn has_modifiers(&self) -> bool { self.verbatim.is_some() || self.kind.has_modifiers() } + + pub fn wasm_import_module(&self) -> Option<Symbol> { + if self.kind == NativeLibKind::WasmImportModule { Some(self.name) } else { None } + } } /// Different ways that the PE Format can decorate a symbol name. @@ -254,6 +257,6 @@ pub type CrateStoreDyn = dyn CrateStore + sync::Sync + sync::Send; pub struct Untracked { pub cstore: RwLock<Box<CrateStoreDyn>>, /// Reference span for definitions. - pub source_span: AppendOnlyVec<LocalDefId, Span>, + pub source_span: AppendOnlyIndexVec<LocalDefId, Span>, pub definitions: RwLock<Definitions>, } diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index f1fbf3821..7fdbd48d5 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -1,5 +1,6 @@ //! A module for searching for libraries +use rustc_fs_util::try_canonicalize; use smallvec::{smallvec, SmallVec}; use std::env; use std::fs; @@ -67,6 +68,7 @@ fn current_dll_path() -> Result<PathBuf, String> { use std::ffi::{CStr, OsStr}; use std::os::unix::prelude::*; + #[cfg(not(target_os = "aix"))] unsafe { let addr = current_dll_path as usize as *mut _; let mut info = std::mem::zeroed(); @@ -80,6 +82,49 @@ fn current_dll_path() -> Result<PathBuf, String> { let os = OsStr::from_bytes(bytes); Ok(PathBuf::from(os)) } + + #[cfg(target_os = "aix")] + unsafe { + // On AIX, the symbol `current_dll_path` references a function descriptor. + // A function descriptor is consisted of (See https://reviews.llvm.org/D62532) + // * The address of the entry point of the function. + // * The TOC base address for the function. + // * The environment pointer. + // The function descriptor is in the data section. + let addr = current_dll_path as u64; + let mut buffer = vec![std::mem::zeroed::<libc::ld_info>(); 64]; + loop { + if libc::loadquery( + libc::L_GETINFO, + buffer.as_mut_ptr() as *mut i8, + (std::mem::size_of::<libc::ld_info>() * buffer.len()) as u32, + ) >= 0 + { + break; + } else { + if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM { + return Err("loadquery failed".into()); + } + buffer.resize(buffer.len() * 2, std::mem::zeroed::<libc::ld_info>()); + } + } + let mut current = buffer.as_mut_ptr() as *mut libc::ld_info; + loop { + let data_base = (*current).ldinfo_dataorg as u64; + let data_end = data_base + (*current).ldinfo_datasize; + if (data_base..data_end).contains(&addr) { + let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes(); + let os = OsStr::from_bytes(bytes); + return Ok(PathBuf::from(os)); + } + if (*current).ldinfo_next == 0 { + break; + } + current = + (current as *mut i8).offset((*current).ldinfo_next as isize) as *mut libc::ld_info; + } + return Err(format!("current dll's address {} is not in the load map", addr)); + } } #[cfg(windows)] @@ -87,42 +132,45 @@ fn current_dll_path() -> Result<PathBuf, String> { use std::ffi::OsString; use std::io; use std::os::windows::prelude::*; - use std::ptr; - use winapi::um::libloaderapi::{ - GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + use windows::{ + core::PCWSTR, + Win32::Foundation::HINSTANCE, + Win32::System::LibraryLoader::{ + GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + }, }; + let mut module = HINSTANCE::default(); unsafe { - let mut module = ptr::null_mut(); - let r = GetModuleHandleExW( + GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - current_dll_path as usize as *mut _, + PCWSTR(current_dll_path as *mut u16), &mut module, - ); - if r == 0 { - return Err(format!("GetModuleHandleExW failed: {}", io::Error::last_os_error())); - } - let mut space = Vec::with_capacity(1024); - let r = GetModuleFileNameW(module, space.as_mut_ptr(), space.capacity() as u32); - if r == 0 { - return Err(format!("GetModuleFileNameW failed: {}", io::Error::last_os_error())); - } - let r = r as usize; - if r >= space.capacity() { - return Err(format!("our buffer was too small? {}", io::Error::last_os_error())); - } - space.set_len(r); - let os = OsString::from_wide(&space); - Ok(PathBuf::from(os)) + ) + } + .ok() + .map_err(|e| e.to_string())?; + + let mut filename = vec![0; 1024]; + let n = unsafe { GetModuleFileNameW(module, &mut filename) } as usize; + if n == 0 { + return Err(format!("GetModuleFileNameW failed: {}", io::Error::last_os_error())); } + if n >= filename.capacity() { + return Err(format!("our buffer was too small? {}", io::Error::last_os_error())); + } + + filename.truncate(n); + + Ok(OsString::from_wide(&filename).into()) } pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> { let target = crate::config::host_triple(); let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = smallvec![get_or_default_sysroot().expect("Failed finding sysroot")]; - let path = current_dll_path().and_then(|s| s.canonicalize().map_err(|e| e.to_string())); + let path = current_dll_path().and_then(|s| try_canonicalize(s).map_err(|e| e.to_string())); if let Ok(dll) = path { // use `parent` twice to chop off the file name and then also the // directory containing the dll which should be either `lib` or `bin`. @@ -157,7 +205,7 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> { pub fn get_or_default_sysroot() -> Result<PathBuf, String> { // Follow symlinks. If the resolved path is relative, make it absolute. fn canonicalize(path: PathBuf) -> PathBuf { - let path = fs::canonicalize(&path).unwrap_or(path); + let path = try_canonicalize(&path).unwrap_or(path); // See comments on this target function, but the gist is that // gcc chokes on verbatim paths which fs::canonicalize generates // so we try to avoid those kinds of paths. @@ -179,28 +227,29 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> { ))?; // if `dir` points target's dir, move up to the sysroot - if dir.ends_with(crate::config::host_triple()) { + let mut sysroot_dir = if dir.ends_with(crate::config::host_triple()) { dir.parent() // chop off `$target` .and_then(|p| p.parent()) // chop off `rustlib` - .and_then(|p| { - // chop off `lib` (this could be also $arch dir if the host sysroot uses a - // multi-arch layout like Debian or Ubuntu) - match p.parent() { - Some(p) => match p.file_name() { - Some(f) if f == "lib" => p.parent(), // first chop went for $arch, so chop again for `lib` - _ => Some(p), - }, - None => None, - } - }) + .and_then(|p| p.parent()) // chop off `lib` .map(|s| s.to_owned()) - .ok_or(format!( - "Could not move 3 levels upper using `parent()` on {}", - dir.display() - )) + .ok_or_else(|| { + format!("Could not move 3 levels upper using `parent()` on {}", dir.display()) + })? } else { - Ok(dir.to_owned()) + dir.to_owned() + }; + + // On multiarch linux systems, there will be multiarch directory named + // with the architecture(e.g `x86_64-linux-gnu`) under the `lib` directory. + // Which cause us to mistakenly end up in the lib directory instead of the sysroot directory. + if sysroot_dir.ends_with("lib") { + sysroot_dir = + sysroot_dir.parent().map(|real_sysroot| real_sysroot.to_owned()).ok_or_else( + || format!("Could not move to parent path of {}", sysroot_dir.display()), + )? } + + Ok(sysroot_dir) } // Use env::args().next() to get the path of the executable without diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index e1f1a5f6d..968728905 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -2,7 +2,7 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(never_type)] -#![feature(once_cell)] +#![feature(lazy_cell)] #![feature(option_get_or_insert_default)] #![feature(rustc_attrs)] #![feature(map_many_mut)] @@ -42,7 +42,7 @@ pub mod output; pub use getopts; -fluent_messages! { "../locales/en-US.ftl" } +fluent_messages! { "../messages.ftl" } /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b466a3fcd..631dd0a21 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -4,6 +4,7 @@ use crate::early_error; use crate::lint; use crate::search_paths::SearchPath; use crate::utils::NativeLib; +use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{LanguageIdentifier, TerminalUrl}; use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet}; use rustc_target::spec::{ @@ -365,6 +366,7 @@ mod desc { pub const parse_number: &str = "a number"; pub const parse_opt_number: &str = parse_number; pub const parse_threads: &str = parse_number; + pub const parse_time_passes_format: &str = "`text` (default) or `json`"; pub const parse_passes: &str = "a space-separated list of passes, or `all`"; pub const parse_panic_strategy: &str = "either `unwind` or `abort`"; pub const parse_opt_panic_strategy: &str = parse_panic_strategy; @@ -375,6 +377,7 @@ mod desc { pub const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; + pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -765,6 +768,18 @@ mod parse { true } + pub(crate) fn parse_debuginfo(slot: &mut DebugInfo, v: Option<&str>) -> bool { + match v { + Some("0") | Some("none") => *slot = DebugInfo::None, + Some("line-directives-only") => *slot = DebugInfo::LineDirectivesOnly, + Some("line-tables-only") => *slot = DebugInfo::LineTablesOnly, + Some("1") | Some("limited") => *slot = DebugInfo::Limited, + Some("2") | Some("full") => *slot = DebugInfo::Full, + _ => return false, + } + true + } + pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavorCli>, v: Option<&str>) -> bool { match v.and_then(LinkerFlavorCli::from_str) { Some(lf) => *slot = Some(lf), @@ -829,6 +844,21 @@ mod parse { true } + pub(crate) fn parse_time_passes_format(slot: &mut TimePassesFormat, v: Option<&str>) -> bool { + match v { + None => true, + Some("json") => { + *slot = TimePassesFormat::Json; + true + } + Some("text") => { + *slot = TimePassesFormat::Text; + true + } + Some(_) => false, + } + } + pub(crate) fn parse_dump_mono_stats(slot: &mut DumpMonoStatsFormat, v: Option<&str>) -> bool { match v { None => true, @@ -894,7 +924,7 @@ mod parse { let mut seen_instruction_threshold = false; let mut seen_skip_entry = false; let mut seen_skip_exit = false; - for option in v.into_iter().map(|v| v.split(',')).flatten() { + for option in v.into_iter().flat_map(|v| v.split(',')) { match option { "always" if !seen_always && !seen_never => { options.always = true; @@ -1200,9 +1230,9 @@ options! { "use Windows Control Flow Guard (default: no)"), debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED], "explicitly enable the `cfg(debug_assertions)` directive"), - debuginfo: usize = (0, parse_number, [TRACKED], - "debug info emission level (0 = no debug info, 1 = line tables only, \ - 2 = full debug info with variable and type information; default: 0)"), + debuginfo: DebugInfo = (DebugInfo::None, parse_debuginfo, [TRACKED], + "debug info emission level (0-2, none, line-directives-only, \ + line-tables-only, limited, or full; default: 0)"), default_linker_libraries: bool = (false, parse_bool, [UNTRACKED], "allow the linker to link its default libraries (default: no)"), embed_bitcode: bool = (true, parse_bool, [TRACKED], @@ -1422,6 +1452,9 @@ options! { fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED], "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \ (default: no)"), + flatten_format_args: bool = (false, parse_bool, [TRACKED], + "flatten nested format_args!() and literals into a simplified format_args!() call \ + (default: no)"), force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED], "force all crates to be `rustc_private` unstable (default: no)"), fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED], @@ -1706,6 +1739,8 @@ options! { "measure time of each LLVM pass (default: no)"), time_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each rustc pass (default: no)"), + time_passes_format: TimePassesFormat = (TimePassesFormat::Text, parse_time_passes_format, [UNTRACKED], + "the format to use for -Z time-passes (`text` (default) or `json`)"), tiny_const_eval_limit: bool = (false, parse_bool, [TRACKED], "sets a tiny, non-configurable limit for const eval; useful for compiler tests"), #[rustc_lint_opt_deny_field_access("use `Session::tls_model` instead of this field")] diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index c3f0c4b58..fdb9fae44 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -5,7 +5,7 @@ use crate::errors::{ InvalidCharacterInCrateName, }; use crate::Session; -use rustc_ast as ast; +use rustc_ast::{self as ast, attr}; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; use std::path::{Path, PathBuf}; @@ -56,7 +56,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute]) -> Symbol { // the command line over one found in the #[crate_name] attribute. If we // find both we ensure that they're the same later on as well. let attr_crate_name = - sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s))); + attr::find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s))); if let Some(ref s) = sess.opts.crate_name { let s = Symbol::intern(s); diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 4e8c3f73e..15e27952c 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -8,7 +8,7 @@ use crate::lint::{ }; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_data_structures::sync::{Lock, Lrc}; +use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, @@ -84,12 +84,12 @@ impl SymbolGallery { /// Construct a diagnostic for a language feature error due to the given `span`. /// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`. -pub fn feature_err<'a>( - sess: &'a ParseSess, +pub fn feature_err( + sess: &ParseSess, feature: Symbol, span: impl Into<MultiSpan>, explain: impl Into<DiagnosticMessage>, -) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +) -> DiagnosticBuilder<'_, ErrorGuaranteed> { feature_err_issue(sess, feature, span, GateIssue::Language, explain) } @@ -98,20 +98,21 @@ pub fn feature_err<'a>( /// This variant allows you to control whether it is a library or language feature. /// Almost always, you want to use this for a language feature. If so, prefer `feature_err`. #[track_caller] -pub fn feature_err_issue<'a>( - sess: &'a ParseSess, +pub fn feature_err_issue( + sess: &ParseSess, feature: Symbol, span: impl Into<MultiSpan>, issue: GateIssue, explain: impl Into<DiagnosticMessage>, -) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let span = span.into(); // Cancel an earlier warning for this same error, if it exists. if let Some(span) = span.primary_span() { - sess.span_diagnostic - .steal_diagnostic(span, StashKey::EarlySyntaxWarning) - .map(|err| err.cancel()); + if let Some(err) = sess.span_diagnostic.steal_diagnostic(span, StashKey::EarlySyntaxWarning) + { + err.cancel() + } } let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() }); @@ -194,7 +195,7 @@ pub struct ParseSess { pub edition: Edition, /// Places where raw identifiers were used. This is used to avoid complaining about idents /// clashing with keywords in new editions. - pub raw_identifier_spans: Lock<Vec<Span>>, + pub raw_identifier_spans: AppendOnlyVec<Span>, /// Places where identifiers that contain invalid Unicode codepoints but that look like they /// should be. Useful to avoid bad tokenization when encountering emoji. We group them to /// provide a single error per unique incorrect identifier. @@ -208,7 +209,7 @@ pub struct ParseSess { pub gated_spans: GatedSpans, pub symbol_gallery: SymbolGallery, /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. - pub reached_eof: Lock<bool>, + pub reached_eof: AtomicBool, /// Environment variables accessed during the build and their values when they exist. pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>, /// File paths accessed during the build. @@ -219,7 +220,7 @@ pub struct ParseSess { pub assume_incomplete_release: bool, /// Spans passed to `proc_macro::quote_span`. Each span has a numerical /// identifier represented by its position in the vector. - pub proc_macro_quoted_spans: Lock<Vec<Span>>, + pub proc_macro_quoted_spans: AppendOnlyVec<Span>, /// Used to generate new `AttrId`s. Every `AttrId` is unique. pub attr_id_generator: AttrIdGenerator, } @@ -247,14 +248,14 @@ impl ParseSess { config: FxIndexSet::default(), check_config: CrateCheckConfig::default(), edition: ExpnId::root().expn_data().edition, - raw_identifier_spans: Lock::new(Vec::new()), + raw_identifier_spans: Default::default(), bad_unicode_identifiers: Lock::new(Default::default()), source_map, buffered_lints: Lock::new(vec![]), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), gated_spans: GatedSpans::default(), symbol_gallery: SymbolGallery::default(), - reached_eof: Lock::new(false), + reached_eof: AtomicBool::new(false), env_depinfo: Default::default(), file_depinfo: Default::default(), type_ascription_path_suggestions: Default::default(), @@ -324,13 +325,13 @@ impl ParseSess { } pub fn save_proc_macro_span(&self, span: Span) -> usize { - let mut spans = self.proc_macro_quoted_spans.lock(); - spans.push(span); - return spans.len() - 1; + self.proc_macro_quoted_spans.push(span) } - pub fn proc_macro_quoted_spans(&self) -> Vec<Span> { - self.proc_macro_quoted_spans.lock().clone() + pub fn proc_macro_quoted_spans(&self) -> impl Iterator<Item = (usize, Span)> + '_ { + // This is equivalent to `.iter().copied().enumerate()`, but that isn't possible for + // AppendOnlyVec, so we resort to this scheme. + self.proc_macro_quoted_spans.iter_enumerated() } #[track_caller] diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 12634f671..340bb158e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -11,7 +11,7 @@ use crate::{filesearch, lint}; pub use rustc_ast::attr::MarkedAttrs; pub use rustc_ast::Attribute; use rustc_data_structures::flock; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{ @@ -30,7 +30,7 @@ use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; use rustc_span::edition::Edition; use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap, Span}; -use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; +use rustc_span::{SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; use rustc_target::spec::{ @@ -207,10 +207,10 @@ pub struct Session { pub asm_arch: Option<InlineAsmArch>, /// Set of enabled features for the current target. - pub target_features: FxHashSet<Symbol>, + pub target_features: FxIndexSet<Symbol>, /// Set of enabled features for the current target, including unstable ones. - pub unstable_target_features: FxHashSet<Symbol>, + pub unstable_target_features: FxIndexSet<Symbol>, } pub struct PerfStats { @@ -224,6 +224,13 @@ pub struct PerfStats { pub normalize_projection_ty: AtomicUsize, } +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub enum MetadataKind { + None, + Uncompressed, + Compressed, +} + impl Session { pub fn miri_unleashed_feature(&self, span: Span, feature_gate: Option<Symbol>) { self.miri_unleashed_features.lock().push((span, feature_gate)); @@ -287,6 +294,43 @@ impl Session { self.crate_types.get().unwrap().as_slice() } + /// Returns true if the crate is a testing one. + pub fn is_test_crate(&self) -> bool { + self.opts.test + } + + pub fn needs_crate_hash(&self) -> bool { + // Why is the crate hash needed for these configurations? + // - debug_assertions: for the "fingerprint the result" check in + // `rustc_query_system::query::plumbing::execute_job`. + // - incremental: for query lookups. + // - needs_metadata: for putting into crate metadata. + // - instrument_coverage: for putting into coverage data (see + // `hash_mir_source`). + cfg!(debug_assertions) + || self.opts.incremental.is_some() + || self.needs_metadata() + || self.instrument_coverage() + } + + pub fn metadata_kind(&self) -> MetadataKind { + self.crate_types() + .iter() + .map(|ty| match *ty { + CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => { + MetadataKind::None + } + CrateType::Rlib => MetadataKind::Uncompressed, + CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed, + }) + .max() + .unwrap_or(MetadataKind::None) + } + + pub fn needs_metadata(&self) -> bool { + self.metadata_kind() != MetadataKind::None + } + pub fn init_crate_types(&self, crate_types: Vec<CrateType>) { self.crate_types.set(crate_types).expect("`crate_types` was initialized twice") } @@ -964,40 +1008,6 @@ impl Session { || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) } - pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool { - [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive] - .iter() - .any(|kind| attr.has_name(*kind)) - } - - pub fn contains_name(&self, attrs: &[Attribute], name: Symbol) -> bool { - attrs.iter().any(|item| item.has_name(name)) - } - - pub fn find_by_name<'a>( - &'a self, - attrs: &'a [Attribute], - name: Symbol, - ) -> Option<&'a Attribute> { - attrs.iter().find(|attr| attr.has_name(name)) - } - - pub fn filter_by_name<'a>( - &'a self, - attrs: &'a [Attribute], - name: Symbol, - ) -> impl Iterator<Item = &'a Attribute> { - attrs.iter().filter(move |attr| attr.has_name(name)) - } - - pub fn first_attr_value_str_by_name( - &self, - attrs: &[Attribute], - name: Symbol, - ) -> Option<Symbol> { - attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str()) - } - pub fn diagnostic_width(&self) -> usize { let default_column_width = 140; if let Some(width) = self.opts.diagnostic_width { @@ -1448,7 +1458,10 @@ pub fn build_session( CguReuseTracker::new_disabled() }; - let prof = SelfProfilerRef::new(self_profiler, sopts.unstable_opts.time_passes); + let prof = SelfProfilerRef::new( + self_profiler, + sopts.unstable_opts.time_passes.then(|| sopts.unstable_opts.time_passes_format), + ); let ctfe_backtrace = Lock::new(match env::var("RUSTC_CTFE_BACKTRACE") { Ok(ref val) if val == "immediate" => CtfeBacktrace::Immediate, @@ -1488,8 +1501,8 @@ pub fn build_session( ctfe_backtrace, miri_unleashed_features: Lock::new(Default::default()), asm_arch, - target_features: FxHashSet::default(), - unstable_target_features: FxHashSet::default(), + target_features: Default::default(), + unstable_target_features: Default::default(), }; validate_commandline_args_with_session_available(&sess); diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index b996d36a3..1d15e2c28 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -1,5 +1,6 @@ use crate::session::Session; use rustc_data_structures::profiling::VerboseTimingGuard; +use rustc_fs_util::try_canonicalize; use std::path::{Path, PathBuf}; impl Session { @@ -37,6 +38,10 @@ pub enum NativeLibKind { /// Argument which is passed to linker, relative order with libraries and other arguments /// is preserved LinkArg, + + /// Module imported from WebAssembly + WasmImportModule, + /// The library kind wasn't specified, `Dylib` is currently used as a default. Unspecified, } @@ -50,7 +55,10 @@ impl NativeLibKind { NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => { as_needed.is_some() } - NativeLibKind::RawDylib | NativeLibKind::Unspecified | NativeLibKind::LinkArg => false, + NativeLibKind::RawDylib + | NativeLibKind::Unspecified + | NativeLibKind::LinkArg + | NativeLibKind::WasmImportModule => false, } } @@ -91,7 +99,7 @@ pub struct CanonicalizedPath { impl CanonicalizedPath { pub fn new(path: &Path) -> Self { - Self { original: path.to_owned(), canonicalized: std::fs::canonicalize(path).ok() } + Self { original: path.to_owned(), canonicalized: try_canonicalize(path).ok() } } pub fn canonicalized(&self) -> &PathBuf { |