about summary refs log tree commit diff
diff options
context:
space:
mode:
author1011X <1011XXXXX@gmail.com>2018-03-04 13:35:21 -0500
committer1011X <1011XXXXX@gmail.com>2018-03-04 13:35:21 -0500
commitdf283db4c175d32d7859f981ac67c17669bb1fa8 (patch)
treef199018ad7b4a6d71a5d14e02a6e9d19119ca396
parent4e4c1b5b325c4c474426a7e3c346c316fbc644f1 (diff)
parent1e1bfc715f8dfe36a38d8fae36fcbe92e7463a3f (diff)
downloadrust-df283db4c175d32d7859f981ac67c17669bb1fa8.tar.gz
rust-df283db4c175d32d7859f981ac67c17669bb1fa8.zip
Merge branch 'master' of github.com:1011X/rust
-rw-r--r--.gitmodules9
-rw-r--r--.travis.yml4
-rw-r--r--README.md3
-rw-r--r--appveyor.yml10
-rw-r--r--config.toml.example7
-rw-r--r--src/Cargo.lock10
m---------src/binaryen0
-rw-r--r--src/bootstrap/bin/rustc.rs2
-rw-r--r--src/bootstrap/bootstrap.py52
-rw-r--r--src/bootstrap/builder.rs31
-rw-r--r--src/bootstrap/cc_detect.rs3
-rw-r--r--src/bootstrap/compile.rs29
-rw-r--r--src/bootstrap/config.rs9
-rwxr-xr-xsrc/bootstrap/configure.py5
-rw-r--r--src/bootstrap/dist.rs23
-rw-r--r--src/bootstrap/doc.rs1
-rw-r--r--src/bootstrap/lib.rs8
-rw-r--r--src/bootstrap/native.rs201
-rw-r--r--src/bootstrap/test.rs2
-rw-r--r--src/ci/docker/arm-android/Dockerfile4
-rw-r--r--src/ci/docker/armhf-gnu/Dockerfile4
-rw-r--r--src/ci/docker/asmjs/Dockerfile2
-rw-r--r--src/ci/docker/disabled/aarch64-gnu/Dockerfile1
-rw-r--r--src/ci/docker/disabled/dist-aarch64-android/Dockerfile2
-rw-r--r--src/ci/docker/disabled/dist-armv7-android/Dockerfile2
-rw-r--r--src/ci/docker/disabled/dist-i686-android/Dockerfile2
-rw-r--r--src/ci/docker/disabled/dist-x86_64-android/Dockerfile2
-rw-r--r--src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile2
-rw-r--r--src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile4
-rw-r--r--src/ci/docker/disabled/dist-x86_64-redox/Dockerfile2
-rw-r--r--src/ci/docker/disabled/wasm32-exp/Dockerfile2
-rw-r--r--src/ci/docker/disabled/wasm32/Dockerfile3
-rw-r--r--src/ci/docker/dist-aarch64-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-android/Dockerfile1
-rw-r--r--src/ci/docker/dist-arm-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-armhf-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-armv7-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile4
-rw-r--r--src/ci/docker/dist-i686-freebsd/Dockerfile2
-rw-r--r--src/ci/docker/dist-i686-linux/Dockerfile9
-rw-r--r--src/ci/docker/dist-mips-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-mips64-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-mips64el-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-mipsel-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-powerpc-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-powerpc64-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-powerpc64le-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-s390x-linux/Dockerfile2
-rw-r--r--src/ci/docker/dist-various-1/Dockerfile1
-rw-r--r--src/ci/docker/dist-various-2/Dockerfile2
-rw-r--r--src/ci/docker/dist-x86_64-freebsd/Dockerfile2
-rw-r--r--src/ci/docker/dist-x86_64-linux/Dockerfile6
-rw-r--r--src/ci/docker/dist-x86_64-musl/Dockerfile1
-rw-r--r--src/ci/docker/dist-x86_64-netbsd/Dockerfile2
-rw-r--r--src/ci/docker/wasm32-unknown/Dockerfile4
-rwxr-xr-xsrc/ci/run.sh6
-rw-r--r--src/etc/wasm32-shim.js2
-rw-r--r--src/liballoc/vec.rs138
-rw-r--r--src/libcore/lib.rs33
-rw-r--r--src/librustc_back/lib.rs60
-rw-r--r--src/librustc_back/target/aarch64_unknown_cloudabi.rs2
-rw-r--r--src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs2
-rw-r--r--src/librustc_back/target/armv7_unknown_linux_musleabihf.rs16
-rw-r--r--src/librustc_back/target/asmjs_unknown_emscripten.rs3
-rw-r--r--src/librustc_back/target/emscripten_base.rs17
-rw-r--r--src/librustc_back/target/haiku_base.rs1
-rw-r--r--src/librustc_back/target/i686_unknown_cloudabi.rs2
-rw-r--r--src/librustc_back/target/l4re_base.rs1
-rw-r--r--src/librustc_back/target/mod.rs9
-rw-r--r--src/librustc_back/target/msp430_none_elf.rs2
-rw-r--r--src/librustc_back/target/thumb_base.rs2
-rw-r--r--src/librustc_back/target/wasm32_experimental_emscripten.rs3
-rw-r--r--src/librustc_back/target/wasm32_unknown_emscripten.rs3
-rw-r--r--src/librustc_back/target/wasm32_unknown_unknown.rs55
-rw-r--r--src/librustc_back/target/windows_base.rs2
-rw-r--r--src/librustc_back/target/windows_msvc_base.rs1
-rw-r--r--src/librustc_back/target/x86_64_rumprun_netbsd.rs2
-rw-r--r--src/librustc_back/target/x86_64_unknown_cloudabi.rs2
-rw-r--r--src/librustc_binaryen/BinaryenWrapper.cpp160
-rw-r--r--src/librustc_binaryen/Cargo.toml16
-rw-r--r--src/librustc_binaryen/build.rs60
-rw-r--r--src/librustc_binaryen/lib.rs172
-rw-r--r--src/librustc_data_structures/transitive_relation.rs20
-rw-r--r--src/librustc_driver/lib.rs4
-rw-r--r--src/librustc_trans/Cargo.toml5
-rw-r--r--src/librustc_trans/back/command.rs28
-rw-r--r--src/librustc_trans/back/link.rs126
-rw-r--r--src/librustc_trans/back/linker.rs121
-rw-r--r--src/librustc_trans/back/symbol_export.rs17
-rw-r--r--src/librustc_trans/back/write.rs87
-rw-r--r--src/librustc_trans/lib.rs2
-rw-r--r--src/librustdoc/README.md172
-rw-r--r--src/libstd/lib.rs30
-rw-r--r--src/libstd_unicode/char.rs6
-rw-r--r--src/libsyntax/feature_gate.rs8
m---------src/stdsimd0
-rw-r--r--src/test/compile-fail/integral-indexing.rs8
-rw-r--r--src/test/run-pass/issue-15487.rs1
-rw-r--r--src/test/ui/feature-gate-wasm_import_memory.rs14
-rw-r--r--src/test/ui/feature-gate-wasm_import_memory.stderr11
-rw-r--r--src/test/ui/index-help.stderr7
m---------src/tools/lld0
-rw-r--r--src/tools/tidy/src/lib.rs3
103 files changed, 847 insertions, 1094 deletions
diff --git a/.gitmodules b/.gitmodules
index fc2f8bbc8a3..55f586389b1 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -41,12 +41,15 @@
 [submodule "src/dlmalloc"]
 	path = src/dlmalloc
 	url = https://github.com/alexcrichton/dlmalloc-rs.git
-[submodule "src/binaryen"]
-	path = src/binaryen
-	url = https://github.com/alexcrichton/binaryen.git
 [submodule "src/doc/rust-by-example"]
 	path = src/doc/rust-by-example
 	url = https://github.com/rust-lang/rust-by-example
 [submodule "src/llvm-emscripten"]
 	path = src/llvm-emscripten
 	url = https://github.com/rust-lang/llvm
+[submodule "src/stdsimd"]
+	path = src/stdsimd
+	url = https://github.com/rust-lang-nursery/stdsimd
+[submodule "src/tools/lld"]
+	path = src/tools/lld
+	url = https://github.com/rust-lang/lld.git
diff --git a/.travis.yml b/.travis.yml
index 0d8641e45ed..4738f91665d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -81,7 +81,7 @@ matrix:
     # OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7.
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended --enable-profiler --enable-emscripten"
+        RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler"
         SRC=.
         DEPLOY=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
@@ -95,7 +95,7 @@ matrix:
 
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended --enable-sanitizers --enable-profiler --enable-emscripten"
+        RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler"
         SRC=.
         DEPLOY=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
