about summary refs log tree commit diff
path: root/compiler/rustc_session/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_session/src')
-rw-r--r--compiler/rustc_session/src/config.rs136
-rw-r--r--compiler/rustc_session/src/filesearch.rs170
-rw-r--r--compiler/rustc_session/src/options.rs14
-rw-r--r--compiler/rustc_session/src/output.rs2
-rw-r--r--compiler/rustc_session/src/session.rs11
5 files changed, 178 insertions, 155 deletions
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 7af221c9607..ed336cc5596 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -44,7 +44,7 @@ pub mod sigpipe;
 
 pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
     // tidy-alphabetical-start
-    ("all-target-specs-json", PrintKind::AllTargetSpecs),
+    ("all-target-specs-json", PrintKind::AllTargetSpecsJson),
     ("calling-conventions", PrintKind::CallingConventions),
     ("cfg", PrintKind::Cfg),
     ("check-cfg", PrintKind::CheckCfg),
@@ -58,12 +58,13 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
     ("relocation-models", PrintKind::RelocationModels),
     ("split-debuginfo", PrintKind::SplitDebuginfo),
     ("stack-protector-strategies", PrintKind::StackProtectorStrategies),
+    ("supported-crate-types", PrintKind::SupportedCrateTypes),
     ("sysroot", PrintKind::Sysroot),
     ("target-cpus", PrintKind::TargetCPUs),
     ("target-features", PrintKind::TargetFeatures),
     ("target-libdir", PrintKind::TargetLibdir),
     ("target-list", PrintKind::TargetList),
-    ("target-spec-json", PrintKind::TargetSpec),
+    ("target-spec-json", PrintKind::TargetSpecJson),
     ("tls-models", PrintKind::TlsModels),
     // tidy-alphabetical-end
 ];
