about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-05-08 14:44:17 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-05-12 14:50:36 -0700
commit4cc025d83c5e3e54130dff08987982a0926e4cfa (patch)
treeeb585e4661c73071ccffd27a005f90524f0da4f1 /src
parent315750ac92a8114a96b35352ec88f82d21d5fbec (diff)
downloadrust-4cc025d83c5e3e54130dff08987982a0926e4cfa.tar.gz
rust-4cc025d83c5e3e54130dff08987982a0926e4cfa.zip
Scale back changes made
Diffstat (limited to 'src')
-rw-r--r--src/librustc/session/config.rs1
-rw-r--r--src/librustc_back/target/aarch64_unknown_linux_gnu.rs1
-rw-r--r--src/librustc_back/target/i686_unknown_linux_gnu.rs4
-rw-r--r--src/librustc_back/target/mod.rs1
-rw-r--r--src/librustc_back/target/windows_msvc_base.rs3
-rw-r--r--src/librustc_back/target/x86_64_pc_windows_msvc.rs2
-rw-r--r--src/librustc_llvm/lib.rs14
-rw-r--r--src/librustc_trans/back/link.rs13
-rw-r--r--src/librustc_trans/back/link_gnu.rs568
-rw-r--r--src/librustc_trans/back/link_msvc.rs460
-rw-r--r--src/librustc_trans/lib.rs3
-rw-r--r--src/librustc_trans/trans/base.rs12
-rw-r--r--src/librustc_trans/trans/consts.rs8
-rw-r--r--src/libstd/num/f32.rs40
-rw-r--r--src/libstd/num/f64.rs11
-rw-r--r--src/libstd/rt/mod.rs9
-rw-r--r--src/libstd/rt/unwind_msvc.rs302
17 files changed, 29 insertions, 1423 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 4154ee29388..b999929c4af 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -632,7 +632,6 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let mut ret = vec![ // Target bindings.
          attr::mk_word_item(fam.clone()),
          mk(InternedString::new("target_os"), intern(os)),
-         mk(InternedString::new("target_abi"), intern(abi)),
          mk(InternedString::new("target_family"), fam),
          mk(InternedString::new("target_arch"), intern(arch)),
          mk(InternedString::new("target_endian"), intern(end)),
diff --git a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
index 796aa3b08ca..18e67d066d0 100644
--- a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
@@ -22,7 +22,6 @@ pub fn target() -> Target {
         target_env: "gnu".to_string(),
         arch: "aarch64".to_string(),
         target_os: "linux".to_string(),
-        target_abi: "".to_string(),
         options: base,
     }
 }
diff --git a/src/librustc_back/target/i686_unknown_linux_gnu.rs b/src/librustc_back/target/i686_unknown_linux_gnu.rs
index 425077e9738..21094ad905e 100644
--- a/src/librustc_back/target/i686_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/i686_unknown_linux_gnu.rs
@@ -22,11 +22,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "linux".to_string(),
-<<<<<<< HEAD
         target_env: "gnu".to_string(),
-=======
-        target_abi: "".to_string(),
->>>>>>> 9f1453c... Very hacky MSVC hacks.
         options: base,
     }
 }
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index de8086bec4f..a3cb357dc05 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -59,6 +59,7 @@ mod freebsd_base;
 mod linux_base;
 mod openbsd_base;
 mod windows_base;
+mod windows_msvc_base;
 
 /// Everything `rustc` knows about how to compile for a specific target.
 ///
diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs
index f53f0df0e63..f4f25ea8569 100644
--- a/src/librustc_back/target/windows_msvc_base.rs
+++ b/src/librustc_back/target/windows_msvc_base.rs
@@ -13,8 +13,7 @@ use std::default::Default;
 
 pub fn opts() -> TargetOptions {
     TargetOptions {
-        // FIXME(#13846) this should be enabled for windows
-        function_sections: false,
+        function_sections: true,
         linker: "link".to_string(),
         dynamic_linking: true,
         executables: true,
diff --git a/src/librustc_back/target/x86_64_pc_windows_msvc.rs b/src/librustc_back/target/x86_64_pc_windows_msvc.rs
index 1cbf7aabeef..aac1afbb97c 100644
--- a/src/librustc_back/target/x86_64_pc_windows_msvc.rs
+++ b/src/librustc_back/target/x86_64_pc_windows_msvc.rs
@@ -24,7 +24,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
-        target_abi: "msvc".to_string(),
+        target_env: "msvc".to_string(),
         options: base,
     }
 }
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 74d7dc95b24..2a2aa2bf4cf 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -55,7 +55,6 @@ pub use self::CallConv::*;
 pub use self::Visibility::*;
 pub use self::DiagnosticSeverity::*;
 pub use self::Linkage::*;
-pub use self::DLLStorageClass::*;
 
 use std::ffi::CString;
 use std::cell::RefCell;
@@ -115,13 +114,6 @@ pub enum Linkage {
     CommonLinkage = 14,
 }
 
-#[derive(Copy)]
-pub enum DLLStorageClass {
-    DefaultStorageClass = 0,
-    DLLImportStorageClass = 1,
-    DLLExportStorageClass = 2,
-}
-
 #[repr(C)]
 #[derive(Copy, Clone, Debug)]
 pub enum DiagnosticSeverity {
@@ -2133,12 +2125,6 @@ pub fn SetLinkage(global: ValueRef, link: Linkage) {
     }
 }
 
