From 7ebbd82f2b398843de2b44476eaa5dfe8246502a Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 28 Jul 2020 13:43:33 -0700
Subject: [PATCH] test

---
 Cargo.lock                              |  11 +-
 Cargo.toml                              |   1 +
 foo.sh                                  |  52 ++++++++++
 library/std/src/path.rs                 |   2 +-
 src/bootstrap/builder.rs                |   2 +-
 src/bootstrap/configure.py              |   2 +
 src/bootstrap/util.rs                   |   8 +-
 src/librustc_codegen_ssa/Cargo.toml     |   1 +
 src/librustc_codegen_ssa/back/link.rs   |  38 ++++---
 src/librustc_data_structures/Cargo.toml |   2 +
 src/librustc_data_structures/stack.rs   |   8 +-
 src/librustc_driver/Cargo.toml          |   2 +-
 src/librustc_driver/lib.rs              |   7 +-
 src/librustc_errors/lib.rs              |   6 +-
 src/librustc_interface/Cargo.toml       |   3 +
 src/librustc_interface/passes.rs        |   5 +-
 src/librustc_interface/util.rs          | 130 ++++++++++++++++++++----
 src/librustc_metadata/dynamic_lib.rs    |  22 ++++
 src/librustc_metadata/locator.rs        |  55 +++++-----
 src/librustc_session/session.rs         |   3 +-
 src/librustc_span/fatal_error.rs        |   6 +-
 21 files changed, 293 insertions(+), 73 deletions(-)
 create mode 100644 foo.sh

diff --git a/Cargo.lock b/Cargo.lock
index d0ce581343f0b..555a811d3e116 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -69,6 +69,12 @@ version = "1.0.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
 
+[[package]]
+name = "ar"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1"
+
 [[package]]
 name = "arc-swap"
 version = "0.3.7"
