]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/back/link.rs
Replace all ~"" with "".to_owned()
[rust.git] / src / librustc / back / link.rs
index 61725bc27d12247f55ae362856838092fc4d8694..3a75a027246c66f8719d0f7394a8d5435a7e008d 100644 (file)
 
 use std::c_str::{ToCStr, CString};
 use std::char;
+use std::io::{fs, TempDir, Process};
+use std::io;
 use std::os::consts::{macos, freebsd, linux, android, win32};
 use std::ptr;
 use std::str;
-use std::io;
-use std::io::{fs, TempDir, Process};
+use std::strbuf::StrBuf;
 use flate;
 use serialize::hex::ToHex;
 use syntax::abi;
@@ -78,7 +79,7 @@ pub fn WriteOutputFile(
             let result = llvm::LLVMRustWriteOutputFile(
                     target, pm, m, output, file_type);
             if !result {
-                llvm_err(sess, ~"could not write output");
+                llvm_err(sess, "could not write output".to_owned());
             }
         })
     }
@@ -340,8 +341,8 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
 
         // FIXME (#9639): This needs to handle non-utf8 paths
         let args = [
-            ~"-c",
-            ~"-o", object.as_str().unwrap().to_owned(),
+            "-c".to_owned(),
+            "-o".to_owned(), object.as_str().unwrap().to_owned(),
             assembly.as_str().unwrap().to_owned()];
 
         debug!("{} '{}'", cc, args.connect("' '"));