diff --git a/README.md b/README.md
index e78bbb82711..19ef96fae01 100644
--- a/README.md
+++ b/README.md
@@ -129,9 +129,6 @@ CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.
 python x.py build
 ```
 
-If you are seeing build failure when compiling `rustc_binaryen`, make sure the path
-length of the rust folder is not longer than 22 characters.
-
 #### Specifying an ABI
 [specifying-an-abi]: #specifying-an-abi
 
diff --git a/appveyor.yml b/appveyor.yml
index 0ea15dd671c..0735ead8923 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -67,21 +67,19 @@ environment:
   # 32/64 bit MSVC and GNU deployment
   - RUST_CONFIGURE_ARGS: >
       --build=x86_64-pc-windows-msvc
-      --enable-extended
+      --enable-full-tools
       --enable-profiler
-      --enable-emscripten
     SCRIPT: python x.py dist
     DEPLOY: 1
   - RUST_CONFIGURE_ARGS: >
       --build=i686-pc-windows-msvc
       --target=i586-pc-windows-msvc
-      --enable-extended
+      --enable-full-tools
       --enable-profiler
-      --enable-emscripten
     SCRIPT: python x.py dist
     DEPLOY: 1
   - MSYS_BITS: 32
-    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-emscripten
+    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools
     SCRIPT: python x.py dist
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
@@ -89,7 +87,7 @@ environment:
     DEPLOY: 1
   - MSYS_BITS: 64
     SCRIPT: python x.py dist
-    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-emscripten
+    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
     MINGW_DIR: mingw64
diff --git a/config.toml.example b/config.toml.example
index 8d1fa3eec5c..b47f9163c0d 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -321,11 +321,18 @@
 # bootstrap)
 #codegen-backends = ["llvm"]
 
+# This is the name of the directory in which codegen backends will get installed
+#codegen-backends-dir = "codegen-backends"
+
 # Flag indicating whether `libstd` calls an imported function to handle basic IO
 # when targeting WebAssembly. Enable this to debug tests for the `wasm32-unknown-unknown`
 # target, as without this option the test output will not be captured.
 #wasm-syscall = false
 
+# Indicates whether LLD will be compiled and made available in the sysroot for
+# rustc to execute.
+#lld = false
+
 # =============================================================================
 # Options for specific targets
 #
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 7b4bfecea3f..7620fe8ddb3 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -1819,15 +1819,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_binaryen"
-version = "0.0.0"
-dependencies = [
- "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "rustc_borrowck"
 version = "0.0.0"
 dependencies = [
@@ -2107,7 +2098,6 @@ dependencies = [
  "rustc_allocator 0.0.0",
  "rustc_apfloat 0.0.0",
  "rustc_back 0.0.0",
- "rustc_binaryen 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
diff --git a/src/binaryen b/src/binaryen
deleted file mode 160000
-Subproject 17841e155edf858c8ea7802dd5f5ecbef54b989
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index ca35a896e08..6c3c48aba72 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -224,7 +224,7 @@ fn main() {
                 // flesh out rpath support more fully in the future.
                 cmd.arg("-Z").arg("osx-rpath-install-name");
                 Some("-Wl,-rpath,@loader_path/../lib")
-            } else if !target.contains("windows") {
+            } else if !target.contains("windows") && !target.contains("wasm32") {
                 Some("-Wl,-rpath,$ORIGIN/../lib")
             } else {
                 None
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 5966bb65df9..d8f7cd7ed92 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -314,7 +314,6 @@ class RustBuild(object):
         self.build_dir = os.path.join(os.getcwd(), "build")
         self.clean = False
         self.config_toml = ''
-        self.printed = False
         self.rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
         self.use_locked_deps = ''
         self.use_vendored_sources = ''
@@ -336,7 +335,6 @@ class RustBuild(object):
         if self.rustc().startswith(self.bin_root()) and \
                 (not os.path.exists(self.rustc()) or
                  self.program_out_of_date(self.rustc_stamp())):
-            self.print_what_bootstrap_means()
             if os.path.exists(self.bin_root()):
                 shutil.rmtree(self.bin_root())
             filename = "rust-std-{}-{}.tar.gz".format(
@@ -351,10 +349,17 @@ class RustBuild(object):
             with open(self.rustc_stamp(), 'w') as rust_stamp:
                 rust_stamp.write(self.date)
 
+            # This is required so that we don't mix incompatible MinGW
+            # libraries/binaries that are included in rust-std with
+            # the system MinGW ones.
+            if "pc-windows-gnu" in self.build:
+                filename = "rust-mingw-{}-{}.tar.gz".format(
+                    rustc_channel, self.build)
+                self._download_stage0_helper(filename, "rust-mingw")
+
         if self.cargo().startswith(self.bin_root()) and \
                 (not os.path.exists(self.cargo()) or
                  self.program_out_of_date(self.cargo_stamp())):
-            self.print_what_bootstrap_means()
             filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build)
             self._download_stage0_helper(filename, "cargo")
             self.fix_executable("{}/bin/cargo".format(self.bin_root()))
@@ -555,23 +560,6 @@ class RustBuild(object):
             return '.exe'
         return ''
 
-    def print_what_bootstrap_means(self):
-        """Prints more information about the build system"""
-        if hasattr(self, 'printed'):
-            return
-        self.printed = True
-        if os.path.exists(self.bootstrap_binary()):
-            return
-        if '--help' not in sys.argv or len(sys.argv) == 1:
-            return
-
-        print('info: the build system for Rust is written in Rust, so this')
-        print('      script is now going to download a stage0 rust compiler')
-        print('      and then compile the build system itself')
-        print('')
-        print('info: in the meantime you can read more about rustbuild at')
-        print('      src/bootstrap/README.md before the download finishes')
-
     def bootstrap_binary(self):
         """Return the path of the boostrap binary
 
@@ -585,7 +573,6 @@ class RustBuild(object):
 
     def build_bootstrap(self):
         """Build bootstrap"""
-        self.print_what_bootstrap_means()
         build_dir = os.path.join(self.build_dir, "bootstrap")
         if self.clean and os.path.exists(build_dir):
             shutil.rmtree(build_dir)
@@ -654,6 +641,10 @@ class RustBuild(object):
                     continue
                 if self.get_toml('jemalloc'):
                     continue
+            if module.endswith("lld"):
+                config = self.get_toml('lld')
+                if config is None or config == 'false':
+                    continue
             filtered_submodules.append(module)
         run(["git", "submodule", "update",
              "--init", "--recursive"] + filtered_submodules,
@@ -670,8 +661,16 @@ class RustBuild(object):
         self._download_url = 'https://dev-static.rust-lang.org'
 
 
-def bootstrap():
+def bootstrap(help_triggered):
     """Configure, fetch, build and run the initial bootstrap"""
+
+    # If the user is asking for help, let them know that the whole download-and-build
+    # process has to happen before anything is printed out.
+    if help_triggered:
+        print("info: Downloading and building bootstrap before processing --help")
+        print("      command. See src/bootstrap/README.md for help with common")
+        print("      commands.")
+
     parser = argparse.ArgumentParser(description='Build rust')
     parser.add_argument('--config')
     parser.add_argument('--build')
@@ -708,7 +707,7 @@ def bootstrap():
             print('      and so in order to preserve your $HOME this will now')
             print('      use vendored sources by default. Note that if this')
             print('      does not work you should run a normal build first')
-            print('      before running a command like `sudo make install`')
+            print('      before running a command like `sudo ./x.py install`')
 
     if build.use_vendored_sources:
         if not os.path.exists('.cargo'):
@@ -734,7 +733,10 @@ def bootstrap():
     if 'dev' in data:
         build.set_dev_environment()
 
-    build.update_submodules()
+    # No help text depends on submodules. This check saves ~1 minute of git commands, even if
+    # all the submodules are present and downloaded!
+    if not help_triggered:
+        build.update_submodules()
 
     # Fetch/build the bootstrap
     build.build = args.build or build.build_triple()
@@ -760,7 +762,7 @@ def main():
     help_triggered = (
         '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1)
     try:
-        bootstrap()
+        bootstrap(help_triggered)
         if not help_triggered:
             print("Build completed successfully in {}".format(
                 format_build_time(time() - start_time)))
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 1df85323c41..22656e5a9da 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -316,7 +316,7 @@ impl<'a> Builder<'a> {
                 tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest,
                 tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient,
                 tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy,
-                native::Llvm, tool::Rustfmt, tool::Miri),
+                native::Llvm, tool::Rustfmt, tool::Miri, native::Lld),
             Kind::Check => describe!(check::Std, check::Test, check::Rustc),
             Kind::Test => describe!(test::Tidy, test::Bootstrap, test::Ui, test::RunPass,
                 test::CompileFail, test::ParseFail, test::RunFail, test::RunPassValgrind,
@@ -464,7 +464,7 @@ impl<'a> Builder<'a> {
 
     pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
         self.sysroot_libdir(compiler, compiler.host)
-            .with_file_name("codegen-backends")
+            .with_file_name(self.build.config.rust_codegen_backends_dir.clone())
     }
 
     /// Returns the compiler's libdir where it stores the dynamic libraries that
@@ -688,9 +688,25 @@ impl<'a> Builder<'a> {
         //
         // FIXME: the guard against msvc shouldn't need to be here
         if !target.contains("msvc") {
-            let cc = self.cc(target);
-            cargo.env(format!("CC_{}", target), cc)
-                 .env("CC", cc);
+            let ccache = self.config.ccache.as_ref();
+            let ccacheify = |s: &Path| {
+                let ccache = match ccache {
+                    Some(ref s) => s,
+                    None => return s.display().to_string(),
+                };
+                // FIXME: the cc-rs crate only recognizes the literal strings
+                // `ccache` and `sccache` when doing caching compilations, so we
+                // mirror that here. It should probably be fixed upstream to
+                // accept a new env var or otherwise work with custom ccache
+                // vars.
+                match &ccache[..] {
+                    "ccache" | "sccache" => format!("{} {}", ccache, s.display()),
+                    _ => s.display().to_string(),
+                }
+            };
+            let cc = ccacheify(&self.cc(target));
+            cargo.env(format!("CC_{}", target), &cc)
+                 .env("CC", &cc);
 
             let cflags = self.cflags(target).join(" ");
             cargo.env(format!("CFLAGS_{}", target), cflags.clone())
@@ -705,8 +721,9 @@ impl<'a> Builder<'a> {
             }
 
             if let Ok(cxx) = self.cxx(target) {
-                cargo.env(format!("CXX_{}", target), cxx)
-                     .env("CXX", cxx)
+                let cxx = ccacheify(&cxx);
+                cargo.env(format!("CXX_{}", target), &cxx)
+                     .env("CXX", &cxx)
                      .env(format!("CXXFLAGS_{}", target), cflags.clone())
                      .env("CXXFLAGS", cflags);
             }
diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs
index e531fdaf292..9e1b1f7db2f 100644
--- a/src/bootstrap/cc_detect.rs
+++ b/src/bootstrap/cc_detect.rs
@@ -79,6 +79,9 @@ pub fn find(build: &mut Build) {
         let mut cfg = cc::Build::new();
         cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false)
            .target(&target).host(&build.build);
+        if target.contains("msvc") {
+            cfg.static_crt(true);
+        }
 
         let config = build.config.target_config.get(&target);
         if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 408d63be6c6..695cf04a82c 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -514,7 +514,8 @@ fn rustc_cargo_env(build: &Build, cargo: &mut Command) {
     cargo.env("CFG_RELEASE", build.rust_release())
          .env("CFG_RELEASE_CHANNEL", &build.config.channel)
          .env("CFG_VERSION", build.rust_version())
-         .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
+         .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default())
+         .env("CFG_CODEGEN_BACKENDS_DIR", &build.config.rust_codegen_backends_dir);
 
     let libdir_relative = build.config.libdir_relative().unwrap_or(Path::new("lib"));
     cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
@@ -746,6 +747,21 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder,
     }
 }
 
+fn copy_lld_to_sysroot(builder: &Builder,
+                       target_compiler: Compiler,
+                       lld_install_root: &Path) {
+    let target = target_compiler.host;
+
+    let dst = builder.sysroot_libdir(target_compiler, target)
+        .parent()
+        .unwrap()
+        .join("bin");
+    t!(fs::create_dir_all(&dst));
+
+    let exe = exe("lld", &target);
+    copy(&lld_install_root.join("bin").join(&exe), &dst.join(&exe));
+}
+
 /// Cargo's output path for the standard library in a given stage, compiled
 /// by a particular compiler for the specified target.
 pub fn libstd_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
@@ -895,6 +911,14 @@ impl Step for Assemble {
             }
         }
 
+        let lld_install = if build.config.lld_enabled && target_compiler.stage > 0 {
+            Some(builder.ensure(native::Lld {
+                target: target_compiler.host,
+            }))
+        } else {
+            None
+        };
+
         let stage = target_compiler.stage;
         let host = target_compiler.host;
         println!("Assembling stage{} compiler ({})", stage, host);
@@ -914,6 +938,9 @@ impl Step for Assemble {
         copy_codegen_backends_to_sysroot(builder,
                                          build_compiler,
                                          target_compiler);
+        if let Some(lld_install) = lld_install {
+            copy_lld_to_sysroot(builder, target_compiler, &lld_install);
+        }
 
         // Link the compiler binary itself into place
         let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host);
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 6bc20181a03..f15d4d35858 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -81,6 +81,8 @@ pub struct Config {
     pub llvm_experimental_targets: String,
     pub llvm_link_jobs: Option<u32>,
 
+    pub lld_enabled: bool,
+
     // rust codegen options
     pub rust_optimize: bool,
     pub rust_codegen_units: Option<u32>,
@@ -96,6 +98,7 @@ pub struct Config {
     pub rust_debuginfo_tests: bool,
     pub rust_dist_src: bool,
     pub rust_codegen_backends: Vec<Interned<String>>,
+    pub rust_codegen_backends_dir: String,
 
     pub build: Interned<String>,
     pub hosts: Vec<Interned<String>>,
@@ -289,7 +292,9 @@ struct Rust {
     test_miri: Option<bool>,
     save_toolstates: Option<String>,
     codegen_backends: Option<Vec<String>>,
+    codegen_backends_dir: Option<String>,
     wasm_syscall: Option<bool>,
+    lld: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -330,6 +335,7 @@ impl Config {
         config.rust_dist_src = true;
         config.test_miri = false;
         config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
+        config.rust_codegen_backends_dir = "codegen-backends".to_owned();
 
         config.rustc_error_format = flags.rustc_error_format;
         config.on_fail = flags.on_fail;
@@ -477,6 +483,7 @@ impl Config {
             set(&mut config.quiet_tests, rust.quiet_tests);
             set(&mut config.test_miri, rust.test_miri);
             set(&mut config.wasm_syscall, rust.wasm_syscall);
+            set(&mut config.lld_enabled, rust.lld);
             config.rustc_parallel_queries = rust.experimental_parallel_queries.unwrap_or(false);
             config.rustc_default_linker = rust.default_linker.clone();
             config.musl_root = rust.musl_root.clone().map(PathBuf::from);
@@ -488,6 +495,8 @@ impl Config {
                     .collect();
             }
 
+            set(&mut config.rust_codegen_backends_dir, rust.codegen_backends_dir.clone());
+
             match rust.codegen_units {
                 Some(0) => config.rust_codegen_units = Some(num_cpus::get() as u32),
                 Some(n) => config.rust_codegen_units = Some(n),
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 99a3ee4e4c3..e9b4a233d0a 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -66,6 +66,7 @@ o("dist-src", "rust.dist-src", "when building tarballs enables building a source
 o("cargo-openssl-static", "build.openssl-static", "static openssl in cargo")
 o("profiler", "build.profiler", "build the profiler runtime")
 o("emscripten", None, "compile the emscripten backend as well as LLVM")
+o("full-tools", None, "enable all tools")
 
 # Optimization and debugging options. These may be overridden by the release
 # channel, etc.
@@ -326,6 +327,10 @@ for key in known_args:
         set('build.target', value.split(','))
     elif option.name == 'emscripten':
         set('rust.codegen-backends', ['llvm', 'emscripten'])
+    elif option.name == 'full-tools':
+        set('rust.codegen-backends', ['llvm', 'emscripten'])
+        set('rust.lld', True)
+        set('build.extended', True)
     elif option.name == 'option-checking':
         # this was handled above
         pass
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index e7aed7eb4fe..576e5078247 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -28,7 +28,7 @@ use build_helper::output;
 
 use {Build, Compiler, Mode};
 use channel;
-use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file};
+use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file, exe};
 use builder::{Builder, RunConfig, ShouldRun, Step};
 use compile;
 use native;
@@ -443,6 +443,22 @@ impl Step for Rustc {
             t!(fs::create_dir_all(&backends_dst));
             cp_r(&backends_src, &backends_dst);
 
+            // Copy over lld if it's there
+            if builder.config.lld_enabled {
+                let exe = exe("lld", &compiler.host);
+                let src = builder.sysroot_libdir(compiler, host)
+                    .parent()
+                    .unwrap()
+                    .join("bin")
+                    .join(&exe);
+                let dst = image.join("lib/rustlib")
+                    .join(&*host)
+                    .join("bin")
+                    .join(&exe);
+                t!(fs::create_dir_all(&dst.parent().unwrap()));
+                copy(&src, &dst);
+            }
+
             // Man pages
             t!(fs::create_dir_all(image.join("share/man/man1")));
             let man_src = build.src.join("src/doc/man");
@@ -590,7 +606,10 @@ impl Step for Std {
         let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
         src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
         cp_filtered(&src, &dst, &|path| {
-            path.file_name().and_then(|s| s.to_str()) != Some("codegen-backends")
+            let name = path.file_name().and_then(|s| s.to_str());
+            name != Some(build.config.rust_codegen_backends_dir.as_str()) &&
+                name != Some("bin")
+
         });
 
         let mut cmd = rust_installer(builder);
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 55d9723527e..a791dd13f0f 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -312,6 +312,7 @@ fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned<String
     cmd.arg("--html-after-content").arg(&footer)
         .arg("--html-before-content").arg(&version_info)
         .arg("--html-in-header").arg(&favicon)
+        .arg("--markdown-no-toc")
         .arg("--markdown-playground-url")
         .arg("https://play.rust-lang.org/")
         .arg("-o").arg(&out)
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 90f50275b6b..f3d9246c6fc 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -501,6 +501,10 @@ impl Build {
         self.out.join(&*target).join("llvm-emscripten")
     }
 
+    fn lld_out(&self, target: Interned<String>) -> PathBuf {
+        self.out.join(&*target).join("lld")
+    }
+
     /// Output directory for all documentation for a target
     fn doc_out(&self, target: Interned<String>) -> PathBuf {
         self.out.join(&*target).join("doc")
@@ -685,7 +689,9 @@ impl Build {
                                                        .and_then(|c| c.linker.as_ref()) {
             Some(linker)
         } else if target != self.config.build &&
-                  !target.contains("msvc") && !target.contains("emscripten") {
+                  !target.contains("msvc") &&
+                  !target.contains("emscripten") &&
+                  !target.contains("wasm32") {
             Some(self.cc(target))
         } else {
             None
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 653606e5d24..7888f0b938d 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -81,11 +81,11 @@ impl Step for Llvm {
 
         let (out_dir, llvm_config_ret_dir) = if emscripten {
             let dir = build.emscripten_llvm_out(target);
-            let config_dir = dir.join("bin");
+            let config_dir = dir.join("build/bin");
             (dir, config_dir)
         } else {
             (build.llvm_out(target),
-                build.llvm_out(build.config.build).join("bin"))
+                build.llvm_out(build.config.build).join("build/bin"))
         };
         let done_stamp = out_dir.join("llvm-finished-building");
         let build_llvm_config = llvm_config_ret_dir
@@ -110,9 +110,6 @@ impl Step for Llvm {
         // http://llvm.org/docs/CMake.html
         let root = if self.emscripten { "src/llvm-emscripten" } else { "src/llvm" };
         let mut cfg = cmake::Config::new(build.src.join(root));
-        if build.config.ninja {
-            cfg.generator("Ninja");
-        }
 
         let profile = match (build.config.llvm_optimize, build.config.llvm_release_debuginfo) {
             (false, _) => "Debug",
@@ -139,9 +136,7 @@ impl Step for Llvm {
 
         let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
 
-        cfg.target(&target)
-           .host(&build.build)
-           .out_dir(&out_dir)
+        cfg.out_dir(&out_dir)
            .profile(profile)
            .define("LLVM_ENABLE_ASSERTIONS", assertions)
            .define("LLVM_TARGETS_TO_BUILD", llvm_targets)
@@ -213,67 +208,7 @@ impl Step for Llvm {
             cfg.define("LLVM_NATIVE_BUILD", build.llvm_out(build.build).join("build"));
         }
 
-        let sanitize_cc = |cc: &Path| {
-            if target.contains("msvc") {
-                OsString::from(cc.to_str().unwrap().replace("\\", "/"))
-            } else {
-                cc.as_os_str().to_owned()
-            }
-        };
-
-        let configure_compilers = |cfg: &mut cmake::Config| {
-            // MSVC with CMake uses msbuild by default which doesn't respect these
-            // vars that we'd otherwise configure. In that case we just skip this
-            // entirely.
-            if target.contains("msvc") && !build.config.ninja {
-                return
-            }
-
-            let cc = build.cc(target);
-            let cxx = build.cxx(target).unwrap();
-
-            // Handle msvc + ninja + ccache specially (this is what the bots use)
-            if target.contains("msvc") &&
-               build.config.ninja &&
-               build.config.ccache.is_some() {
-                let mut cc = env::current_exe().expect("failed to get cwd");
-                cc.set_file_name("sccache-plus-cl.exe");
-
-               cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc))
-                  .define("CMAKE_CXX_COMPILER", sanitize_cc(&cc));
-               cfg.env("SCCACHE_PATH",
-                       build.config.ccache.as_ref().unwrap())
-                  .env("SCCACHE_TARGET", target);
-
-            // If ccache is configured we inform the build a little differently hwo
-            // to invoke ccache while also invoking our compilers.
-            } else if let Some(ref ccache) = build.config.ccache {
-               cfg.define("CMAKE_C_COMPILER", ccache)
-                  .define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc))
-                  .define("CMAKE_CXX_COMPILER", ccache)
-                  .define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx));
-            } else {
-               cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc))
-                  .define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
-            }
-
-            cfg.build_arg("-j").build_arg(build.jobs().to_string());
-            cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" "));
-            cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" "));
-            if let Some(ar) = build.ar(target) {
-                if ar.is_absolute() {
-                    // LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it
-                    // tries to resolve this path in the LLVM build directory.
-                    cfg.define("CMAKE_AR", sanitize_cc(ar));
-                }
-            }
-        };
-
-        configure_compilers(&mut cfg);
-
-        if env::var_os("SCCACHE_ERROR_LOG").is_some() {
-            cfg.env("RUST_LOG", "sccache=warn");
-        }
+        configure_cmake(build, target, &mut cfg, false);
 
         // FIXME: we don't actually need to build all LLVM tools and all LLVM
         //        libraries here, e.g. we just want a few components and a few
@@ -304,6 +239,134 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
     panic!("\n\nbad LLVM version: {}, need >=3.9\n\n", version)
 }
 
+fn configure_cmake(build: &Build,
+                   target: Interned<String>,
+                   cfg: &mut cmake::Config,
+                   building_dist_binaries: bool) {
+    if build.config.ninja {
+        cfg.generator("Ninja");
+    }
+    cfg.target(&target)
+       .host(&build.config.build);
+
+    let sanitize_cc = |cc: &Path| {
+        if target.contains("msvc") {
+            OsString::from(cc.to_str().unwrap().replace("\\", "/"))
+        } else {
+            cc.as_os_str().to_owned()
+        }
+    };
+
+    // MSVC with CMake uses msbuild by default which doesn't respect these
+    // vars that we'd otherwise configure. In that case we just skip this
+    // entirely.
+    if target.contains("msvc") && !build.config.ninja {
+        return
+    }
+
+    let cc = build.cc(target);
+    let cxx = build.cxx(target).unwrap();
+
+    // Handle msvc + ninja + ccache specially (this is what the bots use)
+    if target.contains("msvc") &&
+       build.config.ninja &&
+       build.config.ccache.is_some() {
+        let mut cc = env::current_exe().expect("failed to get cwd");
+        cc.set_file_name("sccache-plus-cl.exe");
+
+       cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc))
+          .define("CMAKE_CXX_COMPILER", sanitize_cc(&cc));
+       cfg.env("SCCACHE_PATH",
+               build.config.ccache.as_ref().unwrap())
+          .env("SCCACHE_TARGET", target);
+
+    // If ccache is configured we inform the build a little differently hwo
+    // to invoke ccache while also invoking our compilers.
+    } else if let Some(ref ccache) = build.config.ccache {
+       cfg.define("CMAKE_C_COMPILER", ccache)
+          .define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc))
+          .define("CMAKE_CXX_COMPILER", ccache)
+          .define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx));
+    } else {
+       cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc))
+          .define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
+    }
+
+    cfg.build_arg("-j").build_arg(build.jobs().to_string());
+    cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" "));
+    let mut cxxflags = build.cflags(target).join(" ");
+    if building_dist_binaries {
+        if build.config.llvm_static_stdcpp && !target.contains("windows") {
+            cxxflags.push_str(" -static-libstdc++");
+        }
+    }
+    cfg.define("CMAKE_CXX_FLAGS", cxxflags);
+    if let Some(ar) = build.ar(target) {
+        if ar.is_absolute() {
+            // LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it
+            // tries to resolve this path in the LLVM build directory.
+            cfg.define("CMAKE_AR", sanitize_cc(ar));
+        }
+    }
+
+    if env::var_os("SCCACHE_ERROR_LOG").is_some() {
+        cfg.env("RUST_LOG", "sccache=warn");
+    }
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct Lld {
+    pub target: Interned<String>,
+}
+
+impl Step for Lld {
+    type Output = PathBuf;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        run.path("src/tools/lld")
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(Lld { target: run.target });
+    }
+
+    /// Compile LLVM for `target`.
+    fn run(self, builder: &Builder) -> PathBuf {
+        let target = self.target;
+        let build = builder.build;
+
+        let llvm_config = builder.ensure(Llvm {
+            target: self.target,
+            emscripten: false,
+        });
+
+        let out_dir = build.lld_out(target);
+        let done_stamp = out_dir.join("lld-finished-building");
+        if done_stamp.exists() {
+            return out_dir
+        }
+
+        let _folder = build.fold_output(|| "lld");
+        println!("Building LLD for {}", target);
+        let _time = util::timeit();
+        t!(fs::create_dir_all(&out_dir));
+
+        let mut cfg = cmake::Config::new(build.src.join("src/tools/lld"));
+        configure_cmake(build, target, &mut cfg, true);
+
+        cfg.out_dir(&out_dir)
+           .profile("Release")
+           .define("LLVM_CONFIG_PATH", llvm_config)
+           .define("LLVM_INCLUDE_TESTS", "OFF");
+
+        cfg.build();
+
+        t!(File::create(&done_stamp));
+        out_dir
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct TestHelpers {
     pub target: Interned<String>,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index b27ddfdbc5e..c0998c1e42c 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -914,7 +914,7 @@ impl Step for Compiletest {
         }
 
         if build.config.llvm_enabled {
-            let llvm_config = build.llvm_config(target);
+            let llvm_config = build.llvm_config(build.config.build);
             let llvm_version = output(Command::new(&llvm_config).arg("--version"));
             cmd.arg("--llvm-version").arg(llvm_version);
             if !build.is_rust_llvm(target) {
diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile
index f2773a720cf..e10ccd56a4a 100644
--- a/src/ci/docker/arm-android/Dockerfile
+++ b/src/ci/docker/arm-android/Dockerfile
@@ -31,9 +31,7 @@ ENV PATH=$PATH:/android/sdk/platform-tools
 
 ENV TARGETS=arm-linux-androideabi
 
-ENV RUST_CONFIGURE_ARGS \
-      --target=$TARGETS \
-      --arm-linux-androideabi-ndk=/android/ndk/arm-14
+ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14
 
 ENV SCRIPT python2.7 ../x.py test --target $TARGETS
 
diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile
index 191f8e3a289..2b7624d53ee 100644
--- a/src/ci/docker/armhf-gnu/Dockerfile
+++ b/src/ci/docker/armhf-gnu/Dockerfile
@@ -76,9 +76,7 @@ RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/cu
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENV RUST_CONFIGURE_ARGS \
-      --target=arm-unknown-linux-gnueabihf \
-      --qemu-armhf-rootfs=/tmp/rootfs
+ENV RUST_CONFIGURE_ARGS --qemu-armhf-rootfs=/tmp/rootfs
 ENV SCRIPT python2.7 ../x.py test --target arm-unknown-linux-gnueabihf
 
 ENV NO_CHANGE_USER=1
diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile
index ff0708459bc..2a0901691a5 100644
--- a/src/ci/docker/asmjs/Dockerfile
+++ b/src/ci/docker/asmjs/Dockerfile
@@ -29,6 +29,6 @@ ENV EM_CONFIG=/emsdk-portable/.emscripten
 
 ENV TARGETS=asmjs-unknown-emscripten
 
-ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-emscripten
+ENV RUST_CONFIGURE_ARGS --enable-emscripten
 
 ENV SCRIPT python2.7 ../x.py test --target $TARGETS
diff --git a/src/ci/docker/disabled/aarch64-gnu/Dockerfile b/src/ci/docker/disabled/aarch64-gnu/Dockerfile
index fedb4094c8a..b2a3ba3ec26 100644
--- a/src/ci/docker/disabled/aarch64-gnu/Dockerfile
+++ b/src/ci/docker/disabled/aarch64-gnu/Dockerfile
@@ -74,7 +74,6 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS \
-      --target=aarch64-unknown-linux-gnu \
       --qemu-aarch64-rootfs=/tmp/rootfs
 ENV SCRIPT python2.7 ../x.py test --target aarch64-unknown-linux-gnu
 ENV NO_CHANGE_USER=1
diff --git a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile
index ce5e8cfaf09..a7903b6f425 100644
--- a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile
+++ b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile
@@ -14,8 +14,6 @@ ENV DEP_Z_ROOT=/android/ndk/arm64-21/sysroot/usr/
 ENV HOSTS=aarch64-linux-android
 
 ENV RUST_CONFIGURE_ARGS \
-      --host=$HOSTS \
-      --target=$HOSTS \
       --aarch64-linux-android-ndk=/android/ndk/arm64-21 \
       --disable-rpath \
       --enable-extended \
diff --git a/src/ci/docker/disabled/dist-armv7-android/Dockerfile b/src/ci/docker/disabled/dist-armv7-android/Dockerfile
index 3177fa2147f..c02a5e5a095 100644
--- a/src/ci/docker/disabled/dist-armv7-android/Dockerfile
+++ b/src/ci/docker/disabled/dist-armv7-android/Dockerfile
@@ -20,8 +20,6 @@ ENV DEP_Z_ROOT=/android/ndk/arm-14/sysroot/usr/
 ENV HOSTS=armv7-linux-androideabi
 
 ENV RUST_CONFIGURE_ARGS \
-      --host=$HOSTS \
-      --target=$HOSTS \
       --armv7-linux-androideabi-ndk=/android/ndk/arm \
       --disable-rpath \
       --enable-extended \
diff --git a/src/ci/docker/disabled/dist-i686-android/Dockerfile b/src/ci/docker/disabled/dist-i686-android/Dockerfile
index ace9c4feb4f..04e83a431c4 100644
--- a/src/ci/docker/disabled/dist-i686-android/Dockerfile
+++ b/src/ci/docker/disabled/dist-i686-android/Dockerfile
@@ -20,8 +20,6 @@ ENV DEP_Z_ROOT=/android/ndk/x86-14/sysroot/usr/
 ENV HOSTS=i686-linux-android
 
 ENV RUST_CONFIGURE_ARGS \
-      --host=$HOSTS \
-      --target=$HOSTS \
       --i686-linux-android-ndk=/android/ndk/x86 \
       --disable-rpath \
       --enable-extended \
diff --git a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile
index 322d26f0adc..937301864cd 100644
--- a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile
+++ b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile
@@ -14,8 +14,6 @@ ENV DEP_Z_ROOT=/android/ndk/x86_64-21/sysroot/usr/
 ENV HOSTS=x86_64-linux-android
 
 ENV RUST_CONFIGURE_ARGS \
-      --host=$HOSTS \
-      --target=$HOSTS \
       --x86_64-linux-android-ndk=/android/ndk/x86_64-21 \
       --disable-rpath \
       --enable-extended \
diff --git a/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile b/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile
index f3509efdb98..dbff9e32e13 100644
--- a/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile
+++ b/src/ci/docker/disabled/dist-x86_64-dragonfly/Dockerfile
@@ -32,5 +32,5 @@ ENV \
 
 ENV HOSTS=x86_64-unknown-dragonfly
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile b/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile
index 621976b5cbe..440afd7c97f 100644
--- a/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile
+++ b/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile
@@ -42,8 +42,8 @@ RUN sh /scripts/sccache.sh
 ENV HOST=x86_64-unknown-haiku
 ENV TARGET=target.$HOST
 
-ENV RUST_CONFIGURE_ARGS --host=$HOST --target=$HOST --disable-jemalloc \
+ENV RUST_CONFIGURE_ARGS --disable-jemalloc \
   --set=$TARGET.cc=x86_64-unknown-haiku-gcc \
   --set=$TARGET.cxx=x86_64-unknown-haiku-g++ \
   --set=$TARGET.llvm-config=/bin/llvm-config-haiku
-ENV SCRIPT python2.7 ../x.py dist
+ENV SCRIPT python2.7 ../x.py dist --host=$HOST --target=$HOST
diff --git a/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile
index ed19939545f..f4c25f791bc 100644
--- a/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile
+++ b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile
@@ -18,5 +18,5 @@ ENV \
     CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \
     CXX_x86_64_unknown_redox=x86_64-unknown-redox-g++
 
-ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-redox --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --target x86_64-unknown-redox
diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile
index 8653b0e8b46..420d47b314c 100644
--- a/src/ci/docker/disabled/wasm32-exp/Dockerfile
+++ b/src/ci/docker/disabled/wasm32-exp/Dockerfile
@@ -30,6 +30,6 @@ ENV EM_CONFIG=/root/.emscripten
 
 ENV TARGETS=wasm32-experimental-emscripten
 
-ENV RUST_CONFIGURE_ARGS --target=$TARGETS --experimental-targets=WebAssembly
+ENV RUST_CONFIGURE_ARGS --experimental-targets=WebAssembly
 
 ENV SCRIPT python2.7 ../x.py test --target $TARGETS
diff --git a/src/ci/docker/disabled/wasm32/Dockerfile b/src/ci/docker/disabled/wasm32/Dockerfile
index 7f6f8ae0882..6ac90d17450 100644
--- a/src/ci/docker/disabled/wasm32/Dockerfile
+++ b/src/ci/docker/disabled/wasm32/Dockerfile
@@ -29,7 +29,4 @@ ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/
 ENV EM_CONFIG=/emsdk-portable/.emscripten
 
 ENV TARGETS=wasm32-unknown-emscripten
-
-ENV RUST_CONFIGURE_ARGS --target=$TARGETS
-
 ENV SCRIPT python2.7 ../x.py test --target $TARGETS
diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile
index 841d3012125..dbc319312aa 100644
--- a/src/ci/docker/dist-aarch64-linux/Dockerfile
+++ b/src/ci/docker/dist-aarch64-linux/Dockerfile
@@ -32,5 +32,5 @@ ENV CC_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnueabi-gcc \
 
 ENV HOSTS=aarch64-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile
index 5d7545a3c2a..aa5da136758 100644
--- a/src/ci/docker/dist-android/Dockerfile
+++ b/src/ci/docker/dist-android/Dockerfile
@@ -21,7 +21,6 @@ ENV TARGETS=$TARGETS,aarch64-linux-android
 ENV TARGETS=$TARGETS,x86_64-linux-android
 
 ENV RUST_CONFIGURE_ARGS \
-      --target=$TARGETS \
       --enable-extended \
       --arm-linux-androideabi-ndk=/android/ndk/arm-14 \
       --armv7-linux-androideabi-ndk=/android/ndk/arm-14 \
diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile
index ecd5090ea05..89f7f85cb3b 100644
--- a/src/ci/docker/dist-arm-linux/Dockerfile
+++ b/src/ci/docker/dist-arm-linux/Dockerfile
@@ -32,5 +32,5 @@ ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \
 
 ENV HOSTS=arm-unknown-linux-gnueabi
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-armhf-linux/Dockerfile b/src/ci/docker/dist-armhf-linux/Dockerfile
index 5bbd17bd414..e0c1b9a9e85 100644
--- a/src/ci/docker/dist-armhf-linux/Dockerfile
+++ b/src/ci/docker/dist-armhf-linux/Dockerfile
@@ -32,5 +32,5 @@ ENV CC_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-gcc \
 
 ENV HOSTS=arm-unknown-linux-gnueabihf
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile
index ea9034d7178..e7d4f464ffc 100644
--- a/src/ci/docker/dist-armv7-linux/Dockerfile
+++ b/src/ci/docker/dist-armv7-linux/Dockerfile
@@ -32,5 +32,5 @@ ENV CC_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-gcc \
 
 ENV HOSTS=armv7-unknown-linux-gnueabihf
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile
index 035846b4f64..7bcc649f4aa 100644
--- a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile
+++ b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile
@@ -30,7 +30,6 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS \
-      --target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
       --musl-root-i586=/musl-i586 \
       --musl-root-i686=/musl-i686 \
       --enable-extended
@@ -46,8 +45,7 @@ ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
 #       https://github.com/alexcrichton/cc-rs/pull/281
 ENV CFLAGS_i586_unknown_linux_musl="-Wa,-mrelax-relocations=no -Wl,-melf_i386"
 
-ENV TARGETS=i586-unknown-linux-gnu
-ENV TARGETS=$TARGETS,i686-unknown-linux-musl
+ENV TARGETS=i586-unknown-linux-gnu,i686-unknown-linux-musl
 
 ENV SCRIPT \
       python2.7 ../x.py test --target $TARGETS && \
diff --git a/src/ci/docker/dist-i686-freebsd/Dockerfile b/src/ci/docker/dist-i686-freebsd/Dockerfile
index 673fa4c0c4b..1f595ba7a29 100644
--- a/src/ci/docker/dist-i686-freebsd/Dockerfile
+++ b/src/ci/docker/dist-i686-freebsd/Dockerfile
@@ -29,5 +29,5 @@ ENV \
 
 ENV HOSTS=i686-unknown-freebsd
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile
index 5e405aa72e8..0ec57ee0886 100644
--- a/src/ci/docker/dist-i686-linux/Dockerfile
+++ b/src/ci/docker/dist-i686-linux/Dockerfile
@@ -82,13 +82,10 @@ RUN sh /scripts/sccache.sh
 ENV HOSTS=i686-unknown-linux-gnu
 
 ENV RUST_CONFIGURE_ARGS \
-      --host=$HOSTS \
-      --enable-extended \
+      --enable-full-tools \
       --enable-sanitizers \
-      --enable-profiler \
-      --enable-emscripten \
-      --build=i686-unknown-linux-gnu
-ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
+      --enable-profiler
+ENV SCRIPT python2.7 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS
 
 # This is the only builder which will create source tarballs
 ENV DIST_SRC 1
diff --git a/src/ci/docker/dist-mips-linux/Dockerfile b/src/ci/docker/dist-mips-linux/Dockerfile
index 94a3cf8a382..37ab5bdcce5 100644
--- a/src/ci/docker/dist-mips-linux/Dockerfile
+++ b/src/ci/docker/dist-mips-linux/Dockerfile
@@ -22,5 +22,5 @@ RUN sh /scripts/sccache.sh
 
 ENV HOSTS=mips-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-mips64-linux/Dockerfile b/src/ci/docker/dist-mips64-linux/Dockerfile
index 0b0dfff1fe3..a5180780b22 100644
--- a/src/ci/docker/dist-mips64-linux/Dockerfile
+++ b/src/ci/docker/dist-mips64-linux/Dockerfile
@@ -21,5 +21,5 @@ RUN sh /scripts/sccache.sh
 
 ENV HOSTS=mips64-unknown-linux-gnuabi64
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-mips64el-linux/Dockerfile b/src/ci/docker/dist-mips64el-linux/Dockerfile
index 1810b1cdc5a..d38ed24f625 100644
--- a/src/ci/docker/dist-mips64el-linux/Dockerfile
+++ b/src/ci/docker/dist-mips64el-linux/Dockerfile
@@ -22,5 +22,5 @@ RUN sh /scripts/sccache.sh
 
 ENV HOSTS=mips64el-unknown-linux-gnuabi64
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-mipsel-linux/Dockerfile b/src/ci/docker/dist-mipsel-linux/Dockerfile
index f5be0748475..491c57ba677 100644
--- a/src/ci/docker/dist-mipsel-linux/Dockerfile
+++ b/src/ci/docker/dist-mipsel-linux/Dockerfile
@@ -21,5 +21,5 @@ RUN sh /scripts/sccache.sh
 
 ENV HOSTS=mipsel-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile
index 14ce3654fce..c503f2af9cd 100644
--- a/src/ci/docker/dist-powerpc-linux/Dockerfile
+++ b/src/ci/docker/dist-powerpc-linux/Dockerfile
@@ -34,7 +34,7 @@ ENV \
 
 ENV HOSTS=powerpc-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
 
 # FIXME(#36150) this will fail the bootstrap. Probably means something bad is
diff --git a/src/ci/docker/dist-powerpc64-linux/Dockerfile b/src/ci/docker/dist-powerpc64-linux/Dockerfile
index 1f6e83e2f49..4a369177736 100644
--- a/src/ci/docker/dist-powerpc64-linux/Dockerfile
+++ b/src/ci/docker/dist-powerpc64-linux/Dockerfile
@@ -35,5 +35,5 @@ ENV \
 
 ENV HOSTS=powerpc64-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/dist-powerpc64le-linux/Dockerfile
index d4677e18060..bf6c8b4b712 100644
--- a/src/ci/docker/dist-powerpc64le-linux/Dockerfile
+++ b/src/ci/docker/dist-powerpc64le-linux/Dockerfile
@@ -32,5 +32,5 @@ ENV \
 
 ENV HOSTS=powerpc64le-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-s390x-linux/Dockerfile b/src/ci/docker/dist-s390x-linux/Dockerfile
index 39478e92f7c..a2ebf590bab 100644
--- a/src/ci/docker/dist-s390x-linux/Dockerfile
+++ b/src/ci/docker/dist-s390x-linux/Dockerfile
@@ -34,5 +34,5 @@ ENV \
 
 ENV HOSTS=s390x-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile
index c83f101d0ac..a23153645cd 100644
--- a/src/ci/docker/dist-various-1/Dockerfile
+++ b/src/ci/docker/dist-various-1/Dockerfile
@@ -89,7 +89,6 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft"
 
 ENV RUST_CONFIGURE_ARGS \
-      --target=$TARGETS \
       --musl-root-arm=/musl-arm \
       --musl-root-armhf=/musl-armhf \
       --musl-root-armv7=/musl-armv7 \
diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile
index 5f342eb5705..4505a60e463 100644
--- a/src/ci/docker/dist-various-2/Dockerfile
+++ b/src/ci/docker/dist-various-2/Dockerfile
@@ -55,5 +55,5 @@ ENV TARGETS=$TARGETS,x86_64-sun-solaris
 ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32
 ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi
 
-ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
diff --git a/src/ci/docker/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/dist-x86_64-freebsd/Dockerfile
index f9f5b7062f8..dd595a19205 100644
--- a/src/ci/docker/dist-x86_64-freebsd/Dockerfile
+++ b/src/ci/docker/dist-x86_64-freebsd/Dockerfile
@@ -29,5 +29,5 @@ ENV \
 
 ENV HOSTS=x86_64-unknown-freebsd
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile
index d368a00b55b..3b98b0aa926 100644
--- a/src/ci/docker/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/dist-x86_64-linux/Dockerfile
@@ -82,11 +82,9 @@ RUN sh /scripts/sccache.sh
 ENV HOSTS=x86_64-unknown-linux-gnu
 
 ENV RUST_CONFIGURE_ARGS \
-      --host=$HOSTS \
-      --enable-extended \
+      --enable-full-tools \
       --enable-sanitizers \
-      --enable-profiler \
-      --enable-emscripten
+      --enable-profiler
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
 
 # This is the only builder which will create source tarballs
diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile
index c1061309c30..3a9ad178c63 100644
--- a/src/ci/docker/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/dist-x86_64-musl/Dockerfile
@@ -30,7 +30,6 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS \
-      --target=x86_64-unknown-linux-musl \
       --musl-root-x86_64=/musl-x86_64 \
       --enable-extended
 
diff --git a/src/ci/docker/dist-x86_64-netbsd/Dockerfile b/src/ci/docker/dist-x86_64-netbsd/Dockerfile
index 4fd2503c31b..06298a12fc7 100644
--- a/src/ci/docker/dist-x86_64-netbsd/Dockerfile
+++ b/src/ci/docker/dist-x86_64-netbsd/Dockerfile
@@ -33,5 +33,5 @@ ENV \
 
 ENV HOSTS=x86_64-unknown-netbsd
 
-ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV RUST_CONFIGURE_ARGS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/wasm32-unknown/Dockerfile b/src/ci/docker/wasm32-unknown/Dockerfile
index dc1727b7014..0972eb85191 100644
--- a/src/ci/docker/wasm32-unknown/Dockerfile
+++ b/src/ci/docker/wasm32-unknown/Dockerfile
@@ -22,8 +22,8 @@ RUN sh /scripts/sccache.sh
 ENV TARGETS=wasm32-unknown-unknown
 
 ENV RUST_CONFIGURE_ARGS \
-  --target=$TARGETS \
-  --set build.nodejs=/node-v9.2.0-linux-x64/bin/node
+  --set build.nodejs=/node-v9.2.0-linux-x64/bin/node \
+  --set rust.lld
 
 ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \
   src/test/ui \
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 02480c6937d..3be1c255c16 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -67,6 +67,12 @@ else
   fi
 fi
 
+# We've had problems in the past of shell scripts leaking fds into the sccache
+# server (#48192) which causes Cargo to erroneously think that a build script
+# hasn't finished yet. Try to solve that problem by starting a very long-lived
+# sccache server at the start of the build, but no need to worry if this fails.
+SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true
+
 travis_fold start configure
 travis_time_start
 $SRC/configure $RUST_CONFIGURE_ARGS
diff --git a/src/etc/wasm32-shim.js b/src/etc/wasm32-shim.js
index 69647f37eec..98d6202a63f 100644
--- a/src/etc/wasm32-shim.js
+++ b/src/etc/wasm32-shim.js
@@ -107,6 +107,8 @@ imports.env = {
   exp2f: function(x) { return Math.pow(2, x); },
   ldexp: function(x, y) { return x * Math.pow(2, y); },
   ldexpf: function(x, y) { return x * Math.pow(2, y); },
+  log: Math.log,
+  log2: Math.log2,
   log10: Math.log10,
   log10f: Math.log10,
 
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 3c9b6b94b44..feed7c8699a 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1527,142 +1527,26 @@ impl<T: Hash> Hash for Vec<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> Index<usize> for Vec<T> {
-    type Output = T;
-
-    #[inline]
-    fn index(&self, index: usize) -> &T {
-        // NB built-in indexing via `&[T]`
-        &(**self)[index]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> IndexMut<usize> for Vec<T> {
-    #[inline]
-    fn index_mut(&mut self, index: usize) -> &mut T {
-        // NB built-in indexing via `&mut [T]`
-        &mut (**self)[index]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::Index<ops::Range<usize>> for Vec<T> {
-    type Output = [T];
-
-    #[inline]
-    fn index(&self, index: ops::Range<usize>) -> &[T] {
-        Index::index(&**self, index)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::Index<ops::RangeTo<usize>> for Vec<T> {
-    type Output = [T];
-
-    #[inline]
-    fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
-        Index::index(&**self, index)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::Index<ops::RangeFrom<usize>> for Vec<T> {
-    type Output = [T];
-
-    #[inline]
-    fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
-        Index::index(&**self, index)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::Index<ops::RangeFull> for Vec<T> {
-    type Output = [T];
-
-    #[inline]
-    fn index(&self, _index: ops::RangeFull) -> &[T] {
-        self
-    }
-}
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::Index<ops::RangeInclusive<usize>> for Vec<T> {
-    type Output = [T];
-
-    #[inline]
-    fn index(&self, index: ops::RangeInclusive<usize>) -> &[T] {
-        Index::index(&**self, index)
-    }
-}
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::Index<ops::RangeToInclusive<usize>> for Vec<T> {
-    type Output = [T];
+impl<T, I> Index<I> for Vec<T>
+where
+    I: ::core::slice::SliceIndex<[T]>,
+{
+    type Output = I::Output;
 
     #[inline]
-    fn index(&self, index: ops::RangeToInclusive<usize>) -> &[T] {
+    fn index(&self, index: I) -> &Self::Output {
         Index::index(&**self, index)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::IndexMut<ops::Range<usize>> for Vec<T> {
-    #[inline]
-    fn index_mut(&mut self, index: ops::Range<usize>) -> &mut [T] {
-        IndexMut::index_mut(&mut **self, index)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::IndexMut<ops::RangeTo<usize>> for Vec<T> {
-    #[inline]
-    fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut [T] {
-        IndexMut::index_mut(&mut **self, index)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::IndexMut<ops::RangeFrom<usize>> for Vec<T> {
-    #[inline]
-    fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut [T] {
-        IndexMut::index_mut(&mut **self, index)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::IndexMut<ops::RangeFull> for Vec<T> {
-    #[inline]
-    fn index_mut(&mut self, _index: ops::RangeFull) -> &mut [T] {
-        self
-    }
-}
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::IndexMut<ops::RangeInclusive<usize>> for Vec<T> {
-    #[inline]
-    fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut [T] {
-        IndexMut::index_mut(&mut **self, index)
-    }
-}
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
-impl<T> ops::IndexMut<ops::RangeToInclusive<usize>> for Vec<T> {
+impl<T, I> IndexMut<I> for Vec<T>
+where
+    I: ::core::slice::SliceIndex<[T]>,
+{
     #[inline]
-    fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut [T] {
+    fn index_mut(&mut self, index: I) -> &mut Self::Output {
         IndexMut::index_mut(&mut **self, index)
     }
 }
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 3dd30ee1c69..1efd605112d 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -68,16 +68,21 @@
 #![feature(allow_internal_unstable)]
 #![feature(asm)]
 #![feature(associated_type_defaults)]
+#![feature(attr_literals)]
 #![feature(cfg_target_feature)]
 #![feature(cfg_target_has_atomic)]
 #![feature(concat_idents)]
 #![feature(const_fn)]
 #![feature(custom_attribute)]
+#![feature(doc_spotlight)]
 #![feature(fundamental)]
 #![feature(i128_type)]
 #![feature(inclusive_range_syntax)]
 #![feature(intrinsics)]
+#![feature(iterator_flatten)]
+#![feature(iterator_repeat_with)]
 #![feature(lang_items)]
+#![feature(link_llvm_intrinsics)]
 #![feature(never_type)]
 #![feature(no_core)]
 #![feature(on_unimplemented)]
@@ -85,15 +90,17 @@
 #![feature(prelude_import)]
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(rustc_attrs)]
+#![feature(rustc_const_unstable)]
+#![feature(simd_ffi)]
 #![feature(specialization)]
 #![feature(staged_api)]
+#![feature(stmt_expr_attributes)]
+#![feature(target_feature)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
-#![feature(doc_spotlight)]
-#![feature(rustc_const_unstable)]
-#![feature(iterator_repeat_with)]
-#![feature(iterator_flatten)]
+
+#![cfg_attr(stage0, allow(unused_attributes))]
 
 #[prelude_import]
 #[allow(unused)]
@@ -179,3 +186,21 @@ mod char_private;
 mod iter_private;
 mod tuple;
 mod unit;
+
+// Pull in the the `coresimd` crate directly into libcore. This is where all the
+// architecture-specific (and vendor-specific) intrinsics are defined. AKA
+// things like SIMD and such. Note that the actual source for all this lies in a
+// different repository, rust-lang-nursery/stdsimd. That's why the setup here is
+// a bit wonky.
+#[path = "../stdsimd/coresimd/mod.rs"]
+#[allow(missing_docs, missing_debug_implementations, dead_code)]
+#[unstable(feature = "stdsimd", issue = "48556")]
+#[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
+mod coresimd;
+
+#[unstable(feature = "stdsimd", issue = "48556")]
+#[cfg(not(stage0))]
+pub use coresimd::simd;
+#[unstable(feature = "stdsimd", issue = "48556")]
+#[cfg(not(stage0))]
+pub use coresimd::arch;
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
index 8bf60b091a7..9de56cca339 100644
--- a/src/librustc_back/lib.rs
+++ b/src/librustc_back/lib.rs
@@ -43,14 +43,32 @@ use std::str::FromStr;
 
 use serialize::json::{Json, ToJson};
 
-macro_rules! linker_flavor {
-    ($(($variant:ident, $string:expr),)+) => {
-        #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
-                 RustcEncodable, RustcDecodable)]
-        pub enum LinkerFlavor {
-            $($variant,)+
-        }
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
+         RustcEncodable, RustcDecodable)]
+pub enum LinkerFlavor {
+    Em,
+    Gcc,
+    Ld,
+    Msvc,
+    Lld(LldFlavor),
+}
+
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
+         RustcEncodable, RustcDecodable)]
+pub enum LldFlavor {
+    Wasm,
+    Ld64,
+    Ld,
+    Link,
+}
 
+impl ToJson for LinkerFlavor {
+    fn to_json(&self) -> Json {
+        self.desc().to_json()
+    }
+}
+macro_rules! flavor_mappings {
+    ($((($($flavor:tt)*), $string:expr),)*) => (
         impl LinkerFlavor {
             pub const fn one_of() -> &'static str {
                 concat!("one of: ", $($string, " ",)+)
@@ -58,32 +76,30 @@ macro_rules! linker_flavor {
 
             pub fn from_str(s: &str) -> Option<Self> {
                 Some(match s {
-                    $($string => LinkerFlavor::$variant,)+
+                    $($string => $($flavor)*,)+
                     _ => return None,
                 })
             }
 
             pub fn desc(&self) -> &str {
                 match *self {
-                    $(LinkerFlavor::$variant => $string,)+
+                    $($($flavor)* => $string,)+
                 }
             }
         }
-
-        impl ToJson for LinkerFlavor {
-            fn to_json(&self) -> Json {
-                self.desc().to_json()
-            }
-        }
-    }
+    )
 }
 
-linker_flavor! {
-    (Em, "em"),
-    (Binaryen, "binaryen"),
-    (Gcc, "gcc"),
-    (Ld, "ld"),
-    (Msvc, "msvc"),
+
+flavor_mappings! {
+    ((LinkerFlavor::Em), "em"),
+    ((LinkerFlavor::Gcc), "gcc"),
+    ((LinkerFlavor::Ld), "ld"),
+    ((LinkerFlavor::Msvc), "msvc"),
+    ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
+    ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
+    ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
+    ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_back/target/aarch64_unknown_cloudabi.rs b/src/librustc_back/target/aarch64_unknown_cloudabi.rs
index 59c82e06a67..a5d0e5bf166 100644
--- a/src/librustc_back/target/aarch64_unknown_cloudabi.rs
+++ b/src/librustc_back/target/aarch64_unknown_cloudabi.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
     base.max_atomic_width = Some(128);
     base.abi_blacklist = super::arm_base::abi_blacklist();
-    base.linker = "aarch64-unknown-cloudabi-cc".to_string();
+    base.linker = Some("aarch64-unknown-cloudabi-cc".to_string());
 
     Ok(Target {
         llvm_target: "aarch64-unknown-cloudabi".to_string(),
diff --git a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs
index faa2c4fdceb..fa66a35abbf 100644
--- a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs
+++ b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs
@@ -17,7 +17,7 @@ pub fn target() -> TargetResult {
     base.max_atomic_width = Some(64);
     base.features = "+v7,+vfp3,+neon".to_string();
     base.abi_blacklist = super::arm_base::abi_blacklist();
-    base.linker = "armv7-unknown-cloudabi-eabihf-cc".to_string();
+    base.linker = Some("armv7-unknown-cloudabi-eabihf-cc".to_string());
 
     Ok(Target {
         llvm_target: "armv7-unknown-cloudabi-eabihf".to_string(),
diff --git a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
index a36e26c0b7d..88f2b596751 100644
--- a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
+++ b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
@@ -12,13 +12,7 @@ use LinkerFlavor;
 use target::{Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
-    let mut base = super::linux_musl_base::opts();
-
-    // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
-    // target.
-    base.features = "+v7,+vfp3,+neon".to_string();
-    base.cpu = "cortex-a8".to_string();
-    base.max_atomic_width = Some(64);
+    let base = super::linux_musl_base::opts();
     Ok(Target {
         // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
         // uses it to determine the calling convention and float ABI, and LLVM
@@ -33,9 +27,15 @@ pub fn target() -> TargetResult {
         target_env: "musl".to_string(),
         target_vendor: "unknown".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
+
+        // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
+        // target.
         options: TargetOptions {
+            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+            cpu: "generic".to_string(),
+            max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
             .. base
-        },
+        }
     })
 }
diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs
index 5d9f0f6012b..f114926740a 100644
--- a/src/librustc_back/target/asmjs_unknown_emscripten.rs
+++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs
@@ -10,7 +10,6 @@
 
 use LinkerFlavor;
 use super::{LinkArgs, Target, TargetOptions};
-use super::emscripten_base::{cmd};
 
 pub fn target() -> Result<Target, String> {
     let mut args = LinkArgs::new();
@@ -19,8 +18,6 @@ pub fn target() -> Result<Target, String> {
                      "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
 
     let opts = TargetOptions {
-        linker: cmd("emcc"),
-
         dynamic_linking: false,
         executables: true,
         exe_suffix: ".js".to_string(),
diff --git a/src/librustc_back/target/emscripten_base.rs b/src/librustc_back/target/emscripten_base.rs
deleted file mode 100644
index bacada3f5ab..00000000000
--- a/src/librustc_back/target/emscripten_base.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub fn cmd(name: &str) -> String {
-    if cfg!(windows) {
-        format!("{}.bat", name)
-    } else {
-        name.to_string()
-    }
-}
diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_back/target/haiku_base.rs
index 112f424f7a8..a1ccb632cab 100644
--- a/src/librustc_back/target/haiku_base.rs
+++ b/src/librustc_back/target/haiku_base.rs
@@ -13,7 +13,6 @@ use std::default::Default;
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        linker: "cc".to_string(),
         dynamic_linking: true,
         executables: true,
         has_rpath: false,
diff --git a/src/librustc_back/target/i686_unknown_cloudabi.rs b/src/librustc_back/target/i686_unknown_cloudabi.rs
index e244f443d3e..69c3b298cab 100644
--- a/src/librustc_back/target/i686_unknown_cloudabi.rs
+++ b/src/librustc_back/target/i686_unknown_cloudabi.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
-    base.linker = "i686-unknown-cloudabi-cc".to_string();
+    base.linker = Some("i686-unknown-cloudabi-cc".to_string());
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
     base.stack_probes = true;
 
diff --git a/src/librustc_back/target/l4re_base.rs b/src/librustc_back/target/l4re_base.rs
index 31d428d2668..7cb7f8d613d 100644
--- a/src/librustc_back/target/l4re_base.rs
+++ b/src/librustc_back/target/l4re_base.rs
@@ -73,7 +73,6 @@ pub fn opts() -> Result<TargetOptions, String> {
         has_elf_tls: false,
         exe_allocation_crate: None,
         panic_strategy: PanicStrategy::Abort,
-        linker: "ld".to_string(),
         pre_link_args,
         post_link_args,
         target_family: Some("unix".to_string()),
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index be69127d8f2..0a3e1826f3a 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -58,7 +58,6 @@ mod arm_base;
 mod bitrig_base;
 mod cloudabi_base;
 mod dragonfly_base;
-mod emscripten_base;
 mod freebsd_base;
 mod haiku_base;
 mod linux_base;
@@ -279,8 +278,8 @@ pub struct TargetOptions {
     /// Whether the target is built-in or loaded from a custom target specification.
     pub is_builtin: bool,
 
-    /// Linker to invoke. Defaults to "cc".
-    pub linker: String,
+    /// Linker to invoke
+    pub linker: Option<String>,
 
     /// Linker arguments that are unconditionally passed *before* any
     /// user-defined libraries.
@@ -482,7 +481,7 @@ impl Default for TargetOptions {
     fn default() -> TargetOptions {
         TargetOptions {
             is_builtin: false,
-            linker: option_env!("CFG_DEFAULT_LINKER").unwrap_or("cc").to_string(),
+            linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
             pre_link_args: LinkArgs::new(),
             post_link_args: LinkArgs::new(),
             asm_args: Vec::new(),
@@ -732,7 +731,7 @@ impl Target {
         }
 
         key!(is_builtin, bool);
-        key!(linker);
+        key!(linker, optional);
         key!(pre_link_args, link_args);
         key!(pre_link_objects_exe, list);
         key!(pre_link_objects_dll, list);
diff --git a/src/librustc_back/target/msp430_none_elf.rs b/src/librustc_back/target/msp430_none_elf.rs
index 966df897f01..d0f512ae47c 100644
--- a/src/librustc_back/target/msp430_none_elf.rs
+++ b/src/librustc_back/target/msp430_none_elf.rs
@@ -32,7 +32,7 @@ pub fn target() -> TargetResult {
             // to gcc to get object files. For this reason we have a hard
             // dependency on this specific gcc.
             asm_args: vec!["-mcpu=msp430".to_string()],
-            linker: "msp430-elf-gcc".to_string(),
+            linker: Some("msp430-elf-gcc".to_string()),
             no_integrated_as: true,
 
             // There are no atomic instructions available in the MSP430
diff --git a/src/librustc_back/target/thumb_base.rs b/src/librustc_back/target/thumb_base.rs
index 6bb496649a8..6a8f52f5093 100644
--- a/src/librustc_back/target/thumb_base.rs
+++ b/src/librustc_back/target/thumb_base.rs
@@ -45,7 +45,7 @@ pub fn opts() -> TargetOptions {
         executables: true,
         // In 99%+ of cases, we want to use the `arm-none-eabi-gcc` compiler (there aren't many
         // options around)
-        linker: "arm-none-eabi-gcc".to_string(),
+        linker: Some("arm-none-eabi-gcc".to_string()),
         // Because these devices have very little resources having an unwinder is too onerous so we
         // default to "abort" because the "unwind" strategy is very rare.
         panic_strategy: PanicStrategy::Abort,
diff --git a/src/librustc_back/target/wasm32_experimental_emscripten.rs b/src/librustc_back/target/wasm32_experimental_emscripten.rs
index a261c982b3f..13dee3a5768 100644
--- a/src/librustc_back/target/wasm32_experimental_emscripten.rs
+++ b/src/librustc_back/target/wasm32_experimental_emscripten.rs
@@ -10,7 +10,6 @@
 
 use LinkerFlavor;
 use super::{LinkArgs, Target, TargetOptions};
-use super::emscripten_base::{cmd};
 
 pub fn target() -> Result<Target, String> {
     let mut post_link_args = LinkArgs::new();
@@ -24,8 +23,6 @@ pub fn target() -> Result<Target, String> {
                                "-g3".to_string()]);
 
     let opts = TargetOptions {
-        linker: cmd("emcc"),
-
         dynamic_linking: false,
         executables: true,
         // Today emcc emits two files - a .js file to bootstrap and
diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs
index 4823541f226..2770e67e30a 100644
--- a/src/librustc_back/target/wasm32_unknown_emscripten.rs
+++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs
@@ -10,7 +10,6 @@
 
 use LinkerFlavor;
 use super::{LinkArgs, Target, TargetOptions};
-use super::emscripten_base::{cmd};
 
 pub fn target() -> Result<Target, String> {
     let mut post_link_args = LinkArgs::new();
@@ -21,8 +20,6 @@ pub fn target() -> Result<Target, String> {
                                "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
 
     let opts = TargetOptions {
-        linker: cmd("emcc"),
-
         dynamic_linking: false,
         executables: true,
         // Today emcc emits two files - a .js file to bootstrap and
diff --git a/src/librustc_back/target/wasm32_unknown_unknown.rs b/src/librustc_back/target/wasm32_unknown_unknown.rs
index 242860e5c6e..1d84e137517 100644
--- a/src/librustc_back/target/wasm32_unknown_unknown.rs
+++ b/src/librustc_back/target/wasm32_unknown_unknown.rs
@@ -8,41 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// The wasm32-unknown-unknown target is currently a highly experimental version
-// of a wasm-based target which does *not* use the Emscripten toolchain. Instead
-// this is a pretty flavorful (aka hacked up) target right now. The definition
-// and semantics of this target are likely to change and so this shouldn't be
-// relied on just yet.
+// The wasm32-unknown-unknown target is currently an experimental version of a
+// wasm-based target which does *not* use the Emscripten toolchain. Instead
+// this toolchain is based purely on LLVM's own toolchain, using LLVM's native
+// WebAssembly backend as well as LLD for a native linker.
 //
-// In general everyone is currently waiting on a linker for wasm code. In the
-// meantime we have no means of actually making use of the traditional separate
-// compilation model. At a high level this means that assembling Rust programs
-// into a WebAssembly program looks like:
-//
-//  1. All intermediate artifacts are LLVM bytecode. We'll be using LLVM as
-//     a linker later on.
-//  2. For the final artifact we emit one giant assembly file (WebAssembly
-//     doesn't have an object file format). To do this we force LTO to be turned
-//     on (`requires_lto` below) to ensure all Rust code is in one module. Any
-//     "linked" C library is basically just ignored.
-//  3. Using LLVM we emit a `foo.s` file (assembly) with some... what I can only
-//     describe as arcane syntax. From there we need to actually change this
-//     into a wasm module. For this step we use the `binaryen` project. This
-//     project is mostly intended as a WebAssembly code generator, but for now
-//     we're just using its LLVM-assembly-to-wasm-module conversion utilities.
-//
-// And voila, out comes a web assembly module! There's some various tweaks here
-// and there, but that's the high level at least. Note that this will be
-// rethought from the ground up once a linker (lld) is available, so this is all
-// temporary and should improve in the future.
+// There's some trickery below on crate types supported and various defaults
+// (aka panic=abort by default), but otherwise this is in general a relatively
+// standard target.
 
-use LinkerFlavor;
+use {LinkerFlavor, LldFlavor};
 use super::{Target, TargetOptions, PanicStrategy};
 
 pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
-        linker: "not-used".to_string(),
-
         // we allow dynamic linking, but only cdylibs. Basically we allow a
         // final library artifact that exports some symbols (a wasm module) but
         // we don't allow intermediate `dylib` crate types
@@ -58,9 +37,6 @@ pub fn target() -> Result<Target, String> {
         dll_suffix: ".wasm".to_string(),
         linker_is_gnu: false,
 
-        // We're storing bitcode for now in all the rlibs
-        obj_is_bitcode: true,
-
         // A bit of a lie, but "eh"
         max_atomic_width: Some(32),
 
@@ -69,27 +45,17 @@ pub fn target() -> Result<Target, String> {
         // the future once unwinding is implemented. Don't rely on this.
         panic_strategy: PanicStrategy::Abort,
 
-        // There's no linker yet so we're forced to use LLVM as a linker. This
-        // means that we must always enable LTO for final artifacts.
-        requires_lto: true,
-
         // Wasm doesn't have atomics yet, so tell LLVM that we're in a single
         // threaded model which will legalize atomics to normal operations.
         singlethread: true,
 
-        // Because we're always enabling LTO we can't enable builtin lowering as
-        // otherwise we'll lower the definition of the `memcpy` function to
-        // memcpy itself. Note that this is specifically because we're
-        // performing LTO with compiler-builtins.
-        no_builtins: true,
-
         // no dynamic linking, no need for default visibility!
         default_hidden_visibility: true,
 
         .. Default::default()
     };
     Ok(Target {
-        llvm_target: "wasm32-unknown-unknown".to_string(),
+        llvm_target: "wasm32-unknown-unknown-wasm".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
@@ -100,8 +66,7 @@ pub fn target() -> Result<Target, String> {
         target_vendor: "unknown".to_string(),
         data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
         arch: "wasm32".to_string(),
-        // A bit of a lie, but it gets the job done
-        linker_flavor: LinkerFlavor::Binaryen,
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Wasm),
         options: opts,
     })
 }
diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs
index 30038400f6c..05b6247c951 100644
--- a/src/librustc_back/target/windows_base.rs
+++ b/src/librustc_back/target/windows_base.rs
@@ -75,7 +75,7 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         // FIXME(#13846) this should be enabled for windows
         function_sections: false,
-        linker: "gcc".to_string(),
+        linker: Some("gcc".to_string()),
         dynamic_linking: true,
         executables: true,
         dll_prefix: "".to_string(),
diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs
index e0bf36ee407..34aa17267f8 100644
--- a/src/librustc_back/target/windows_msvc_base.rs
+++ b/src/librustc_back/target/windows_msvc_base.rs
@@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions {
 
     TargetOptions {
         function_sections: true,
-        linker: "link.exe".to_string(),
         dynamic_linking: true,
         executables: true,
         dll_prefix: "".to_string(),
diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs
index 18f6380b6ee..3158665a2e2 100644
--- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs
+++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
     base.cpu = "x86-64".to_string();
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
-    base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
+    base.linker = Some("x86_64-rumprun-netbsd-gcc".to_string());
     base.max_atomic_width = Some(64);
 
     base.dynamic_linking = false;
diff --git a/src/librustc_back/target/x86_64_unknown_cloudabi.rs b/src/librustc_back/target/x86_64_unknown_cloudabi.rs
index 1ce3c6444f1..d1a9cb1cd7e 100644
--- a/src/librustc_back/target/x86_64_unknown_cloudabi.rs
+++ b/src/librustc_back/target/x86_64_unknown_cloudabi.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
-    base.linker = "x86_64-unknown-cloudabi-cc".to_string();
+    base.linker = Some("x86_64-unknown-cloudabi-cc".to_string());
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.stack_probes = true;
 
diff --git a/src/librustc_binaryen/BinaryenWrapper.cpp b/src/librustc_binaryen/BinaryenWrapper.cpp
deleted file mode 100644
index 55f11665f6d..00000000000
--- a/src/librustc_binaryen/BinaryenWrapper.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This is a small C API inserted on top of the Binaryen C++ API which we use
-// from Rust. Once we have a real linker for we'll be able to remove all this,
-// and otherwise this is just all on a "as we need it" basis for now.
-
-#include <stdint.h>
-#include <string>
-#include <sstream>
-#include <stdlib.h>
-
-#include "s2wasm.h"
-#include "wasm-binary.h"
-#include "wasm-linker.h"
-
-using namespace wasm;
-
-struct BinaryenRustModule {
-  BufferWithRandomAccess buffer;
-  std::string sourceMapJSON;
-};
-
-struct BinaryenRustModuleOptions {
-  uint64_t globalBase;
-  bool debug;
-  uint64_t stackAllocation;
-  uint64_t initialMem;
-  uint64_t maxMem;
-  bool importMemory;
-  bool ignoreUnknownSymbols;
-  bool debugInfo;
-  std::string startFunction;
-  std::string sourceMapUrl;
-
-  BinaryenRustModuleOptions() :
-    globalBase(0),
-    debug(false),
-    stackAllocation(0),
-    initialMem(0),
-    maxMem(0),
-    importMemory(false),
-    ignoreUnknownSymbols(false),
-    debugInfo(false),
-    startFunction(""),
-    sourceMapUrl("")
-  {}
-
-};
-
-extern "C" BinaryenRustModuleOptions*
-BinaryenRustModuleOptionsCreate() {
-  return new BinaryenRustModuleOptions;
-}
-
-extern "C" void
-BinaryenRustModuleOptionsFree(BinaryenRustModuleOptions *options) {
-  delete options;
-}
-
-extern "C" void
-BinaryenRustModuleOptionsSetDebugInfo(BinaryenRustModuleOptions *options,
-                                      bool debugInfo) {
-  options->debugInfo = debugInfo;
-}
-
-extern "C" void
-BinaryenRustModuleOptionsSetStart(BinaryenRustModuleOptions *options,
-                                  char *start) {
-  options->startFunction = start;
-}
-
-extern "C" void
-BinaryenRustModuleOptionsSetSourceMapUrl(BinaryenRustModuleOptions *options,
-                                         char *sourceMapUrl) {
-  options->sourceMapUrl = sourceMapUrl;
-}
-
-extern "C" void
-BinaryenRustModuleOptionsSetStackAllocation(BinaryenRustModuleOptions *options,
-                                            uint64_t stack) {
-  options->stackAllocation = stack;
-}
-
-extern "C" void
-BinaryenRustModuleOptionsSetImportMemory(BinaryenRustModuleOptions *options,
-                                         bool import) {
-  options->importMemory = import;
-}
-
-extern "C" BinaryenRustModule*
-BinaryenRustModuleCreate(const BinaryenRustModuleOptions *options,
-                         const char *assembly) {
-  Linker linker(
-      options->globalBase,
-      options->stackAllocation,
-      options->initialMem,
-      options->maxMem,
-      options->importMemory,
-      options->ignoreUnknownSymbols,
-      options->startFunction,
-      options->debug);
-
-  S2WasmBuilder mainbuilder(assembly, options->debug);
-  linker.linkObject(mainbuilder);
-  linker.layout();
-
-  auto ret = make_unique<BinaryenRustModule>();
-  {
-    WasmBinaryWriter writer(&linker.getOutput().wasm, ret->buffer, options->debug);
-    writer.setNamesSection(options->debugInfo);
-
-    std::unique_ptr<std::ostringstream> sourceMapStream = nullptr;
-    {
-      sourceMapStream = make_unique<std::ostringstream>();
-      writer.setSourceMap(sourceMapStream.get(), options->sourceMapUrl);
-    }
-
-    // FIXME: support symbol maps?
-    // writer.setSymbolMap(symbolMap);
-    writer.write();
-
-    if (sourceMapStream) {
-      ret->sourceMapJSON = sourceMapStream->str();
-    }
-  }
-  return ret.release();
-}
-
-extern "C" const uint8_t*
-BinaryenRustModulePtr(const BinaryenRustModule *M) {
-  return M->buffer.data();
-}
-
-extern "C" size_t
-BinaryenRustModuleLen(const BinaryenRustModule *M) {
-  return M->buffer.size();
-}
-
-extern "C" const char*
-BinaryenRustModuleSourceMapPtr(const BinaryenRustModule *M) {
-  return M->sourceMapJSON.data();
-}
-
-extern "C" size_t
-BinaryenRustModuleSourceMapLen(const BinaryenRustModule *M) {
-  return M->sourceMapJSON.length();
-}
-
-extern "C" void
-BinaryenRustModuleFree(BinaryenRustModule *M) {
-  delete M;
-}
diff --git a/src/librustc_binaryen/Cargo.toml b/src/librustc_binaryen/Cargo.toml
deleted file mode 100644
index 9573c894714..00000000000
--- a/src/librustc_binaryen/Cargo.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-# Wondering what this crate is? Take a look at the `lib.rs`!
-
-[package]
-name = "rustc_binaryen"
-version = "0.0.0"
-authors = ["The Rust Project Developers"]
-
-[lib]
-path = "lib.rs"
-
-[dependencies]
-libc = "0.2"
-
-[build-dependencies]
-cmake = "0.1"
-cc = "1.0"
diff --git a/src/librustc_binaryen/build.rs b/src/librustc_binaryen/build.rs
deleted file mode 100644
index f23ff3cee55..00000000000
--- a/src/librustc_binaryen/build.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern crate cc;
-extern crate cmake;
-
-use std::env;
-
-use cmake::Config;
-
-fn main() {
-    let target = env::var("TARGET").unwrap();
-
-    // Bring in `__emutls_get_address` which is apparently needed for now
-    if target.contains("pc-windows-gnu") {
-        println!("cargo:rustc-link-lib=gcc_eh");
-        println!("cargo:rustc-link-lib=pthread");
-    }
-
-    Config::new("../binaryen")
-        .define("BUILD_STATIC_LIB", "ON")
-        .build_target("binaryen")
-        .build();
-
-    // I couldn't figure out how to link just one of these, so link everything.
-    println!("cargo:rustc-link-lib=static=asmjs");
-    println!("cargo:rustc-link-lib=static=binaryen");
-    println!("cargo:rustc-link-lib=static=cfg");
-    println!("cargo:rustc-link-lib=static=emscripten-optimizer");
-    println!("cargo:rustc-link-lib=static=ir");
-    println!("cargo:rustc-link-lib=static=passes");
-    println!("cargo:rustc-link-lib=static=support");
-    println!("cargo:rustc-link-lib=static=wasm");
-
-    let out_dir = env::var("OUT_DIR").unwrap();
-    println!("cargo:rustc-link-search=native={}/build/lib", out_dir);
-
-    // Add in our own little shim along with some extra files that weren't
-    // included in the main build.
-    let mut cfg = cc::Build::new();
-    cfg.file("BinaryenWrapper.cpp")
-        .file("../binaryen/src/wasm-linker.cpp")
-        .file("../binaryen/src/wasm-emscripten.cpp")
-        .include("../binaryen/src")
-        .cpp_link_stdlib(None)
-        .warnings(false)
-        .cpp(true);
-
-    if !target.contains("msvc") {
-        cfg.flag("-std=c++11");
-    }
-    cfg.compile("binaryen_wrapper");
-}
diff --git a/src/librustc_binaryen/lib.rs b/src/librustc_binaryen/lib.rs
deleted file mode 100644
index 36174e11ba0..00000000000
--- a/src/librustc_binaryen/lib.rs
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Rustc bindings to the binaryen project.
-//!
-//! This crate is a small shim around the binaryen project which provides us the
-//! ability to take LLVM's output and generate a wasm module. Specifically this
-//! only supports one operation, creating a module from LLVM's assembly format
-//! and then serializing that module to a wasm module.
-
-extern crate libc;
-
-use std::slice;
-use std::ffi::{CString, CStr};
-
-/// In-memory representation of a serialized wasm module.
-pub struct Module {
-    ptr: *mut BinaryenRustModule,
-}
-
-impl Module {
-    /// Creates a new wasm module from the LLVM-assembly provided (in a C string
-    /// format).
-    ///
-    /// The actual module creation can be tweaked through the various options in
-    /// `ModuleOptions` as well. Any errors are just returned as a bland string.
-    pub fn new(assembly: &CStr, opts: &ModuleOptions) -> Result<Module, String> {
-        unsafe {
-            let ptr = BinaryenRustModuleCreate(opts.ptr, assembly.as_ptr());
-            if ptr.is_null() {
-                Err(format!("failed to create binaryen module"))
-            } else {
-                Ok(Module { ptr })
-            }
-        }
-    }
-
-    /// Returns the data of the serialized wasm module. This is a `foo.wasm`
-    /// file contents.
-    pub fn data(&self) -> &[u8] {
-        unsafe {
-            let ptr = BinaryenRustModulePtr(self.ptr);
-            let len = BinaryenRustModuleLen(self.ptr);
-            slice::from_raw_parts(ptr, len)
-        }
-    }
-
-    /// Returns the data of the source map JSON.
-    pub fn source_map(&self) -> &[u8] {
-        unsafe {
-            let ptr = BinaryenRustModuleSourceMapPtr(self.ptr);
-            let len = BinaryenRustModuleSourceMapLen(self.ptr);
-            slice::from_raw_parts(ptr, len)
-        }
-    }
-}
-
-impl Drop for Module {
-    fn drop(&mut self) {
-        unsafe {
-            BinaryenRustModuleFree(self.ptr);
-        }
-    }
-}
-
-pub struct ModuleOptions {
-    ptr: *mut BinaryenRustModuleOptions,
-}
-
-impl ModuleOptions {
-    pub fn new() -> ModuleOptions {
-        unsafe {
-            let ptr = BinaryenRustModuleOptionsCreate();
-            ModuleOptions { ptr }
-        }
-    }
-
-    /// Turns on or off debug info.
-    ///
-    /// From what I can tell this just creates a "names" section of the wasm
-    /// module which contains a table of the original function names.
-    pub fn debuginfo(&mut self, debug: bool) -> &mut Self {
-        unsafe {
-            BinaryenRustModuleOptionsSetDebugInfo(self.ptr, debug);
-        }
-        self
-    }
-
-    /// Configures a `start` function for the module, to be executed when it's
-    /// loaded.
-    pub fn start(&mut self, func: &str) -> &mut Self {
-        let func = CString::new(func).unwrap();
-        unsafe {
-            BinaryenRustModuleOptionsSetStart(self.ptr, func.as_ptr());
-        }
-        self
-    }
-
-    /// Configures a `sourceMappingURL` custom section value for the module.
-    pub fn source_map_url(&mut self, url: &str) -> &mut Self {
-        let url = CString::new(url).unwrap();
-        unsafe {
-            BinaryenRustModuleOptionsSetSourceMapUrl(self.ptr, url.as_ptr());
-        }
-        self
-    }
-
-    /// Configures how much stack is initially allocated for the module. 1MB is
-    /// probably good enough for now.
-    pub fn stack(&mut self, amt: u64) -> &mut Self {
-        unsafe {
-            BinaryenRustModuleOptionsSetStackAllocation(self.ptr, amt);
-        }
-        self
-    }
-
-    /// Flags whether the initial memory should be imported or exported. So far
-    /// we export it by default.
-    pub fn import_memory(&mut self, import: bool) -> &mut Self {
-        unsafe {
-            BinaryenRustModuleOptionsSetImportMemory(self.ptr, import);
-        }
-        self
-    }
-}
-
-impl Drop for ModuleOptions {
-    fn drop(&mut self) {
-        unsafe {
-            BinaryenRustModuleOptionsFree(self.ptr);
-        }
-    }
-}
-
-enum BinaryenRustModule {}
-enum BinaryenRustModuleOptions {}
-
-extern {
-    fn BinaryenRustModuleCreate(opts: *const BinaryenRustModuleOptions,
-                                assembly: *const libc::c_char)
-        -> *mut BinaryenRustModule;
-    fn BinaryenRustModulePtr(module: *const BinaryenRustModule) -> *const u8;
-    fn BinaryenRustModuleLen(module: *const BinaryenRustModule) -> usize;
-    fn BinaryenRustModuleSourceMapPtr(module: *const BinaryenRustModule) -> *const u8;
-    fn BinaryenRustModuleSourceMapLen(module: *const BinaryenRustModule) -> usize;
-    fn BinaryenRustModuleFree(module: *mut BinaryenRustModule);
-
-    fn BinaryenRustModuleOptionsCreate()
-        -> *mut BinaryenRustModuleOptions;
-    fn BinaryenRustModuleOptionsSetDebugInfo(module: *mut BinaryenRustModuleOptions,
-                                             debuginfo: bool);
-    fn BinaryenRustModuleOptionsSetStart(module: *mut BinaryenRustModuleOptions,
-                                         start: *const libc::c_char);
-    fn BinaryenRustModuleOptionsSetSourceMapUrl(module: *mut BinaryenRustModuleOptions,
-                                                sourceMapUrl: *const libc::c_char);
-    fn BinaryenRustModuleOptionsSetStackAllocation(
-        module: *mut BinaryenRustModuleOptions,
-        stack: u64,
-    );
-    fn BinaryenRustModuleOptionsSetImportMemory(
-        module: *mut BinaryenRustModuleOptions,
-        import: bool,
-    );
-    fn BinaryenRustModuleOptionsFree(module: *mut BinaryenRustModuleOptions);
-}
diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs
index ba7ab0c07c6..6d63bc4436f 100644
--- a/src/librustc_data_structures/transitive_relation.rs
+++ b/src/librustc_data_structures/transitive_relation.rs
@@ -10,16 +10,16 @@
 
 use bitvec::BitMatrix;
 use fx::FxHashMap;
+use sync::Lock;
 use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
 use stable_hasher::{HashStable, StableHasher, StableHasherResult};
-use std::cell::RefCell;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::mem;
 
 
 #[derive(Clone, Debug)]
-pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash + Clone> {
+pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash> {
     // List of elements. This is used to map from a T to a usize.
     elements: Vec<T>,
 
@@ -32,14 +32,14 @@ pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash + Clone> {
 
     // This is a cached transitive closure derived from the edges.
     // Currently, we build it lazilly and just throw out any existing
-    // copy whenever a new edge is added. (The RefCell is to permit
+    // copy whenever a new edge is added. (The Lock is to permit
     // the lazy computation.) This is kind of silly, except for the
     // fact its size is tied to `self.elements.len()`, so I wanted to
     // wait before building it up to avoid reallocating as new edges
     // are added with new elements. Perhaps better would be to ask the
     // user for a batch of edges to minimize this effect, but I
     // already wrote the code this way. :P -nmatsakis
-    closure: RefCell<Option<BitMatrix>>,
+    closure: Lock<Option<BitMatrix>>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
@@ -51,13 +51,13 @@ struct Edge {
     target: Index,
 }
 
-impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
+impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
     pub fn new() -> TransitiveRelation<T> {
         TransitiveRelation {
             elements: vec![],
             map: FxHashMap(),
             edges: vec![],
-            closure: RefCell::new(None),
+            closure: Lock::new(None),
         }
     }
 
@@ -72,7 +72,7 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
     fn add_index(&mut self, a: T) -> Index {
         let &mut TransitiveRelation {
             ref mut elements,
-            ref closure,
+            ref mut closure,
             ref mut map,
             ..
         } = self;
@@ -82,7 +82,7 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
                elements.push(a);
 
                // if we changed the dimensions, clear the cache
-               *closure.borrow_mut() = None;
+               *closure.get_mut() = None;
 
                Index(elements.len() - 1)
            })
@@ -122,7 +122,7 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
             self.edges.push(edge);
 
             // added an edge, clear the cache
-            *self.closure.borrow_mut() = None;
+            *self.closure.get_mut() = None;
         }
     }
 
@@ -443,7 +443,7 @@ impl<T> Decodable for TransitiveRelation<T>
                               .enumerate()
                               .map(|(index, elem)| (elem.clone(), Index(index)))
                               .collect();
-            Ok(TransitiveRelation { elements, edges, map, closure: RefCell::new(None) })
+            Ok(TransitiveRelation { elements, edges, map, closure: Lock::new(None) })
         })
     }
 }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 4d1ec111c47..d89a3e9d907 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -303,7 +303,9 @@ fn get_trans_sysroot(backend_name: &str) -> fn() -> Box<TransCrate> {
     let sysroot = sysroot_candidates.iter()
         .map(|sysroot| {
             let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
-            sysroot.join(libdir).with_file_name("codegen-backends")
+            sysroot.join(libdir)
+                .with_file_name(option_env!("CFG_CODEGEN_BACKENDS_DIR")
+                                .unwrap_or("codegen-backends"))
         })
         .filter(|f| {
             info!("codegen backend candidate: {}", f.display());
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index 500c4fdf4e8..805d2086ee4 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -11,6 +11,7 @@ test = false
 
 [dependencies]
 bitflags = "1.0"
+cc = "1.0.1"
 flate2 = "1.0"
 jobserver = "0.1.5"
 libc = "0.2"
@@ -21,7 +22,6 @@ rustc-demangle = "0.1.4"
 rustc_allocator = { path = "../librustc_allocator" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_back = { path = "../librustc_back" }
-rustc_binaryen = { path = "../librustc_binaryen" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
@@ -35,9 +35,6 @@ syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 tempdir = "0.3"
 
-[target."cfg(windows)".dependencies]
-cc = "1.0.1"
-
 [features]
 # Used to communicate the feature to `rustc_back` in the same manner that the
 # `rustc` driver script communicate this.
diff --git a/src/librustc_trans/back/command.rs b/src/librustc_trans/back/command.rs
index 0bccef1e62a..ecf7bf5036e 100644
--- a/src/librustc_trans/back/command.rs
+++ b/src/librustc_trans/back/command.rs
@@ -17,6 +17,8 @@ use std::io;
 use std::mem;
 use std::process::{self, Output};
 
+use rustc_back::LldFlavor;
+
 #[derive(Clone)]
 pub struct Command {
     program: Program,
@@ -28,6 +30,7 @@ pub struct Command {
 enum Program {
     Normal(OsString),
     CmdBatScript(OsString),
+    Lld(OsString, LldFlavor)
 }
 
 impl Command {
@@ -39,6 +42,10 @@ impl Command {
         Command::_new(Program::CmdBatScript(program.as_ref().to_owned()))
     }
 
+    pub fn lld<P: AsRef<OsStr>>(program: P, flavor: LldFlavor) -> Command {
+        Command::_new(Program::Lld(program.as_ref().to_owned(), flavor))
+    }
+
     fn _new(program: Program) -> Command {
         Command {
             program,
@@ -74,17 +81,6 @@ impl Command {
         self
     }
 
-    pub fn envs<I, K, V>(&mut self, envs: I) -> &mut Command
-        where I: IntoIterator<Item=(K, V)>,
-              K: AsRef<OsStr>,
-              V: AsRef<OsStr>
-    {
-        for (key, value) in envs {
-            self._env(key.as_ref(), value.as_ref());
-        }
-        self
-    }
-
     fn _env(&mut self, key: &OsStr, value: &OsStr) {
         self.env.push((key.to_owned(), value.to_owned()));
     }
@@ -101,6 +97,16 @@ impl Command {
                 c.arg("/c").arg(p);
                 c
             }
+            Program::Lld(ref p, flavor) => {
+                let mut c = process::Command::new(p);
+                c.arg("-flavor").arg(match flavor {
+                    LldFlavor::Wasm => "wasm",
+                    LldFlavor::Ld => "gnu",
+                    LldFlavor::Link => "link",
+                    LldFlavor::Ld64 => "darwin",
+                });
+                c
+            }
         };
         ret.args(&self.args);
         ret.envs(self.env.clone());
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 8f308e72686..636b3984117 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use cc::windows_registry;
 use super::archive::{ArchiveBuilder, ArchiveConfig};
 use super::bytecode::RLIB_BYTECODE_EXTENSION;
 use super::linker::Linker;
@@ -15,6 +16,7 @@ use super::command::Command;
 use super::rpath::RPathConfig;
 use super::rpath;
 use metadata::METADATA_FILENAME;
+use rustc_back::LinkerFlavor;
 use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, PrintRequest};
 use rustc::session::config::{RUST_CGU_EXT, Lto};
 use rustc::session::filesearch;
@@ -27,14 +29,13 @@ use rustc::util::common::time;
 use rustc::util::fs::fix_windows_verbatim_for_gcc;
 use rustc::hir::def_id::CrateNum;
 use tempdir::TempDir;
-use rustc_back::{PanicStrategy, RelroLevel, LinkerFlavor};
+use rustc_back::{PanicStrategy, RelroLevel};
 use context::get_reloc_model;
 use llvm;
 
 use std::ascii;
 use std::char;
 use std::env;
-use std::ffi::OsString;
 use std::fmt;
 use std::fs;
 use std::io;
@@ -57,9 +58,7 @@ pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_o
 // The third parameter is for env vars, used on windows to set up the
 // path for MSVC to find its DLLs, and gcc to find its bundled
 // toolchain
-pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString)>) {
-    let envs = vec![("PATH".into(), command_path(sess))];
-
+pub fn get_linker(sess: &Session) -> (PathBuf, Command) {
     // If our linker looks like a batch script on Windows then to execute this
     // we'll need to spawn `cmd` explicitly. This is primarily done to handle
     // emscripten where the linker is `emcc.bat` and needs to be spawned as
@@ -74,56 +73,57 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString)
                 return Command::bat_script(linker)
             }
         }
-        Command::new(linker)
-    };
+        match sess.linker_flavor() {
+            LinkerFlavor::Lld(f) => Command::lld(linker, f),
+            _ => Command::new(linker),
 
-    if let Some(ref linker) = sess.opts.cg.linker {
-        (linker.clone(), cmd(linker), envs)
-    } else if sess.target.target.options.is_like_msvc {
-        let (cmd, envs) = msvc_link_exe_cmd(sess);
-        (PathBuf::from("link.exe"), cmd, envs)
-    } else {
-        let linker = PathBuf::from(&sess.target.target.options.linker);
-        let cmd = cmd(&linker);
-        (linker, cmd, envs)
-    }
-}
-
-#[cfg(windows)]
-pub fn msvc_link_exe_cmd(sess: &Session) -> (Command, Vec<(OsString, OsString)>) {
-    use cc::windows_registry;
+        }
+    };
 
-    let target = &sess.opts.target_triple;
-    let tool = windows_registry::find_tool(target, "link.exe");
+    let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple, "link.exe");
 
-    if let Some(tool) = tool {
-        let mut cmd = Command::new(tool.path());
-        cmd.args(tool.args());
-        for &(ref k, ref v) in tool.env() {
-            cmd.env(k, v);
-        }
-        let envs = tool.env().to_vec();
-        (cmd, envs)
-    } else {
-        debug!("Failed to locate linker.");
-        (Command::new("link.exe"), vec![])
-    }
-}
+    let linker_path = sess.opts.cg.linker.as_ref().map(|s| &**s)
+        .or(sess.target.target.options.linker.as_ref().map(|s| s.as_ref()))
+        .unwrap_or(match sess.linker_flavor() {
+            LinkerFlavor::Msvc => {
+                msvc_tool.as_ref().map(|t| t.path()).unwrap_or("link.exe".as_ref())
+            }
+            LinkerFlavor::Em if cfg!(windows) => "emcc.bat".as_ref(),
+            LinkerFlavor::Em => "emcc".as_ref(),
+            LinkerFlavor::Gcc => "cc".as_ref(),
+            LinkerFlavor::Ld => "ld".as_ref(),
+            LinkerFlavor::Lld(_) => "lld".as_ref(),
+        });
 
-#[cfg(not(windows))]
-pub fn msvc_link_exe_cmd(_sess: &Session) -> (Command, Vec<(OsString, OsString)>) {
-    (Command::new("link.exe"), vec![])
-}
+    let mut cmd = cmd(linker_path);
 
-fn command_path(sess: &Session) -> OsString {
     // The compiler's sysroot often has some bundled tools, so add it to the
     // PATH for the child.
     let mut new_path = sess.host_filesearch(PathKind::All)
                            .get_tools_search_paths();
-    if let Some(path) = env::var_os("PATH") {
-        new_path.extend(env::split_paths(&path));
+    let mut msvc_changed_path = false;
+    if sess.target.target.options.is_like_msvc {
+        if let Some(ref tool) = msvc_tool {
+            cmd.args(tool.args());
+            for &(ref k, ref v) in tool.env() {
+                if k == "PATH" {
+                    new_path.extend(env::split_paths(v));
+                    msvc_changed_path = true;
+                } else {
+                    cmd.env(k, v);
+                }
+            }
+        }
+    }
+
+    if !msvc_changed_path {
+        if let Some(path) = env::var_os("PATH") {
+            new_path.extend(env::split_paths(&path));
+        }
     }
-    env::join_paths(new_path).unwrap()
+    cmd.env("PATH", env::join_paths(new_path).unwrap());
+
+    (linker_path.to_path_buf(), cmd)
 }
 
 pub fn remove(sess: &Session, path: &Path) {
@@ -612,15 +612,8 @@ fn link_natively(sess: &Session,
     info!("preparing {:?} to {:?}", crate_type, out_filename);
     let flavor = sess.linker_flavor();
 
-    // The "binaryen linker" is massively special, so skip everything below.
-    if flavor == LinkerFlavor::Binaryen {
-        return link_binaryen(sess, crate_type, out_filename, trans, tmpdir);
-    }
-
     // The invocations of cc share some flags across platforms
-    let (pname, mut cmd, envs) = get_linker(sess);
-    // This will set PATH on windows
-    cmd.envs(envs);
+    let (pname, mut cmd) = get_linker(sess);
 
     let root = sess.target_filesearch(PathKind::Native).get_lib_path();
     if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
@@ -1485,33 +1478,6 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
     }
 }
 
-/// For now "linking with binaryen" is just "move the one module we generated in
-/// the backend to the final output"
-///
-/// That is, all the heavy lifting happens during the `back::write` phase. Here
-/// we just clean up after that.
-///
-/// Note that this is super temporary and "will not survive the night", this is
-/// guaranteed to get removed as soon as a linker for wasm exists. This should
-/// not be used for anything other than wasm.
-fn link_binaryen(sess: &Session,
-                 _crate_type: config::CrateType,
-                 out_filename: &Path,
-                 trans: &CrateTranslation,
-                 _tmpdir: &Path) {
-    assert!(trans.allocator_module.is_none());
-    assert_eq!(trans.modules.len(), 1);
-
-    let object = trans.modules[0].object.as_ref().expect("object must exist");
-    let res = fs::hard_link(object, out_filename)
-        .or_else(|_| fs::copy(object, out_filename).map(|_| ()));
-    if let Err(e) = res {
-        sess.fatal(&format!("failed to create `{}`: {}",
-                            out_filename.display(),
-                            e));
-    }
-}
-
 fn is_full_lto_enabled(sess: &Session) -> bool {
     match sess.lto() {
         Lto::Yes |
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
index 7e7811c56c7..a3ff39a47a2 100644
--- a/src/librustc_trans/back/linker.rs
+++ b/src/librustc_trans/back/linker.rs
@@ -23,7 +23,7 @@ use rustc::middle::dependency_format::Linkage;
 use rustc::session::Session;
 use rustc::session::config::{self, CrateType, OptLevel, DebugInfoLevel};
 use rustc::ty::TyCtxt;
-use rustc_back::LinkerFlavor;
+use rustc_back::{LinkerFlavor, LldFlavor};
 use serialize::{json, Encoder};
 
 /// For all the linkers we support, and information they might
@@ -45,6 +45,7 @@ impl LinkerInfo {
                          cmd: Command,
                          sess: &'a Session) -> Box<Linker+'a> {
         match sess.linker_flavor() {
+            LinkerFlavor::Lld(LldFlavor::Link) |
             LinkerFlavor::Msvc => {
                 Box::new(MsvcLinker {
                     cmd,
@@ -68,6 +69,9 @@ impl LinkerInfo {
                     is_ld: false,
                 }) as Box<Linker>
             }
+
+            LinkerFlavor::Lld(LldFlavor::Ld) |
+            LinkerFlavor::Lld(LldFlavor::Ld64) |
             LinkerFlavor::Ld => {
                 Box::new(GccLinker {
                     cmd,
@@ -77,8 +81,11 @@ impl LinkerInfo {
                     is_ld: true,
                 }) as Box<Linker>
             }
-            LinkerFlavor::Binaryen => {
-                panic!("can't instantiate binaryen linker")
+
+            LinkerFlavor::Lld(LldFlavor::Wasm) => {
+                Box::new(WasmLd {
+                    cmd,
+                }) as Box<Linker>
             }
         }
     }
@@ -785,3 +792,111 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
 
     symbols
 }
+
+pub struct WasmLd {
+    cmd: Command,
+}
+
+impl Linker for WasmLd {
+    fn link_dylib(&mut self, lib: &str) {
+        self.cmd.arg("-l").arg(lib);
+    }
+
+    fn link_staticlib(&mut self, lib: &str) {
+        self.cmd.arg("-l").arg(lib);
+    }
+
+    fn link_rlib(&mut self, lib: &Path) {
+        self.cmd.arg(lib);
+    }
+
+    fn include_path(&mut self, path: &Path) {
+        self.cmd.arg("-L").arg(path);
+    }
+
+    fn framework_path(&mut self, _path: &Path) {
+        panic!("frameworks not supported")
+    }
+
+    fn output_filename(&mut self, path: &Path) {
+        self.cmd.arg("-o").arg(path);
+    }
+
+    fn add_object(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn position_independent_executable(&mut self) {
+    }
+
+    fn partial_relro(&mut self) {
+    }
+
+    fn full_relro(&mut self) {
+    }
+
+    fn build_static_executable(&mut self) {
+    }
+
+    fn args(&mut self, args: &[String]) {
+        self.cmd.args(args);
+    }
+
+    fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+        self.cmd.arg("-l").arg(lib);
+    }
+
+    fn link_framework(&mut self, _framework: &str) {
+        panic!("frameworks not supported")
+    }
+
+    fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
+        self.cmd.arg("-l").arg(lib);
+    }
+
+    fn link_whole_rlib(&mut self, lib: &Path) {
+        self.cmd.arg(lib);
+    }
+
+    fn gc_sections(&mut self, _keep_metadata: bool) {
+    }
+
+    fn optimize(&mut self) {
+    }
+
+    fn debuginfo(&mut self) {
+    }
+
+    fn no_default_libraries(&mut self) {
+    }
+
+    fn build_dylib(&mut self, _out_filename: &Path) {
+    }
+
+    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {
+    }
+
+    fn subsystem(&mut self, _subsystem: &str) {
+    }
+
+    fn no_position_independent_executable(&mut self) {
+    }
+
+    fn finalize(&mut self) -> Command {
+        self.cmd.arg("--threads");
+
+        // FIXME we probably shouldn't pass this but instead pass an explicit
+        // whitelist of symbols we'll allow to be undefined. Unfortunately
+        // though we can't handle symbols like `log10` that LLVM injects at a
+        // super late date without actually parsing object files. For now let's
+        // stick to this and hopefully fix it before stabilization happens.
+        self.cmd.arg("--allow-undefined");
+
+        // For now we just never have an entry symbol
+        self.cmd.arg("--no-entry");
+
+        let mut cmd = Command::new("");
+        ::std::mem::swap(&mut cmd, &mut self.cmd);
+        cmd
+    }
+}
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index 68c0ba02650..55ef4e7ed3a 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -21,7 +21,6 @@ use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
 use rustc::util::nodemap::FxHashMap;
 use rustc_allocator::ALLOCATOR_METHODS;
-use rustc_back::LinkerFlavor;
 use syntax::attr;
 
 pub type ExportedSymbols = FxHashMap<
@@ -156,26 +155,12 @@ pub fn provide_extern(providers: &mut Providers) {
         let special_runtime_crate =
             tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
 
-        // Dealing with compiler-builtins and wasm right now is super janky.
-        // There's no linker! As a result we need all of the compiler-builtins
-        // exported symbols to make their way through all the way to the end of
-        // compilation. We want to make sure that LLVM doesn't remove them as
-        // well because we may or may not need them in the final output
-        // artifact. For now just force them to always get exported at the C
-        // layer, and we'll worry about gc'ing them later.
-        let compiler_builtins_and_binaryen =
-            tcx.is_compiler_builtins(cnum) &&
-            tcx.sess.linker_flavor() == LinkerFlavor::Binaryen;
-
         let mut crate_exports: Vec<_> = tcx
             .exported_symbol_ids(cnum)
             .iter()
             .map(|&def_id| {
                 let name = tcx.symbol_name(Instance::mono(tcx, def_id));
-                let export_level = if compiler_builtins_and_binaryen &&
-                                      tcx.contains_extern_indicator(def_id) {
-                    SymbolExportLevel::C
-                } else if special_runtime_crate {
+                let export_level = if special_runtime_crate {
                     // We can probably do better here by just ensuring that
                     // it has hidden visibility rather than public
                     // visibility, as this is primarily here to ensure it's
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index af5178eb565..78b26a37485 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -23,7 +23,6 @@ use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePass
                              AllPasses, Sanitizer, Lto};
 use rustc::session::Session;
 use rustc::util::nodemap::FxHashMap;
-use rustc_back::LinkerFlavor;
 use time_graph::{self, TimeGraph, Timeline};
 use llvm;
 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
@@ -344,9 +343,7 @@ pub struct CodegenContext {
     pub tm_factory: Arc<Fn() -> Result<TargetMachineRef, String> + Send + Sync>,
     pub msvc_imps_needed: bool,
     pub target_pointer_width: String,
-    binaryen_linker: bool,
     debuginfo: config::DebugInfoLevel,
-    wasm_import_memory: bool,
 
     // Number of cgus excluding the allocator/metadata modules
     pub total_cgus: usize,
@@ -639,13 +636,6 @@ unsafe fn codegen(cgcx: &CodegenContext,
         f(cpm)
     }
 
-    // If we're going to generate wasm code from the assembly that llvm
-    // generates then we'll be transitively affecting a ton of options below.
-    // This only happens on the wasm target now.
-    let asm2wasm = cgcx.binaryen_linker &&
-        !cgcx.crate_types.contains(&config::CrateTypeRlib) &&
-        mtrans.kind == ModuleKind::Regular;
-
     // If we don't have the integrated assembler, then we need to emit asm
     // from LLVM and use `gcc` to create the object file.
     let asm_to_obj = config.emit_obj && config.no_integrated_as;
@@ -654,10 +644,10 @@ unsafe fn codegen(cgcx: &CodegenContext,
     // just llvm bitcode. In that case write bitcode, and possibly
     // delete the bitcode if it wasn't requested. Don't generate the
     // machine code, instead copy the .o file from the .bc
-    let write_bc = config.emit_bc || (config.obj_is_bitcode && !asm2wasm);
-    let rm_bc = !config.emit_bc && config.obj_is_bitcode && !asm2wasm;
-    let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm2wasm && !asm_to_obj;
-    let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode && !asm2wasm;
+    let write_bc = config.emit_bc || config.obj_is_bitcode;
+    let rm_bc = !config.emit_bc && config.obj_is_bitcode;
+    let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj;
+    let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
 
     let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
     let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
@@ -736,13 +726,13 @@ unsafe fn codegen(cgcx: &CodegenContext,
             timeline.record("ir");
         }
 
-        if config.emit_asm || (asm2wasm && config.emit_obj) || asm_to_obj {
+        if config.emit_asm || asm_to_obj {
             let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
 
             // We can't use the same module for asm and binary output, because that triggers
             // various errors like invalid IR or broken binaries, so we might have to clone the
             // module to produce the asm output
-            let llmod = if config.emit_obj && !asm2wasm {
+            let llmod = if config.emit_obj {
                 llvm::LLVMCloneModule(llmod)
             } else {
                 llmod
@@ -751,24 +741,13 @@ unsafe fn codegen(cgcx: &CodegenContext,
                 write_output_file(diag_handler, tm, cpm, llmod, &path,
                                   llvm::FileType::AssemblyFile)
             })?;
-            if config.emit_obj && !asm2wasm {
+            if config.emit_obj {
                 llvm::LLVMDisposeModule(llmod);
             }
             timeline.record("asm");
         }
 
-        if asm2wasm && config.emit_obj {
-            let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
-            let suffix = ".wasm.map"; // FIXME use target suffix
-            let map = cgcx.output_filenames.path(OutputType::Exe)
-                .with_extension(&suffix[1..]);
-            binaryen_assemble(cgcx, diag_handler, &assembly, &obj_out, &map);
-            timeline.record("binaryen");
-
-            if !config.emit_asm {
-                drop(fs::remove_file(&assembly));
-            }
-        } else if write_obj {
+        if write_obj {
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
                 write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
                                   llvm::FileType::ObjectFile)
@@ -808,49 +787,6 @@ unsafe fn codegen(cgcx: &CodegenContext,
                                    &cgcx.output_filenames))
 }
 
-/// Translates the LLVM-generated `assembly` on the filesystem into a wasm
-/// module using binaryen, placing the output at `object`.
-///
-/// In this case the "object" is actually a full and complete wasm module. We
-/// won't actually be doing anything else to the output for now. This is all
-/// pretty janky and will get removed as soon as a linker for wasm exists.
-fn binaryen_assemble(cgcx: &CodegenContext,
-                     handler: &Handler,
-                     assembly: &Path,
-                     object: &Path,
-                     map: &Path) {
-    use rustc_binaryen::{Module, ModuleOptions};
-
-    let input = fs::read(&assembly).and_then(|contents| {
-        Ok(CString::new(contents)?)
-    });
-    let mut options = ModuleOptions::new();
-    if cgcx.debuginfo != config::NoDebugInfo {
-        options.debuginfo(true);
-        let map_file_name = map.file_name().unwrap();
-        options.source_map_url(map_file_name.to_str().unwrap());
-    }
-
-    options.stack(1024 * 1024);
-    options.import_memory(cgcx.wasm_import_memory);
-    let assembled = input.and_then(|input| {
-        Module::new(&input, &options)
-            .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
-    });
-    let err = assembled.and_then(|binary| {
-        fs::write(&object, binary.data()).and_then(|()| {
-            if cgcx.debuginfo != config::NoDebugInfo {
-                fs::write(map, binary.source_map())
-            } else {
-                Ok(())
-            }
-        })
-    });
-    if let Err(e) = err {
-        handler.err(&format!("failed to run binaryen assembler: {}", e));
-    }
-}
-
 pub(crate) struct CompiledModules {
     pub modules: Vec<CompiledModule>,
     pub metadata_module: CompiledModule,
@@ -1431,12 +1367,9 @@ fn start_executing_work(tcx: TyCtxt,
         each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
     }));
 
-    let wasm_import_memory =
-        attr::contains_name(&tcx.hir.krate().attrs, "wasm_import_memory");
-
     let assembler_cmd = if modules_config.no_integrated_as {
         // HACK: currently we use linker (gcc) as our assembler
-        let (name, mut cmd, _) = get_linker(sess);
+        let (name, mut cmd) = get_linker(sess);
         cmd.args(&sess.target.target.options.asm_args);
         Some(Arc::new(AssemblerCommand {
             name,
@@ -1471,9 +1404,7 @@ fn start_executing_work(tcx: TyCtxt,
         total_cgus,
         msvc_imps_needed: msvc_imps_needed(tcx),
         target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
-        binaryen_linker: tcx.sess.linker_flavor() == LinkerFlavor::Binaryen,
         debuginfo: tcx.sess.opts.debuginfo,
-        wasm_import_memory,
         assembler_cmd,
     };
 
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 6cb9d2027c7..0b8da10b78e 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -49,7 +49,6 @@ extern crate rustc_mir;
 extern crate rustc_allocator;
 extern crate rustc_apfloat;
 extern crate rustc_back;
-extern crate rustc_binaryen;
 extern crate rustc_const_math;
 extern crate rustc_data_structures;
 extern crate rustc_demangle;
@@ -63,7 +62,6 @@ extern crate rustc_trans_utils;
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
 extern crate serialize;
-#[cfg(windows)]
 extern crate cc; // Used to locate MSVC
 extern crate tempdir;
 
diff --git a/src/librustdoc/README.md b/src/librustdoc/README.md
new file mode 100644
index 00000000000..b0a5ae3718d
--- /dev/null
+++ b/src/librustdoc/README.md
@@ -0,0 +1,172 @@
+# The walking tour of rustdoc
+
+Rustdoc is implemented entirely within the crate `librustdoc`. After partially compiling a crate to
+get its AST (technically the HIR map) from rustc, librustdoc performs two major steps past that to
+render a set of documentation:
+
+* "Clean" the AST into a form that's more suited to creating documentation (and slightly more
+  resistant to churn in the compiler).
+* Use this cleaned AST to render a crate's documentation, one page at a time.
+
+Naturally, there's more than just this, and those descriptions simplify out lots of details, but
+that's the high-level overview.
+
+(Side note: this is a library crate! The `rustdoc` binary is crated using the project in
+`src/tools/rustdoc`. Note that literally all that does is call the `main()` that's in this crate's
+`lib.rs`, though.)
+
+## Cheat sheet
+
+* Use `x.py build --stage 1 src/libstd src/tools/rustdoc` to make a useable rustdoc you can run on
+  other projects.
+  * Add `src/libtest` to be able to use `rustdoc --test`.
+  * If you've used `rustup toolchain link local /path/to/build/$TARGET/stage1` previously, then
+    after the previous build command, `cargo +local doc` will Just Work.
+* Use `x.py doc --stage 1 src/libstd` to use this rustdoc to generate the standard library docs.
+  * The completed docs will be available in `build/$TARGET/doc/std`, though the bundle is meant to
+    be used as though you would copy out the `doc` folder to a web server, since that's where the
+    CSS/JS and landing page are.
+* Most of the HTML printing code is in `html/format.rs` and `html/render.rs`. It's in a bunch of
+  `fmt::Display` implementations and supplementary functions.
+* The types that got `Display` impls above are defined in `clean/mod.rs`, right next to the custom
+  `Clean` trait used to process them out of the rustc HIR.
+* The bits specific to using rustdoc as a test harness are in `test.rs`.
+* The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting
+  doctests from a given block of Markdown.
+* The tests on rustdoc *output* are located in `src/test/rustdoc`, where they're handled by the test
+  runner of rustbuild and the supplementary script `src/etc/htmldocck.py`.
+* Tests on search index generation are located in `src/test/rustdoc-js`, as a series of JavaScript
+  files that encode queries on the standard library search index and expected results.
+
+## From crate to clean
+
+In `core.rs` are two central items: the `DocContext` struct, and the `run_core` function. The latter
+is where rustdoc calls out to rustc to compile a crate to the point where rustdoc can take over. The
+former is a state container used when crawling through a crate to gather its documentation.
+
+The main process of crate crawling is done in `clean/mod.rs` through several implementations of the
+`Clean` trait defined within. This is a conversion trait, which defines one method:
+
+```rust
+pub trait Clean<T> {
+    fn clean(&self, cx: &DocContext) -> T;
+}
+```
+
+`clean/mod.rs` also defines the types for the "cleaned" AST used later on to render documentation
+pages. Each usually accompanies an implementation of `Clean` that takes some AST or HIR type from
+rustc and converts it into the appropriate "cleaned" type. "Big" items like modules or associated
+items may have some extra processing in its `Clean` implementation, but for the most part these
+impls are straightforward conversions. The "entry point" to this module is the `impl Clean<Crate>
+for visit_ast::RustdocVisitor`, which is called by `run_core` above.
+
+You see, I actually lied a little earlier: There's another AST transformation that happens before
+the events in `clean/mod.rs`.  In `visit_ast.rs` is the type `RustdocVisitor`, which *actually*
+crawls a `hir::Crate` to get the first intermediate representation, defined in `doctree.rs`. This
+pass is mainly to get a few intermediate wrappers around the HIR types and to process visibility
+and inlining. This is where `#[doc(inline)]`, `#[doc(no_inline)]`, and `#[doc(hidden)]` are
+processed, as well as the logic for whether a `pub use` should get the full page or a "Reexport"
+line in the module page.
+
+The other major thing that happens in `clean/mod.rs` is the collection of doc comments and
+`#[doc=""]` attributes into a separate field of the Attributes struct, present on anything that gets
+hand-written documentation. This makes it easier to collect this documentation later in the process.
+
+The primary output of this process is a clean::Crate with a tree of Items which describe the
+publicly-documentable items in the target crate.
+
+### Hot potato
+
+Before moving on to the next major step, a few important "passes" occur over the documentation.
+These do things like combine the separate "attributes" into a single string and strip leading
+whitespace to make the document easier on the markdown parser, or drop items that are not public or
+deliberately hidden with `#[doc(hidden)]`. These are all implemented in the `passes/` directory, one
+file per pass. By default, all of these passes are run on a crate, but the ones regarding dropping
+private/hidden items can be bypassed by passing `--document-private-items` to rustdoc.
+
+(Strictly speaking, you can fine-tune the passes run and even add your own, but [we're trying to
+deprecate that][44136]. If you need finer-grain control over these passes, please let us know!)
+
+[44136]: https://github.com/rust-lang/rust/issues/44136
+
+## From clean to crate
+
+This is where the "second phase" in rustdoc begins. This phase primarily lives in the `html/`
+folder, and it all starts with `run()` in `html/render.rs`. This code is responsible for setting up
+the `Context`, `SharedContext`, and `Cache` which are used during rendering, copying out the static
+files which live in every rendered set of documentation (things like the fonts, CSS, and JavaScript
+that live in `html/static/`), creating the search index, and printing out the source code rendering,
+before beginning the process of rendering all the documentation for the crate.
+
+Several functions implemented directly on `Context` take the `clean::Crate` and set up some state
+between rendering items or recursing on a module's child items. From here the "page rendering"
+begins, via an enormous `write!()` call in `html/layout.rs`. The parts that actually generate HTML
+from the items and documentation occurs within a series of `std::fmt::Display` implementations and
+functions that pass around a `&mut std::fmt::Formatter`. The top-level implementation that writes
+out the page body is the `impl<'a> fmt::Display for Item<'a>` in `html/render.rs`, which switches
+out to one of several `item_*` functions based on the kind of `Item` being rendered.
+
+Depending on what kind of rendering code you're looking for, you'll probably find it either in
+`html/render.rs` for major items like "what sections should I print for a struct page" or
+`html/format.rs` for smaller component pieces like "how should I print a where clause as part of
+some other item".
+
+Whenever rustdoc comes across an item that should print hand-written documentation alongside, it
+calls out to `html/markdown.rs` which interfaces with the Markdown parser. This is exposed as a
+series of types that wrap a string of Markdown, and implement `fmt::Display` to emit HTML text. It
+takes special care to enable certain features like footnotes and tables and add syntax highlighting
+to Rust code blocks (via `html/highlight.rs`) before running the Markdown parser. There's also a
+function in here (`find_testable_code`) that specifically scans for Rust code blocks so the
+test-runner code can find all the doctests in the crate.
+
+### From soup to nuts
+
+(alternate title: ["An unbroken thread that stretches from those first `Cell`s to us"][video])
+
+[video]: https://www.youtube.com/watch?v=hOLAGYmUQV0
+
+It's important to note that the AST cleaning can ask the compiler for information (crucially,
+`DocContext` contains a `TyCtxt`), but page rendering cannot. The `clean::Crate` created within
+`run_core` is passed outside the compiler context before being handed to `html::render::run`. This
+means that a lot of the "supplementary data" that isn't immediately available inside an item's
+definition, like which trait is the `Deref` trait used by the language, needs to be collected during
+cleaning, stored in the `DocContext`, and passed along to the `SharedContext` during HTML rendering.
+This manifests as a bunch of shared state, context variables, and `RefCell`s.
+
+Also of note is that some items that come from "asking the compiler" don't go directly into the
+`DocContext` - for example, when loading items from a foreign crate, rustdoc will ask about trait
+implementations and generate new `Item`s for the impls based on that information. This goes directly
+into the returned `Crate` rather than roundabout through the `DocContext`. This way, these
+implementations can be collected alongside the others, right before rendering the HTML.
+
+## Other tricks up its sleeve
+
+All this describes the process for generating HTML documentation from a Rust crate, but there are
+couple other major modes that rustdoc runs in. It can also be run on a standalone Markdown file, or
+it can run doctests on Rust code or standalone Markdown files. For the former, it shortcuts straight
+to `html/markdown.rs`, optionally including a mode which inserts a Table of Contents to the output
+HTML.
+
+For the latter, rustdoc runs a similar partial-compilation to get relevant documentation in
+`test.rs`, but instead of going through the full clean and render process, it runs a much simpler
+crate walk to grab *just* the hand-written documentation. Combined with the aforementioned
+"`find_testable_code`" in `html/markdown.rs`, it builds up a collection of tests to run before
+handing them off to the libtest test runner. One notable location in `test.rs` is the function
+`make_test`, which is where hand-written doctests get transformed into something that can be
+executed.
+
+## Dotting i's and crossing t's
+
+So that's rustdoc's code in a nutshell, but there's more things in the repo that deal with it. Since
+we have the full `compiletest` suite at hand, there's a set of tests in `src/test/rustdoc` that make
+sure the final HTML is what we expect in various situations. These tests also use a supplementary
+script, `src/etc/htmldocck.py`, that allows it to look through the final HTML using XPath notation
+to get a precise look at the output. The full description of all the commands available to rustdoc
+tests is in `htmldocck.py`.
+
+In addition, there are separate tests for the search index and rustdoc's ability to query it. The
+files in `src/test/rustdoc-js` each contain a different search query and the expected results,
+broken out by search tab. These files are processed by a script in `src/tools/rustdoc-js` and the
+Node.js runtime. These tests don't have as thorough of a writeup, but a broad example that features
+results in all tabs can be found in `basic.js`. The basic idea is that you match a given `QUERY`
+with a set of `EXPECTED` results, complete with the full item path of each item.
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index d7d856fe3ad..a7e1c0ce732 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -299,6 +299,7 @@
 #![feature(rand)]
 #![feature(raw)]
 #![feature(rustc_attrs)]