@@ -1792,8 +1798,6 @@ checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
 [[package]]
 name = "memmap"
 version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
 dependencies = [
  "libc",
  "winapi 0.3.8",
@@ -3327,6 +3331,7 @@ version = "0.0.0"
 dependencies = [
  "bitflags",
  "cc",
+ "cfg-if",
  "jobserver",
  "libc",
  "log",
@@ -3544,6 +3549,8 @@ dependencies = [
 name = "rustc_interface"
 version = "0.0.0"
 dependencies = [
+ "ar",
+ "cfg-if",
  "libc",
  "log",
  "once_cell",
diff --git a/Cargo.toml b/Cargo.toml
index 4e49d697be1fb..e97b7c37818e7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -79,6 +79,7 @@ rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' }
 rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' }
 rustc-std-workspace-alloc = { path = 'library/rustc-std-workspace-alloc' }
 rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' }
+memmap = { path = "../memmap-rs" }
 
 [patch."https://github.com/rust-lang/rust-clippy"]
 clippy_lints = { path = "src/tools/clippy/clippy_lints" }
diff --git a/foo.sh b/foo.sh
new file mode 100644
index 0000000000000..ec53f13987d92
--- /dev/null
+++ b/foo.sh
@@ -0,0 +1,52 @@
+set -ex
+
+# ./configure \
+#   --set rust.deny-warnings=false \
+#   --set target.wasm32-wasi.wasi-root=/home/alex/code/wasi-libc/sysroot \
+#   --set rust.lld \
+#   --enable-ccache
+
+# ./x.py build --target wasm32-wasi --stage 1 library/std
+
+# rm -rf rust-sysroot
+# mkdir rust-sysroot
+# cp -r build/x86_64-unknown-linux-gnu/stage1/lib rust-sysroot/lib
+
+# ./configure \
+#   --set rust.deny-warnings=false \
+#   --set target.wasm32-wasi.wasi-root=/home/alex/code/wasi-libc/sysroot \
+#   --set rust.codegen-backends=[]
+
+# RUSTFLAGS='-Ctarget-feature=+bulk-memory,+simd128' \
+# PATH=`pwd`/rust-sysroot/lib/rustlib/x86_64-unknown-linux-gnu/bin:$PATH \
+#   ./x.py build --host wasm32-wasi --stage 1 src/rustc
+
+wasmtime="../wasmtime/target/release/wasmtime \
+    run \
+    --enable-simd \
+    --jitdump \
+    --enable-bulk-memory \
+    --mapdir /::. \
+    --mapdir /sysroot::./rust-sysroot \
+    --"
+
+rustc="$wasmtime \
+  build/wasm32-wasi/stage1/bin/rustc.wasm \
+    --sysroot /sysroot \
+    -Z codegen-backend=dummy"
+
+echo 'pub fn foo() {}' > foo.rs
+echo 'pub fn bar() { foo::foo(); }' > bar.rs
+
+$rustc \
+    /foo.rs \
+    --emit metadata \
+    -o /libfoo.rmeta \
+    --crate-type lib
+
+perf record -k 1 $rustc \
+    /bar.rs \
+    --emit metadata \
+    -o /libbar.rmeta \
+    --crate-type lib \
+    --extern foo=/libfoo.rmeta
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 392c815ef2803..b9e991d4cbcab 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1896,7 +1896,7 @@ impl Path {
             // FIXME: Allow Redox prefixes
             self.has_root() || has_redox_scheme(self.as_u8_slice())
         } else {
-            self.has_root() && (cfg!(unix) || self.prefix().is_some())
+            self.has_root() && (cfg!(not(windows)) || self.prefix().is_some())
         }
     }
 
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index c1e56347ab1e0..43ad25c7756ff 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -850,7 +850,7 @@ impl<'a> Builder<'a> {
             Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}
             Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
                 // Build proc macros both for the host and the target
-                if target != compiler.host && cmd != "check" {
+                if target != compiler.host && cmd != "check" && !target.contains("wasm32") {
                     cargo.arg("-Zdual-proc-macros");
                     rustflags.arg("-Zdual-proc-macros");
                 }
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 47673ce1e8703..7cdb221ceafd4 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -296,6 +296,8 @@ def set(key, value):
                 value = True
             elif keyval[1] == "false":
                 value = False
+            elif keyval[1] == "[]":
+                value = []
             else:
                 value = keyval[1]
             set(keyval[0], value)
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index a307ef39d03a8..e266b104f55c2 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -24,7 +24,13 @@ pub fn staticlib(name: &str, target: TargetSelection) -> String {
 /// Given an executable called `name`, return the filename for the
 /// executable for a particular target.
 pub fn exe(name: &str, target: TargetSelection) -> String {
-    if target.contains("windows") { format!("{}.exe", name) } else { name.to_string() }
+    if target.contains("windows") {
+        format!("{}.exe", name)
+    } else if target.contains("wasm32") {
+        format!("{}.wasm", name)
+    } else {
+        name.to_string()
+    }
 }
 
 /// Returns `true` if the file name given looks like a dynamic library.
diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml
index e100e0095c92a..e0dd6ecee68b8 100644
--- a/src/librustc_codegen_ssa/Cargo.toml
+++ b/src/librustc_codegen_ssa/Cargo.toml
@@ -12,6 +12,7 @@ test = false
 [dependencies]
 bitflags = "1.2.1"
 cc = "1.0.1"
+cfg-if = "0.1"
 num_cpus = "1.0"
 memmap = "0.7"
 log = "0.4.5"
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 9191c68d4537a..f1c791e879f72 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -648,7 +648,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
             status.signal() == Some(libc::SIGILL)
         }
 
-        #[cfg(windows)]
+        #[cfg(not(unix))]
         fn is_illegal_instruction(_status: &ExitStatus) -> bool {
             false
         }
@@ -1172,12 +1172,6 @@ fn exec_linker(
     flush_linked_file(&output, out_filename)?;
     return output;
 
-    #[cfg(unix)]
-    fn flush_linked_file(_: &io::Result<Output>, _: &Path) -> io::Result<()> {
-        Ok(())
-    }
-
-    #[cfg(windows)]
     fn flush_linked_file(
         command_output: &io::Result<Output>,
         out_filename: &Path,
@@ -1189,11 +1183,13 @@ fn exec_linker(
         //
         // А full writeup of the original Chrome bug can be found at
         // randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/amp
-
-        if let &Ok(ref out) = command_output {
-            if out.status.success() {
-                if let Ok(of) = fs::OpenOptions::new().write(true).open(out_filename) {
-                    of.sync_all()?;
+        #[cfg(windows)]
+        {
+            if let &Ok(ref out) = command_output {
+                if out.status.success() {
+                    if let Ok(of) = fs::OpenOptions::new().write(true).open(out_filename) {
+                        of.sync_all()?;
+                    }
                 }
             }
         }
@@ -1201,15 +1197,17 @@ fn exec_linker(
         Ok(())
     }
 
-    #[cfg(unix)]
-    fn command_line_too_big(err: &io::Error) -> bool {
-        err.raw_os_error() == Some(::libc::E2BIG)
-    }
-
-    #[cfg(windows)]
     fn command_line_too_big(err: &io::Error) -> bool {
-        const ERROR_FILENAME_EXCED_RANGE: i32 = 206;
-        err.raw_os_error() == Some(ERROR_FILENAME_EXCED_RANGE)
+        cfg_if::cfg_if! {
+            if #[cfg(unix)] {
+                err.raw_os_error() == Some(::libc::E2BIG)
+            } else if #[cfg(windows)] {
+                const ERROR_FILENAME_EXCED_RANGE: i32 = 206;
+                err.raw_os_error() == Some(ERROR_FILENAME_EXCED_RANGE)
+            } else {
+                false
+            }
+        }
     }
 
     struct Escape<'a> {
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 1c2fb90b2d8b4..7c6a6288d63b5 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -29,6 +29,8 @@ rustc_index = { path = "../librustc_index", package = "rustc_index" }
 bitflags = "1.2.1"
 measureme = "0.7.1"
 libc = "0.2"
+
+[target.'cfg(any(unix, windows))'.dependencies]
 stacker = "0.1.9"
 
 [dependencies.parking_lot]
diff --git a/src/librustc_data_structures/stack.rs b/src/librustc_data_structures/stack.rs
index a4964b7aa0cc8..0cb15ae81a7a4 100644
--- a/src/librustc_data_structures/stack.rs
+++ b/src/librustc_data_structures/stack.rs
@@ -13,5 +13,11 @@ const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB
 ///
 /// Should not be sprinkled around carelessly, as it causes a little bit of overhead.
 pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
-    stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f)
+    cfg_if::cfg_if! {
+        if #[cfg(any(unix, windows))] {
+            stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f)
+        } else {
+            f()
+        }
+    }
 }
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 75d6592076655..45bf37285e00f 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2018"
 [lib]
 name = "rustc_driver"
 path = "lib.rs"
-crate-type = ["dylib"]
+#crate-type = ["dylib"]
 
 [dependencies]
 lazy_static = "1.0"
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index ab4eac9440b41..99436a92b3646 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -423,7 +423,7 @@ pub fn set_sigpipe_handler() {
     }
 }
 
-#[cfg(windows)]
+#[cfg(not(unix))]
 pub fn set_sigpipe_handler() {}
 
 // Extract output directory and file from matches.
@@ -506,6 +506,11 @@ fn stdout_isatty() -> bool {
     }
 }
 
+#[cfg(not(any(unix, windows)))]
+fn stdout_isatty() -> bool {
+    false
+}
+
 fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
     let normalised =
         if code.starts_with('E') { code.to_string() } else { format!("E{0:0>4}", code) };
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 73d71063b2362..d47c2a13f8077 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -1006,7 +1006,11 @@ impl Level {
 #[macro_export]
 macro_rules! pluralize {
     ($x:expr) => {
-        if $x != 1 { "s" } else { "" }
+        if $x != 1 {
+            "s"
+        } else {
+            ""
+        }
     };
 }
 
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index 112dc7037f588..b9e2f72e038f6 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -10,6 +10,8 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
+ar = "0.8"
+cfg-if = "0.1"
 libc = "0.2"
 log = "0.4"
 rayon = { version = "0.3.0", package = "rustc-rayon" }
@@ -42,6 +44,7 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_plugin_impl = { path = "../librustc_plugin_impl" }
 rustc_privacy = { path = "../librustc_privacy" }
 rustc_resolve = { path = "../librustc_resolve" }
+rustc_target = { path = "../librustc_target" }
 rustc_trait_selection = { path = "../librustc_trait_selection" }
 rustc_ty = { path = "../librustc_ty" }
 tempfile = "3.0.5"
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index f1b9fafc78158..6ff1fd8403e44 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -990,7 +990,10 @@ fn encode_and_write_metadata(
         let metadata_tmpdir = TempFileBuilder::new()
             .prefix("rmeta")
             .tempdir_in(out_filename.parent().unwrap())
-            .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
+            .unwrap_or_else(|err| {
+                println!("{:?}", out_filename.parent());
+                tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err))
+            });
         let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir);
         if let Err(e) = fs::rename(&metadata_filename, &out_filename) {
             tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 5b648608b6b43..844d00e677a0a 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -106,24 +106,30 @@ impl Write for Sink {
 /// for `'static` bounds.
 #[cfg(not(parallel_compiler))]
 pub fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R {
-    struct Ptr(*mut ());
-    unsafe impl Send for Ptr {}
-    unsafe impl Sync for Ptr {}
-
-    let mut f = Some(f);
-    let run = Ptr(&mut f as *mut _ as *mut ());
-    let mut result = None;
-    let result_ptr = Ptr(&mut result as *mut _ as *mut ());
-
-    let thread = cfg.spawn(move || {
-        let run = unsafe { (*(run.0 as *mut Option<F>)).take().unwrap() };
-        let result = unsafe { &mut *(result_ptr.0 as *mut Option<R>) };
-        *result = Some(run());
-    });
+    cfg_if::cfg_if! {
+        if #[cfg(target_os = "wasi")] {
+            f()
+        } else {
+            struct Ptr(*mut ());
+            unsafe impl Send for Ptr {}
+            unsafe impl Sync for Ptr {}
+
+            let mut f = Some(f);
+            let run = Ptr(&mut f as *mut _ as *mut ());
+            let mut result = None;
+            let result_ptr = Ptr(&mut result as *mut _ as *mut ());
+
+            let thread = cfg.spawn(move || {
+                let run = unsafe { (*(run.0 as *mut Option<F>)).take().unwrap() };
+                let result = unsafe { &mut *(result_ptr.0 as *mut Option<R>) };
+                *result = Some(run());
+            });
 
-    match thread.unwrap().join() {
-        Ok(()) => result.unwrap(),
-        Err(p) => panic::resume_unwind(p),
+            match thread.unwrap().join() {
+                Ok(()) => result.unwrap(),
+                Err(p) => panic::resume_unwind(p),
+            }
+        }
     }
 }
 
@@ -364,6 +370,11 @@ fn sysroot_candidates() -> Vec<PathBuf> {
             Some(PathBuf::from(os))
         }
     }
+
+    #[cfg(not(any(unix, windows)))]
+    fn current_dll_path() -> Option<PathBuf> {
+        None
+    }
 }
 
 pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
@@ -373,11 +384,96 @@ pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box<dyn Codege
             return rustc_codegen_llvm::LlvmCodegenBackend::new;
         }
     }
