summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_session
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_session')
-rw-r--r--compiler/rustc_session/Cargo.toml8
-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.rs12
-rw-r--r--compiler/rustc_session/src/config.rs61
-rw-r--r--compiler/rustc_session/src/cstore.rs11
-rw-r--r--compiler/rustc_session/src/filesearch.rs131
-rw-r--r--compiler/rustc_session/src/lib.rs4
-rw-r--r--compiler/rustc_session/src/options.rs43
-rw-r--r--compiler/rustc_session/src/output.rs4
-rw-r--r--compiler/rustc_session/src/parse.rs41
-rw-r--r--compiler/rustc_session/src/session.rs95
-rw-r--r--compiler/rustc_session/src/utils.rs12
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 {