@@ -873,27 +874,30 @@ pub struct PrintRequest {
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PrintKind {
+    // tidy-alphabetical-start
+    AllTargetSpecsJson,
+    CallingConventions,
+    Cfg,
+    CheckCfg,
+    CodeModels,
+    CrateName,
+    DeploymentTarget,
     FileNames,
     HostTuple,
+    LinkArgs,
+    NativeStaticLibs,
+    RelocationModels,
+    SplitDebuginfo,
+    StackProtectorStrategies,
+    SupportedCrateTypes,
     Sysroot,
-    TargetLibdir,
-    CrateName,
-    Cfg,
-    CheckCfg,
-    CallingConventions,
-    TargetList,
     TargetCPUs,
     TargetFeatures,
-    RelocationModels,
-    CodeModels,
+    TargetLibdir,
+    TargetList,
+    TargetSpecJson,
     TlsModels,
-    TargetSpec,
-    AllTargetSpecs,
-    NativeStaticLibs,
-    StackProtectorStrategies,
-    LinkArgs,
-    SplitDebuginfo,
-    DeploymentTarget,
+    // tidy-alphabetical-end
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)]
@@ -1214,7 +1218,7 @@ impl Default for Options {
             describe_lints: false,
             output_types: OutputTypes(BTreeMap::new()),
             search_paths: vec![],
-            maybe_sysroot: None,
+            sysroot: filesearch::materialize_sysroot(None),
             target_triple: TargetTuple::from_tuple(host_tuple()),
             test: false,
             incremental: None,
@@ -2030,49 +2034,13 @@ fn collect_print_requests(
     prints.extend(matches.opt_strs("print").into_iter().map(|req| {
         let (req, out) = split_out_file_name(&req);
 
-        let kind = match PRINT_KINDS.iter().find(|&&(name, _)| name == req) {
-            Some((_, PrintKind::TargetSpec)) => {
-                if unstable_opts.unstable_options {
-                    PrintKind::TargetSpec
-                } else {
-                    early_dcx.early_fatal(
-                        "the `-Z unstable-options` flag must also be passed to \
-                         enable the target-spec-json print option",
-                    );
-                }
-            }
-            Some((_, PrintKind::AllTargetSpecs)) => {
-                if unstable_opts.unstable_options {
-                    PrintKind::AllTargetSpecs
-                } else {
-                    early_dcx.early_fatal(
-                        "the `-Z unstable-options` flag must also be passed to \
-                         enable the all-target-specs-json print option",
-                    );
-                }
-            }
-            Some((_, PrintKind::CheckCfg)) => {
-                if unstable_opts.unstable_options {
-                    PrintKind::CheckCfg
-                } else {
-                    early_dcx.early_fatal(
-                        "the `-Z unstable-options` flag must also be passed to \
-                         enable the check-cfg print option",
-                    );
-                }
-            }
-            Some(&(_, print_kind)) => print_kind,
-            None => {
-                let prints =
-                    PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
-                let prints = prints.join(", ");
-
-                let mut diag =
-                    early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
-                #[allow(rustc::diagnostic_outside_of_impl)]
-                diag.help(format!("valid print requests are: {prints}"));
-                diag.emit()
-            }
+        let kind = if let Some((print_name, print_kind)) =
+            PRINT_KINDS.iter().find(|&&(name, _)| name == req)
+        {
+            check_print_request_stability(early_dcx, unstable_opts, (print_name, *print_kind));
+            *print_kind
+        } else {
+            emit_unknown_print_request_help(early_dcx, req)
         };
 
         let out = out.unwrap_or(OutFileName::Stdout);
@@ -2091,6 +2059,43 @@ fn collect_print_requests(
     prints
 }
 
+fn check_print_request_stability(
+    early_dcx: &EarlyDiagCtxt,
+    unstable_opts: &UnstableOptions,
+    (print_name, print_kind): (&str, PrintKind),
+) {
+    match print_kind {
+        PrintKind::AllTargetSpecsJson
+        | PrintKind::CheckCfg
+        | PrintKind::SupportedCrateTypes
+        | PrintKind::TargetSpecJson
+            if !unstable_opts.unstable_options =>
+        {
+            early_dcx.early_fatal(format!(
+                "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \
+                print option"
+            ));
+        }
+        _ => {}
+    }
+}
+
+fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str) -> ! {
+    let prints = PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>();
+    let prints = prints.join(", ");
+
+    let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
+    #[allow(rustc::diagnostic_outside_of_impl)]
+    diag.help(format!("valid print requests are: {prints}"));
+
+    if req == "lints" {
+        diag.help(format!("use `-Whelp` to print a list of lints"));
+    }
+
+    diag.help(format!("for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information"));
+    diag.emit()
+}
+
 pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> TargetTuple {
     match matches.opt_str("target") {
         Some(target) if target.ends_with(".json") => {
@@ -2618,7 +2623,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
         describe_lints,
         output_types,
         search_paths,
-        maybe_sysroot: Some(sysroot),
+        sysroot,
         target_triple,
         test,
         incremental,
@@ -2709,7 +2714,12 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
                 "cdylib" => CrateType::Cdylib,
                 "bin" => CrateType::Executable,
                 "proc-macro" => CrateType::ProcMacro,
-                _ => return Err(format!("unknown crate type: `{part}`")),
+                _ => {
+                    return Err(format!(
+                        "unknown crate type: `{part}`, expected one of: \
+                        `lib`, `rlib`, `staticlib`, `dylib`, `cdylib`, `bin`, `proc-macro`",
+                    ));
+                }
             };
             if !crate_types.contains(&new_part) {
                 crate_types.push(new_part)
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index cc2decc2fe4..bdeca91eb64 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -60,66 +60,76 @@ pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf {
 
 #[cfg(unix)]
 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();
-        if libc::dladdr(addr, &mut info) == 0 {
-            return Err("dladdr failed".into());
-        }
-        if info.dli_fname.is_null() {
-            return Err("dladdr returned null pointer".into());
-        }
-        let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
-        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 u8,
-                (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());
+    use std::sync::OnceLock;
+
+    // This is somewhat expensive relative to other work when compiling `fn main() {}` as `dladdr`
+    // needs to iterate over the symbol table of librustc_driver.so until it finds a match.
+    // As such cache this to avoid recomputing if we try to get the sysroot in multiple places.
+    static CURRENT_DLL_PATH: OnceLock<Result<PathBuf, String>> = OnceLock::new();
+    CURRENT_DLL_PATH
+        .get_or_init(|| {
+            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();
+                if libc::dladdr(addr, &mut info) == 0 {
+                    return Err("dladdr 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();
+                if info.dli_fname.is_null() {
+                    return Err("dladdr returned null pointer".into());
+                }
+                let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
                 let os = OsStr::from_bytes(bytes);
-                return Ok(PathBuf::from(os));
+                Ok(PathBuf::from(os))
             }
-            if (*current).ldinfo_next == 0 {
-                break;
+
+            #[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 u8,
+                        (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));
             }
-            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));
-    }
+        })
+        .clone()
 }
 
 #[cfg(windows)]
@@ -160,8 +170,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
 
 pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
     let target = crate::config::host_tuple();
-    let mut sysroot_candidates: SmallVec<[PathBuf; 2]> =
-        smallvec![get_or_default_sysroot().expect("Failed finding sysroot")];
+    let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = smallvec![get_or_default_sysroot()];
     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
@@ -195,12 +204,12 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
 /// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none.
 /// Panics if [`get_or_default_sysroot`]  returns an error.
 pub fn materialize_sysroot(maybe_sysroot: Option<PathBuf>) -> PathBuf {
-    maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot().expect("Failed finding sysroot"))
+    maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot())
 }
 
 /// This function checks if sysroot is found using env::args().next(), and if it
 /// is not found, finds sysroot from current rustc_driver dll.
-pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
+pub fn get_or_default_sysroot() -> PathBuf {
     // Follow symlinks. If the resolved path is relative, make it absolute.
     fn canonicalize(path: PathBuf) -> PathBuf {
         let path = try_canonicalize(&path).unwrap_or(path);
@@ -255,30 +264,25 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
     // binary able to locate Rust libraries in systems using content-addressable
     // storage (CAS).
     fn from_env_args_next() -> Option<PathBuf> {
-        match env::args_os().next() {
-            Some(first_arg) => {
-                let mut p = PathBuf::from(first_arg);
-
-                // Check if sysroot is found using env::args().next() only if the rustc in argv[0]
-                // is a symlink (see #79253). We might want to change/remove it to conform with
-                // https://www.gnu.org/prep/standards/standards.html#Finding-Program-Files in the
-                // future.
-                if fs::read_link(&p).is_err() {
-                    // Path is not a symbolic link or does not exist.
-                    return None;
-                }
-
-                // Pop off `bin/rustc`, obtaining the suspected sysroot.
-                p.pop();
-                p.pop();
-                // Look for the target rustlib directory in the suspected sysroot.
-                let mut rustlib_path = rustc_target::relative_target_rustlib_path(&p, "dummy");
-                rustlib_path.pop(); // pop off the dummy target.
-                rustlib_path.exists().then_some(p)
-            }
-            None => None,
+        let mut p = PathBuf::from(env::args_os().next()?);
+
+        // Check if sysroot is found using env::args().next() only if the rustc in argv[0]
+        // is a symlink (see #79253). We might want to change/remove it to conform with
+        // https://www.gnu.org/prep/standards/standards.html#Finding-Program-Files in the
+        // future.
+        if fs::read_link(&p).is_err() {
+            // Path is not a symbolic link or does not exist.
+            return None;
         }
+
+        // Pop off `bin/rustc`, obtaining the suspected sysroot.
+        p.pop();
+        p.pop();
+        // Look for the target rustlib directory in the suspected sysroot.
+        let mut rustlib_path = rustc_target::relative_target_rustlib_path(&p, "dummy");
+        rustlib_path.pop(); // pop off the dummy target.
+        rustlib_path.exists().then_some(p)
     }
 
-    Ok(from_env_args_next().unwrap_or(default_from_rustc_driver_dll()?))
+    from_env_args_next().unwrap_or(default_from_rustc_driver_dll().expect("Failed finding sysroot"))
 }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 599b4fa9109..4cc666b3e37 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -337,7 +337,7 @@ top_level_options!(
         output_types: OutputTypes [TRACKED],
         search_paths: Vec<SearchPath> [UNTRACKED],
         libs: Vec<NativeLib> [TRACKED],
-        maybe_sysroot: Option<PathBuf> [UNTRACKED],
+        sysroot: PathBuf [UNTRACKED],
 
         target_triple: TargetTuple [TRACKED],
 
@@ -393,7 +393,7 @@ top_level_options!(
         ///
         /// This directory is what the virtual `/rustc/$hash` is translated back to,
         /// if Rust was built with path remapping to `/rustc/$hash` enabled
-        /// (the `rust.remap-debuginfo` option in `config.toml`).
+        /// (the `rust.remap-debuginfo` option in `bootstrap.toml`).
         real_rust_source_base_dir: Option<PathBuf> [TRACKED_NO_CRATE_HASH],
 
         edition: Edition [TRACKED],
@@ -1890,7 +1890,8 @@ pub mod parse {
     pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool {
         match v {
             Some("spec") => *slot = WasmCAbi::Spec,
-            Some("legacy") => *slot = WasmCAbi::Legacy,
+            // Explicitly setting the `-Z` flag suppresses the lint.
+            Some("legacy") => *slot = WasmCAbi::Legacy { with_lint: false },
             _ => return false,
         }
         true
@@ -2231,7 +2232,8 @@ options! {
     incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
         "verify extended properties for incr. comp. (default: no):
         - hashes of green query instances
-        - hash collisions of query keys"),
+        - hash collisions of query keys
+        - hash collisions when creating dep-nodes"),
     inline_llvm: bool = (true, parse_bool, [TRACKED],
         "enable LLVM inlining (default: yes)"),
     inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -2529,7 +2531,7 @@ written to standard error output)"),
         "for every macro invocation, print its name and arguments (default: no)"),
     track_diagnostics: bool = (false, parse_bool, [UNTRACKED],
         "tracks where in rustc a diagnostic was emitted"),
-    // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
+    // Diagnostics are considered side-effects of a query (see `QuerySideEffect`) and are saved
     // alongside query results and changes to translation options can affect diagnostics - so
     // translation options should be tracked.
     translate_additional_ftl: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
@@ -2603,7 +2605,7 @@ written to standard error output)"),
         Requires `-Clto[=[fat,yes]]`"),
     wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
         "whether to build a wasi command or reactor"),
-    wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy, parse_wasm_c_abi, [TRACKED],
+    wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy { with_lint: true }, parse_wasm_c_abi, [TRACKED],
         "use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"),
     write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED],
         "whether long type names should be written to files instead of being printed in errors"),
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index b37a80274c0..a24919e434c 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -103,7 +103,7 @@ pub fn filename_for_input(
             OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")))
         }
         CrateType::Staticlib => {
-            let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix);
+            let (prefix, suffix) = sess.staticlib_components(false);
             OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}")))
         }
         CrateType::Executable => {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index bcd9a73d9d3..a87b1961a99 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -143,7 +143,6 @@ pub struct Session {
     pub target: Target,
     pub host: Target,
     pub opts: config::Options,
-    pub host_tlib_path: Arc<SearchPath>,
     pub target_tlib_path: Arc<SearchPath>,
     pub psess: ParseSess,
     pub sysroot: PathBuf,
@@ -587,6 +586,14 @@ impl Session {
             .or(self.target.options.default_visibility)
             .unwrap_or(SymbolVisibility::Interposable)
     }
+
+    pub fn staticlib_components(&self, verbatim: bool) -> (&str, &str) {
+        if verbatim {
+            ("", "")
+        } else {
+            (&*self.target.staticlib_prefix, &*self.target.staticlib_suffix)
+        }
+    }
 }
 
 // JUSTIFICATION: defn of the suggested wrapper fns
@@ -1042,6 +1049,7 @@ pub fn build_session(
 
     let host_triple = config::host_tuple();
     let target_triple = sopts.target_triple.tuple();
+    // FIXME use host sysroot?
     let host_tlib_path = Arc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple));
     let target_tlib_path = if host_triple == target_triple {
         // Use the same `SearchPath` if host and target triple are identical to avoid unnecessary
@@ -1070,7 +1078,6 @@ pub fn build_session(
         target,
         host,
         opts: sopts,
-        host_tlib_path,
         target_tlib_path,
         psess,
         sysroot,