about summary refs log tree commit diff
path: root/compiler/rustc_interface/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_interface/src')
-rw-r--r--compiler/rustc_interface/src/passes.rs7
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_interface/src/util.rs140
3 files changed, 141 insertions, 7 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index bbb47a6e807..9dbd59506b1 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -63,6 +63,13 @@ impl mut_visit::MutVisitor for TokenStripper {
         i.tokens = None;
         mut_visit::noop_flat_map_item(i, self)
     }
+    fn flat_map_foreign_item(
+        &mut self,
+        mut i: P<ast::ForeignItem>,
+    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
+        i.tokens = None;
+        mut_visit::noop_flat_map_foreign_item(i, self)
+    }
     fn visit_block(&mut self, b: &mut P<ast::Block>) {
         b.tokens = None;
         mut_visit::noop_visit_block(b, self);
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 6553d0ecfdb..235e049c3f5 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -550,6 +550,7 @@ fn test_debugging_options_tracking_hash() {
     tracked!(force_overflow_checks, Some(true));
     tracked!(force_unstable_if_unmarked, true);
     tracked!(fuel, Some(("abc".to_string(), 99)));
+    tracked!(function_sections, Some(false));
     tracked!(human_readable_cgu_names, true);
     tracked!(inline_in_all_cgus, Some(true));
     tracked!(insert_sideeffect, true);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index c1b359c7d0d..46a6c5861d5 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -24,11 +24,13 @@ use rustc_span::source_map::FileLoader;
 use rustc_span::symbol::{sym, Symbol};
 use smallvec::SmallVec;
 use std::env;
+use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::io::{self, Write};
 use std::lazy::SyncOnceCell;
 use std::mem;
 use std::ops::DerefMut;
 use std::path::{Path, PathBuf};
+use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::{Arc, Mutex, Once};
 #[cfg(not(parallel_compiler))]
 use std::{panic, thread};
@@ -113,6 +115,11 @@ impl Write for Sink {
         Ok(())
     }
 }
+impl io::LocalOutput for Sink {
+    fn clone_box(&self) -> Box<dyn io::LocalOutput> {
+        Box::new(Self(self.0.clone()))
+    }
+}
 
 /// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need
 /// for `'static` bounds.
@@ -238,7 +245,19 @@ pub fn get_codegen_backend(sopts: &config::Options) -> Box<dyn CodegenBackend> {
     static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
 
     INIT.call_once(|| {
-        let codegen_name = sopts.debugging_opts.codegen_backend.as_deref().unwrap_or("llvm");
+        #[cfg(feature = "llvm")]
+        const DEFAULT_CODEGEN_BACKEND: &'static str = "llvm";
+
+        #[cfg(not(feature = "llvm"))]
+        const DEFAULT_CODEGEN_BACKEND: &'static str = "cranelift";
+
+        let codegen_name = sopts
+            .debugging_opts
+            .codegen_backend
+            .as_ref()
+            .map(|name| &name[..])
+            .unwrap_or(DEFAULT_CODEGEN_BACKEND);
+
         let backend = match codegen_name {
             filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()),
             codegen_name => get_builtin_codegen_backend(codegen_name),
@@ -367,15 +386,102 @@ fn sysroot_candidates() -> Vec<PathBuf> {
 }
 
 pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
-    #[cfg(feature = "llvm")]
-    {
-        if backend_name == "llvm" {
-            return rustc_codegen_llvm::LlvmCodegenBackend::new;
+    match backend_name {
+        #[cfg(feature = "llvm")]
+        "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
+        _ => get_codegen_sysroot(backend_name),
+    }
+}
+
+pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
+    // For now we only allow this function to be called once as it'll dlopen a
+    // few things, which seems to work best if we only do that once. In
+    // general this assertion never trips due to the once guard in `get_codegen_backend`,
+    // but there's a few manual calls to this function in this file we protect
+    // against.
+    static LOADED: AtomicBool = AtomicBool::new(false);
+    assert!(
+        !LOADED.fetch_or(true, Ordering::SeqCst),
+        "cannot load the default codegen backend twice"
+    );
+
+    let target = session::config::host_triple();
+    let sysroot_candidates = sysroot_candidates();
+
+    let sysroot = sysroot_candidates
+        .iter()
+        .map(|sysroot| {
+            let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
+            sysroot.join(libdir).with_file_name("codegen-backends")
+        })
+        .filter(|f| {
+            info!("codegen backend candidate: {}", f.display());
+            f.exists()
+        })
+        .next();
+    let sysroot = sysroot.unwrap_or_else(|| {
+        let candidates = sysroot_candidates
+            .iter()
+            .map(|p| p.display().to_string())
+            .collect::<Vec<_>>()
+            .join("\n* ");
+        let err = format!(
+            "failed to find a `codegen-backends` folder \
+                           in the sysroot candidates:\n* {}",
+            candidates
+        );
+        early_error(ErrorOutputType::default(), &err);
+    });
+    info!("probing {} for a codegen backend", sysroot.display());
+
+    let d = sysroot.read_dir().unwrap_or_else(|e| {
+        let err = format!(
+            "failed to load default codegen backend, couldn't \
+                           read `{}`: {}",
+            sysroot.display(),
+            e
+        );
+        early_error(ErrorOutputType::default(), &err);
+    });
+
+    let mut file: Option<PathBuf> = None;
+
+    let expected_name =
+        format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE"));
+    for entry in d.filter_map(|e| e.ok()) {
+        let path = entry.path();
+        let filename = match path.file_name().and_then(|s| s.to_str()) {
+            Some(s) => s,
+            None => continue,
+        };
+        if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) {
+            continue;
+        }
+        let name = &filename[DLL_PREFIX.len()..filename.len() - DLL_SUFFIX.len()];
+        if name != expected_name {
+            continue;
         }
+        if let Some(ref prev) = file {
+            let err = format!(
+                "duplicate codegen backends found\n\
+                               first:  {}\n\
+                               second: {}\n\
+            ",
+                prev.display(),
+                path.display()
+            );
+            early_error(ErrorOutputType::default(), &err);
+        }
+        file = Some(path.clone());
     }
 
-    let err = format!("unsupported builtin codegen backend `{}`", backend_name);
-    early_error(ErrorOutputType::default(), &err);
+    match file {
+        Some(ref s) => load_backend_from_dylib(s),
+        None => {
+            let err = format!("unsupported builtin codegen backend `{}`", backend_name);
+            early_error(ErrorOutputType::default(), &err);
+        }
+    }
 }
 
 pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
@@ -782,3 +888,23 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
         noop_visit_mac(mac, self)
     }
 }
+
+/// Returns a version string such as "rustc 1.46.0 (04488afe3 2020-08-24)"
+pub fn version_str() -> Option<&'static str> {
+    option_env!("CFG_VERSION")
+}
+
+/// Returns a version string such as "0.12.0-dev".
+pub fn release_str() -> Option<&'static str> {
+    option_env!("CFG_RELEASE")
+}
+
+/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
+pub fn commit_hash_str() -> Option<&'static str> {
+    option_env!("CFG_VER_HASH")
+}
+
+/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
+pub fn commit_date_str() -> Option<&'static str> {
+    option_env!("CFG_VER_DATE")
+}