+    if backend_name == "dummy" {
+        return || Box::new(DummyCodegenBackend);
+    }
 
     let err = format!("unsupported builtin codegen backend `{}`", backend_name);
     early_error(ErrorOutputType::default(), &err);
 }
 
+use rustc_middle::dep_graph::DepGraph;
+use rustc_middle::middle::cstore::EncodedMetadata;
+use rustc_middle::middle::cstore::MetadataLoaderDyn;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::TyCtxt;
+use std::any::Any;
+
+struct DummyCodegenBackend;
+
+impl CodegenBackend for DummyCodegenBackend {
+    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
+        Box::new(DummyMetadataLoader)
+    }
+
+    fn provide(&self, providers: &mut Providers) {
+        self.provide_extern(providers);
+    }
+
+    fn provide_extern(&self, providers: &mut Providers) {
+        providers.supported_target_features = |_tcx, _cnum| Default::default();
+    }
+
+    fn codegen_crate<'tcx>(
+        &self,
+        _tcx: TyCtxt<'tcx>,
+        _metadata: EncodedMetadata,
+        _need_metadata_module: bool,
+    ) -> Box<dyn Any> {
+        Box::new(())
+    }
+
+    fn join_codegen(
+        &self,
+        _ongoing_codegen: Box<dyn Any>,
+        _sess: &Session,
+        _dep_graph: &DepGraph,
+    ) -> Result<Box<dyn Any>, rustc_errors::ErrorReported> {
+        Ok(Box::new(()))
+    }
+
+    fn link(
+        &self,
+        _sess: &Session,
+        _codegen_results: Box<dyn Any>,
+        _outputs: &OutputFilenames,
+    ) -> Result<(), rustc_errors::ErrorReported> {
+        Ok(())
+    }
+}
+
+use rustc_data_structures::sync::MetadataRef;
+use rustc_target::spec::Target;
+
+struct DummyMetadataLoader;
+
+impl rustc_middle::middle::cstore::MetadataLoader for DummyMetadataLoader {
+    fn get_rlib_metadata(&self, _target: &Target, filename: &Path) -> Result<MetadataRef, String> {
+        use rustc_data_structures::{owning_ref::*, rustc_erase_owner};
+        use std::io::Read;
+
+        let file = std::fs::File::open(filename).map_err(|e| e.to_string())?;
+        let mut ar = ar::Archive::new(file);
+        while let Some(entry) = ar.next_entry() {
+            let mut entry = entry.map_err(|e| e.to_string())?;
+            if !entry.header().identifier().ends_with(b".rmeta") {
+                continue;
+            }
+
+            let mut contents = Vec::with_capacity(entry.header().size() as usize);
+            entry.read_to_end(&mut contents).map_err(|e| e.to_string())?;
+            let contents: OwningRef<Vec<u8>, [u8]> = OwningRef::new(contents).into();
+            return Ok(rustc_erase_owner!(contents.map_owner_box()));
+        }
+
+        Err("failed to find metadata".to_string())
+    }
+
+    fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String> {
+        Err("unimplemented dylib".to_string())
+    }
+}
+
 pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
     use std::hash::Hasher;
 