@@ -546,8 +547,11 @@ fn truncated_hash_result(symbol_hasher: &mut Sha256) -> ~str {
 
 
 // This calculates STH for a symbol, as defined above
-fn symbol_hash(tcx: &ty::ctxt, symbol_hasher: &mut Sha256,
-               t: ty::t, link_meta: &LinkMeta) -> ~str {
+fn symbol_hash(tcx: &ty::ctxt,
+               symbol_hasher: &mut Sha256,
+               t: ty::t,
+               link_meta: &LinkMeta)
+               -> ~str {
     // NB: do *not* use abbrevs here as we want the symbol names
     // to be independent of one another in the crate.
 
@@ -557,10 +561,10 @@ fn symbol_hash(tcx: &ty::ctxt, symbol_hasher: &mut Sha256,
     symbol_hasher.input_str(link_meta.crate_hash.as_str());
     symbol_hasher.input_str("-");
     symbol_hasher.input_str(encoder::encoded_ty(tcx, t));
-    let mut hash = truncated_hash_result(symbol_hasher);
     // Prefix with 'h' so that it never blends into adjacent digits
-    hash.unshift_char('h');
-    hash
+    let mut hash = StrBuf::from_str("h");
+    hash.push_str(truncated_hash_result(symbol_hasher));
+    hash.into_owned()
 }
 
 fn get_symbol_hash(ccx: &CrateContext, t: ty::t) -> ~str {
@@ -580,7 +584,7 @@ fn get_symbol_hash(ccx: &CrateContext, t: ty::t) -> ~str {
 // gas doesn't!
 // gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
 pub fn sanitize(s: &str) -> ~str {
-    let mut result = ~"";
+    let mut result = StrBuf::new();
     for c in s.chars() {
         match c {
             // Escape these with $ sequences
@@ -605,19 +609,20 @@ pub fn sanitize(s: &str) -> ~str {
             | '_' | '.' | '$' => result.push_char(c),
 
             _ => {
-                let mut tstr = ~"";
+                let mut tstr = StrBuf::new();
                 char::escape_unicode(c, |c| tstr.push_char(c));
                 result.push_char('$');
-                result.push_str(tstr.slice_from(1));
+                result.push_str(tstr.as_slice().slice_from(1));
             }
         }
     }
 
     // Underscore-qualify anything that didn't start as an ident.
+    let result = result.into_owned();
     if result.len() > 0u &&
         result[0] != '_' as u8 &&
         ! char::is_XID_start(result[0] as char) {
-        return ~"_" + result;
+        return "_".to_owned() + result;
     }
 
     return result;
@@ -640,9 +645,9 @@ pub fn mangle<PI: Iterator<PathElem>>(mut path: PI,
     // To be able to work on all platforms and get *some* reasonable output, we
     // use C++ name-mangling.
 
-    let mut n = ~"_ZN"; // _Z == Begin name-sequence, N == nested
+    let mut n = StrBuf::from_str("_ZN"); // _Z == Begin name-sequence, N == nested
 
-    fn push(n: &mut ~str, s: &str) {
+    fn push(n: &mut StrBuf, s: &str) {
         let sani = sanitize(s);
         n.push_str(format!("{}{}", sani.len(), sani));
     }
@@ -662,7 +667,7 @@ fn push(n: &mut ~str, s: &str) {
     }
 
     n.push_char('E'); // End name-sequence.
-    n
+    n.into_owned()
 }
 
 pub fn exported_name(path: PathElems, hash: &str, vers: &str) -> ~str {
@@ -679,7 +684,7 @@ pub fn exported_name(path: PathElems, hash: &str, vers: &str) -> ~str {
 
 pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems,
                             t: ty::t, id: ast::NodeId) -> ~str {
-    let mut hash = get_symbol_hash(ccx, t);
+    let mut hash = StrBuf::from_owned_str(get_symbol_hash(ccx, t));
 
     // Paths can be completely identical for different nodes,
     // e.g. `fn foo() { { fn a() {} } { fn a() {} } }`, so we
@@ -699,7 +704,9 @@ pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems,
     hash.push_char(EXTRA_CHARS[extra2] as char);
     hash.push_char(EXTRA_CHARS[extra3] as char);
 
-    exported_name(path, hash, ccx.link_meta.crateid.version_or_default())
+    exported_name(path,
+                  hash.as_slice(),
+                  ccx.link_meta.crateid.version_or_default())
 }
 
 pub fn mangle_internal_name_by_type_and_seq(ccx: &CrateContext,
@@ -731,7 +738,7 @@ pub fn get_cc_prog(sess: &Session) -> ~str {
     // instead of hard-coded gcc.
     // For win32, there is no cc command, so we add a condition to make it use gcc.
     match sess.targ_cfg.os {
-        abi::OsWin32 => return ~"gcc",
+        abi::OsWin32 => return "gcc".to_owned(),
         _ => {},
     }
 
@@ -945,11 +952,14 @@ fn link_rlib<'a>(sess: &'a Session,
             let bc_deflated = obj_filename.with_extension("bc.deflate");
             match fs::File::open(&bc).read_to_end().and_then(|data| {
                 fs::File::create(&bc_deflated)
-                    .write(flate::deflate_bytes(data.as_slice()).as_slice())
+                    .write(match flate::deflate_bytes(data.as_slice()) {
+                        Some(compressed) => compressed,
+                        None => sess.fatal("failed to compress bytecode")
+                     }.as_slice())
             }) {
                 Ok(()) => {}
                 Err(e) => {
-                    sess.err(format!("failed to compress bytecode: {}", e));
+                    sess.err(format!("failed to write compressed bytecode: {}", e));
                     sess.abort_if_errors()
                 }
             }
@@ -1079,13 +1089,13 @@ fn link_args(sess: &Session,
     // The location of crates will be determined as needed.
     // FIXME (#9639): This needs to handle non-utf8 paths
     let lib_path = sess.filesearch().get_target_lib_path();
-    let stage: ~str = ~"-L" + lib_path.as_str().unwrap();
+    let stage: ~str = "-L".to_owned() + lib_path.as_str().unwrap();
 
     let mut args = vec!(stage);
 
     // FIXME (#9639): This needs to handle non-utf8 paths
     args.push_all([
-        ~"-o", out_filename.as_str().unwrap().to_owned(),
+        "-o".to_owned(), out_filename.as_str().unwrap().to_owned(),
         obj_filename.as_str().unwrap().to_owned()]);
 
     // Stack growth requires statically linking a __morestack function. Note
@@ -1103,7 +1113,7 @@ fn link_args(sess: &Session,
     // line, but inserting this farther to the left makes the
     // "rust_stack_exhausted" symbol an outstanding undefined symbol, which
     // flags libstd as a required library (or whatever provides the symbol).
-    args.push(~"-lmorestack");
+    args.push("-lmorestack".to_owned());
 
     // 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
@@ -1121,14 +1131,14 @@ fn link_args(sess: &Session,
     //
     // FIXME(#11937) we should invoke the system linker directly
     if sess.targ_cfg.os != abi::OsWin32 {
-        args.push(~"-nodefaultlibs");
+        args.push("-nodefaultlibs".to_owned());
     }
 
     if sess.targ_cfg.os == abi::OsLinux {
         // GNU-style linkers will use this to omit linking to libraries which
         // don't actually fulfill any relocations, but only for libraries which
         // follow this flag. Thus, use it before specifying libraries to link to.
-        args.push(~"-Wl,--as-needed");
+        args.push("-Wl,--as-needed".to_owned());
 
         // GNU-style linkers support optimization with -O. --gc-sections
         // removes metadata and potentially other useful things, so don't
@@ -1136,7 +1146,7 @@ fn link_args(sess: &Session,
         // do.
         if sess.opts.optimize == session::Default ||
            sess.opts.optimize == session::Aggressive {
-            args.push(~"-Wl,-O1");
+            args.push("-Wl,-O1".to_owned());
         }
     }
 
@@ -1144,7 +1154,7 @@ fn link_args(sess: &Session,
         // Make sure that we link to the dynamic libgcc, otherwise cross-module
         // DWARF stack unwinding will not work.
         // This behavior may be overridden by --link-args "-static-libgcc"
-        args.push(~"-shared-libgcc");
+        args.push("-shared-libgcc".to_owned());
 
         // And here, we see obscure linker flags #45. On windows, it has been
         // found to be necessary to have this flag to compile liblibc.
@@ -1171,13 +1181,13 @@ fn link_args(sess: &Session,
         //
         // [1] - https://sourceware.org/bugzilla/show_bug.cgi?id=13130
         // [2] - https://code.google.com/p/go/issues/detail?id=2139
-        args.push(~"-Wl,--enable-long-section-names");
+        args.push("-Wl,--enable-long-section-names".to_owned());
     }
 
     if sess.targ_cfg.os == abi::OsAndroid {
         // Many of the symbols defined in compiler-rt are also defined in libgcc.
         // Android linker doesn't like that by default.
-        args.push(~"-Wl,--allow-multiple-definition");
+        args.push("-Wl,--allow-multiple-definition".to_owned());
     }
 
     // Take careful note of the ordering of the arguments we pass to the linker
@@ -1222,22 +1232,22 @@ fn link_args(sess: &Session,
     if dylib {
         // On mac we need to tell the linker to let this library be rpathed
         if sess.targ_cfg.os == abi::OsMacos {
-            args.push(~"-dynamiclib");
-            args.push(~"-Wl,-dylib");
+            args.push("-dynamiclib".to_owned());
+            args.push("-Wl,-dylib".to_owned());
             // FIXME (#9639): This needs to handle non-utf8 paths
             if !sess.opts.cg.no_rpath {
-                args.push(~"-Wl,-install_name,@rpath/" +
+                args.push("-Wl,-install_name,@rpath/".to_owned() +
                           out_filename.filename_str().unwrap());
             }
         } else {
-            args.push(~"-shared")
+            args.push("-shared".to_owned())
         }
     }
 
     if sess.targ_cfg.os == abi::OsFreebsd {
-        args.push_all([~"-L/usr/local/lib",
-                       ~"-L/usr/local/lib/gcc46",
-                       ~"-L/usr/local/lib/gcc44"]);
+        args.push_all(["-L/usr/local/lib".to_owned(),
+                       "-L/usr/local/lib/gcc46".to_owned(),
+                       "-L/usr/local/lib/gcc44".to_owned()]);
     }
 
     // FIXME (#2397): At some point we want to rpath our guesses as to
@@ -1254,7 +1264,7 @@ fn link_args(sess: &Session,
     //
     // This is the end of the command line, so this library is used to resolve
     // *all* undefined symbols in all other libraries, and this is intentional.
-    args.push(~"-lcompiler-rt");
+    args.push("-lcompiler-rt".to_owned());
 
     // Finally add all the linker arguments provided on the command line along
     // with any #[link_args] attributes found inside the crate
@@ -1294,7 +1304,7 @@ fn add_local_native_libraries(args: &mut Vec<~str>, sess: &Session) {
                 args.push("-l" + *l);
             }
             cstore::NativeFramework => {
-                args.push(~"-framework");
+                args.push("-framework".to_owned());
                 args.push(l.to_owned());
             }
         }
@@ -1477,20 +1487,29 @@ fn add_dynamic_crates(args: &mut Vec<~str>, sess: &Session,
 //    crate as well.
 //
 // The use case for this is a little subtle. In theory the native
-// dependencies of a crate a purely an implementation detail of the crate
+// 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(args: &mut Vec<~str>, sess: &Session) {
-    let cstore = &sess.cstore;
-    cstore.iter_crate_data(|cnum, _| {
-        let libs = csearch::get_native_libraries(cstore, cnum);
+    // Be sure to use a topological sorting of crates becuase 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.move_iter() {
+        let libs = csearch::get_native_libraries(&sess.cstore, cnum);
         for &(kind, ref lib) in libs.iter() {
             match kind {
                 cstore::NativeUnknown => args.push("-l" + *lib),
                 cstore::NativeFramework => {
-                    args.push(~"-framework");
+                    args.push("-framework".to_owned());
                     args.push(lib.to_owned());
                 }
                 cstore::NativeStatic => {
@@ -1498,5 +1517,5 @@ fn add_upstream_native_libraries(args: &mut Vec<~str>, sess: &Session) {
                 }
             }
         }
-    });
+    }
 }