-pub fn SetDLLStorageClass(global: ValueRef, storage_class: DLLStorageClass) {
-    unsafe {
-        LLVMRustSetDLLStorageClass(global, storage_class as c_uint);
-    }
-}
-
 pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
     unsafe {
         LLVMSetUnnamedAddr(global, unnamed as Bool);
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index aa51afac1a4..38ad909dd01 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -8,21 +8,22 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::archive::{ArchiveBuilder, ArchiveConfig, METADATA_FILENAME};
+use super::archive::{Archive, ArchiveBuilder, ArchiveConfig, METADATA_FILENAME};
+use super::archive;
+use super::rpath;
+use super::rpath::RPathConfig;
 use super::svh::Svh;
-
-use super::link_gnu;
-use super::link_msvc;
-
 use session::config;
+use session::config::NoDebugInfo;
 use session::config::{OutputFilenames, Input, OutputTypeBitcode, OutputTypeExe, OutputTypeObject};
 use session::search_paths::PathKind;
 use session::Session;
 use metadata::common::LinkMeta;
-use metadata::{encoder, cstore, csearch, creader};
+use metadata::{encoder, cstore, filesearch, csearch, creader};
 use metadata::filesearch::FileDoesntMatch;
 use trans::{CrateContext, CrateTranslation, gensym_name};
 use middle::ty::{self, Ty};
+use util::common::time;
 use util::ppaux;
 use util::sha2::{Digest, Sha256};
 use util::fs::fix_windows_verbatim_for_gcc;
diff --git a/src/librustc_trans/back/link_gnu.rs b/src/librustc_trans/back/link_gnu.rs
deleted file mode 100644
index b1582a1a3c5..00000000000
--- a/src/librustc_trans/back/link_gnu.rs
+++ /dev/null
@@ -1,568 +0,0 @@
-// Copyright 2012-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.
-
-use super::archive::{Archive, ArchiveConfig};
-use super::archive;
-use super::rpath;
-use super::rpath::RPathConfig;
-
-use session::config;
-use session::config::NoDebugInfo;
-use session::search_paths::PathKind;
-use session::Session;
-use metadata::{cstore, filesearch, csearch};
-use metadata::filesearch::FileDoesntMatch;
-use trans::{CrateTranslation};
-use util::common::time;
-
-use std::str;
-use std::old_io::{fs, TempDir, Command};
-use std::old_io;
-
-// Create a dynamic library or executable
-//
-// This will invoke the system linker/cc to create the resulting file. This
-// links to all upstream files as well.
-pub fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
-                 obj_filename: &Path, out_filename: &Path) {
-    let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir");
-
-    // The invocations of cc share some flags across platforms
-    let pname = super::link::get_cc_prog(sess);
-    let mut cmd = Command::new(&pname[..]);
-
-    cmd.args(&sess.target.target.options.pre_link_args[]);
-    link_args(&mut cmd, sess, dylib, tmpdir.path(),
-              trans, obj_filename, out_filename);
-    cmd.args(&sess.target.target.options.post_link_args[]);
-    if !sess.target.target.options.no_compiler_rt {
-        cmd.arg("-lcompiler-rt");
-    }
-
-    if sess.opts.debugging_opts.print_link_args {
-        println!("{:?}", &cmd);
-    }
-
-    // May have not found libraries in the right formats.
-    sess.abort_if_errors();
-
-    // Invoke the system linker
-    debug!("{:?}", &cmd);
-    let prog = time(sess.time_passes(), "running linker", (), |()| cmd.output());
-    match prog {
-        Ok(prog) => {
-            if !prog.status.success() {
-                sess.err(&format!("linking with `{}` failed: {}",
-                                 pname,
-                                 prog.status)[]);
-                sess.note(&format!("{:?}", &cmd)[]);
-                let mut output = prog.error.clone();
-                output.push_all(&prog.output[]);
-                sess.note(str::from_utf8(&output[..]).unwrap());
-                sess.abort_if_errors();
-            }
-            debug!("linker stderr:\n{}", String::from_utf8(prog.error).unwrap());
-            debug!("linker stdout:\n{}", String::from_utf8(prog.output).unwrap());
-        },
-        Err(e) => {
-            sess.err(&format!("could not exec the linker `{}`: {}",
-                             pname,
-                             e)[]);
-            sess.abort_if_errors();
-        }
-    }
-
-
-    // On OSX, debuggers need this utility to get run to do some munging of
-    // the symbols
-    if sess.target.target.options.is_like_osx && sess.opts.debuginfo != NoDebugInfo {
-        match Command::new("dsymutil").arg(out_filename).output() {
-            Ok(..) => {}
-            Err(e) => {
-                sess.err(&format!("failed to run dsymutil: {}", e)[]);
-                sess.abort_if_errors();
-            }
-        }
-    }
-}
-
-fn link_args(cmd: &mut Command,
-             sess: &Session,
-             dylib: bool,
-             tmpdir: &Path,
-             trans: &CrateTranslation,
-             obj_filename: &Path,
-             out_filename: &Path) {
-
-    // The default library location, we need this to find the runtime.
-    // The location of crates will be determined as needed.
-    let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
-
-    // target descriptor
-    let t = &sess.target.target;
-
-    cmd.arg("-L").arg(&lib_path);
-
-    cmd.arg("-o").arg(out_filename).arg(obj_filename);
-
-
-    // Stack growth requires statically linking a __morestack function. Note
-    // that this is listed *before* all other libraries. Due to the usage of the
-    // --as-needed flag below, the standard library may only be useful for its
-    // rust_stack_exhausted function. In this case, we must ensure that the
-    // libmorestack.a file appears *before* the standard library (so we put it
-    // at the very front).
-    //
-    // Most of the time this is sufficient, except for when LLVM gets super
-    // clever. If, for example, we have a main function `fn main() {}`, LLVM
-    // will optimize out calls to `__morestack` entirely because the function
-    // doesn't need any stack at all!
-    //
-    // To get around this snag, we specially tell the linker to always include
-    // all contents of this library. This way we're guaranteed that the linker
-    // will include the __morestack symbol 100% of the time, always resolving
-    // references to it even if the object above didn't use it.
-    if t.options.morestack {
-        if t.options.is_like_osx {
-            let morestack = lib_path.join("libmorestack.a");
-
-            let mut v = b"-Wl,-force_load,".to_vec();
-            v.push_all(morestack.as_vec());
-            cmd.arg(&v[..]);
-        } else {
-            cmd.args(&["-Wl,--whole-archive", "-lmorestack", "-Wl,--no-whole-archive"]);
-        }
-    }
-
-    // When linking a dynamic library, we put the metadata into a section of the
-    // executable. This metadata is in a separate object file from the main
-    // object file, so we link that in here.
-    if dylib {
-        cmd.arg(obj_filename.with_extension("metadata.o"));
-    }
-
-    if t.options.is_like_osx {
-        // The dead_strip option to the linker specifies that functions and data
-        // unreachable by the entry point will be removed. This is quite useful
-        // with Rust's compilation model of compiling libraries at a time into
-        // one object file. For example, this brings hello world from 1.7MB to
-        // 458K.
-        //
-        // Note that this is done for both executables and dynamic libraries. We
-        // won't get much benefit from dylibs because LLVM will have already
-        // stripped away as much as it could. This has not been seen to impact
-        // link times negatively.
-        //
-        // -dead_strip can't be part of the pre_link_args because it's also used for partial
-        // linking when using multiple codegen units (-r). So we insert it here.
-        cmd.arg("-Wl,-dead_strip");
-    }
-
-    // If we're building a dylib, we don't use --gc-sections because LLVM has
-    // already done the best it can do, and we also don't want to eliminate the
-    // metadata. If we're building an executable, however, --gc-sections drops
-    // the size of hello world from 1.8MB to 597K, a 67% reduction.
-    if !dylib && !t.options.is_like_osx {
-        cmd.arg("-Wl,--gc-sections");
-    }
-
-    let used_link_args = sess.cstore.get_used_link_args().borrow();
-
-    if t.options.position_independent_executables {
-        let empty_vec = Vec::new();
-        let empty_str = String::new();
-        let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
-        let mut args = args.iter().chain(used_link_args.iter());
-        if !dylib
-            && (t.options.relocation_model == "pic"
-                || *sess.opts.cg.relocation_model.as_ref()
-                   .unwrap_or(&empty_str) == "pic")
-            && !args.any(|x| *x == "-static") {
-            cmd.arg("-pie");
-        }
-    }
-
-    if t.options.linker_is_gnu {
-        // GNU-style linkers support optimization with -O. GNU ld doesn't need a
-        // numeric argument, but other linkers do.
-        if sess.opts.optimize == config::Default ||
-           sess.opts.optimize == config::Aggressive {
-            cmd.arg("-Wl,-O1");
-        }
-    }
-
-    // We want to prevent the compiler from accidentally leaking in any system
-    // libraries, so we explicitly ask gcc to not link to any libraries by
-    // default. Note that this does not happen for windows because windows pulls
-    // in some large number of libraries and I couldn't quite figure out which
-    // subset we wanted.
-    if !t.options.is_like_windows {
-        cmd.arg("-nodefaultlibs");
-    }
-
-    // Mark all dynamic libraries and executables as compatible with ASLR
-    // FIXME #17098: ASLR breaks gdb
-    if t.options.is_like_windows && sess.opts.debuginfo == NoDebugInfo {
-        // cmd.arg("-Wl,--dynamicbase");
-    }
-
-    // Take careful note of the ordering of the arguments we pass to the linker
-    // here. Linkers will assume that things on the left depend on things to the
-    // right. Things on the right cannot depend on things on the left. This is
-    // all formally implemented in terms of resolving symbols (libs on the right
-    // resolve unknown symbols of libs on the left, but not vice versa).
-    //
-    // For this reason, we have organized the arguments we pass to the linker as
-    // such:
-    //
-    //  1. The local object that LLVM just generated
-    //  2. Upstream rust libraries
-    //  3. Local native libraries
-    //  4. Upstream native libraries
-    //
-    // This is generally fairly natural, but some may expect 2 and 3 to be
-    // swapped. The reason that all native libraries are put last is that it's
-    // not recommended for a native library to depend on a symbol from a rust
-    // crate. If this is the case then a staticlib crate is recommended, solving
-    // the problem.
-    //
-    // Additionally, it is occasionally the case that upstream rust libraries
-    // depend on a local native library. In the case of libraries such as
-    // lua/glfw/etc the name of the library isn't the same across all platforms,
-    // so only the consumer crate of a library knows the actual name. This means
-    // that downstream crates will provide the #[link] attribute which upstream
-    // crates will depend on. Hence local native libraries are after out
-    // upstream rust crates.
-    //
-    // In theory this means that a symbol in an upstream native library will be
-    // shadowed by a local native library when it wouldn't have been before, but
-    // this kind of behavior is pretty platform specific and generally not
-    // recommended anyway, so I don't think we're shooting ourself in the foot
-    // much with that.
-    add_upstream_rust_crates(cmd, sess, dylib, tmpdir, trans);
-    add_local_native_libraries(cmd, sess);
-    add_upstream_native_libraries(cmd, sess);
-
-    // # Telling the linker what we're doing
-
-    if dylib {
-        // On mac we need to tell the linker to let this library be rpathed
-        if sess.target.target.options.is_like_osx {
-            cmd.args(&["-dynamiclib", "-Wl,-dylib"]);
-
-            if sess.opts.cg.rpath {
-                let mut v = "-Wl,-install_name,@rpath/".as_bytes().to_vec();
-                v.push_all(out_filename.filename().unwrap());
-                cmd.arg(&v[..]);
-            }
-        } else {
-            cmd.arg("-shared");
-        }
-    }
-
-    // FIXME (#2397): At some point we want to rpath our guesses as to
-    // where extern libraries might live, based on the
-    // addl_lib_search_paths
-    if sess.opts.cg.rpath {
-        let sysroot = sess.sysroot();
-        let target_triple = &sess.opts.target_triple[];
-        let get_install_prefix_lib_path = || {
-            let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
-            let tlib = filesearch::relative_target_lib_path(sysroot, target_triple);
-            let mut path = Path::new(install_prefix);
-            path.push(&tlib);
-
-            path
-        };
-        let rpath_config = RPathConfig {
-            used_crates: sess.cstore.get_used_crates(cstore::RequireDynamic),
-            out_filename: out_filename.clone(),
-            has_rpath: sess.target.target.options.has_rpath,
-            is_like_osx: sess.target.target.options.is_like_osx,
-            get_install_prefix_lib_path: get_install_prefix_lib_path,
-            realpath: ::util::fs::realpath
-        };
-        cmd.args(&rpath::get_rpath_flags(rpath_config)[]);
-    }
-
-    // Finally add all the linker arguments provided on the command line along
-    // with any #[link_args] attributes found inside the crate
-    let empty = Vec::new();
-    cmd.args(&sess.opts.cg.link_args.as_ref().unwrap_or(&empty)[]);
-    cmd.args(&used_link_args[..]);
-}
-
-// # Native library linking
-//
-// User-supplied library search paths (-L on the command line). These are
-// the same paths used to find Rust crates, so some of them may have been
-// added already by the previous crate linking code. This only allows them
-// to be found at compile time so it is still entirely up to outside
-// forces to make sure that library can be found at runtime.
-//
-// Also note that the native libraries linked here are only the ones located
-// in the current crate. Upstream crates with native library dependencies
-// may have their native library pulled in above.
-fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
-    sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| {
-        match k {
-            PathKind::Framework => { cmd.arg("-F").arg(path); }
-            _ => { cmd.arg("-L").arg(path); }
-        }
-        FileDoesntMatch
-    });
-
-    // Some platforms take hints about whether a library is static or dynamic.
-    // For those that support this, we ensure we pass the option if the library
-    // was flagged "static" (most defaults are dynamic) to ensure that if
-    // libfoo.a and libfoo.so both exist that the right one is chosen.
-    let takes_hints = !sess.target.target.options.is_like_osx;
-
-    let libs = sess.cstore.get_used_libraries();
-    let libs = libs.borrow();
-
-    let staticlibs = libs.iter().filter_map(|&(ref l, kind)| {
-        if kind == cstore::NativeStatic {Some(l)} else {None}
-    });
-    let others = libs.iter().filter(|&&(_, kind)| {
-        kind != cstore::NativeStatic
-    });
-
-    // Platforms that take hints generally also support the --whole-archive
-    // flag. We need to pass this flag when linking static native libraries to
-    // ensure the entire library is included.
-    //
-    // For more details see #15460, but the gist is that the linker will strip
-    // away any unused objects in the archive if we don't otherwise explicitly
-    // reference them. This can occur for libraries which are just providing
-    // bindings, libraries with generic functions, etc.
-    if takes_hints {
-        cmd.arg("-Wl,--whole-archive").arg("-Wl,-Bstatic");
-    }
-    let search_path = super::link::archive_search_paths(sess);
-    for l in staticlibs {
-        if takes_hints {
-            cmd.arg(format!("-l{}", l));
-        } else {
-            // -force_load is the OSX equivalent of --whole-archive, but it
-            // involves passing the full path to the library to link.
-            let lib = archive::find_library(&l[..],
-                                            &sess.target.target.options.staticlib_prefix,
-                                            &sess.target.target.options.staticlib_suffix,
-                                            &search_path[..],
-                                            &sess.diagnostic().handler);
-            let mut v = b"-Wl,-force_load,".to_vec();
-            v.push_all(lib.as_vec());
-            cmd.arg(&v[..]);
-        }
-    }
-    if takes_hints {
-        cmd.arg("-Wl,--no-whole-archive").arg("-Wl,-Bdynamic");
-    }
-
-    for &(ref l, kind) in others {
-        match kind {
-            cstore::NativeUnknown => {
-                cmd.arg(format!("-l{}", l));
-            }
-            cstore::NativeFramework => {
-                cmd.arg("-framework").arg(&l[..]);
-            }
-            cstore::NativeStatic => unreachable!(),
-        }
-    }
-}
-
-// # Rust Crate linking
-//
-// Rust crates are not considered at all when creating an rlib output. All
-// dependencies will be linked when producing the final output (instead of
-// the intermediate rlib version)
-fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
-                            dylib: bool, tmpdir: &Path,
-                            trans: &CrateTranslation) {
-    // All of the heavy lifting has previously been accomplished by the
-    // dependency_format module of the compiler. This is just crawling the
-    // output of that module, adding crates as necessary.
-    //
-    // Linking to a rlib involves just passing it to the linker (the linker
-    // will slurp up the object files inside), and linking to a dynamic library
-    // involves just passing the right -l flag.
-
-    let data = if dylib {
-        &trans.crate_formats[config::CrateTypeDylib]
-    } else {
-        &trans.crate_formats[config::CrateTypeExecutable]
-    };
-
-    // Invoke get_used_crates to ensure that we get a topological sorting of
-    // crates.
-    let deps = sess.cstore.get_used_crates(cstore::RequireDynamic);
-
-    for &(cnum, _) in &deps {
-        // We may not pass all crates through to the linker. Some crates may
-        // appear statically in an existing dylib, meaning we'll pick up all the
-        // symbols from the dylib.
-        let kind = match data[cnum as uint - 1] {
-            Some(t) => t,
-            None => continue
-        };
-        let src = sess.cstore.get_used_crate_source(cnum).unwrap();
-        match kind {
-            cstore::RequireDynamic => {
-                add_dynamic_crate(cmd, sess, src.dylib.unwrap().0)
-            }
-            cstore::RequireStatic => {
-                add_static_crate(cmd, sess, tmpdir, src.rlib.unwrap().0)
-            }
-        }
-
-    }
-
-    // Converts a library file-stem into a cc -l argument
-    fn unlib<'a>(config: &config::Config, stem: &'a [u8]) -> &'a [u8] {
-        if stem.starts_with("lib".as_bytes()) && !config.target.options.is_like_windows {
-            &stem[3..]
-        } else {
-            stem
-        }
-    }
-
-    // Adds the static "rlib" versions of all crates to the command line.
-    fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
-                        cratepath: Path) {
-        // When performing LTO on an executable output, all of the
-        // bytecode from the upstream libraries has already been
-        // included in our object file output. We need to modify all of
-        // the upstream archives to remove their corresponding object
-        // file to make sure we don't pull the same code in twice.
-        //
-        // We must continue to link to the upstream archives to be sure
-        // to pull in native static dependencies. As the final caveat,
-        // on Linux it is apparently illegal to link to a blank archive,
-        // so if an archive no longer has any object files in it after
-        // we remove `lib.o`, then don't link against it at all.
-        //
-        // If we're not doing LTO, then our job is simply to just link
-        // against the archive.
-        if sess.lto() {
-            let name = cratepath.filename_str().unwrap();
-            let name = &name[3..name.len() - 5]; // chop off lib/.rlib
-            time(sess.time_passes(),
-                 &format!("altering {}.rlib", name)[],
-                 (), |()| {
-                let dst = tmpdir.join(cratepath.filename().unwrap());
-                match fs::copy(&cratepath, &dst) {
-                    Ok(..) => {}
-                    Err(e) => {
-                        sess.err(&format!("failed to copy {} to {}: {}",
-                                         cratepath.display(),
-                                         dst.display(),
-                                         e)[]);
-                        sess.abort_if_errors();
-                    }
-                }
-                // Fix up permissions of the copy, as fs::copy() preserves
-                // permissions, but the original file may have been installed
-                // by a package manager and may be read-only.
-                match fs::chmod(&dst, old_io::USER_READ | old_io::USER_WRITE) {
-                    Ok(..) => {}
-                    Err(e) => {
-                        sess.err(&format!("failed to chmod {} when preparing \
-                                          for LTO: {}", dst.display(),
-                                         e)[]);
-                        sess.abort_if_errors();
-                    }
-                }
-                let handler = &sess.diagnostic().handler;
-                let config = ArchiveConfig {
-                    handler: handler,
-                    dst: dst.clone(),
-                    lib_search_paths: super::link::archive_search_paths(sess),
-                    slib_prefix: sess.target.target.options.staticlib_prefix.clone(),
-                    slib_suffix: sess.target.target.options.staticlib_suffix.clone(),
-                    maybe_ar_prog: sess.opts.cg.ar.clone()
-                };
-                let mut archive = Archive::open(config);
-                archive.remove_file(&format!("{}.o", name)[]);
-                let files = archive.files();
-                if files.iter().any(|s| s[].ends_with(".o")) {
-                    cmd.arg(dst);
-                }
-            });
-        } else {
-            cmd.arg(cratepath);
-        }
-    }
-
-    // Same thing as above, but for dynamic crates instead of static crates.
-    fn add_dynamic_crate(cmd: &mut Command, sess: &Session, cratepath: Path) {
-        // If we're performing LTO, then it should have been previously required
-        // that all upstream rust dependencies were available in an rlib format.
-        assert!(!sess.lto());
-
-        // Just need to tell the linker about where the library lives and
-        // what its name is
-        let dir = cratepath.dirname();
-        if !dir.is_empty() { cmd.arg("-L").arg(dir); }
-
-        let mut v = "-l".as_bytes().to_vec();
-        v.push_all(unlib(&sess.target, cratepath.filestem().unwrap()));
-        cmd.arg(&v[..]);
-    }
-}
-
-// Link in all of our upstream crates' native dependencies. Remember that
-// all of these upstream native dependencies are all non-static
-// dependencies. We've got two cases then:
-//
-// 1. The upstream crate is an rlib. In this case we *must* link in the
-// native dependency because the rlib is just an archive.
-//
-// 2. The upstream crate is a dylib. In order to use the dylib, we have to
-// have the dependency present on the system somewhere. Thus, we don't
-// gain a whole lot from not linking in the dynamic dependency to this
-// crate as well.
-//
-// The use case for this is a little subtle. In theory the native
-// dependencies of a crate are purely an implementation detail of the crate
-// itself, but the problem arises with generic and inlined functions. If a
-// generic function calls a native function, then the generic function must
-// be instantiated in the target crate, meaning that the native symbol must
-// also be resolved in the target crate.
-fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) {
-    // Be sure to use a topological sorting of crates because there may be
-    // interdependencies between native libraries. When passing -nodefaultlibs,
-    // for example, almost all native libraries depend on libc, so we have to
-    // make sure that's all the way at the right (liblibc is near the base of
-    // the dependency chain).
-    //
-    // This passes RequireStatic, but the actual requirement doesn't matter,
-    // we're just getting an ordering of crate numbers, we're not worried about
-    // the paths.
-    let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
-    for (cnum, _) in crates {
-        let libs = csearch::get_native_libraries(&sess.cstore, cnum);
-        for &(kind, ref lib) in &libs {
-            match kind {
-                cstore::NativeUnknown => {
-                    cmd.arg(format!("-l{}", *lib));
-                }
-                cstore::NativeFramework => {
-                    cmd.arg("-framework");
-                    cmd.arg(&lib[..]);
-                }
-                cstore::NativeStatic => {
-                    sess.bug("statics shouldn't be propagated");
-                }
-            }
-        }
-    }
-}
diff --git a/src/librustc_trans/back/link_msvc.rs b/src/librustc_trans/back/link_msvc.rs
deleted file mode 100644
index 0237ac1231c..00000000000
--- a/src/librustc_trans/back/link_msvc.rs
+++ /dev/null
@@ -1,460 +0,0 @@
-// Copyright 2012-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.
-
-use super::archive::{Archive, ArchiveConfig};
-use super::archive;
-use super::rpath;
-use super::rpath::RPathConfig;
-
-use session::config;
-use session::config::NoDebugInfo;
-use session::search_paths::PathKind;
-use session::Session;
-use metadata::{cstore, filesearch, csearch};
-use metadata::filesearch::FileDoesntMatch;
-use trans::CrateTranslation;
-use util::common::time;
-
-use std::str;
-use std::old_io::{fs, TempDir, Command};
-use std::old_io;
-
-// Create a dynamic library or executable
-//
-// This will invoke the system linker/cc to create the resulting file. This
-// links to all upstream files as well.
-pub fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
-                 obj_filename: &Path, out_filename: &Path) {
-    let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir");
-
-    // The invocations of cc share some flags across platforms
-    let pname = super::link::get_cc_prog(sess);
-    let mut cmd = Command::new(&pname[..]);
-
-    cmd.args(&sess.target.target.options.pre_link_args[]);
-    link_args(&mut cmd, sess, dylib, tmpdir.path(),
-              trans, obj_filename, out_filename);
-    cmd.args(&sess.target.target.options.post_link_args[]);
-    if !sess.target.target.options.no_compiler_rt {
-        cmd.arg("msvcrt.lib");
-        cmd.arg("compiler-rt.lib");
-    }
-
-    if sess.opts.debugging_opts.print_link_args {
-        println!("{:?}", &cmd);
-    }
-
-    // May have not found libraries in the right formats.
-    sess.abort_if_errors();
-
-    // Invoke the system linker
-    debug!("{:?}", &cmd);
-    let prog = time(sess.time_passes(), "running linker", (), |()| cmd.output());
-    match prog {
-        Ok(prog) => {
-            if !prog.status.success() {
-                sess.err(&format!("linking with `{}` failed: {}",
-                                 pname,
-                                 prog.status)[]);
-                sess.note(&format!("{:?}", &cmd)[]);
-                let mut output = prog.error.clone();
-                output.push_all(&prog.output[]);
-                sess.note(str::from_utf8(&output[..]).unwrap());
-                sess.abort_if_errors();
-            }
-            debug!("linker stderr:\n{}", String::from_utf8(prog.error).unwrap());
-            debug!("linker stdout:\n{}", String::from_utf8(prog.output).unwrap());
-        },
-        Err(e) => {
-            sess.err(&format!("could not exec the linker `{}`: {}",
-                             pname,
-                             e)[]);
-            sess.abort_if_errors();
-        }
-    }
-
-
-    // On OSX, debuggers need this utility to get run to do some munging of
-    // the symbols
-    if sess.target.target.options.is_like_osx && sess.opts.debuginfo != NoDebugInfo {
-        match Command::new("dsymutil").arg(out_filename).output() {
-            Ok(..) => {}
-            Err(e) => {
-                sess.err(&format!("failed to run dsymutil: {}", e)[]);
-                sess.abort_if_errors();
-            }
-        }
-    }
-}
-
-fn link_args(cmd: &mut Command,
-             sess: &Session,
-             dylib: bool,
-             tmpdir: &Path,
-             trans: &CrateTranslation,
-             obj_filename: &Path,
-             out_filename: &Path) {
-
-    // The default library location, we need this to find the runtime.
-    // The location of crates will be determined as needed.
-    let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
-
-    // target descriptor
-    let t = &sess.target.target;
-
-    lib_path.as_str().map(|lp| cmd.arg(format!("/LIBPATH:{}", lp)));
-    out_filename.as_str().map(|out| cmd.arg(format!("/OUT:{}", out)));
-    
-    cmd.arg(obj_filename);
-
-    // Stack growth requires statically linking a __morestack function. Note
-    // that this is listed *before* all other libraries. Due to the usage of the
-    // --as-needed flag below, the standard library may only be useful for its
-    // rust_stack_exhausted function. In this case, we must ensure that the
-    // libmorestack.a file appears *before* the standard library (so we put it
-    // at the very front).
-    //
-    // Most of the time this is sufficient, except for when LLVM gets super
-    // clever. If, for example, we have a main function `fn main() {}`, LLVM
-    // will optimize out calls to `__morestack` entirely because the function
-    // doesn't need any stack at all!
-    //
-    // To get around this snag, we specially tell the linker to always include
-    // all contents of this library. This way we're guaranteed that the linker
-    // will include the __morestack symbol 100% of the time, always resolving
-    // references to it even if the object above didn't use it.
-    if t.options.morestack {
-        cmd.arg("morestack.lib");
-    }
-
-    // When linking a dynamic library, we put the metadata into a section of the
-    // executable. This metadata is in a separate object file from the main
-    // object file, so we link that in here.
-    if dylib {
-        cmd.arg(obj_filename.with_extension("metadata.o"));
-    }
-
-    let used_link_args = sess.cstore.get_used_link_args().borrow();
-
-    // We want to prevent the compiler from accidentally leaking in any system
-    // libraries, so we explicitly ask gcc to not link to any libraries by
-    // default. Note that this does not happen for windows because windows pulls
-    // in some large number of libraries and I couldn't quite figure out which
-    // subset we wanted.
-
-    // We have to keep this in for now - since we need to link to the MSVCRT for
-    // things such as jemalloc.
-    //cmd.arg("/nodefaultlib");
-
-    // Take careful note of the ordering of the arguments we pass to the linker
-    // here. Linkers will assume that things on the left depend on things to the
-    // right. Things on the right cannot depend on things on the left. This is
-    // all formally implemented in terms of resolving symbols (libs on the right
-    // resolve unknown symbols of libs on the left, but not vice versa).
-    //
-    // For this reason, we have organized the arguments we pass to the linker as
-    // such:
-    //
-    //  1. The local object that LLVM just generated
-    //  2. Upstream rust libraries
-    //  3. Local native libraries
-    //  4. Upstream native libraries
-    //
-    // This is generally fairly natural, but some may expect 2 and 3 to be
-    // swapped. The reason that all native libraries are put last is that it's
-    // not recommended for a native library to depend on a symbol from a rust
-    // crate. If this is the case then a staticlib crate is recommended, solving
-    // the problem.
-    //
-    // Additionally, it is occasionally the case that upstream rust libraries
-    // depend on a local native library. In the case of libraries such as
-    // lua/glfw/etc the name of the library isn't the same across all platforms,
-    // so only the consumer crate of a library knows the actual name. This means
-    // that downstream crates will provide the #[link] attribute which upstream
-    // crates will depend on. Hence local native libraries are after out
-    // upstream rust crates.
-    //
-    // In theory this means that a symbol in an upstream native library will be
-    // shadowed by a local native library when it wouldn't have been before, but
-    // this kind of behavior is pretty platform specific and generally not
-    // recommended anyway, so I don't think we're shooting ourself in the foot
-    // much with that.
-    add_upstream_rust_crates(cmd, sess, dylib, tmpdir, trans);
-    add_local_native_libraries(cmd, sess);
-    add_upstream_native_libraries(cmd, sess);
-
-    // # Telling the linker what we're doing
-
-    if dylib {
-        cmd.arg("/DLL");
-    }
-
-    // FIXME (#2397): At some point we want to rpath our guesses as to
-    // where extern libraries might live, based on the
-    // addl_lib_search_paths
-    if sess.opts.cg.rpath {
-        let sysroot = sess.sysroot();
-        let target_triple = &sess.opts.target_triple[];
-        let get_install_prefix_lib_path = || {
-            let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
-            let tlib = filesearch::relative_target_lib_path(sysroot, target_triple);
-            let mut path = Path::new(install_prefix);
-            path.push(&tlib);
-
-            path
-        };
-        let rpath_config = RPathConfig {
-            used_crates: sess.cstore.get_used_crates(cstore::RequireDynamic),
-            out_filename: out_filename.clone(),
-            has_rpath: sess.target.target.options.has_rpath,
-            is_like_osx: sess.target.target.options.is_like_osx,
-            get_install_prefix_lib_path: get_install_prefix_lib_path,
-            realpath: ::util::fs::realpath
-        };
-        cmd.args(&rpath::get_rpath_flags(rpath_config)[]);
-    }
-
-    // Finally add all the linker arguments provided on the command line along
-    // with any #[link_args] attributes found inside the crate
-    let empty = Vec::new();
-    cmd.args(&sess.opts.cg.link_args.as_ref().unwrap_or(&empty)[]);
-    cmd.args(&used_link_args[..]);
-}
-
-// # Native library linking
-//
-// User-supplied library search paths (-L on the command line). These are
-// the same paths used to find Rust crates, so some of them may have been
-// added already by the previous crate linking code. This only allows them
-// to be found at compile time so it is still entirely up to outside
-// forces to make sure that library can be found at runtime.
-//
-// Also note that the native libraries linked here are only the ones located
-// in the current crate. Upstream crates with native library dependencies
-// may have their native library pulled in above.
-fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
-    sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, _k| {
-        path.as_str().map(|s| cmd.arg(format!("/LIBPATH:{}", s)));
-        FileDoesntMatch
-    });
-
-    let libs = sess.cstore.get_used_libraries();
-    let libs = libs.borrow();
-
-    let staticlibs = libs.iter().filter_map(|&(ref l, kind)| {
-        if kind == cstore::NativeStatic {Some(l)} else {None}
-    });
-    let others = libs.iter().filter(|&&(_, kind)| {
-        kind != cstore::NativeStatic
-    });
-
-    let search_path = super::link::archive_search_paths(sess);
-    for l in staticlibs {
-        let lib = archive::find_library(&l[..],
-                                        &sess.target.target.options.staticlib_prefix,
-                                        &sess.target.target.options.staticlib_suffix,
-                                        &search_path[..],
-                                        &sess.diagnostic().handler);
-        let mut v = Vec::new();
-        v.push_all(lib.as_vec());
-        cmd.arg(&v[..]);
-    }
-
-    for &(ref l, kind) in others {
-        match kind {
-            cstore::NativeUnknown => {
-                cmd.arg(format!("{}.lib", l));
-            }
-            cstore::NativeFramework => {}
-            cstore::NativeStatic => unreachable!(),
-        }
-    }
-}
-
-// # Rust Crate linking
-//
-// Rust crates are not considered at all when creating an rlib output. All
-// dependencies will be linked when producing the final output (instead of
-// the intermediate rlib version)
-fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
-                            dylib: bool, tmpdir: &Path,
-                            trans: &CrateTranslation) {
-    // All of the heavy lifting has previously been accomplished by the
-    // dependency_format module of the compiler. This is just crawling the
-    // output of that module, adding crates as necessary.
-    //
-    // Linking to a rlib involves just passing it to the linker (the linker
-    // will slurp up the object files inside), and linking to a dynamic library
-    // involves just passing the right -l flag.
-
-    let data = if dylib {
-        &trans.crate_formats[config::CrateTypeDylib]
-    } else {
-        &trans.crate_formats[config::CrateTypeExecutable]
-    };
-
-    // Invoke get_used_crates to ensure that we get a topological sorting of
-    // crates.
-    let deps = sess.cstore.get_used_crates(cstore::RequireDynamic);
-
-    for &(cnum, _) in &deps {
-        // We may not pass all crates through to the linker. Some crates may
-        // appear statically in an existing dylib, meaning we'll pick up all the
-        // symbols from the dylib.
-        let kind = match data[cnum as uint - 1] {
-            Some(t) => t,
-            None => continue
-        };
-        let src = sess.cstore.get_used_crate_source(cnum).unwrap();
-        match kind {
-            cstore::RequireDynamic => {
-                add_dynamic_crate(cmd, sess, src.dylib.unwrap().0)
-            }
-            cstore::RequireStatic => {
-                add_static_crate(cmd, sess, tmpdir, src.rlib.unwrap().0)
-            }
-        }
-
-    }
-
-    // Converts a library file-stem into a cc -l argument
-    fn unlib<'a>(config: &config::Config, stem: &'a [u8]) -> &'a [u8] {
-        if stem.starts_with("lib".as_bytes()) && !config.target.options.is_like_windows {
-            &stem[3..]
-        } else {
-            stem
-        }
-    }
-
-    // Adds the static "rlib" versions of all crates to the command line.
-    fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
-                        cratepath: Path) {
-        // When performing LTO on an executable output, all of the
-        // bytecode from the upstream libraries has already been
-        // included in our object file output. We need to modify all of
-        // the upstream archives to remove their corresponding object
-        // file to make sure we don't pull the same code in twice.
-        //
-        // We must continue to link to the upstream archives to be sure
-        // to pull in native static dependencies. As the final caveat,
-        // on Linux it is apparently illegal to link to a blank archive,
-        // so if an archive no longer has any object files in it after
-        // we remove `lib.o`, then don't link against it at all.
-        //
-        // If we're not doing LTO, then our job is simply to just link
-        // against the archive.
-        if sess.lto() {
-            let name = cratepath.filename_str().unwrap();
-            let name = &name[3..name.len() - 5]; // chop off lib/.rlib
-            time(sess.time_passes(),
-                 &format!("altering {}.rlib", name)[],
-                 (), |()| {
-                let dst = tmpdir.join(cratepath.filename().unwrap());
-                match fs::copy(&cratepath, &dst) {
-                    Ok(..) => {}
-                    Err(e) => {
-                        sess.err(&format!("failed to copy {} to {}: {}",
-                                         cratepath.display(),
-                                         dst.display(),
-                                         e)[]);
-                        sess.abort_if_errors();
-                    }
-                }
-                // Fix up permissions of the copy, as fs::copy() preserves
-                // permissions, but the original file may have been installed
-                // by a package manager and may be read-only.
-                match fs::chmod(&dst, old_io::USER_READ | old_io::USER_WRITE) {
-                    Ok(..) => {}
-                    Err(e) => {
-                        sess.err(&format!("failed to chmod {} when preparing \
-                                          for LTO: {}", dst.display(),
-                                         e)[]);
-                        sess.abort_if_errors();
-                    }
-                }
-                let handler = &sess.diagnostic().handler;
-                let config = ArchiveConfig {
-                    handler: handler,
-                    dst: dst.clone(),
-                    lib_search_paths: super::link::archive_search_paths(sess),
-                    slib_prefix: sess.target.target.options.staticlib_prefix.clone(),
-                    slib_suffix: sess.target.target.options.staticlib_suffix.clone(),
-                    maybe_ar_prog: sess.opts.cg.ar.clone()
-                };
-                let mut archive = Archive::open(config);
-                archive.remove_file(&format!("{}.o", name)[]);
-                let files = archive.files();
-                if files.iter().any(|s| s[].ends_with(".o")) {
-                    cmd.arg(dst);
-                }
-            });
-        } else {
-            cmd.arg(cratepath);
-        }
-    }
-
-    // Same thing as above, but for dynamic crates instead of static crates.
-    fn add_dynamic_crate(cmd: &mut Command, sess: &Session, cratepath: Path) {
-        // If we're performing LTO, then it should have been previously required
-        // that all upstream rust dependencies were available in an rlib format.
-        assert!(!sess.lto());
-
-        cratepath.as_str().map(|s| {
-            let libname = s.replace(".dll", ".lib");
-            cmd.arg(&libname[]);
-        });
-    }
-}
-
-// Link in all of our upstream crates' native dependencies. Remember that
-// all of these upstream native dependencies are all non-static
-// dependencies. We've got two cases then:
-//
-// 1. The upstream crate is an rlib. In this case we *must* link in the
-// native dependency because the rlib is just an archive.
-//
-// 2. The upstream crate is a dylib. In order to use the dylib, we have to
-// have the dependency present on the system somewhere. Thus, we don't
-// gain a whole lot from not linking in the dynamic dependency to this
-// crate as well.
-//
-// The use case for this is a little subtle. In theory the native
-// dependencies of a crate are purely an implementation detail of the crate
-// itself, but the problem arises with generic and inlined functions. If a
-// generic function calls a native function, then the generic function must
-// be instantiated in the target crate, meaning that the native symbol must
-// also be resolved in the target crate.
-fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) {
-    // Be sure to use a topological sorting of crates because there may be
-    // interdependencies between native libraries. When passing -nodefaultlibs,
-    // for example, almost all native libraries depend on libc, so we have to
-    // make sure that's all the way at the right (liblibc is near the base of
-    // the dependency chain).
-    //
-    // This passes RequireStatic, but the actual requirement doesn't matter,
-    // we're just getting an ordering of crate numbers, we're not worried about
-    // the paths.
-    let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
-    for (cnum, _) in crates {
-        let libs = csearch::get_native_libraries(&sess.cstore, cnum);
-        for &(kind, ref lib) in &libs {
-            match kind {
-                cstore::NativeUnknown => {
-                    cmd.arg(format!("{}.lib", lib));
-                }
-                cstore::NativeFramework => {
-                }
-                cstore::NativeStatic => {
-                    sess.bug("statics shouldn't be propagated");
-                }
-            }
-        }
-    }
-}
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 97c672df148..3e2db80a9c5 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -75,9 +75,6 @@ pub mod back {
     pub use rustc_back::x86_64;
 
     pub mod link;
-    mod link_gnu;
-    mod link_msvc;
-
     pub mod lto;
     pub mod write;
 
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 413e5e1f49f..4879975dde6 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -1907,16 +1907,6 @@ pub fn update_linkage(ccx: &CrateContext,
                       llval: ValueRef,
                       id: Option<ast::NodeId>,
                       llval_origin: ValueOrigin) {
-
-    // TODO: This should be conditionaly set based on whether we're producing a
-    //       dynamic library or not to follow the conventions on Windows. (ricky26)
-
-    if ccx.sess().target.target.options.is_like_msvc {
-        llvm::SetDLLStorageClass(llval, llvm::DLLExportStorageClass);
-        llvm::SetLinkage(llval, llvm::ExternalLinkage);
-        return;
-    }
-
     match llval_origin {
         InlinedCopy => {
             // `llval` is a translation of an item defined in a separate
@@ -2181,7 +2171,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
         // FIXME: #16581: Marking a symbol in the executable with `dllexport`
         // linkage forces MinGW's linker to output a `.reloc` section for ASLR
         if ccx.sess().target.target.options.is_like_windows {
-            llvm::SetDLLStorageClass(llfn, llvm::DLLExportStorageClass);
+            unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) }
         }
 
         let llbb = unsafe {
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 989ef8d8bf4..503bdf8dadb 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -863,14 +863,6 @@ pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) ->
         };
         llvm::LLVMSetInitializer(g, v);
 
-        // TODO: This should be conditionaly set based on whether we're producing a
-        //       dynamic library or not to follow the conventions on Windows. (ricky26)
-        
-        if ccx.sess().target.target.options.is_like_msvc {
-            llvm::SetDLLStorageClass(g, llvm::DLLExportStorageClass);
-            llvm::SetLinkage(g, llvm::ExternalLinkage);
-        }
-
         // As an optimization, all shared statics which do not have interior
         // mutability are placed into read-only memory.
         if m != ast::MutMutable {
diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs
index 934cf056ec1..e31d97b3240 100644
--- a/src/libstd/num/f32.rs
+++ b/src/libstd/num/f32.rs
@@ -31,10 +31,7 @@ pub use core::f32::consts;
 #[allow(dead_code)]
 mod cmath {
     use libc::{c_float, c_int};
-    #[cfg(windows)]
-    use libc::c_double;
 
-    #[link_name = "m"]
     extern {
         pub fn acosf(n: c_float) -> c_float;
         pub fn asinf(n: c_float) -> c_float;
@@ -59,35 +56,28 @@ mod cmath {
         pub fn tanhf(n: c_float) -> c_float;
         pub fn tgammaf(n: c_float) -> c_float;
 
-        #[cfg(unix)]
+        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgammaf_r")]
         pub fn lgammaf_r(n: c_float, sign: &mut c_int) -> c_float;
-        #[cfg(unix)]
+        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypotf")]
         pub fn hypotf(x: c_float, y: c_float) -> c_float;
-        #[cfg(unix)]
+
+        #[cfg(any(unix, all(windows, not(target_env = "msvc"))))]
         pub fn frexpf(n: c_float, value: &mut c_int) -> c_float;
-        #[cfg(unix)]
+        #[cfg(any(unix, all(windows, not(target_env = "msvc"))))]
         pub fn ldexpf(x: c_float, n: c_int) -> c_float;
-
-        #[cfg(windows)]
-        #[link_name="__lgammaf_r"]
-        pub fn lgammaf_r(n: c_float, sign: &mut c_int) -> c_float;
-
-        #[cfg(windows)]
-        #[link_name="_hypotf"]
-        pub fn hypotf(x: c_float, y: c_float) -> c_float;
-
-        #[cfg(windows)]
-        fn frexp(n: c_double, value: &mut c_int) -> c_double;
-
-        #[cfg(windows)]
-        fn ldexp(x: c_double, n: c_int) -> c_double;
     }
 
-    #[cfg(windows)]
-    pub unsafe fn ldexpf(x: c_float, n: c_int) -> c_float { return ldexp(x as c_double, n) as c_float; }
+    #[cfg(all(windows, target_env = "msvc"))]
+    pub unsafe fn ldexpf(x: c_float, n: c_int) -> c_float {
+        f64::ldexp(x as f64, n as isize) as c_float
+    }
 
-    #[cfg(windows)]
-    pub unsafe fn frexpf(x: c_float, value: &mut c_int) -> c_float { return frexp(x as c_double, value) as c_float; }
+    #[cfg(all(windows, target_env = "msvc"))]
+    pub unsafe fn frexpf(x: c_float, value: &mut c_int) -> c_float {
+        let (a, b) = f64::frexp(x as f64);
+        *value = b as c_int;
+        a as c_float
+    }
 }
 
 #[cfg(not(test))]
diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs
index a09a82b8552..e87855ffd4e 100644
--- a/src/libstd/num/f64.rs
+++ b/src/libstd/num/f64.rs
@@ -68,17 +68,10 @@ mod cmath {
         pub fn y1(n: c_double) -> c_double;
         pub fn yn(i: c_int, n: c_double) -> c_double;
 
-        #[cfg(unix)]
+        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgamma_r")]
         pub fn lgamma_r(n: c_double, sign: &mut c_int) -> c_double;
-        #[cfg(windows)]
-        #[link_name="__lgamma_r"]
-        pub fn lgamma_r(n: c_double, sign: &mut c_int) -> c_double;
-
-        #[cfg(unix)]
-        pub fn hypot(x: c_double, y: c_double) -> c_double;
 
-        #[cfg(windows)]
-        #[link_name="_hypot"]
+        #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypot")]
         pub fn hypot(x: c_double, y: c_double) -> c_double;
     }
 }
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index d7eede6e953..0d26206f26b 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -39,17 +39,10 @@ mod macros;
 
 // These should be refactored/moved/made private over time
 pub mod util;
-pub mod args;
-
-#[cfg(not(all(target_os = "windows", target_abi = "msvc")))]
-pub mod unwind;
-#[cfg(all(target_os = "windows", target_abi = "msvc"))]
-#[path = "unwind_msvc.rs"]
 pub mod unwind;
+pub mod args;
 
 mod at_exit_imp;
-
-#[cfg(not(all(target_os = "windows", target_abi = "msvc")))]
 mod libunwind;
 
 /// The default error code of the rust runtime if the main thread panics instead
diff --git a/src/libstd/rt/unwind_msvc.rs b/src/libstd/rt/unwind_msvc.rs
deleted file mode 100644
index b71db510c00..00000000000
--- a/src/libstd/rt/unwind_msvc.rs
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright 2013 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.
-
-//! Implementation of Rust stack unwinding
-//!
-//! For background on exception handling and stack unwinding please see
-//! "Exception Handling in LLVM" (llvm.org/docs/ExceptionHandling.html) and
-//! documents linked from it.
-//! These are also good reads:
-//!     http://theofilos.cs.columbia.edu/blog/2013/09/22/base_abi/
-//!     http://monoinfinito.wordpress.com/series/exception-handling-in-c/
-//!     http://www.airs.com/blog/index.php?s=exception+frames
-//!
-//! ## A brief summary
-//!
-//! Exception handling happens in two phases: a search phase and a cleanup phase.
-//!
-//! In both phases the unwinder walks stack frames from top to bottom using
-//! information from the stack frame unwind sections of the current process's
-//! modules ("module" here refers to an OS module, i.e. an executable or a
-//! dynamic library).
-//!
-//! For each stack frame, it invokes the associated "personality routine", whose
-//! address is also stored in the unwind info section.
-//!
-//! In the search phase, the job of a personality routine is to examine exception
-//! object being thrown, and to decide whether it should be caught at that stack
-//! frame.  Once the handler frame has been identified, cleanup phase begins.
-//!
-//! In the cleanup phase, personality routines invoke cleanup code associated
-//! with their stack frames (i.e. destructors).  Once stack has been unwound down
-//! to the handler frame level, unwinding stops and the last personality routine
-//! transfers control to its catch block.
-//!
-//! ## Frame unwind info registration
-//!
-//! Each module has its own frame unwind info section (usually ".eh_frame"), and
-//! unwinder needs to know about all of them in order for unwinding to be able to
-//! cross module boundaries.
-//!
-//! On some platforms, like Linux, this is achieved by dynamically enumerating
-//! currently loaded modules via the dl_iterate_phdr() API and finding all
-//! .eh_frame sections.
-//!
-//! Others, like Windows, require modules to actively register their unwind info
-//! sections by calling __register_frame_info() API at startup.  In the latter
-//! case it is essential that there is only one copy of the unwinder runtime in
-//! the process.  This is usually achieved by linking to the dynamic version of
-//! the unwind runtime.
-//!
-//! Currently Rust uses unwind runtime provided by libgcc.
-
-use prelude::v1::*;
-
-use any::Any;
-use cell::Cell;
-use cmp;
-use panicking;
-use fmt;
-use intrinsics;
-use mem;
-use sync::atomic::{self, Ordering};
-use sync::{Once, ONCE_INIT};
-
-pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint);
-
-// Variables used for invoking callbacks when a thread starts to unwind.
-//
-// For more information, see below.
-const MAX_CALLBACKS: uint = 16;
-static CALLBACKS: [atomic::AtomicUsize; MAX_CALLBACKS] =
-        [atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
-         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT];
-static CALLBACK_CNT: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
-
-thread_local! { static PANICKING: Cell<bool> = Cell::new(false) }
-
-/// Invoke a closure, capturing the cause of panic if one occurs.
-///
-/// This function will return `Ok(())` if the closure did not panic, and will
-/// return `Err(cause)` if the closure panics. The `cause` returned is the
-/// object with which panic was originally invoked.
-///
-/// This function also is unsafe for a variety of reasons:
-///
-/// * This is not safe to call in a nested fashion. The unwinding
-///   interface for Rust is designed to have at most one try/catch block per
-///   thread, not multiple. No runtime checking is currently performed to uphold
-///   this invariant, so this function is not safe. A nested try/catch block
-///   may result in corruption of the outer try/catch block's state, especially
-///   if this is used within a thread itself.
-///
-/// * It is not sound to trigger unwinding while already unwinding. Rust threads
-///   have runtime checks in place to ensure this invariant, but it is not
-///   guaranteed that a rust thread is in place when invoking this function.
-///   Unwinding twice can lead to resource leaks where some destructors are not
-///   run.
-pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
-    f();
-    Ok(())
-}
-
-/// Determines whether the current thread is unwinding because of panic.
-pub fn panicking() -> bool {
-    PANICKING.with(|s| s.get())
-}
-
-// An uninlined, unmangled function upon which to slap yer breakpoints
-#[inline(never)]
-#[no_mangle]
-#[allow(private_no_mangle_fns)]
-fn rust_panic(_cause: Box<Any + Send + 'static>) -> ! {
-    loop {}
-}
-
-// See also: rt/rust_try.ll
-#[cfg(all(not(test)))]
-#[doc(hidden)]
-#[allow(non_camel_case_types, non_snake_case)]
-pub mod eabi {
-    pub use self::EXCEPTION_DISPOSITION::*;
-    use libc::c_void;
-
-    #[repr(C)]
-    pub struct EXCEPTION_RECORD;
-    #[repr(C)]
-    pub struct CONTEXT;
-    #[repr(C)]
-    pub struct DISPATCHER_CONTEXT;
-
-    #[repr(C)]
-    #[derive(Copy)]
-    pub enum EXCEPTION_DISPOSITION {
-        ExceptionContinueExecution,
-        ExceptionContinueSearch,
-        ExceptionNestedException,
-        ExceptionCollidedUnwind
-    }
-
-    #[lang="eh_personality"]
-    #[no_mangle] // referenced from rust_try.ll
-    #[allow(private_no_mangle_fns)]
-    extern "C" fn rust_eh_personality(
-        _exceptionRecord: *mut EXCEPTION_RECORD,
-        _establisherFrame: *mut c_void,
-        _contextRecord: *mut CONTEXT,
-        _dispatcherContext: *mut DISPATCHER_CONTEXT
-    ) -> EXCEPTION_DISPOSITION
-    {
-        EXCEPTION_DISPOSITION::ExceptionContinueSearch
-    }
-
-    #[no_mangle] // referenced from rust_try.ll
-    pub extern "C" fn rust_eh_personality_catch(
-        _exceptionRecord: *mut EXCEPTION_RECORD,
-        _establisherFrame: *mut c_void,
-        _contextRecord: *mut CONTEXT,
-        _dispatcherContext: *mut DISPATCHER_CONTEXT
-    ) -> EXCEPTION_DISPOSITION
-    {
-        EXCEPTION_DISPOSITION::ExceptionContinueSearch
-    }
-}
-
-#[cfg(not(test))]
-/// Entry point of panic from the libcore crate.
-#[lang = "panic_fmt"]
-pub extern fn rust_begin_unwind(msg: fmt::Arguments,
-                                file: &'static str, line: uint) -> ! {
-    begin_unwind_fmt(msg, &(file, line))
-}
-
-/// The entry point for unwinding with a formatted message.
-///
-/// This is designed to reduce the amount of code required at the call
-/// site as much as possible (so that `panic!()` has as low an impact
-/// on (e.g.) the inlining of other functions as possible), by moving
-/// the actual formatting into this shared place.
-#[inline(never)] #[cold]
-#[stable(since = "1.0.0", feature = "rust1")]
-pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
-    use fmt::Write;
-
-    // We do two allocations here, unfortunately. But (a) they're
-    // required with the current scheme, and (b) we don't handle
-    // panic + OOM properly anyway (see comment in begin_unwind
-    // below).
-
-    let mut s = String::new();
-    let _ = write!(&mut s, "{}", msg);
-    begin_unwind_inner(box s, file_line)
-}
-
-/// This is the entry point of unwinding for panic!() and assert!().
-#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
-#[stable(since = "1.0.0", feature = "rust1")]
-pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) -> ! {
-    // Note that this should be the only allocation performed in this code path.
-    // Currently this means that panic!() on OOM will invoke this code path,
-    // but then again we're not really ready for panic on OOM anyway. If
-    // we do start doing this, then we should propagate this allocation to
-    // be performed in the parent of this thread instead of the thread that's
-    // panicking.
-
-    // see below for why we do the `Any` coercion here.
-    begin_unwind_inner(box msg, file_line)
-}
-
-/// The core of the unwinding.
-///
-/// This is non-generic to avoid instantiation bloat in other crates
-/// (which makes compilation of small crates noticeably slower). (Note:
-/// we need the `Any` object anyway, we're not just creating it to
-/// avoid being generic.)
-///
-/// Doing this split took the LLVM IR line counts of `fn main() { panic!()
-/// }` from ~1900/3700 (-O/no opts) to 180/590.
-#[inline(never)] #[cold] // this is the slow path, please never inline this
-fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> ! {
-    // Make sure the default panic handler is registered before we look at the
-    // callbacks.
-    static INIT: Once = ONCE_INIT;
-    INIT.call_once(|| unsafe { register(panicking::on_panic); });
-
-    // First, invoke call the user-defined callbacks triggered on thread panic.
-    //
-    // By the time that we see a callback has been registered (by reading
-    // MAX_CALLBACKS), the actual callback itself may have not been stored yet,
-    // so we just chalk it up to a race condition and move on to the next
-    // callback. Additionally, CALLBACK_CNT may briefly be higher than
-    // MAX_CALLBACKS, so we're sure to clamp it as necessary.
-    let callbacks = {
-        let amt = CALLBACK_CNT.load(Ordering::SeqCst);
-        &CALLBACKS[..cmp::min(amt, MAX_CALLBACKS)]
-    };
-    for cb in callbacks {
-        match cb.load(Ordering::SeqCst) {
-            0 => {}
-            n => {
-                let f: Callback = unsafe { mem::transmute(n) };
-                let (file, line) = *file_line;
-                f(&*msg, file, line);
-            }
-        }
-    };
-
-    // Now that we've run all the necessary unwind callbacks, we actually
-    // perform the unwinding.
-    if panicking() {
-        // If a thread panics while it's already unwinding then we
-        // have limited options. Currently our preference is to
-        // just abort. In the future we may consider resuming
-        // unwinding or otherwise exiting the thread cleanly.
-        rterrln!("thread panicked while panicking. aborting.");
-        unsafe { intrinsics::abort() }
-    }
-    PANICKING.with(|s| s.set(true));
-    rust_panic(msg);
-}
-
-/// Register a callback to be invoked when a thread unwinds.
-///
-/// This is an unsafe and experimental API which allows for an arbitrary
-/// callback to be invoked when a thread panics. This callback is invoked on both
-/// the initial unwinding and a double unwinding if one occurs. Additionally,
-/// the local `Task` will be in place for the duration of the callback, and
-/// the callback must ensure that it remains in place once the callback returns.
-///
-/// Only a limited number of callbacks can be registered, and this function
-/// returns whether the callback was successfully registered or not. It is not
-/// currently possible to unregister a callback once it has been registered.
-#[unstable(feature = "std_misc")]
-pub unsafe fn register(f: Callback) -> bool {
-    match CALLBACK_CNT.fetch_add(1, Ordering::SeqCst) {
-        // The invocation code has knowledge of this window where the count has
-        // been incremented, but the callback has not been stored. We're
-        // guaranteed that the slot we're storing into is 0.
-        n if n < MAX_CALLBACKS => {
-            let prev = CALLBACKS[n].swap(mem::transmute(f), Ordering::SeqCst);
-            rtassert!(prev == 0);
-            true
-        }
-        // If we accidentally bumped the count too high, pull it back.
-        _ => {
-            CALLBACK_CNT.store(MAX_CALLBACKS, Ordering::SeqCst);
-            false
-        }
-    }
-}