+#![feature(stdsimd)]
 #![feature(sip_hash_13)]
 #![feature(slice_bytes)]
 #![feature(slice_concat_ext)]
@@ -501,6 +502,35 @@ mod memchr;
 // compiler
 pub mod rt;
 
+// Pull in the the `stdsimd` crate directly into libstd. This is the same as
+// libcore's arch/simd modules where the source of truth here is in a different
+// repository, but we pull things in here manually to get it into libstd.
+//
+// Note that the #[cfg] here is intended to do two things. First it allows us to
+// change the rustc implementation of intrinsics in stage0 by not compiling simd
+// intrinsics in stage0. Next it doesn't compile anything in test mode as
+// stdsimd has tons of its own tests which we don't want to run.
+#[path = "../stdsimd/stdsimd/mod.rs"]
+#[allow(missing_debug_implementations, missing_docs, dead_code)]
+#[unstable(feature = "stdsimd", issue = "48556")]
+#[cfg(all(not(stage0), not(test)))]
+mod stdsimd;
+
+// A "fake" module needed by the `stdsimd` module to compile, not actually
+// exported though.
+#[cfg(not(stage0))]
+mod coresimd {
+    pub use core::arch;
+    pub use core::simd;
+}
+
+#[unstable(feature = "stdsimd", issue = "48556")]
+#[cfg(all(not(stage0), not(test)))]
+pub use stdsimd::simd;
+#[unstable(feature = "stdsimd", issue = "48556")]
+#[cfg(all(not(stage0), not(test)))]
+pub use stdsimd::arch;
+
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
 // because rustdoc only looks for these modules at the crate level.
diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs
index 844ff7a3c12..5dd9c627750 100644
--- a/src/libstd_unicode/char.rs
+++ b/src/libstd_unicode/char.rs
@@ -59,7 +59,7 @@ pub use version::UnicodeVersion;
 /// [`to_lowercase`]: ../../std/primitive.char.html#method.to_lowercase
 /// [`char`]: ../../std/primitive.char.html
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 pub struct ToLowercase(CaseMappingIter);
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -81,7 +81,7 @@ impl FusedIterator for ToLowercase {}
 /// [`to_uppercase`]: ../../std/primitive.char.html#method.to_uppercase
 /// [`char`]: ../../std/primitive.char.html
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 pub struct ToUppercase(CaseMappingIter);
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -95,7 +95,7 @@ impl Iterator for ToUppercase {
 #[unstable(feature = "fused", issue = "35602")]
 impl FusedIterator for ToUppercase {}
 
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 enum CaseMappingIter {
     Three(char, char, char),
     Two(char, char),
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 70ea015de4e..058df1d5169 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -414,9 +414,6 @@ declare_features! (
     // Allow trait methods with arbitrary self types
     (active, arbitrary_self_types, "1.23.0", Some(44874)),
 
-    // #![wasm_import_memory] attribute
-    (active, wasm_import_memory, "1.22.0", None),
-
     // `crate` in paths
     (active, crate_in_paths, "1.23.0", Some(45477)),
 
@@ -985,11 +982,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                                         never be stable",
                                                        cfg_fn!(rustc_attrs))),
 
-    ("wasm_import_memory", Whitelisted, Gated(Stability::Unstable,
-                                 "wasm_import_memory",
-                                 "wasm_import_memory attribute is currently unstable",
-                                 cfg_fn!(wasm_import_memory))),
-
     ("rustc_args_required_const", Whitelisted, Gated(Stability::Unstable,
                                  "rustc_attrs",
                                  "never will be stable",
diff --git a/src/stdsimd b/src/stdsimd
new file mode 160000
+Subproject 678cbd325c84070c9dbe4303969fbd2734c0b4e
diff --git a/src/test/compile-fail/integral-indexing.rs b/src/test/compile-fail/integral-indexing.rs
index 659b08b55a0..4b01afb8131 100644
--- a/src/test/compile-fail/integral-indexing.rs
+++ b/src/test/compile-fail/integral-indexing.rs
@@ -13,10 +13,10 @@ pub fn main() {
     let s: String = "abcdef".to_string();
     v[3_usize];
     v[3];
-    v[3u8];  //~ERROR : std::ops::Index<u8>` is not satisfied
-    v[3i8];  //~ERROR : std::ops::Index<i8>` is not satisfied
-    v[3u32]; //~ERROR : std::ops::Index<u32>` is not satisfied
-    v[3i32]; //~ERROR : std::ops::Index<i32>` is not satisfied
+    v[3u8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+    v[3i8];  //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+    v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
+    v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
     s.as_bytes()[3_usize];
     s.as_bytes()[3];
     s.as_bytes()[3u8];  //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
diff --git a/src/test/run-pass/issue-15487.rs b/src/test/run-pass/issue-15487.rs
index cc5db0af88b..3616ab9e6c7 100644
--- a/src/test/run-pass/issue-15487.rs
+++ b/src/test/run-pass/issue-15487.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-windows
+// ignore-wasm32-bare no libs to link
 
 #![feature(link_args)]
 
diff --git a/src/test/ui/feature-gate-wasm_import_memory.rs b/src/test/ui/feature-gate-wasm_import_memory.rs
deleted file mode 100644
index a010ebb3551..00000000000
--- a/src/test/ui/feature-gate-wasm_import_memory.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![wasm_import_memory] //~ ERROR: currently unstable
-
-fn main() {}
-
diff --git a/src/test/ui/feature-gate-wasm_import_memory.stderr b/src/test/ui/feature-gate-wasm_import_memory.stderr
deleted file mode 100644
index 0ec50272467..00000000000
--- a/src/test/ui/feature-gate-wasm_import_memory.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: wasm_import_memory attribute is currently unstable
-  --> $DIR/feature-gate-wasm_import_memory.rs:11:1
-   |
-LL | #![wasm_import_memory] //~ ERROR: currently unstable
-   | ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(wasm_import_memory)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-If you want more information on this error, try using "rustc --explain E0658"
diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr
index f4dde95b104..ae3cd529ac4 100644
--- a/src/test/ui/index-help.stderr
+++ b/src/test/ui/index-help.stderr
@@ -1,10 +1,11 @@
-error[E0277]: the trait bound `std::vec::Vec<{integer}>: std::ops::Index<i32>` is not satisfied
+error[E0277]: the trait bound `i32: std::slice::SliceIndex<[{integer}]>` is not satisfied
   --> $DIR/index-help.rs:13:5
    |
 LL |     x[0i32]; //~ ERROR E0277
-   |     ^^^^^^^ vector indices are of type `usize` or ranges of `usize`
+   |     ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
-   = help: the trait `std::ops::Index<i32>` is not implemented for `std::vec::Vec<{integer}>`
+   = help: the trait `std::slice::SliceIndex<[{integer}]>` is not implemented for `i32`
+   = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `std::vec::Vec<{integer}>`
 
 error: aborting due to previous error
 
diff --git a/src/tools/lld b/src/tools/lld
new file mode 160000
+Subproject b87873eaceb75cf9342d5273f01ba2c020f61ca
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 4d89008d5ca..5134c869912 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -50,7 +50,6 @@ pub mod unstable_book;
 
 fn filter_dirs(path: &Path) -> bool {
     let skip = [
-        "src/binaryen",
         "src/dlmalloc",
         "src/jemalloc",
         "src/llvm",
@@ -68,9 +67,11 @@ fn filter_dirs(path: &Path) -> bool {
         "src/tools/rust-installer",
         "src/tools/rustfmt",
         "src/tools/miri",
+        "src/tools/lld",
         "src/librustc/mir/interpret",
         "src/librustc_mir/interpret",
         "src/target",
+        "src/stdsimd",
     ];
     skip.iter().any(|p| path.ends_with(p))
 }