diff --git a/src/librustc_metadata/dynamic_lib.rs b/src/librustc_metadata/dynamic_lib.rs
index ce19240a009d0..453b34d3a7c8c 100644
--- a/src/librustc_metadata/dynamic_lib.rs
+++ b/src/librustc_metadata/dynamic_lib.rs
@@ -154,3 +154,25 @@ mod dl {
         if ptr.is_null() { Err(io::Error::last_os_error().to_string()) } else { Ok(ptr) }
     }
 }
+
+#[cfg(target_os = "wasi")]
+mod dl {
+    use std::ffi::OsStr;
+    use std::io;
+    use std::ptr;
+
+    pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> {
+        Err("dlopen not supported on wasi".to_string())
+    }
+
+    pub(super) unsafe fn symbol(
+        handle: *mut u8,
+        symbol: *const libc::c_char,
+    ) -> Result<*mut u8, String> {
+        Err("dlopen not supported on wasi".to_string())
+    }
+
+    pub(super) unsafe fn close(handle: *mut u8) {
+        panic!()
+    }
+}
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 371ec4cd91148..eb4a9aef8795c 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -426,20 +426,17 @@ impl<'a> CrateLocator<'a> {
             info!("lib candidate: {}", spf.path.display());
 
             let (rlibs, rmetas, dylibs) = candidates.entry(hash.to_string()).or_default();
-            fs::canonicalize(&spf.path)
-                .map(|p| {
-                    if seen_paths.contains(&p) {
-                        return FileDoesntMatch;
-                    };
-                    seen_paths.insert(p.clone());
-                    match found_kind {
-                        CrateFlavor::Rlib => rlibs.insert(p, kind),
-                        CrateFlavor::Rmeta => rmetas.insert(p, kind),
-                        CrateFlavor::Dylib => dylibs.insert(p, kind),
-                    };
-                    FileMatches
-                })
-                .unwrap_or(FileDoesntMatch)
+            let path = fs::canonicalize(&spf.path).unwrap_or(spf.path.clone());
+            if seen_paths.contains(&path) {
+                return FileDoesntMatch;
+            }
+            seen_paths.insert(path.clone());
+            match found_kind {
+                CrateFlavor::Rlib => rlibs.insert(path, kind),
+                CrateFlavor::Rmeta => rmetas.insert(path, kind),
+                CrateFlavor::Dylib => dylibs.insert(path, kind),
+            };
+            FileMatches
         });
         self.rejected_via_kind.extend(staticlibs);
 
