Skip to content

msvc: Get codegen-units working #26869

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 9, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,5 @@ pub fn oom() -> ! {
// optimize it out).
#[doc(hidden)]
#[unstable(feature = "issue_14344_fixme")]
#[cfg(stage0)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}
1 change: 1 addition & 0 deletions src/libcollections/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ pub mod btree_set {
// FIXME(#14344) this shouldn't be necessary
#[doc(hidden)]
#[unstable(feature = "issue_14344_fixme")]
#[cfg(stage0)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}

#[cfg(not(test))]
Expand Down
1 change: 1 addition & 0 deletions src/liblibc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6431,6 +6431,7 @@ pub mod funcs {
}

#[doc(hidden)]
#[cfg(stage0)]
pub fn issue_14344_workaround() {} // FIXME #14344 force linkage to happen correctly

#[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows
6 changes: 1 addition & 5 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2136,11 +2136,7 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
let mut rbml_w = Encoder::new(wr);

encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
encode_crate_triple(&mut rbml_w,
&tcx.sess
.opts
.target_triple
);
encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
encode_dylib_dependency_formats(&mut rbml_w, &ecx);

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,8 +804,8 @@ fn write_out_deps(sess: &Session,
match *output_type {
config::OutputTypeExe => {
for output in sess.crate_types.borrow().iter() {
let p = link::filename_for_input(sess, *output,
id, &file);
let p = link::filename_for_input(sess, *output, id,
outputs);
out_filenames.push(p);
}
}
Expand Down
6 changes: 2 additions & 4 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,10 +452,8 @@ impl RustcDefaultCalls {
let metadata = driver::collect_crate_metadata(sess, attrs);
*sess.crate_metadata.borrow_mut() = metadata;
for &style in &crate_types {
let fname = link::filename_for_input(sess,
style,
&id,
&t_outputs.with_extension(""));
let fname = link::filename_for_input(sess, style, &id,
&t_outputs);
println!("{}", fname.file_name().unwrap()
.to_string_lossy());
}
Expand Down
266 changes: 139 additions & 127 deletions src/librustc_trans/back/link.rs

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions src/librustc_trans/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub trait Linker {
fn link_framework(&mut self, framework: &str);
fn link_staticlib(&mut self, lib: &str);
fn link_rlib(&mut self, lib: &Path);
fn link_whole_rlib(&mut self, lib: &Path);
fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]);
fn include_path(&mut self, path: &Path);
fn framework_path(&mut self, path: &Path);
Expand Down Expand Up @@ -96,6 +97,17 @@ impl<'a> Linker for GnuLinker<'a> {
}
}

fn link_whole_rlib(&mut self, lib: &Path) {
if self.sess.target.target.options.is_like_osx {
let mut v = OsString::from("-Wl,-force_load,");
v.push(lib);
self.cmd.arg(&v);
} else {
self.cmd.arg("-Wl,--whole-archive").arg(lib)
.arg("-Wl,--no-whole-archive");
}
}

fn gc_sections(&mut self, is_dylib: bool) {
// The dead_strip option to the linker specifies that functions and data
// unreachable by the entry point will be removed. This is quite useful
Expand Down Expand Up @@ -250,6 +262,10 @@ impl<'a> Linker for MsvcLinker<'a> {
// not supported?
self.link_staticlib(lib);
}
fn link_whole_rlib(&mut self, path: &Path) {
// not supported?
self.link_rlib(path);
}
fn optimize(&mut self) {
// Needs more investigation of `/OPT` arguments
}
Expand Down
39 changes: 9 additions & 30 deletions src/librustc_trans/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,33 +56,14 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
};

let archive = ArchiveRO::open(&path).expect("wanted an rlib");
let file = path.file_name().unwrap().to_str().unwrap();
let file = &file[3..file.len() - 5]; // chop off lib/.rlib
debug!("reading {}", file);
for i in 0.. {
let filename = format!("{}.{}.bytecode.deflate", file, i);
let msg = format!("check for {}", filename);
let bc_encoded = time(sess.time_passes(), &msg, (), |_| {
archive.iter().find(|section| {
section.name() == Some(&filename[..])
})
});
let bc_encoded = match bc_encoded {
Some(data) => data,
None => {
if i == 0 {
// No bitcode was found at all.
sess.fatal(&format!("missing compressed bytecode in {}",
path.display()));
}
// No more bitcode files to read.
break
}
};
let bc_encoded = bc_encoded.data();
let bytecodes = archive.iter().filter_map(|child| {
child.name().map(|name| (name, child))
}).filter(|&(name, _)| name.ends_with("bytecode.deflate"));
for (name, data) in bytecodes {
let bc_encoded = data.data();

let bc_decoded = if is_versioned_bytecode_format(bc_encoded) {
time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| {
time(sess.time_passes(), &format!("decode {}", name), (), |_| {
// Read the version
let version = extract_bytecode_format_version(bc_encoded);

Expand All @@ -106,7 +87,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
}
})
} else {
time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| {
time(sess.time_passes(), &format!("decode {}", name), (), |_| {
// the object must be in the old, pre-versioning format, so simply
// inflate everything and let LLVM decide if it can make sense of it
match flate::inflate_bytes(bc_encoded) {
Expand All @@ -120,10 +101,8 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
};

let ptr = bc_decoded.as_ptr();
debug!("linking {}, part {}", name, i);
time(sess.time_passes(),
&format!("ll link {}.{}", name, i),
(),
debug!("linking {}", name);
time(sess.time_passes(), &format!("ll link {}", name), (),
|()| unsafe {
if !llvm::LLVMRustLinkInExternalBitcode(llmod,
ptr as *const libc::c_char,
Expand Down
95 changes: 14 additions & 81 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use std::ffi::{CStr, CString};
use std::fs;
use std::mem;
use std::path::Path;
use std::process::Stdio;
use std::ptr;
use std::str;
use std::sync::{Arc, Mutex};
Expand Down Expand Up @@ -619,6 +618,8 @@ pub fn run_passes(sess: &Session,
let needs_crate_bitcode =
sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
sess.opts.output_types.contains(&config::OutputTypeExe);
let needs_crate_object =
sess.opts.output_types.contains(&config::OutputTypeExe);
if needs_crate_bitcode {
modules_config.emit_bc = true;
}
Expand Down Expand Up @@ -696,7 +697,8 @@ pub fn run_passes(sess: &Session,
if sess.opts.cg.codegen_units == 1 {
// 1) Only one codegen unit. In this case it's no difficulty
// to copy `foo.0.x` to `foo.x`.
copy_gracefully(&crate_output.with_extension(ext), &crate_output.path(output_type));
copy_gracefully(&crate_output.with_extension(ext),
&crate_output.path(output_type));
if !sess.opts.cg.save_temps && !keep_numbered {
// The user just wants `foo.x`, not `foo.0.x`.
remove(sess, &crate_output.with_extension(ext));
Expand All @@ -715,76 +717,11 @@ pub fn run_passes(sess: &Session,
}
};

let link_obj = |output_path: &Path| {
// Running `ld -r` on a single input is kind of pointless.
if sess.opts.cg.codegen_units == 1 {
copy_gracefully(&crate_output.with_extension("0.o"), output_path);
// Leave the .0.o file around, to mimic the behavior of the normal
// code path.
return;
}

// Some builds of MinGW GCC will pass --force-exe-suffix to ld, which
// will automatically add a .exe extension if the extension is not
// already .exe or .dll. To ensure consistent behavior on Windows, we
// add the .exe suffix explicitly and then rename the output file to
// the desired path. This will give the correct behavior whether or
// not GCC adds --force-exe-suffix.
let windows_output_path =
if sess.target.target.options.is_like_windows {
Some(output_path.with_extension("o.exe"))
} else {
None
};

let (pname, mut cmd) = get_linker(sess);

cmd.args(&sess.target.target.options.pre_link_args);
cmd.arg("-nostdlib");

for index in 0..trans.modules.len() {
cmd.arg(&crate_output.with_extension(&format!("{}.o", index)));
}

cmd.arg("-r").arg("-o")
.arg(windows_output_path.as_ref().map(|s| &**s).unwrap_or(output_path));

cmd.args(&sess.target.target.options.post_link_args);

if sess.opts.debugging_opts.print_link_args {
println!("{:?}", &cmd);
}

cmd.stdin(Stdio::null());
match cmd.status() {
Ok(status) => {
if !status.success() {
sess.err(&format!("linking of {} with `{:?}` failed",
output_path.display(), cmd));
sess.abort_if_errors();
}
},
Err(e) => {
sess.err(&format!("could not exec the linker `{}`: {}",
pname, e));
sess.abort_if_errors();
},
}

match windows_output_path {
Some(ref windows_path) => {
fs::rename(windows_path, output_path).unwrap();
},
None => {
// The file is already named according to `output_path`.
}
}
};

// Flag to indicate whether the user explicitly requested bitcode.
// Otherwise, we produced it only as a temporary output, and will need
// to get rid of it.
let mut user_wants_bitcode = false;
let mut user_wants_objects = false;
for output_type in output_types {
match *output_type {
config::OutputTypeBitcode => {
Expand All @@ -801,17 +738,10 @@ pub fn run_passes(sess: &Session,
copy_if_one_unit("0.s", config::OutputTypeAssembly, false);
}
config::OutputTypeObject => {
link_obj(&crate_output.path(config::OutputTypeObject));
}
config::OutputTypeExe => {
// If config::OutputTypeObject is already in the list, then
// `crate.o` will be handled by the config::OutputTypeObject case.
// Otherwise, we need to create the temporary object so we
// can run the linker.
if !sess.opts.output_types.contains(&config::OutputTypeObject) {
link_obj(&crate_output.temp_path(config::OutputTypeObject));
}
user_wants_objects = true;
copy_if_one_unit("0.o", config::OutputTypeObject, true);
}
config::OutputTypeExe |
config::OutputTypeDepInfo => {}
}
}
Expand Down Expand Up @@ -848,15 +778,18 @@ pub fn run_passes(sess: &Session,
let keep_numbered_bitcode = needs_crate_bitcode ||
(user_wants_bitcode && sess.opts.cg.codegen_units > 1);

let keep_numbered_objects = needs_crate_object ||
(user_wants_objects && sess.opts.cg.codegen_units > 1);

for i in 0..trans.modules.len() {
if modules_config.emit_obj {
if modules_config.emit_obj && !keep_numbered_objects {
let ext = format!("{}.o", i);
remove(sess, &crate_output.with_extension(&ext[..]));
remove(sess, &crate_output.with_extension(&ext));
}

if modules_config.emit_bc && !keep_numbered_bitcode {
let ext = format!("{}.bc", i);
remove(sess, &crate_output.with_extension(&ext[..]));
remove(sess, &crate_output.with_extension(&ext));
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/test/auxiliary/issue-14344-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 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.

// no-prefer-dynamic

#![crate_type = "rlib"]

pub fn foo() {}
13 changes: 13 additions & 0 deletions src/test/auxiliary/issue-14344-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 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.

extern crate issue_14344_1;

pub fn bar() {}
18 changes: 18 additions & 0 deletions src/test/auxiliary/issue-25185-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 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.

// no-prefer-dynamic

#![crate_type = "rlib"]

#[link(name = "rust_test_helpers", kind = "static")]
extern {
pub fn rust_dbg_extern_identity_u32(u: u32) -> u32;
}
13 changes: 13 additions & 0 deletions src/test/auxiliary/issue-25185-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 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.

extern crate issue_25185_1;

pub use issue_25185_1::rust_dbg_extern_identity_u32;
4 changes: 2 additions & 2 deletions src/test/run-make/extern-fn-reachable/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
TARGET_RPATH_DIR:=$(TARGET_RPATH_DIR):$(TMPDIR)

all:
$(RUSTC) dylib.rs -o $(TMPDIR)/libdylib.so
$(RUSTC) main.rs
$(RUSTC) dylib.rs -o $(TMPDIR)/libdylib.so -C prefer-dynamic
$(RUSTC) main.rs -C prefer-dynamic
$(call RUN,main)
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

all:
$(RUSTC) -C extra-filename=bar foo.rs -C save-temps
rm $(TMPDIR)/foobar.o
rm $(TMPDIR)/foobar.0.o
rm $(TMPDIR)/$(call BIN,foobar)
Loading