@@ -688,12 +685,13 @@ impl<'a> CrateLocator<'a> {
                     && file.ends_with(&self.target.options.dll_suffix)
             {
                 // Make sure there's at most one rlib and at most one dylib.
+                let loc = fs::canonicalize(&loc).unwrap_or(loc.clone());
                 if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
-                    rlibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
+                    rlibs.insert(loc, PathKind::ExternFlag);
                 } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
-                    rmetas.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
+                    rmetas.insert(loc, PathKind::ExternFlag);
                 } else {
-                    dylibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
+                    dylibs.insert(loc, PathKind::ExternFlag);
                 }
             } else {
                 self.rejected_via_filename
@@ -770,14 +768,23 @@ fn get_metadata_section(
             }
         }
         CrateFlavor::Rmeta => {
-            // mmap the file, because only a small fraction of it is read.
-            let file = std::fs::File::open(filename)
-                .map_err(|_| format!("failed to open rmeta metadata: '{}'", filename.display()))?;
-            let mmap = unsafe { memmap::Mmap::map(&file) };
-            let mmap = mmap
-                .map_err(|_| format!("failed to mmap rmeta metadata: '{}'", filename.display()))?;
+            if cfg!(target_os = "wasi") {
+                let rmeta = std::fs::read(filename)
+                    .map_err(|e| format!("failed to read `{}`: {}", filename.display(), e))?;
+                let rmeta: OwningRef<Vec<u8>, [u8]> = OwningRef::new(rmeta).into();
+                rustc_erase_owner!(rmeta.map_owner_box())
+            } else {
+                // mmap the file, because only a small fraction of it is read.
+                let file = std::fs::File::open(filename).map_err(|_| {
+                    format!("failed to open rmeta metadata: '{}'", filename.display())
+                })?;
+                let mmap = unsafe { memmap::Mmap::map(&file) };
+                let mmap = mmap.map_err(|_| {
+                    format!("failed to mmap rmeta metadata: '{}'", filename.display())
+                })?;
 
-            rustc_erase_owner!(OwningRef::new(StableDerefMmap(mmap)).map_owner_box())
+                rustc_erase_owner!(OwningRef::new(StableDerefMmap(mmap)).map_owner_box())
+            }
         }
     };
     let blob = MetadataBlob::new(raw_bytes);
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index 0d4298fa6f502..a8d45b1b627af 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -1193,7 +1193,8 @@ pub fn build_session(
     let print_fuel = AtomicU64::new(0);
 
     let working_dir = env::current_dir().unwrap_or_else(|e| {
-        parse_sess.span_diagnostic.fatal(&format!("Current directory is invalid: {}", e)).raise()
+        ".".into()
+        // parse_sess.span_diagnostic.fatal(&format!("Current directory is invalid: {}", e)).raise()
     });
     let working_dir = file_path_mapping.map_prefix(working_dir);
 
diff --git a/src/librustc_span/fatal_error.rs b/src/librustc_span/fatal_error.rs
index 718c0ddbc63ea..e52be7415deff 100644
--- a/src/librustc_span/fatal_error.rs
+++ b/src/librustc_span/fatal_error.rs
@@ -13,7 +13,11 @@ impl !Send for FatalError {}
 
 impl FatalError {
     pub fn raise(self) -> ! {
-        std::panic::resume_unwind(Box::new(FatalErrorMarker))
+        if cfg!(target_os = "wasi") {
+            std::process::exit(2);
+        } else {
+            std::panic::resume_unwind(Box::new(FatalErrorMarker))
+        }
     }
 }